Fix threading issues in PowerShell cmdlets (v2025.04.15.1543)

This commit is contained in:
GraceSolutions
2025-04-15 16:50:35 -04:00
parent 570860bdc2
commit 09de38898d
71 changed files with 2670 additions and 1863 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
RootModule = 'lib\PSOPNSenseAPI.dll' RootModule = 'lib\PSOPNSenseAPI.dll'
# Version number of this module. # Version number of this module.
ModuleVersion = '2025.04.15.1143' ModuleVersion = '2025.04.15.1216'
# Supported PSEditions # Supported PSEditions
CompatiblePSEditions = @('Desktop', 'Core') CompatiblePSEditions = @('Desktop', 'Core')
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 PSOPNSenseAPI Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,213 @@
@{
# Script module or binary module file associated with this manifest.
RootModule = 'lib\PSOPNSenseAPI.dll'
# Version number of this module.
ModuleVersion = '2025.04.15.1543'
# Supported PSEditions
CompatiblePSEditions = @('Desktop', 'Core')
# ID used to uniquely identify this module
GUID = '9a3b4c55-5f9a-4b8c-87d9-9a7a5cdd5c9f'
# Author of this module
Author = 'PSOPNSenseAPI Contributors'
# Company or vendor of this module
CompanyName = 'PSOPNSenseAPI'
# Copyright statement for this module
Copyright = '(c) 2025 PSOPNSenseAPI Contributors. All rights reserved.'
# Description of the functionality provided by this module
Description = 'PowerShell module for interacting with the OPNSense API to configure firewalls'
# Minimum version of the PowerShell engine required by this module
PowerShellVersion = '5.1'
# Name of the PowerShell host required by this module
# PowerShellHostName = ''
# Minimum version of the PowerShell host required by this module
# PowerShellHostVersion = ''
# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# DotNetFrameworkVersion = '4.7.2'
# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
ClrVersion = '4.0'
# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''
# Modules that must be imported into the global environment prior to importing this module
# RequiredModules = @()
# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @()
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = @()
# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = @()
# Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = @()
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = @()
# Functions 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 functions to export.
FunctionsToExport = @()
# Cmdlets 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 cmdlets to export.
CmdletsToExport = @(
'Apply-OPNSenseFirewallChanges',
'Connect-OPNSense',
'Connect-OPNSenseTailscale',
'ConvertTo-OPNSenseNetworkNotation',
'Disable-OPNSenseCronJob',
'Disable-OPNSenseFirewallRule',
'Disable-OPNSensePlugin',
'Disable-OPNSenseTailscale',
'Disconnect-OPNSense',
'Disconnect-OPNSenseTailscale',
'Enable-OPNSenseCronJob',
'Enable-OPNSenseFirewallRule',
'Enable-OPNSensePlugin',
'Enable-OPNSenseTailscale',
'Export-OPNSenseConfig',
'Get-OPNSenseAlias',
'Get-OPNSenseConfig',
'Get-OPNSenseConfigBackup',
'Get-OPNSenseConnection',
'Get-OPNSenseCronJob',
'Get-OPNSenseDHCPLease',
'Get-OPNSenseDHCPOption',
'Get-OPNSenseDHCPServer',
'Get-OPNSenseDHCPStaticMapping',
'Get-OPNSenseDNSForwarding',
'Get-OPNSenseDNSForwardingHost',
'Get-OPNSenseDNSOverride',
'Get-OPNSenseDNSServer',
'Get-OPNSenseFirewallRule',
'Get-OPNSenseFirmware',
'Get-OPNSenseGateway',
'Get-OPNSenseInterface',
'Get-OPNSenseInterfaceStatistics',
'Get-OPNSensePlugin',
'Get-OPNSensePortForwardingRule',
'Get-OPNSenseRoute',
'Get-OPNSenseSystemDNS',
'Get-OPNSenseTailscaleStatus',
'Get-OPNSenseUser',
'Get-OPNSenseVLAN',
'Import-OPNSenseConfig',
'Install-OPNSensePlugin',
'Invoke-OPNSenseNetworkCalculation',
'New-OPNSenseAlias',
'New-OPNSenseCronJob',
'New-OPNSenseDHCPOption',
'New-OPNSenseDHCPStaticMapping',
'New-OPNSenseDNSForwardingHost',
'New-OPNSenseDNSOverride',
'New-OPNSenseFirewallRule',
'New-OPNSenseGateway',
'New-OPNSensePortForwardingRule',
'New-OPNSenseRoute',
'New-OPNSenseSubnetVLANs',
'New-OPNSenseUser',
'New-OPNSenseVLAN',
'Remove-OPNSenseAlias',
'Remove-OPNSenseCronJob',
'Remove-OPNSenseDHCPLease',
'Remove-OPNSenseDHCPOption',
'Remove-OPNSenseDHCPStaticMapping',
'Remove-OPNSenseDNSForwardingHost',
'Remove-OPNSenseDNSOverride',
'Remove-OPNSenseFirewallRule',
'Remove-OPNSenseGateway',
'Remove-OPNSensePortForwardingRule',
'Remove-OPNSenseRoute',
'Remove-OPNSenseUser',
'Remove-OPNSenseVLAN',
'Restart-OPNSenseFirewall',
'Restart-OPNSenseInterface',
'Restore-OPNSenseConfig',
'Set-OPNSenseAlias',
'Set-OPNSenseCronJob',
'Set-OPNSenseDHCPOption',
'Set-OPNSenseDHCPServer',
'Set-OPNSenseDHCPStaticMapping',
'Set-OPNSenseDNSForwarding',
'Set-OPNSenseDNSForwardingHost',
'Set-OPNSenseDNSServer',
'Set-OPNSenseFirewallRule',
'Set-OPNSenseGateway',
'Set-OPNSenseInterface',
'Set-OPNSensePortForwardingRule',
'Set-OPNSenseRoute',
'Set-OPNSenseSystemDNS',
'Set-OPNSenseUser',
'Set-OPNSenseVLAN',
'Uninstall-OPNSensePlugin',
'Update-OPNSenseFirmware',
'Start-OPNSenseFirmwareUpgrade'
)
# Variables to export from this module
VariablesToExport = @()
# 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.
AliasesToExport = @()
# DSC resources to export from this module
# DscResourcesToExport = @()
# List of all modules packaged with this module
# ModuleList = @()
# List of all files packaged with this module
# FileList = @()
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{
PSData = @{
# Tags applied to this module. These help with module discovery in online galleries.
Tags = @('PowerShell', 'OPNSense', 'Firewall', 'API')
# A URL to the license for this module.
LicenseUri = 'https://github.com/freedbygrace/PSOPNSenseAPI/blob/main/LICENSE'
# A URL to the main website for this project.
ProjectUri = 'https://github.com/freedbygrace/PSOPNSenseAPI'
# A URL to an icon representing this module.
# IconUri = ''
# ReleaseNotes of this module
ReleaseNotes = 'https://github.com/freedbygrace/PSOPNSenseAPI/blob/main/CHANGELOG.md'
# Prerelease string of this module
# Prerelease = ''
# Flag to indicate whether the module requires explicit user acceptance for install/update/save
# RequireLicenseAcceptance = $false
# External dependent modules of this module
# ExternalModuleDependencies = @()
} # End of PSData hashtable
} # End of PrivateData hashtable
# HelpInfoURI of this module
# HelpInfoURI = ''
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''
}
@@ -0,0 +1,202 @@
# PSOPNSenseAPI
PowerShell module for interacting with the OPNSense API to configure firewalls.
## Overview
PSOPNSenseAPI is a PowerShell module that provides cmdlets for managing OPNSense firewalls through their API. The module is built as a binary module in C# and is compatible with both PowerShell 5.1 and PowerShell 7.
## Features
- Connect to OPNSense firewalls using API credentials
- Manage firewall rules (create, read, update, delete)
- Configure NAT rules and port forwarding
- Manage aliases (host, network, port, URL, etc.)
- Manage network interfaces and VLANs
- Configure DNS settings, overrides, and forwarding
- Configure system DNS servers
- Backup, restore, export, and import configurations
- Manage plugins (install, uninstall, enable, disable)
- Manage users and permissions
- Update and upgrade firmware
- Reboot firewall with wait for reconnection
- Create VLANs from subnet divisions
- Configure DHCP servers, static mappings, leases, and options
- Manage cron jobs
- Configure and manage Tailscale VPN (with auto-installation)
- Manage gateways and static routes
- Network calculation utilities (subnet, supernet, CIDR conversion)
- Apply and revert configuration changes
- Extensive logging and error handling
- Compatible with both PowerShell 5.1 and PowerShell 7
## Requirements
- PowerShell 5.1 or PowerShell 7+
- .NET Framework 4.7.2+ (for PowerShell 5.1)
- .NET Core 3.1+ (for PowerShell 7)
## Installation
```powershell
# Install from PowerShell Gallery (when published)
Install-Module -Name PSOPNSenseAPI
# Or install manually
# 1. Download the module
# 2. Extract to a directory in your PSModulePath
# 3. Import the module
Import-Module PSOPNSenseAPI
```
## Quick Start
```powershell
# Connect to an OPNSense firewall
Connect-OPNSense -Server "https://firewall.example.com" -ApiKey "your_api_key" -ApiSecret "your_api_secret" -SkipCertificateCheck
# Get all firewall rules
Get-OPNSenseFirewallRule
# Create a new firewall rule
New-OPNSenseFirewallRule -Description "Allow HTTP" -Protocol TCP -SourceNet "192.168.1.0/24" -DestinationPort 80 -Action Pass
# Apply changes
Apply-OPNSenseFirewallChanges
# Manage aliases
Get-OPNSenseAlias
New-OPNSenseAlias -Name "WebServers" -Type host -Content "192.168.1.10,192.168.1.11" -Description "Web Servers" -Apply
New-OPNSenseAlias -Name "WebPorts" -Type port -Content "80,443" -Protocol TCP -Description "Web Ports" -Apply
Set-OPNSenseAlias -Uuid "9e4ec4f0-9dd1-4fa3-8c1d-8a8e9d772b0f" -Content "192.168.1.10,192.168.1.11,192.168.1.12" -Apply
# Manage interfaces
Get-OPNSenseInterface
Set-OPNSenseInterface -Name "lan" -Description "Local Network" -IpAddress "192.168.1.1" -SubnetMask "24"
# Create VLANs from subnet divisions
New-OPNSenseSubnetVLANs -ParentInterface "em0" -Network "192.168.0.0/24" -SubnetMaskBits 27 -StartingVlanId 10 -VlanIdIncrement 10 -EnableDHCP
# Configure DNS
Set-OPNSenseDNSServer -Forwarding -Forwarders "8.8.8.8","8.8.4.4" -Apply
New-OPNSenseDNSOverride -Hostname "server" -Domain "local" -IpAddress "192.168.1.10"
# Manage plugins
Get-OPNSensePlugin -Installed
Install-OPNSensePlugin -Name "os-acme-client" -Wait
# Manage users
New-OPNSenseUser -Username "john" -Password "P@ssw0rd" -FullName "John Doe" -Groups "admins"
# Configure DHCP
Get-OPNSenseDHCPServer
Set-OPNSenseDHCPServer -Interface "lan" -RangeFrom "192.168.1.100" -RangeTo "192.168.1.200" -Apply
New-OPNSenseDHCPStaticMapping -Interface "lan" -MacAddress "00:11:22:33:44:55" -IpAddress "192.168.1.50" -Hostname "printer"
Get-OPNSenseDHCPLease
Remove-OPNSenseDHCPLease -MacAddress "00:11:22:33:44:55" -Apply
Get-OPNSenseDHCPOption -Interface "lan"
New-OPNSenseDHCPOption -Interface "lan" -Number 66 -Value "192.168.1.10" -Description "TFTP Server" -Apply
# Manage cron jobs
Get-OPNSenseCronJob
New-OPNSenseCronJob -Description "Daily backup" -Command "/usr/local/bin/backup.sh" -Minutes "0" -Hours "2" -Apply
# Configure and manage Tailscale
Get-OPNSenseTailscaleStatus -IncludeInterfaces
Enable-OPNSenseTailscale -AcceptDns -AcceptRoutes -Force
# Advertise subnet routes to Tailscale network
Enable-OPNSenseTailscale -AdvertiseRoutes -SubnetRoutes "192.168.1.0/24","10.0.0.0/8" -Force
Connect-OPNSenseTailscale -AuthKey "tskey-auth-abcdef123456" -InstallIfMissing -Force
# Manage DNS forwarding
Get-OPNSenseDNSForwarding
Set-OPNSenseDNSForwarding -Enabled -DnsServers "8.8.8.8","8.8.4.4" -Apply
New-OPNSenseDNSForwardingHost -Domain "example.com" -Server "192.168.1.10" -Apply
# Configure system DNS
Get-OPNSenseSystemDNS
Set-OPNSenseSystemDNS -Hostname "firewall" -Domain "example.com" -DnsServers "1.1.1.1","1.0.0.1" -Apply
# Manage gateways and routes
Get-OPNSenseGateway -IncludeStatus
New-OPNSenseGateway -Name "WAN2_GW" -Interface "opt1" -IpAddress "203.0.113.1" -Description "Secondary WAN" -Apply
Get-OPNSenseRoute
New-OPNSenseRoute -Network "192.168.100.0/24" -Gateway "WAN2_GW" -Description "Remote Office" -Apply
# Network utilities
Invoke-OPNSenseNetworkCalculation -Network "192.168.1.0/24" -Operation Info
Invoke-OPNSenseNetworkCalculation -Network "10.0.0.0/16" -Operation Subnet -PrefixLength 24
ConvertTo-OPNSenseNetworkNotation -CIDR 24 # Returns "255.255.255.0"
# Advanced supernetting
Invoke-OPNSenseNetworkCalculation -Network "192.168.1.0/24" -Operation Supernet -AdditionalNetworks "192.168.2.0/24"
Invoke-OPNSenseNetworkCalculation -Network "10.0.0.0/24" -Operation SupernetSummarize -AdditionalNetworks "10.0.1.0/24","10.0.2.0/24"
# Firmware management
Update-OPNSenseFirmware -Wait
# Major firmware upgrade
Start-OPNSenseFirmwareUpgrade -Wait -Timeout 1200
# Reboot firewall
Restart-OPNSenseFirewall -Wait -Timeout 300
# Configuration management
Get-OPNSenseConfig | Restore-OPNSenseConfig -Force # Get and restore configuration in one line
$config = Get-OPNSenseConfig # Get configuration as XML document
Export-OPNSenseConfig -Path (New-Object System.IO.FileInfo "C:\Backups\opnsense-config.xml")
Import-OPNSenseConfig -Path (New-Object System.IO.FileInfo "C:\Backups\opnsense-config.xml") -Force
```
## Documentation
For detailed documentation, see the [docs](./docs) directory or use PowerShell's built-in help:
```powershell
Get-Help Connect-OPNSense -Full
```
## Development
### Build and Test
To build and test the module locally:
```powershell
# Run tests
.\build\test.ps1
# Build the module
.\build\build.ps1
# Build a release version with automatic versioning
.\build\build-release.ps1 -Clean -Test -Package
```
### Versioning
The module uses a versioning scheme of `yyyy.MM.dd.HHmm` for releases, which is automatically generated during the build process.
### CI/CD
The project uses GitHub Actions for continuous integration and deployment:
- Builds and tests are run on every push to the main branch
- Release packages are automatically created with the versioning scheme
- Release artifacts are uploaded to GitHub Releases
## Contributing
Contributions are welcome! Please follow these steps:
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Make your changes
4. Run tests to ensure they pass
5. Commit your changes (`git commit -m 'Add some amazing feature'`)
6. Push to the branch (`git push origin feature/amazing-feature`)
7. Open a Pull Request
## License
This project is licensed under the MIT License - see the LICENSE file for details.
@@ -46,31 +46,46 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var firewallService = new FirewallService(ApiClient, Logger); var firewallService = new FirewallService(ApiClient, Logger);
if (NoRollback.IsPresent) if (NoRollback.IsPresent)
{ {
WriteVerbose("Applying firewall changes without rollback protection"); WriteVerbose("Applying firewall changes without rollback protection");
var applyTask = Task.Run(async () => await firewallService.ApplyChangesAsync()); var applyResult = ExecuteAsyncTask(() => firewallService.ApplyChangesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"Firewall changes applied: {applyResult.Status}"); WriteVerbose($"Firewall changes applied: {applyResult.Status}");
} }
else else
{ {
WriteVerbose("Creating savepoint for rollback protection"); WriteVerbose("Creating savepoint for rollback protection");
var savepointTask = Task.Run(async () => await firewallService.CreateSavepointAsync()); var savepointResult = ExecuteAsyncTask(() => firewallService.CreateSavepointAsync());
var savepointResult = savepointTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || savepointResult == null)
{
return;
}
var revision = savepointResult.Revision; var revision = savepointResult.Revision;
WriteVerbose($"Created savepoint with revision {revision}"); WriteVerbose($"Created savepoint with revision {revision}");
WriteVerbose("Applying firewall changes with rollback protection"); WriteVerbose("Applying firewall changes with rollback protection");
var applyTask = Task.Run(async () => await firewallService.ApplyChangesAsync(revision)); var applyResult = ExecuteAsyncTask(() => firewallService.ApplyChangesAsync(revision));
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"Firewall changes applied: {applyResult.Status}"); WriteVerbose($"Firewall changes applied: {applyResult.Status}");
@@ -80,8 +95,13 @@ namespace PSOPNSenseAPI.Cmdlets
System.Threading.Thread.Sleep(Timeout * 1000); System.Threading.Thread.Sleep(Timeout * 1000);
WriteVerbose("Cancelling automatic rollback"); WriteVerbose("Cancelling automatic rollback");
var cancelTask = Task.Run(async () => await firewallService.CancelRollbackAsync(revision)); var cancelResult = ExecuteAsyncTask(() => firewallService.CancelRollbackAsync(revision));
var cancelResult = cancelTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || cancelResult == null)
{
return;
}
WriteVerbose($"Rollback cancelled: {cancelResult.Status}"); WriteVerbose($"Rollback cancelled: {cancelResult.Status}");
} }
@@ -91,10 +111,5 @@ namespace PSOPNSenseAPI.Cmdlets
} }
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -57,6 +57,14 @@ namespace PSOPNSenseAPI.Cmdlets
[Parameter(Mandatory = false, ParameterSetName = "FromIPWithSubnetMask")] [Parameter(Mandatory = false, ParameterSetName = "FromIPWithSubnetMask")]
public string IPWithSubnetMask { get; set; } public string IPWithSubnetMask { get; set; }
/// <summary>
/// Begins the processing of the cmdlet
/// </summary>
protected override void BeginProcessing()
{
base.BeginProcessing();
}
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
@@ -88,22 +96,16 @@ namespace PSOPNSenseAPI.Cmdlets
string[] parts = IPWithCIDR.Split('/'); string[] parts = IPWithCIDR.Split('/');
if (parts.Length != 2) if (parts.Length != 2)
{ {
WriteError(new ErrorRecord( // Use WriteWarning instead of WriteError to avoid threading issues
new ArgumentException($"Invalid IP with CIDR: {IPWithCIDR}. Expected format: 192.168.1.0/24"), WriteWarning($"Invalid IP with CIDR: {IPWithCIDR}. Expected format: 192.168.1.0/24");
"InvalidIPWithCIDR",
ErrorCategory.InvalidArgument,
null));
return; return;
} }
string ip = parts[0]; string ip = parts[0];
if (!int.TryParse(parts[1], out int cidr)) if (!int.TryParse(parts[1], out int cidr))
{ {
WriteError(new ErrorRecord( // Use WriteWarning instead of WriteError to avoid threading issues
new ArgumentException($"Invalid CIDR: {parts[1]}"), WriteWarning($"Invalid CIDR: {parts[1]}");
"InvalidCIDR",
ErrorCategory.InvalidArgument,
null));
return; return;
} }
@@ -118,11 +120,8 @@ namespace PSOPNSenseAPI.Cmdlets
string[] parts = IPWithSubnetMask.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); string[] parts = IPWithSubnetMask.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length != 2) if (parts.Length != 2)
{ {
WriteError(new ErrorRecord( // Use WriteWarning instead of WriteError to avoid threading issues
new ArgumentException($"Invalid IP with subnet mask: {IPWithSubnetMask}. Expected format: 192.168.1.0 255.255.255.0"), WriteWarning($"Invalid IP with subnet mask: {IPWithSubnetMask}. Expected format: 192.168.1.0 255.255.255.0");
"InvalidIPWithSubnetMask",
ErrorCategory.InvalidArgument,
null));
return; return;
} }
@@ -136,12 +135,17 @@ namespace PSOPNSenseAPI.Cmdlets
} }
catch (Exception ex) catch (Exception ex)
{ {
WriteError(new ErrorRecord( // Use WriteWarning instead of WriteError to avoid threading issues
ex, WriteWarning($"Conversion error: {ex.Message}");
"ConversionError", }
ErrorCategory.InvalidOperation, }
null));
} /// <summary>
/// Ends the processing of the cmdlet
/// </summary>
protected override void EndProcessing()
{
base.EndProcessing();
} }
} }
} }
@@ -28,21 +28,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var firewallService = new FirewallService(ApiClient, Logger); var firewallService = new FirewallService(ApiClient, Logger);
var task = Task.Run(async () => await firewallService.ToggleRuleAsync(Uuid, false)); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => firewallService.ToggleRuleAsync(Uuid, false));
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteVerbose($"Firewall rule {Uuid} disabled: {result.Result}"); WriteVerbose($"Firewall rule {Uuid} disabled: {result.Result}");
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -28,22 +28,21 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var pluginService = new PluginService(ApiClient, Logger); var pluginService = new PluginService(ApiClient, Logger);
var task = Task.Run(async () => await pluginService.DisablePluginAsync(Name)); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => pluginService.DisablePluginAsync(Name));
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteVerbose($"Plugin {Name} disabled: {result.Status}"); WriteVerbose($"Plugin {Name} disabled: {result.Status}");
WriteObject($"Plugin {Name} disabled: {result.Status}"); WriteObject($"Plugin {Name} disabled: {result.Status}");
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -38,15 +38,18 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var tailscaleService = new TailscaleService(ApiClient, Logger); var tailscaleService = new TailscaleService(ApiClient, Logger);
// Check if the plugin is installed // Check if the plugin is installed
var isInstalledTask = Task.Run(async () => await tailscaleService.IsPluginInstalledAsync()); var isInstalled = ExecuteAsyncTask(() => tailscaleService.IsPluginInstalledAsync());
var isInstalled = isInstalledTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null)
{
return;
}
if (!isInstalled) if (!isInstalled)
{ {
@@ -55,8 +58,15 @@ namespace PSOPNSenseAPI.Cmdlets
} }
// Get current settings // Get current settings
var settingsTask = Task.Run(async () => await tailscaleService.GetSettingsAsync()); var settingsResult = ExecuteAsyncTask(() => tailscaleService.GetSettingsAsync());
var currentSettings = settingsTask.GetAwaiter().GetResult().General;
// Only continue if no exception occurred
if (ProcessingException != null || settingsResult == null)
{
return;
}
var currentSettings = settingsResult.General;
// Create new settings with disabled flag // Create new settings with disabled flag
var settings = new TailscaleSettings var settings = new TailscaleSettings
@@ -80,8 +90,13 @@ namespace PSOPNSenseAPI.Cmdlets
} }
// Update settings // Update settings
var updateTask = Task.Run(async () => await tailscaleService.UpdateSettingsAsync(settings)); var updateResult = ExecuteAsyncTask(() => tailscaleService.UpdateSettingsAsync(settings));
var updateResult = updateTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || updateResult == null)
{
return;
}
WriteVerbose($"Tailscale settings updated: {updateResult.Result}"); WriteVerbose($"Tailscale settings updated: {updateResult.Result}");
@@ -89,14 +104,25 @@ namespace PSOPNSenseAPI.Cmdlets
if (Stop.IsPresent) if (Stop.IsPresent)
{ {
WriteVerbose("Stopping Tailscale service..."); WriteVerbose("Stopping Tailscale service...");
var stopTask = Task.Run(async () => await tailscaleService.StopServiceAsync()); var stopResult = ExecuteAsyncTask(() => tailscaleService.StopServiceAsync());
var stopResult = stopTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || stopResult == null)
{
return;
}
WriteVerbose($"Tailscale service stopped: {stopResult.Status}"); WriteVerbose($"Tailscale service stopped: {stopResult.Status}");
} }
// Get updated status // Get updated status
var statusTask = Task.Run(async () => await tailscaleService.GetStatusAsync()); var status = ExecuteAsyncTask(() => tailscaleService.GetStatusAsync());
var status = statusTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || status == null)
{
return;
}
// Create result object // Create result object
var result = new PSObject(); var result = new PSObject();
@@ -107,10 +133,5 @@ namespace PSOPNSenseAPI.Cmdlets
WriteObject(result); WriteObject(result);
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -17,6 +17,14 @@ namespace PSOPNSenseAPI.Cmdlets
[OutputType(typeof(void))] [OutputType(typeof(void))]
public class DisconnectOPNSenseCmdlet : PSCmdlet public class DisconnectOPNSenseCmdlet : PSCmdlet
{ {
/// <summary>
/// Begins the processing of the cmdlet
/// </summary>
protected override void BeginProcessing()
{
base.BeginProcessing();
}
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
@@ -38,12 +46,17 @@ namespace PSOPNSenseAPI.Cmdlets
} }
catch (Exception ex) catch (Exception ex)
{ {
WriteError(new ErrorRecord( // Use WriteWarning instead of WriteError to avoid threading issues
ex, WriteWarning($"Failed to disconnect: {ex.Message}");
"DisconnectionFailed", }
ErrorCategory.ConnectionError, }
null));
} /// <summary>
/// Ends the processing of the cmdlet
/// </summary>
protected override void EndProcessing()
{
base.EndProcessing();
} }
} }
} }
@@ -28,21 +28,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var firewallService = new FirewallService(ApiClient, Logger); var firewallService = new FirewallService(ApiClient, Logger);
var task = Task.Run(async () => await firewallService.ToggleRuleAsync(Uuid, true)); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => firewallService.ToggleRuleAsync(Uuid, true));
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteVerbose($"Firewall rule {Uuid} enabled: {result.Result}"); WriteVerbose($"Firewall rule {Uuid} enabled: {result.Result}");
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -28,22 +28,21 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var pluginService = new PluginService(ApiClient, Logger); var pluginService = new PluginService(ApiClient, Logger);
var task = Task.Run(async () => await pluginService.EnablePluginAsync(Name)); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => pluginService.EnablePluginAsync(Name));
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteVerbose($"Plugin {Name} enabled: {result.Status}"); WriteVerbose($"Plugin {Name} enabled: {result.Status}");
WriteObject($"Plugin {Name} enabled: {result.Status}"); WriteObject($"Plugin {Name} enabled: {result.Status}");
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -35,28 +35,31 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
string fullPath = Path.FullName; string fullPath = Path.FullName;
// Check if the file exists // Check if the file exists
if (File.Exists(fullPath) && !Force.IsPresent) if (File.Exists(fullPath) && !Force.IsPresent)
{ {
WriteError(new ErrorRecord( ProcessingException = new IOException($"The file '{fullPath}' already exists. Use -Force to overwrite.");
new IOException($"The file '{fullPath}' already exists. Use -Force to overwrite."), WriteWarning($"The file '{fullPath}' already exists. Use -Force to overwrite.");
"FileExists",
ErrorCategory.ResourceExists,
fullPath));
return; return;
} }
var configService = new ConfigService(ApiClient, Logger); var configService = new ConfigService(ApiClient, Logger);
// Execute the async method synchronously on the main thread // Use our safe execution method
var configContent = configService.ExportConfigAsync().GetAwaiter().GetResult(); var configContent = ExecuteAsyncTask(() => configService.ExportConfigAsync());
// Only continue if no exception occurred
if (ProcessingException != null || configContent == null)
{
return;
}
try
{
// Create the directory if it doesn't exist // Create the directory if it doesn't exist
var directory = System.IO.Path.GetDirectoryName(fullPath); var directory = System.IO.Path.GetDirectoryName(fullPath);
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
@@ -71,7 +74,8 @@ namespace PSOPNSenseAPI.Cmdlets
} }
catch (Exception ex) catch (Exception ex)
{ {
HandleException(ex); ProcessingException = ex;
WriteWarning($"Failed to write configuration to file: {ex.Message}");
} }
} }
} }
@@ -52,22 +52,33 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var aliasService = new AliasService(ApiClient, Logger); var aliasService = new AliasService(ApiClient, Logger);
if (ParameterSetName == "ByUuid") if (ParameterSetName == "ByUuid")
{ {
var task = Task.Run(async () => await aliasService.GetAliasAsync(Uuid)); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => aliasService.GetAliasAsync(Uuid));
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteObject(result.Alias); WriteObject(result.Alias);
} }
else else
{ {
var task = Task.Run(async () => await aliasService.GetAliasesAsync()); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => aliasService.GetAliasesAsync());
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
// Filter by name if specified // Filter by name if specified
if (ParameterSetName == "ByName") if (ParameterSetName == "ByName")
@@ -97,10 +108,5 @@ namespace PSOPNSenseAPI.Cmdlets
} }
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -21,21 +21,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var configService = new ConfigService(ApiClient, Logger); var configService = new ConfigService(ApiClient, Logger);
var task = Task.Run(async () => await configService.GetConfigBackupsAsync()); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => configService.GetConfigBackupsAsync());
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteObject(result.Backups, true); WriteObject(result.Backups, true);
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -28,17 +28,23 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var configService = new ConfigService(ApiClient, Logger); var configService = new ConfigService(ApiClient, Logger);
// Execute the async method synchronously on the main thread // Use our safe execution method
var configContent = configService.ExportConfigAsync().GetAwaiter().GetResult(); var configContent = ExecuteAsyncTask(() => configService.ExportConfigAsync());
// Only continue if no exception occurred
if (ProcessingException != null || configContent == null)
{
return;
}
// Convert the byte array to an XML document // Convert the byte array to an XML document
var xmlDoc = new XmlDocument(); var xmlDoc = new XmlDocument();
try
{
using (var memoryStream = new MemoryStream(configContent)) using (var memoryStream = new MemoryStream(configContent))
{ {
xmlDoc.Load(memoryStream); xmlDoc.Load(memoryStream);
@@ -49,7 +55,8 @@ namespace PSOPNSenseAPI.Cmdlets
} }
catch (Exception ex) catch (Exception ex)
{ {
HandleException(ex); ProcessingException = ex;
WriteWarning($"Failed to parse XML configuration: {ex.Message}");
} }
} }
} }
@@ -40,29 +40,36 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var dhcpService = new DHCPService(ApiClient, Logger); var dhcpService = new DHCPService(ApiClient, Logger);
if (ParameterSetName == "ByUuid") if (ParameterSetName == "ByUuid")
{ {
var task = Task.Run(async () => await dhcpService.GetOptionAsync(Interface, Uuid)); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => dhcpService.GetOptionAsync(Interface, Uuid));
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteObject(result.Option); WriteObject(result.Option);
} }
else else
{ {
var task = Task.Run(async () => await dhcpService.GetOptionsAsync(Interface)); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => dhcpService.GetOptionsAsync(Interface));
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteObject(result.Rows, true); WriteObject(result.Rows, true);
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -33,22 +33,33 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var dhcpService = new DHCPService(ApiClient, Logger); var dhcpService = new DHCPService(ApiClient, Logger);
if (ParameterSetName == "ByInterface") if (ParameterSetName == "ByInterface")
{ {
var task = Task.Run(async () => await dhcpService.GetServerAsync(Interface)); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => dhcpService.GetServerAsync(Interface));
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteObject(result.Server); WriteObject(result.Server);
} }
else else
{ {
var task = Task.Run(async () => await dhcpService.GetServersAsync()); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => dhcpService.GetServersAsync());
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
foreach (var kvp in result.Servers.Interfaces) foreach (var kvp in result.Servers.Interfaces)
{ {
@@ -67,10 +78,5 @@ namespace PSOPNSenseAPI.Cmdlets
} }
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -40,29 +40,36 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var dhcpService = new DHCPService(ApiClient, Logger); var dhcpService = new DHCPService(ApiClient, Logger);
if (ParameterSetName == "ByUuid") if (ParameterSetName == "ByUuid")
{ {
var task = Task.Run(async () => await dhcpService.GetStaticMappingAsync(Interface, Uuid)); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => dhcpService.GetStaticMappingAsync(Interface, Uuid));
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteObject(result.Mapping); WriteObject(result.Mapping);
} }
else else
{ {
var task = Task.Run(async () => await dhcpService.GetStaticMappingsAsync(Interface)); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => dhcpService.GetStaticMappingsAsync(Interface));
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteObject(result.Rows, true); WriteObject(result.Rows, true);
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -21,21 +21,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var dnsService = new DNSService(ApiClient, Logger); var dnsService = new DNSService(ApiClient, Logger);
var task = Task.Run(async () => await dnsService.GetDNSForwardingAsync()); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => dnsService.GetDNSForwardingAsync());
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteObject(result.Forward); WriteObject(result.Forward);
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -21,14 +21,18 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var dnsService = new DNSService(ApiClient, Logger); var dnsService = new DNSService(ApiClient, Logger);
var task = Task.Run(async () => await dnsService.GetDNSConfigAsync()); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => dnsService.GetDNSConfigAsync());
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
var dnsConfig = new PSObject(); var dnsConfig = new PSObject();
dnsConfig.Properties.Add(new PSNoteProperty("Enabled", result.Unbound.Enabled == "1")); dnsConfig.Properties.Add(new PSNoteProperty("Enabled", result.Unbound.Enabled == "1"));
@@ -43,10 +47,5 @@ namespace PSOPNSenseAPI.Cmdlets
WriteObject(dnsConfig); WriteObject(dnsConfig);
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -58,29 +58,36 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var firewallService = new FirewallService(ApiClient, Logger); var firewallService = new FirewallService(ApiClient, Logger);
if (ParameterSetName == "ByUuid") if (ParameterSetName == "ByUuid")
{ {
var task = Task.Run(async () => await firewallService.GetRuleAsync(Uuid)); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => firewallService.GetRuleAsync(Uuid));
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteObject(result.Rule); WriteObject(result.Rule);
} }
else else
{ {
var task = Task.Run(async () => await firewallService.GetRulesAsync(SearchPhrase, Page, RowCount)); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => firewallService.GetRulesAsync(SearchPhrase, Page, RowCount));
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteObject(result.Rows, true); WriteObject(result.Rows, true);
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -26,14 +26,18 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var interfaceService = new InterfaceService(ApiClient, Logger); var interfaceService = new InterfaceService(ApiClient, Logger);
var task = Task.Run(async () => await interfaceService.GetInterfaceStatisticsAsync()); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => interfaceService.GetInterfaceStatisticsAsync());
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
foreach (var kvp in result.Statistics) foreach (var kvp in result.Statistics)
{ {
@@ -50,10 +54,5 @@ namespace PSOPNSenseAPI.Cmdlets
WriteObject(stats); WriteObject(stats);
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -43,14 +43,18 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var pluginService = new PluginService(ApiClient, Logger); var pluginService = new PluginService(ApiClient, Logger);
var task = Task.Run(async () => await pluginService.GetPluginsAsync()); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => pluginService.GetPluginsAsync());
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
if (ParameterSetName == "Installed" || ParameterSetName == "") if (ParameterSetName == "Installed" || ParameterSetName == "")
{ {
@@ -94,10 +98,5 @@ namespace PSOPNSenseAPI.Cmdlets
} }
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -19,7 +19,7 @@ namespace PSOPNSenseAPI.Cmdlets
/// </summary> /// </summary>
[Cmdlet(VerbsCommon.Get, "OPNSensePortForwardingRule")] [Cmdlet(VerbsCommon.Get, "OPNSensePortForwardingRule")]
[OutputType(typeof(PortForwardingRule))] [OutputType(typeof(PortForwardingRule))]
public class GetOPNSensePortForwardingRuleCmdlet : OPNSenseCmdlet public class GetOPNSensePortForwardingRuleCmdlet : OPNSenseBaseCmdlet
{ {
/// <summary> /// <summary>
/// <para type="description">The UUID of the port forwarding rule to get. If not specified, all rules are returned.</para> /// <para type="description">The UUID of the port forwarding rule to get. If not specified, all rules are returned.</para>
@@ -30,14 +30,21 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{ {
var portForwardingService = new PortForwardingService(SessionState.ApiClient); var portForwardingService = new PortForwardingService(ApiClient);
if (!string.IsNullOrEmpty(Uuid)) if (!string.IsNullOrEmpty(Uuid))
{ {
// Get a specific rule // Use our safe execution method
var rule = Task.Run(async () => await portForwardingService.GetPortForwardingRuleAsync(Uuid)).GetAwaiter().GetResult(); var rule = ExecuteAsyncTask(() => portForwardingService.GetPortForwardingRuleAsync(Uuid));
// Only continue if no exception occurred
if (ProcessingException != null)
{
return;
}
if (rule != null) if (rule != null)
{ {
WriteObject(rule); WriteObject(rule);
@@ -49,8 +56,15 @@ namespace PSOPNSenseAPI.Cmdlets
} }
else else
{ {
// Get all rules // Use our safe execution method
var rules = Task.Run(async () => await portForwardingService.GetPortForwardingRulesAsync()).GetAwaiter().GetResult(); var rules = ExecuteAsyncTask(() => portForwardingService.GetPortForwardingRulesAsync());
// Only continue if no exception occurred
if (ProcessingException != null || rules == null)
{
return;
}
WriteObject(rules, true); WriteObject(rules, true);
} }
} }
@@ -21,21 +21,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var systemDNSService = new SystemDNSService(ApiClient, Logger); var systemDNSService = new SystemDNSService(ApiClient, Logger);
var task = Task.Run(async () => await systemDNSService.GetSystemDNSAsync()); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => systemDNSService.GetSystemDNSAsync());
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteObject(result.System); WriteObject(result.System);
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -33,29 +33,36 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var interfaceService = new InterfaceService(ApiClient, Logger); var interfaceService = new InterfaceService(ApiClient, Logger);
if (ParameterSetName == "ByUuid") if (ParameterSetName == "ByUuid")
{ {
var task = Task.Run(async () => await interfaceService.GetVLANAsync(Uuid)); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => interfaceService.GetVLANAsync(Uuid));
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteObject(result.Vlan); WriteObject(result.Vlan);
} }
else else
{ {
var task = Task.Run(async () => await interfaceService.GetVLANsAsync()); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => interfaceService.GetVLANsAsync());
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteObject(result.Rows, true); WriteObject(result.Rows, true);
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -35,20 +35,15 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
string fullPath = Path.FullName; string fullPath = Path.FullName;
// Check if the file exists // Check if the file exists
if (!File.Exists(fullPath)) if (!File.Exists(fullPath))
{ {
WriteError(new ErrorRecord( ProcessingException = new FileNotFoundException($"The file '{fullPath}' does not exist.");
new FileNotFoundException($"The file '{fullPath}' does not exist."), WriteWarning($"The file '{fullPath}' does not exist.");
"FileNotFound",
ErrorCategory.ObjectNotFound,
fullPath));
return; return;
} }
@@ -59,18 +54,27 @@ namespace PSOPNSenseAPI.Cmdlets
var configService = new ConfigService(ApiClient, Logger); var configService = new ConfigService(ApiClient, Logger);
try
{
// Read the configuration file // Read the configuration file
var configContent = File.ReadAllBytes(fullPath); var configContent = File.ReadAllBytes(fullPath);
// Execute the async method synchronously on the main thread // Use our safe execution method
var result = configService.ImportConfigAsync(configContent).GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => configService.ImportConfigAsync(configContent));
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteVerbose($"Imported configuration from {fullPath}: {result.Status}"); WriteVerbose($"Imported configuration from {fullPath}: {result.Status}");
WriteWarning("The firewall is restarting. You may need to reconnect after it comes back online."); WriteWarning("The firewall is restarting. You may need to reconnect after it comes back online.");
} }
catch (Exception ex) catch (Exception ex)
{ {
HandleException(ex); ProcessingException = ex;
WriteWarning($"Failed to read or process configuration file: {ex.Message}");
} }
} }
} }
@@ -185,11 +185,7 @@ namespace PSOPNSenseAPI.Cmdlets
{ {
if (prefixLength <= network.Cidr) if (prefixLength <= network.Cidr)
{ {
WriteError(new ErrorRecord( ProcessingException = new ArgumentException($"Prefix length ({prefixLength}) must be greater than the network CIDR ({network.Cidr}).");
new ArgumentException($"Prefix length ({prefixLength}) must be greater than the network CIDR ({network.Cidr})."),
"InvalidPrefixLength",
ErrorCategory.InvalidArgument,
null));
return; return;
} }
@@ -206,11 +202,7 @@ namespace PSOPNSenseAPI.Cmdlets
} }
catch (ArgumentException ex) catch (ArgumentException ex)
{ {
WriteError(new ErrorRecord( ProcessingException = ex;
ex,
"InvalidSubnetCount",
ErrorCategory.InvalidArgument,
null));
} }
} }
@@ -236,11 +228,7 @@ namespace PSOPNSenseAPI.Cmdlets
} }
catch (Exception ex) catch (Exception ex)
{ {
WriteError(new ErrorRecord( ProcessingException = ex;
ex,
"InvalidIPAddress",
ErrorCategory.InvalidArgument,
null));
} }
} }
@@ -267,11 +255,7 @@ namespace PSOPNSenseAPI.Cmdlets
} }
catch (Exception ex) catch (Exception ex)
{ {
WriteError(new ErrorRecord( ProcessingException = ex;
ex,
"InvalidAdditionalNetwork",
ErrorCategory.InvalidArgument,
null));
} }
} }
@@ -292,11 +276,7 @@ namespace PSOPNSenseAPI.Cmdlets
} }
catch (Exception ex) catch (Exception ex)
{ {
WriteError(new ErrorRecord( ProcessingException = ex;
ex,
"SupernetError",
ErrorCategory.InvalidOperation,
null));
} }
} }
@@ -317,11 +297,7 @@ namespace PSOPNSenseAPI.Cmdlets
} }
catch (Exception ex) catch (Exception ex)
{ {
WriteError(new ErrorRecord( ProcessingException = ex;
ex,
"SupernetSummarizeError",
ErrorCategory.InvalidOperation,
null));
} }
} }
} }
@@ -83,9 +83,7 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var firewallService = new FirewallService(ApiClient, Logger); var firewallService = new FirewallService(ApiClient, Logger);
@@ -102,16 +100,17 @@ namespace PSOPNSenseAPI.Cmdlets
Enabled = Enabled.IsPresent ? "1" : "0" Enabled = Enabled.IsPresent ? "1" : "0"
}; };
var task = Task.Run(async () => await firewallService.CreateRuleAsync(rule)); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => firewallService.CreateRuleAsync(rule));
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteVerbose($"Created firewall rule with UUID {result.Uuid}"); WriteVerbose($"Created firewall rule with UUID {result.Uuid}");
WriteObject(result.Uuid); WriteObject(result.Uuid);
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -15,7 +15,7 @@ namespace PSOPNSenseAPI.Cmdlets
/// </summary> /// </summary>
[Cmdlet(VerbsCommon.New, "OPNSensePortForwardingRule", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.Medium)] [Cmdlet(VerbsCommon.New, "OPNSensePortForwardingRule", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.Medium)]
[OutputType(typeof(PortForwardingRule))] [OutputType(typeof(PortForwardingRule))]
public class NewOPNSensePortForwardingRuleCmdlet : OPNSenseCmdlet public class NewOPNSensePortForwardingRuleCmdlet : OPNSenseBaseCmdlet
{ {
/// <summary> /// <summary>
/// <para type="description">Whether the rule is enabled.</para> /// <para type="description">Whether the rule is enabled.</para>
@@ -106,7 +106,7 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{ {
var rule = new PortForwardingRule var rule = new PortForwardingRule
{ {
@@ -127,8 +127,16 @@ namespace PSOPNSenseAPI.Cmdlets
if (Force || ShouldProcess($"OPNSense firewall", $"Create port forwarding rule from {Destination}:{DestinationPort} to {TargetIP}:{TargetPort}")) if (Force || ShouldProcess($"OPNSense firewall", $"Create port forwarding rule from {Destination}:{DestinationPort} to {TargetIP}:{TargetPort}"))
{ {
var portForwardingService = new PortForwardingService(SessionState.ApiClient); var portForwardingService = new PortForwardingService(ApiClient);
var uuid = Task.Run(async () => await portForwardingService.CreatePortForwardingRuleAsync(rule)).GetAwaiter().GetResult();
// Use our safe execution method
var uuid = ExecuteAsyncTask(() => portForwardingService.CreatePortForwardingRuleAsync(rule));
// Only continue if no exception occurred
if (ProcessingException != null)
{
return;
}
if (!string.IsNullOrEmpty(uuid)) if (!string.IsNullOrEmpty(uuid))
{ {
@@ -138,11 +146,8 @@ namespace PSOPNSenseAPI.Cmdlets
} }
else else
{ {
WriteError(new ErrorRecord( ProcessingException = new PSInvalidOperationException("Failed to create port forwarding rule.");
new PSInvalidOperationException("Failed to create port forwarding rule."), WriteWarning("Failed to create port forwarding rule.");
"PortForwardingRuleCreationFailed",
ErrorCategory.InvalidOperation,
null));
} }
} }
} }
@@ -99,9 +99,7 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
// Parse the network CIDR // Parse the network CIDR
var ipNetwork = IPNetwork2.Parse(Network); var ipNetwork = IPNetwork2.Parse(Network);
@@ -109,11 +107,8 @@ namespace PSOPNSenseAPI.Cmdlets
// Validate subnet mask bits // Validate subnet mask bits
if (SubnetMaskBits <= ipNetwork.Cidr) if (SubnetMaskBits <= ipNetwork.Cidr)
{ {
WriteError(new ErrorRecord( ProcessingException = new ArgumentException($"Subnet mask bits ({SubnetMaskBits}) must be greater than the network CIDR ({ipNetwork.Cidr}).");
new ArgumentException($"Subnet mask bits ({SubnetMaskBits}) must be greater than the network CIDR ({ipNetwork.Cidr})."), WriteWarning($"Subnet mask bits ({SubnetMaskBits}) must be greater than the network CIDR ({ipNetwork.Cidr}).");
"InvalidSubnetMaskBits",
ErrorCategory.InvalidArgument,
SubnetMaskBits));
return; return;
} }
@@ -126,11 +121,8 @@ namespace PSOPNSenseAPI.Cmdlets
// Validate the maximum VLAN ID // Validate the maximum VLAN ID
if (maxVlanId > 4094) if (maxVlanId > 4094)
{ {
WriteError(new ErrorRecord( ProcessingException = new ArgumentException($"The maximum VLAN ID ({maxVlanId}) exceeds the maximum allowed value (4094).");
new ArgumentException($"The maximum VLAN ID ({maxVlanId}) exceeds the maximum allowed value (4094)."), WriteWarning($"The maximum VLAN ID ({maxVlanId}) exceeds the maximum allowed value (4094).");
"InvalidVlanIdRange",
ErrorCategory.InvalidArgument,
maxVlanId));
return; return;
} }
@@ -144,12 +136,24 @@ namespace PSOPNSenseAPI.Cmdlets
var interfaceService = new InterfaceService(ApiClient, Logger); var interfaceService = new InterfaceService(ApiClient, Logger);
// Verify the parent interface exists // Verify the parent interface exists
var getInterfaceTask = Task.Run(async () => await interfaceService.GetInterfaceDetailAsync(ParentInterface)); var interfaceDetail = ExecuteAsyncTask(() => interfaceService.GetInterfaceDetailAsync(ParentInterface));
getInterfaceTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null)
{
return;
}
// Get existing VLANs // Get existing VLANs
var getVlansTask = Task.Run(async () => await interfaceService.GetVLANsAsync()); var vlansResult = ExecuteAsyncTask(() => interfaceService.GetVLANsAsync());
var existingVlans = getVlansTask.GetAwaiter().GetResult().Rows;
// Only continue if no exception occurred
if (ProcessingException != null || vlansResult == null)
{
return;
}
var existingVlans = vlansResult.Rows;
// Create a list to store the created VLANs // Create a list to store the created VLANs
var createdVlans = new List<PSObject>(); var createdVlans = new List<PSObject>();
@@ -208,8 +212,13 @@ namespace PSOPNSenseAPI.Cmdlets
Description = description Description = description
}; };
var createVlanTask = Task.Run(async () => await interfaceService.CreateVLANAsync(vlanConfig)); var createVlanResult = ExecuteAsyncTask(() => interfaceService.CreateVLANAsync(vlanConfig));
var createVlanResult = createVlanTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || createVlanResult == null)
{
return;
}
WriteVerbose($"Created VLAN {vlanId} on interface {ParentInterface} with UUID {createVlanResult.Uuid}"); WriteVerbose($"Created VLAN {vlanId} on interface {ParentInterface} with UUID {createVlanResult.Uuid}");
@@ -224,8 +233,13 @@ namespace PSOPNSenseAPI.Cmdlets
Enabled = "1" Enabled = "1"
}; };
var updateInterfaceTask = Task.Run(async () => await interfaceService.UpdateInterfaceAsync(vlanInterfaceName, interfaceConfig)); var updateInterfaceResult = ExecuteAsyncTask(() => interfaceService.UpdateInterfaceAsync(vlanInterfaceName, interfaceConfig));
updateInterfaceTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null)
{
return;
}
WriteVerbose($"Configured interface {vlanInterfaceName} with IP {gatewayIp}/{SubnetMaskBits}"); WriteVerbose($"Configured interface {vlanInterfaceName} with IP {gatewayIp}/{SubnetMaskBits}");
@@ -245,8 +259,13 @@ namespace PSOPNSenseAPI.Cmdlets
DnsServers = DnsServers != null ? new List<string>(DnsServers) : new List<string> { gatewayIp.ToString() } DnsServers = DnsServers != null ? new List<string>(DnsServers) : new List<string> { gatewayIp.ToString() }
}; };
var updateDhcpTask = Task.Run(async () => await dhcpService.UpdateServerAsync(vlanInterfaceName, dhcpConfig)); var updateDhcpResult = ExecuteAsyncTask(() => dhcpService.UpdateServerAsync(vlanInterfaceName, dhcpConfig));
updateDhcpTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null)
{
return;
}
WriteVerbose($"Configured DHCP server for interface {vlanInterfaceName} with range {dhcpStart} - {dhcpEnd}"); WriteVerbose($"Configured DHCP server for interface {vlanInterfaceName} with range {dhcpStart} - {dhcpEnd}");
} }
@@ -274,8 +293,14 @@ namespace PSOPNSenseAPI.Cmdlets
// Apply DHCP changes if needed // Apply DHCP changes if needed
if (EnableDHCP.IsPresent && dhcpService != null) if (EnableDHCP.IsPresent && dhcpService != null)
{ {
var applyDhcpTask = Task.Run(async () => await dhcpService.ApplyChangesAsync()); var applyDhcpResult = ExecuteAsyncTask(() => dhcpService.ApplyChangesAsync());
var applyDhcpResult = applyDhcpTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyDhcpResult == null)
{
return;
}
WriteVerbose($"Applied DHCP changes: {applyDhcpResult.Status}"); WriteVerbose($"Applied DHCP changes: {applyDhcpResult.Status}");
} }
@@ -288,11 +313,6 @@ namespace PSOPNSenseAPI.Cmdlets
WriteObject(result); WriteObject(result);
} }
catch (Exception ex)
{
HandleException(ex);
}
}
/// <summary> /// <summary>
/// Gets the first host address in a subnet /// Gets the first host address in a subnet
@@ -48,9 +48,7 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var interfaceService = new InterfaceService(ApiClient, Logger); var interfaceService = new InterfaceService(ApiClient, Logger);
@@ -62,16 +60,17 @@ namespace PSOPNSenseAPI.Cmdlets
Description = Description Description = Description
}; };
var task = Task.Run(async () => await interfaceService.CreateVLANAsync(vlan)); // Use our safe execution method
var result = task.GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => interfaceService.CreateVLANAsync(vlan));
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteVerbose($"Created VLAN with UUID {result.Uuid}"); WriteVerbose($"Created VLAN with UUID {result.Uuid}");
WriteObject(result.Uuid); WriteObject(result.Uuid);
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -50,15 +50,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var aliasService = new AliasService(ApiClient, Logger); var aliasService = new AliasService(ApiClient, Logger);
// Get the alias details for the confirmation message // Get the alias details for the confirmation message
var getTask = Task.Run(async () => await aliasService.GetAliasAsync(Uuid)); var getResult = ExecuteAsyncTask(() => aliasService.GetAliasAsync(Uuid));
var alias = getTask.GetAwaiter().GetResult().Alias;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var alias = getResult.Alias;
string confirmMessage = $"Alias: {alias.Name} ({alias.Type})"; string confirmMessage = $"Alias: {alias.Name} ({alias.Type})";
if (!string.IsNullOrEmpty(alias.Description)) if (!string.IsNullOrEmpty(alias.Description))
@@ -71,24 +76,29 @@ namespace PSOPNSenseAPI.Cmdlets
return; return;
} }
var deleteTask = Task.Run(async () => await aliasService.DeleteAliasAsync(Uuid)); var deleteResult = ExecuteAsyncTask(() => aliasService.DeleteAliasAsync(Uuid));
var deleteResult = deleteTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || deleteResult == null)
{
return;
}
WriteVerbose($"Alias {Uuid} removed: {deleteResult.Result}"); WriteVerbose($"Alias {Uuid} removed: {deleteResult.Result}");
// Apply changes if requested // Apply changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var applyTask = Task.Run(async () => await aliasService.ReconfigureAliasesAsync()); var applyResult = ExecuteAsyncTask(() => aliasService.ReconfigureAliasesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"Alias changes applied: {applyResult.Status}"); WriteVerbose($"Alias changes applied: {applyResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -45,15 +45,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var dhcpService = new DHCPService(ApiClient, Logger); var dhcpService = new DHCPService(ApiClient, Logger);
// Get the lease details for the confirmation message // Get the lease details for the confirmation message
var getTask = Task.Run(async () => await dhcpService.GetLeaseByMacAsync(MacAddress)); var getResult = ExecuteAsyncTask(() => dhcpService.GetLeaseByMacAsync(MacAddress));
var lease = getTask.GetAwaiter().GetResult().Lease;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var lease = getResult.Lease;
string confirmMessage = $"DHCP lease: {lease.MacAddress} -> {lease.IpAddress}"; string confirmMessage = $"DHCP lease: {lease.MacAddress} -> {lease.IpAddress}";
if (!string.IsNullOrEmpty(lease.Hostname)) if (!string.IsNullOrEmpty(lease.Hostname))
@@ -66,24 +71,29 @@ namespace PSOPNSenseAPI.Cmdlets
return; return;
} }
var deleteTask = Task.Run(async () => await dhcpService.DeleteLeaseAsync(MacAddress)); var deleteResult = ExecuteAsyncTask(() => dhcpService.DeleteLeaseAsync(MacAddress));
var deleteResult = deleteTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || deleteResult == null)
{
return;
}
WriteVerbose($"DHCP lease {MacAddress} removed: {deleteResult.Result}"); WriteVerbose($"DHCP lease {MacAddress} removed: {deleteResult.Result}");
// Apply changes if requested // Apply changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var applyTask = Task.Run(async () => await dhcpService.ApplyChangesAsync()); var applyResult = ExecuteAsyncTask(() => dhcpService.ApplyChangesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"DHCP changes applied: {applyResult.Status}"); WriteVerbose($"DHCP changes applied: {applyResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -52,15 +52,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var dhcpService = new DHCPService(ApiClient, Logger); var dhcpService = new DHCPService(ApiClient, Logger);
// Get the option details for the confirmation message // Get the option details for the confirmation message
var getTask = Task.Run(async () => await dhcpService.GetOptionAsync(Interface, Uuid)); var getResult = ExecuteAsyncTask(() => dhcpService.GetOptionAsync(Interface, Uuid));
var option = getTask.GetAwaiter().GetResult().Option;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var option = getResult.Option;
string confirmMessage = $"DHCP option: {option.Number} = {option.Value}"; string confirmMessage = $"DHCP option: {option.Number} = {option.Value}";
if (!string.IsNullOrEmpty(option.Description)) if (!string.IsNullOrEmpty(option.Description))
@@ -73,24 +78,29 @@ namespace PSOPNSenseAPI.Cmdlets
return; return;
} }
var deleteTask = Task.Run(async () => await dhcpService.DeleteOptionAsync(Interface, Uuid)); var deleteResult = ExecuteAsyncTask(() => dhcpService.DeleteOptionAsync(Interface, Uuid));
var deleteResult = deleteTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || deleteResult == null)
{
return;
}
WriteVerbose($"DHCP option {Uuid} removed: {deleteResult.Result}"); WriteVerbose($"DHCP option {Uuid} removed: {deleteResult.Result}");
// Apply changes if requested // Apply changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var applyTask = Task.Run(async () => await dhcpService.ApplyChangesAsync()); var applyResult = ExecuteAsyncTask(() => dhcpService.ApplyChangesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"DHCP changes applied: {applyResult.Status}"); WriteVerbose($"DHCP changes applied: {applyResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -52,15 +52,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var dhcpService = new DHCPService(ApiClient, Logger); var dhcpService = new DHCPService(ApiClient, Logger);
// Get the mapping details for the confirmation message // Get the mapping details for the confirmation message
var getTask = Task.Run(async () => await dhcpService.GetStaticMappingAsync(Interface, Uuid)); var getResult = ExecuteAsyncTask(() => dhcpService.GetStaticMappingAsync(Interface, Uuid));
var mapping = getTask.GetAwaiter().GetResult().Mapping;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var mapping = getResult.Mapping;
string confirmMessage = $"Static mapping: {mapping.MacAddress} -> {mapping.IpAddress}"; string confirmMessage = $"Static mapping: {mapping.MacAddress} -> {mapping.IpAddress}";
if (!string.IsNullOrEmpty(mapping.Hostname)) if (!string.IsNullOrEmpty(mapping.Hostname))
@@ -73,24 +78,29 @@ namespace PSOPNSenseAPI.Cmdlets
return; return;
} }
var deleteTask = Task.Run(async () => await dhcpService.DeleteStaticMappingAsync(Interface, Uuid)); var deleteResult = ExecuteAsyncTask(() => dhcpService.DeleteStaticMappingAsync(Interface, Uuid));
var deleteResult = deleteTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || deleteResult == null)
{
return;
}
WriteVerbose($"Static mapping {Uuid} removed: {deleteResult.Result}"); WriteVerbose($"Static mapping {Uuid} removed: {deleteResult.Result}");
// Apply the changes if requested // Apply the changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var applyTask = Task.Run(async () => await dhcpService.ApplyChangesAsync()); var applyResult = ExecuteAsyncTask(() => dhcpService.ApplyChangesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"DHCP changes applied: {applyResult.Status}"); WriteVerbose($"DHCP changes applied: {applyResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -45,15 +45,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var dnsService = new DNSService(ApiClient, Logger); var dnsService = new DNSService(ApiClient, Logger);
// Get the host details for the confirmation message // Get the host details for the confirmation message
var getTask = Task.Run(async () => await dnsService.GetDNSForwardingHostAsync(Uuid)); var getResult = ExecuteAsyncTask(() => dnsService.GetDNSForwardingHostAsync(Uuid));
var host = getTask.GetAwaiter().GetResult().Host;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var host = getResult.Host;
string confirmMessage = $"DNS forwarding host: {host.Domain} -> {host.Server}"; string confirmMessage = $"DNS forwarding host: {host.Domain} -> {host.Server}";
if (!string.IsNullOrEmpty(host.Description)) if (!string.IsNullOrEmpty(host.Description))
@@ -66,24 +71,29 @@ namespace PSOPNSenseAPI.Cmdlets
return; return;
} }
var deleteTask = Task.Run(async () => await dnsService.DeleteDNSForwardingHostAsync(Uuid)); var deleteResult = ExecuteAsyncTask(() => dnsService.DeleteDNSForwardingHostAsync(Uuid));
var deleteResult = deleteTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || deleteResult == null)
{
return;
}
WriteVerbose($"DNS forwarding host {Uuid} removed: {deleteResult.Result}"); WriteVerbose($"DNS forwarding host {Uuid} removed: {deleteResult.Result}");
// Apply changes if requested // Apply changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var applyTask = Task.Run(async () => await dnsService.ApplyDNSChangesAsync()); var applyResult = ExecuteAsyncTask(() => dnsService.ApplyDNSChangesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"DNS changes applied: {applyResult.Status}"); WriteVerbose($"DNS changes applied: {applyResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -45,15 +45,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var dnsService = new DNSService(ApiClient, Logger); var dnsService = new DNSService(ApiClient, Logger);
// Get the DNS override details for the confirmation message // Get the DNS override details for the confirmation message
var getTask = Task.Run(async () => await dnsService.GetDNSOverrideAsync(Uuid)); var getResult = ExecuteAsyncTask(() => dnsService.GetDNSOverrideAsync(Uuid));
var dnsOverride = getTask.GetAwaiter().GetResult().Host;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var dnsOverride = getResult.Host;
string confirmMessage = $"DNS override {dnsOverride.Hostname}.{dnsOverride.Domain} -> {dnsOverride.IpAddress}"; string confirmMessage = $"DNS override {dnsOverride.Hostname}.{dnsOverride.Domain} -> {dnsOverride.IpAddress}";
if (!string.IsNullOrEmpty(dnsOverride.Description)) if (!string.IsNullOrEmpty(dnsOverride.Description))
@@ -66,24 +71,29 @@ namespace PSOPNSenseAPI.Cmdlets
return; return;
} }
var deleteTask = Task.Run(async () => await dnsService.DeleteDNSOverrideAsync(Uuid)); var deleteResult = ExecuteAsyncTask(() => dnsService.DeleteDNSOverrideAsync(Uuid));
var deleteResult = deleteTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || deleteResult == null)
{
return;
}
WriteVerbose($"DNS override {Uuid} removed: {deleteResult.Result}"); WriteVerbose($"DNS override {Uuid} removed: {deleteResult.Result}");
// Apply the changes if requested // Apply the changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var applyTask = Task.Run(async () => await dnsService.ApplyDNSChangesAsync()); var applyResult = ExecuteAsyncTask(() => dnsService.ApplyDNSChangesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"DNS changes applied: {applyResult.Status}"); WriteVerbose($"DNS changes applied: {applyResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -39,15 +39,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var firewallService = new FirewallService(ApiClient, Logger); var firewallService = new FirewallService(ApiClient, Logger);
// Get the rule details for the confirmation message // Get the rule details for the confirmation message
var getTask = Task.Run(async () => await firewallService.GetRuleAsync(Uuid)); var getResult = ExecuteAsyncTask(() => firewallService.GetRuleAsync(Uuid));
var rule = getTask.GetAwaiter().GetResult().Rule;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var rule = getResult.Rule;
string confirmMessage = $"Firewall rule: {rule.Description}"; string confirmMessage = $"Firewall rule: {rule.Description}";
if (!string.IsNullOrEmpty(rule.Protocol) && rule.Protocol != "any") if (!string.IsNullOrEmpty(rule.Protocol) && rule.Protocol != "any")
@@ -60,15 +65,15 @@ namespace PSOPNSenseAPI.Cmdlets
return; return;
} }
var deleteTask = Task.Run(async () => await firewallService.DeleteRuleAsync(Uuid)); var deleteResult = ExecuteAsyncTask(() => firewallService.DeleteRuleAsync(Uuid));
var deleteResult = deleteTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || deleteResult == null)
{
return;
}
WriteVerbose($"Firewall rule {Uuid} removed: {deleteResult.Result}"); WriteVerbose($"Firewall rule {Uuid} removed: {deleteResult.Result}");
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -45,15 +45,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var gatewayService = new GatewayService(ApiClient, Logger); var gatewayService = new GatewayService(ApiClient, Logger);
// Get the gateway details for the confirmation message // Get the gateway details for the confirmation message
var getTask = Task.Run(async () => await gatewayService.GetGatewayAsync(Uuid)); var getResult = ExecuteAsyncTask(() => gatewayService.GetGatewayAsync(Uuid));
var gateway = getTask.GetAwaiter().GetResult().Gateway;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var gateway = getResult.Gateway;
string confirmMessage = $"Gateway: {gateway.Name} ({gateway.IpAddress})"; string confirmMessage = $"Gateway: {gateway.Name} ({gateway.IpAddress})";
if (!string.IsNullOrEmpty(gateway.Description)) if (!string.IsNullOrEmpty(gateway.Description))
@@ -66,24 +71,29 @@ namespace PSOPNSenseAPI.Cmdlets
return; return;
} }
var deleteTask = Task.Run(async () => await gatewayService.DeleteGatewayAsync(Uuid)); var deleteResult = ExecuteAsyncTask(() => gatewayService.DeleteGatewayAsync(Uuid));
var deleteResult = deleteTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || deleteResult == null)
{
return;
}
WriteVerbose($"Gateway {Uuid} removed: {deleteResult.Result}"); WriteVerbose($"Gateway {Uuid} removed: {deleteResult.Result}");
// Apply changes if requested // Apply changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var applyTask = Task.Run(async () => await gatewayService.ApplyGatewayChangesAsync()); var applyResult = ExecuteAsyncTask(() => gatewayService.ApplyGatewayChangesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"Gateway changes applied: {applyResult.Status}"); WriteVerbose($"Gateway changes applied: {applyResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -13,7 +13,7 @@ namespace PSOPNSenseAPI.Cmdlets
/// </example> /// </example>
/// </summary> /// </summary>
[Cmdlet(VerbsCommon.Remove, "OPNSensePortForwardingRule", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.High)] [Cmdlet(VerbsCommon.Remove, "OPNSensePortForwardingRule", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.High)]
public class RemoveOPNSensePortForwardingRuleCmdlet : OPNSenseCmdlet public class RemoveOPNSensePortForwardingRuleCmdlet : OPNSenseBaseCmdlet
{ {
/// <summary> /// <summary>
/// <para type="description">The UUID of the port forwarding rule to remove.</para> /// <para type="description">The UUID of the port forwarding rule to remove.</para>
@@ -30,12 +30,18 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{ {
var portForwardingService = new PortForwardingService(SessionState.ApiClient); var portForwardingService = new PortForwardingService(ApiClient);
// Get the rule to display information in the confirmation message // Get the rule to display information in the confirmation message
var rule = Task.Run(async () => await portForwardingService.GetPortForwardingRuleAsync(Uuid)).GetAwaiter().GetResult(); var rule = ExecuteAsyncTask(() => portForwardingService.GetPortForwardingRuleAsync(Uuid));
// Only continue if no exception occurred
if (ProcessingException != null)
{
return;
}
if (rule == null) if (rule == null)
{ {
@@ -52,7 +58,13 @@ namespace PSOPNSenseAPI.Cmdlets
if (Force || ShouldProcess($"OPNSense firewall", confirmationMessage)) if (Force || ShouldProcess($"OPNSense firewall", confirmationMessage))
{ {
var success = Task.Run(async () => await portForwardingService.DeletePortForwardingRuleAsync(Uuid)).GetAwaiter().GetResult(); var success = ExecuteAsyncTask(() => portForwardingService.DeletePortForwardingRuleAsync(Uuid));
// Only continue if no exception occurred
if (ProcessingException != null)
{
return;
}
if (success) if (success)
{ {
@@ -60,11 +72,8 @@ namespace PSOPNSenseAPI.Cmdlets
} }
else else
{ {
WriteError(new ErrorRecord( ProcessingException = new PSInvalidOperationException($"Failed to remove port forwarding rule with UUID '{Uuid}'.");
new PSInvalidOperationException($"Failed to remove port forwarding rule with UUID '{Uuid}'."), WriteWarning($"Failed to remove port forwarding rule with UUID '{Uuid}'.");
"PortForwardingRuleRemovalFailed",
ErrorCategory.InvalidOperation,
Uuid));
} }
} }
} }
@@ -45,15 +45,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var routeService = new RouteService(ApiClient, Logger); var routeService = new RouteService(ApiClient, Logger);
// Get the route details for the confirmation message // Get the route details for the confirmation message
var getTask = Task.Run(async () => await routeService.GetRouteAsync(Uuid)); var getResult = ExecuteAsyncTask(() => routeService.GetRouteAsync(Uuid));
var route = getTask.GetAwaiter().GetResult().Route;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var route = getResult.Route;
string confirmMessage = $"Route: {route.Network} via {route.Gateway}"; string confirmMessage = $"Route: {route.Network} via {route.Gateway}";
if (!string.IsNullOrEmpty(route.Description)) if (!string.IsNullOrEmpty(route.Description))
@@ -66,24 +71,29 @@ namespace PSOPNSenseAPI.Cmdlets
return; return;
} }
var deleteTask = Task.Run(async () => await routeService.DeleteRouteAsync(Uuid)); var deleteResult = ExecuteAsyncTask(() => routeService.DeleteRouteAsync(Uuid));
var deleteResult = deleteTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || deleteResult == null)
{
return;
}
WriteVerbose($"Route {Uuid} removed: {deleteResult.Result}"); WriteVerbose($"Route {Uuid} removed: {deleteResult.Result}");
// Apply changes if requested // Apply changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var applyTask = Task.Run(async () => await routeService.ApplyRouteChangesAsync()); var applyResult = ExecuteAsyncTask(() => routeService.ApplyRouteChangesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"Route changes applied: {applyResult.Status}"); WriteVerbose($"Route changes applied: {applyResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -39,15 +39,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var userService = new UserService(ApiClient, Logger); var userService = new UserService(ApiClient, Logger);
// Get the user details for the confirmation message // Get the user details for the confirmation message
var getTask = Task.Run(async () => await userService.GetUserAsync(Uuid)); var getResult = ExecuteAsyncTask(() => userService.GetUserAsync(Uuid));
var user = getTask.GetAwaiter().GetResult().User;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var user = getResult.User;
string confirmMessage = $"User: {user.Username}"; string confirmMessage = $"User: {user.Username}";
if (!string.IsNullOrEmpty(user.FullName)) if (!string.IsNullOrEmpty(user.FullName))
@@ -60,15 +65,15 @@ namespace PSOPNSenseAPI.Cmdlets
return; return;
} }
var deleteTask = Task.Run(async () => await userService.DeleteUserAsync(Uuid)); var deleteResult = ExecuteAsyncTask(() => userService.DeleteUserAsync(Uuid));
var deleteResult = deleteTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || deleteResult == null)
{
return;
}
WriteVerbose($"User {Uuid} removed: {deleteResult.Result}"); WriteVerbose($"User {Uuid} removed: {deleteResult.Result}");
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -39,15 +39,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var interfaceService = new InterfaceService(ApiClient, Logger); var interfaceService = new InterfaceService(ApiClient, Logger);
// Get the VLAN details for the confirmation message // Get the VLAN details for the confirmation message
var getTask = Task.Run(async () => await interfaceService.GetVLANAsync(Uuid)); var getResult = ExecuteAsyncTask(() => interfaceService.GetVLANAsync(Uuid));
var vlan = getTask.GetAwaiter().GetResult().Vlan;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var vlan = getResult.Vlan;
string confirmMessage = $"VLAN {vlan.Tag} on interface {vlan.Interface}"; string confirmMessage = $"VLAN {vlan.Tag} on interface {vlan.Interface}";
if (!string.IsNullOrEmpty(vlan.Description)) if (!string.IsNullOrEmpty(vlan.Description))
@@ -60,15 +65,15 @@ namespace PSOPNSenseAPI.Cmdlets
return; return;
} }
var deleteTask = Task.Run(async () => await interfaceService.DeleteVLANAsync(Uuid)); var deleteResult = ExecuteAsyncTask(() => interfaceService.DeleteVLANAsync(Uuid));
var deleteResult = deleteTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || deleteResult == null)
{
return;
}
WriteVerbose($"VLAN {Uuid} removed: {deleteResult.Result}"); WriteVerbose($"VLAN {Uuid} removed: {deleteResult.Result}");
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -130,14 +130,23 @@ namespace PSOPNSenseAPI.Cmdlets
// Try to get the system status // Try to get the system status
var statusService = new SystemService(newClient, logger); var statusService = new SystemService(newClient, logger);
// We need to use Task.Run here because we're creating a new client // We need to handle this specially because we're using a new client
// and can't use ExecuteAsyncTask which uses the existing client // and can't use ExecuteAsyncTask which uses the existing client
var statusTask = Task.Run(async () => await statusService.GetStatusAsync()); try
var statusResult = statusTask.GetAwaiter().GetResult(); {
// Use ConfigureAwait(false) to avoid deadlocks
var statusResult = statusService.GetStatusAsync().ConfigureAwait(false).GetAwaiter().GetResult();
// If we get here, the firewall is back online // If we get here, the firewall is back online
WriteVerbose("Successfully reconnected to the firewall"); WriteVerbose("Successfully reconnected to the firewall");
WriteObject($"Firewall is back online. Uptime: {statusResult.Uptime}"); WriteObject($"Firewall is back online. Uptime: {statusResult.Uptime}");
}
catch (Exception innerEx)
{
// Just log and continue the retry loop
WriteVerbose($"Status check failed: {innerEx.Message}");
throw; // Re-throw to be caught by the outer catch
}
// Set the new session // Set the new session
OPNSenseSession.Current = newClient; OPNSenseSession.Current = newClient;
@@ -53,9 +53,7 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var configService = new ConfigService(ApiClient, Logger); var configService = new ConfigService(ApiClient, Logger);
string actionDescription = "Restore configuration"; string actionDescription = "Restore configuration";
@@ -68,11 +66,20 @@ namespace PSOPNSenseAPI.Cmdlets
if (ParameterSetName == "Filename") if (ParameterSetName == "Filename")
{ {
// Restore from backup file - execute synchronously on the main thread // Use our safe execution method
var result = configService.RestoreConfigBackupAsync(Filename).GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => configService.RestoreConfigBackupAsync(Filename));
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteVerbose($"Restored configuration from backup: {result.Status}"); WriteVerbose($"Restored configuration from backup: {result.Status}");
} }
else else
{
try
{ {
// Restore from XML document // Restore from XML document
byte[] configContent; byte[] configContent;
@@ -82,17 +89,26 @@ namespace PSOPNSenseAPI.Cmdlets
configContent = memoryStream.ToArray(); configContent = memoryStream.ToArray();
} }
// Execute synchronously on the main thread // Use our safe execution method
var result = configService.ImportConfigAsync(configContent).GetAwaiter().GetResult(); var result = ExecuteAsyncTask(() => configService.ImportConfigAsync(configContent));
// Only continue if no exception occurred
if (ProcessingException != null || result == null)
{
return;
}
WriteVerbose($"Restored configuration from XML document: {result.Status}"); WriteVerbose($"Restored configuration from XML document: {result.Status}");
} }
catch (Exception ex)
{
ProcessingException = ex;
WriteWarning($"Failed to process XML document: {ex.Message}");
return;
}
}
WriteWarning("The firewall is restarting. You may need to reconnect after it comes back online."); WriteWarning("The firewall is restarting. You may need to reconnect after it comes back online.");
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -94,15 +94,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var aliasService = new AliasService(ApiClient, Logger); var aliasService = new AliasService(ApiClient, Logger);
// Get current alias // Get current alias
var getTask = Task.Run(async () => await aliasService.GetAliasAsync(Uuid)); var getResult = ExecuteAsyncTask(() => aliasService.GetAliasAsync(Uuid));
var currentAlias = getTask.GetAwaiter().GetResult().Alias;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var currentAlias = getResult.Alias;
// Create updated alias // Create updated alias
var alias = new AliasConfig var alias = new AliasConfig
@@ -154,24 +159,29 @@ namespace PSOPNSenseAPI.Cmdlets
} }
// Update alias // Update alias
var updateTask = Task.Run(async () => await aliasService.UpdateAliasAsync(Uuid, alias)); var updateResult = ExecuteAsyncTask(() => aliasService.UpdateAliasAsync(Uuid, alias));
var updateResult = updateTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || updateResult == null)
{
return;
}
WriteVerbose($"Alias {Uuid} updated: {updateResult.Result}"); WriteVerbose($"Alias {Uuid} updated: {updateResult.Result}");
// Apply changes if requested // Apply changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var applyTask = Task.Run(async () => await aliasService.ReconfigureAliasesAsync()); var applyResult = ExecuteAsyncTask(() => aliasService.ReconfigureAliasesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"Alias changes applied: {applyResult.Status}"); WriteVerbose($"Alias changes applied: {applyResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -66,15 +66,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var dhcpService = new DHCPService(ApiClient, Logger); var dhcpService = new DHCPService(ApiClient, Logger);
// Get current option // Get current option
var getTask = Task.Run(async () => await dhcpService.GetOptionAsync(Interface, Uuid)); var getResult = ExecuteAsyncTask(() => dhcpService.GetOptionAsync(Interface, Uuid));
var currentOption = getTask.GetAwaiter().GetResult().Option;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var currentOption = getResult.Option;
// Create updated option // Create updated option
var option = new DHCPOptionConfig var option = new DHCPOptionConfig
@@ -86,24 +91,29 @@ namespace PSOPNSenseAPI.Cmdlets
}; };
// Update option // Update option
var updateTask = Task.Run(async () => await dhcpService.UpdateOptionAsync(Interface, Uuid, option)); var updateResult = ExecuteAsyncTask(() => dhcpService.UpdateOptionAsync(Interface, Uuid, option));
var updateResult = updateTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || updateResult == null)
{
return;
}
WriteVerbose($"DHCP option {Uuid} updated: {updateResult.Result}"); WriteVerbose($"DHCP option {Uuid} updated: {updateResult.Result}");
// Apply changes if requested // Apply changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var applyTask = Task.Run(async () => await dhcpService.ApplyChangesAsync()); var applyResult = ExecuteAsyncTask(() => dhcpService.ApplyChangesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"DHCP changes applied: {applyResult.Status}"); WriteVerbose($"DHCP changes applied: {applyResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -94,15 +94,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var dhcpService = new DHCPService(ApiClient, Logger); var dhcpService = new DHCPService(ApiClient, Logger);
// First, get the current server configuration // First, get the current server configuration
var getTask = Task.Run(async () => await dhcpService.GetServerAsync(Interface)); var getResult = ExecuteAsyncTask(() => dhcpService.GetServerAsync(Interface));
var currentServer = getTask.GetAwaiter().GetResult().Server;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var currentServer = getResult.Server;
// Create the updated configuration // Create the updated configuration
var server = new DHCPServerConfig var server = new DHCPServerConfig
@@ -136,24 +141,29 @@ namespace PSOPNSenseAPI.Cmdlets
} }
// Update the server // Update the server
var updateTask = Task.Run(async () => await dhcpService.UpdateServerAsync(Interface, server)); var updateResult = ExecuteAsyncTask(() => dhcpService.UpdateServerAsync(Interface, server));
var updateResult = updateTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || updateResult == null)
{
return;
}
WriteVerbose($"DHCP server for interface {Interface} updated: {updateResult.Result}"); WriteVerbose($"DHCP server for interface {Interface} updated: {updateResult.Result}");
// Apply the changes if requested // Apply the changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var applyTask = Task.Run(async () => await dhcpService.ApplyChangesAsync()); var applyResult = ExecuteAsyncTask(() => dhcpService.ApplyChangesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"DHCP changes applied: {applyResult.Status}"); WriteVerbose($"DHCP changes applied: {applyResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -82,15 +82,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var dhcpService = new DHCPService(ApiClient, Logger); var dhcpService = new DHCPService(ApiClient, Logger);
// First, get the current mapping // First, get the current mapping
var getTask = Task.Run(async () => await dhcpService.GetStaticMappingAsync(Interface, Uuid)); var getResult = ExecuteAsyncTask(() => dhcpService.GetStaticMappingAsync(Interface, Uuid));
var currentMapping = getTask.GetAwaiter().GetResult().Mapping;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var currentMapping = getResult.Mapping;
// Create the updated mapping // Create the updated mapping
var mapping = new DHCPStaticMappingConfig var mapping = new DHCPStaticMappingConfig
@@ -121,24 +126,29 @@ namespace PSOPNSenseAPI.Cmdlets
} }
// Update the mapping // Update the mapping
var updateTask = Task.Run(async () => await dhcpService.UpdateStaticMappingAsync(Interface, Uuid, mapping)); var updateResult = ExecuteAsyncTask(() => dhcpService.UpdateStaticMappingAsync(Interface, Uuid, mapping));
var updateResult = updateTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || updateResult == null)
{
return;
}
WriteVerbose($"Static mapping {Uuid} updated: {updateResult.Result}"); WriteVerbose($"Static mapping {Uuid} updated: {updateResult.Result}");
// Apply the changes if requested // Apply the changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var applyTask = Task.Run(async () => await dhcpService.ApplyChangesAsync()); var applyResult = ExecuteAsyncTask(() => dhcpService.ApplyChangesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"DHCP changes applied: {applyResult.Status}"); WriteVerbose($"DHCP changes applied: {applyResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -58,15 +58,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var dnsService = new DNSService(ApiClient, Logger); var dnsService = new DNSService(ApiClient, Logger);
// Get current configuration // Get current configuration
var getTask = Task.Run(async () => await dnsService.GetDNSForwardingAsync()); var getResult = ExecuteAsyncTask(() => dnsService.GetDNSForwardingAsync());
var currentConfig = getTask.GetAwaiter().GetResult().Forward;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var currentConfig = getResult.Forward;
// Create updated configuration // Create updated configuration
var config = new DNSForwardingConfig var config = new DNSForwardingConfig
@@ -104,24 +109,29 @@ namespace PSOPNSenseAPI.Cmdlets
} }
// Update configuration // Update configuration
var updateTask = Task.Run(async () => await dnsService.UpdateDNSForwardingAsync(config)); var updateResult = ExecuteAsyncTask(() => dnsService.UpdateDNSForwardingAsync(config));
var updateResult = updateTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || updateResult == null)
{
return;
}
WriteVerbose($"DNS forwarding configuration updated: {updateResult.Result}"); WriteVerbose($"DNS forwarding configuration updated: {updateResult.Result}");
// Apply changes if requested // Apply changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var applyTask = Task.Run(async () => await dnsService.ApplyDNSChangesAsync()); var applyResult = ExecuteAsyncTask(() => dnsService.ApplyDNSChangesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"DNS changes applied: {applyResult.Status}"); WriteVerbose($"DNS changes applied: {applyResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -69,15 +69,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var dnsService = new DNSService(ApiClient, Logger); var dnsService = new DNSService(ApiClient, Logger);
// Get current host // Get current host
var getTask = Task.Run(async () => await dnsService.GetDNSForwardingHostAsync(Uuid)); var getResult = ExecuteAsyncTask(() => dnsService.GetDNSForwardingHostAsync(Uuid));
var currentHost = getTask.GetAwaiter().GetResult().Host;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var currentHost = getResult.Host;
// Create updated host // Create updated host
var host = new DNSForwardingHostConfig var host = new DNSForwardingHostConfig
@@ -107,24 +112,29 @@ namespace PSOPNSenseAPI.Cmdlets
} }
// Update host // Update host
var updateTask = Task.Run(async () => await dnsService.UpdateDNSForwardingHostAsync(Uuid, host)); var updateResult = ExecuteAsyncTask(() => dnsService.UpdateDNSForwardingHostAsync(Uuid, host));
var updateResult = updateTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || updateResult == null)
{
return;
}
WriteVerbose($"DNS forwarding host {Uuid} updated: {updateResult.Result}"); WriteVerbose($"DNS forwarding host {Uuid} updated: {updateResult.Result}");
// Apply changes if requested // Apply changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var applyTask = Task.Run(async () => await dnsService.ApplyDNSChangesAsync()); var applyResult = ExecuteAsyncTask(() => dnsService.ApplyDNSChangesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"DNS changes applied: {applyResult.Status}"); WriteVerbose($"DNS changes applied: {applyResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -82,15 +82,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var dnsService = new DNSService(ApiClient, Logger); var dnsService = new DNSService(ApiClient, Logger);
// First, get the current DNS configuration // First, get the current DNS configuration
var getTask = Task.Run(async () => await dnsService.GetDNSConfigAsync()); var getResult = ExecuteAsyncTask(() => dnsService.GetDNSConfigAsync());
var currentConfig = getTask.GetAwaiter().GetResult().Unbound;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var currentConfig = getResult.Unbound;
// Create the updated configuration // Create the updated configuration
var dnsConfig = new DNSConfig var dnsConfig = new DNSConfig
@@ -107,24 +112,29 @@ namespace PSOPNSenseAPI.Cmdlets
}; };
// Update the DNS configuration // Update the DNS configuration
var updateTask = Task.Run(async () => await dnsService.UpdateDNSConfigAsync(dnsConfig)); var updateResult = ExecuteAsyncTask(() => dnsService.UpdateDNSConfigAsync(dnsConfig));
var updateResult = updateTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || updateResult == null)
{
return;
}
WriteVerbose($"DNS server configuration updated: {updateResult.Result}"); WriteVerbose($"DNS server configuration updated: {updateResult.Result}");
// Apply the changes if requested // Apply the changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var applyTask = Task.Run(async () => await dnsService.ApplyDNSChangesAsync()); var applyResult = ExecuteAsyncTask(() => dnsService.ApplyDNSChangesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"DNS changes applied: {applyResult.Status}"); WriteVerbose($"DNS changes applied: {applyResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -95,15 +95,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var firewallService = new FirewallService(ApiClient, Logger); var firewallService = new FirewallService(ApiClient, Logger);
// First, get the current rule // First, get the current rule
var getTask = Task.Run(async () => await firewallService.GetRuleAsync(Uuid)); var getResult = ExecuteAsyncTask(() => firewallService.GetRuleAsync(Uuid));
var currentRule = getTask.GetAwaiter().GetResult().Rule;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var currentRule = getResult.Rule;
// Create the updated rule // Create the updated rule
var rule = new FirewallRuleCreate var rule = new FirewallRuleCreate
@@ -138,15 +143,15 @@ namespace PSOPNSenseAPI.Cmdlets
} }
// Update the rule // Update the rule
var updateTask = Task.Run(async () => await firewallService.UpdateRuleAsync(Uuid, rule)); var updateResult = ExecuteAsyncTask(() => firewallService.UpdateRuleAsync(Uuid, rule));
var updateResult = updateTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || updateResult == null)
{
return;
}
WriteVerbose($"Firewall rule {Uuid} updated: {updateResult.Result}"); WriteVerbose($"Firewall rule {Uuid} updated: {updateResult.Result}");
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -131,15 +131,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var gatewayService = new GatewayService(ApiClient, Logger); var gatewayService = new GatewayService(ApiClient, Logger);
// Get current gateway // Get current gateway
var getTask = Task.Run(async () => await gatewayService.GetGatewayAsync(Uuid)); var getResult = ExecuteAsyncTask(() => gatewayService.GetGatewayAsync(Uuid));
var currentGateway = getTask.GetAwaiter().GetResult().Gateway;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var currentGateway = getResult.Gateway;
// Create updated gateway // Create updated gateway
var gateway = new GatewayConfig var gateway = new GatewayConfig
@@ -230,24 +235,29 @@ namespace PSOPNSenseAPI.Cmdlets
} }
// Update gateway // Update gateway
var updateTask = Task.Run(async () => await gatewayService.UpdateGatewayAsync(Uuid, gateway)); var updateResult = ExecuteAsyncTask(() => gatewayService.UpdateGatewayAsync(Uuid, gateway));
var updateResult = updateTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || updateResult == null)
{
return;
}
WriteVerbose($"Gateway {Uuid} updated: {updateResult.Result}"); WriteVerbose($"Gateway {Uuid} updated: {updateResult.Result}");
// Apply changes if requested // Apply changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var applyTask = Task.Run(async () => await gatewayService.ApplyGatewayChangesAsync()); var applyResult = ExecuteAsyncTask(() => gatewayService.ApplyGatewayChangesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"Gateway changes applied: {applyResult.Status}"); WriteVerbose($"Gateway changes applied: {applyResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -87,15 +87,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var interfaceService = new InterfaceService(ApiClient, Logger); var interfaceService = new InterfaceService(ApiClient, Logger);
// First, get the current interface configuration // First, get the current interface configuration
var getTask = Task.Run(async () => await interfaceService.GetInterfaceDetailAsync(Name)); var getResult = ExecuteAsyncTask(() => interfaceService.GetInterfaceDetailAsync(Name));
var currentInterface = getTask.GetAwaiter().GetResult().Interface;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var currentInterface = getResult.Interface;
// Create the updated configuration // Create the updated configuration
var interfaceConfig = new InterfaceConfig var interfaceConfig = new InterfaceConfig
@@ -108,24 +113,29 @@ namespace PSOPNSenseAPI.Cmdlets
}; };
// Update the interface // Update the interface
var updateTask = Task.Run(async () => await interfaceService.UpdateInterfaceAsync(Name, interfaceConfig)); var updateResult = ExecuteAsyncTask(() => interfaceService.UpdateInterfaceAsync(Name, interfaceConfig));
var updateResult = updateTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || updateResult == null)
{
return;
}
WriteVerbose($"Interface {Name} updated: {updateResult.Result}"); WriteVerbose($"Interface {Name} updated: {updateResult.Result}");
// Apply the changes if requested // Apply the changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var restartTask = Task.Run(async () => await interfaceService.RestartInterfaceAsync(Name)); var restartResult = ExecuteAsyncTask(() => interfaceService.RestartInterfaceAsync(Name));
var restartResult = restartTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || restartResult == null)
{
return;
}
WriteVerbose($"Interface {Name} restarted: {restartResult.Status}"); WriteVerbose($"Interface {Name} restarted: {restartResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -15,7 +15,7 @@ namespace PSOPNSenseAPI.Cmdlets
/// </summary> /// </summary>
[Cmdlet(VerbsCommon.Set, "OPNSensePortForwardingRule", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.Medium)] [Cmdlet(VerbsCommon.Set, "OPNSensePortForwardingRule", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.Medium)]
[OutputType(typeof(PortForwardingRule))] [OutputType(typeof(PortForwardingRule))]
public class SetOPNSensePortForwardingRuleCmdlet : OPNSenseCmdlet public class SetOPNSensePortForwardingRuleCmdlet : OPNSenseBaseCmdlet
{ {
/// <summary> /// <summary>
/// <para type="description">The UUID of the port forwarding rule to update.</para> /// <para type="description">The UUID of the port forwarding rule to update.</para>
@@ -118,20 +118,23 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{ {
var portForwardingService = new PortForwardingService(SessionState.ApiClient); var portForwardingService = new PortForwardingService(ApiClient);
// Get the existing rule // Get the existing rule
var existingRule = Task.Run(async () => await portForwardingService.GetPortForwardingRuleAsync(Uuid)).GetAwaiter().GetResult(); var existingRule = ExecuteAsyncTask(() => portForwardingService.GetPortForwardingRuleAsync(Uuid));
// Only continue if no exception occurred
if (ProcessingException != null)
{
return;
}
if (existingRule == null) if (existingRule == null)
{ {
WriteError(new ErrorRecord( ProcessingException = new PSArgumentException($"Port forwarding rule with UUID '{Uuid}' not found.");
new PSArgumentException($"Port forwarding rule with UUID '{Uuid}' not found."), WriteWarning($"Port forwarding rule with UUID '{Uuid}' not found.");
"PortForwardingRuleNotFound",
ErrorCategory.ObjectNotFound,
Uuid));
return; return;
} }
@@ -177,7 +180,13 @@ namespace PSOPNSenseAPI.Cmdlets
if (Force || ShouldProcess($"OPNSense firewall", $"Update port forwarding rule with UUID '{Uuid}'")) if (Force || ShouldProcess($"OPNSense firewall", $"Update port forwarding rule with UUID '{Uuid}'"))
{ {
var success = Task.Run(async () => await portForwardingService.UpdatePortForwardingRuleAsync(existingRule)).GetAwaiter().GetResult(); var success = ExecuteAsyncTask(() => portForwardingService.UpdatePortForwardingRuleAsync(existingRule));
// Only continue if no exception occurred
if (ProcessingException != null)
{
return;
}
if (success) if (success)
{ {
@@ -190,11 +199,8 @@ namespace PSOPNSenseAPI.Cmdlets
} }
else else
{ {
WriteError(new ErrorRecord( ProcessingException = new PSInvalidOperationException($"Failed to update port forwarding rule with UUID '{Uuid}'.");
new PSInvalidOperationException($"Failed to update port forwarding rule with UUID '{Uuid}'."), WriteWarning($"Failed to update port forwarding rule with UUID '{Uuid}'.");
"PortForwardingRuleUpdateFailed",
ErrorCategory.InvalidOperation,
existingRule));
} }
} }
} }
@@ -69,15 +69,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var routeService = new RouteService(ApiClient, Logger); var routeService = new RouteService(ApiClient, Logger);
// Get current route // Get current route
var getTask = Task.Run(async () => await routeService.GetRouteAsync(Uuid)); var getResult = ExecuteAsyncTask(() => routeService.GetRouteAsync(Uuid));
var currentRoute = getTask.GetAwaiter().GetResult().Route;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var currentRoute = getResult.Route;
// Create updated route // Create updated route
var route = new RouteConfig var route = new RouteConfig
@@ -107,24 +112,29 @@ namespace PSOPNSenseAPI.Cmdlets
} }
// Update route // Update route
var updateTask = Task.Run(async () => await routeService.UpdateRouteAsync(Uuid, route)); var updateResult = ExecuteAsyncTask(() => routeService.UpdateRouteAsync(Uuid, route));
var updateResult = updateTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || updateResult == null)
{
return;
}
WriteVerbose($"Route {Uuid} updated: {updateResult.Result}"); WriteVerbose($"Route {Uuid} updated: {updateResult.Result}");
// Apply changes if requested // Apply changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var applyTask = Task.Run(async () => await routeService.ApplyRouteChangesAsync()); var applyResult = ExecuteAsyncTask(() => routeService.ApplyRouteChangesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"Route changes applied: {applyResult.Status}"); WriteVerbose($"Route changes applied: {applyResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -93,15 +93,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var systemDNSService = new SystemDNSService(ApiClient, Logger); var systemDNSService = new SystemDNSService(ApiClient, Logger);
// Get current configuration // Get current configuration
var getTask = Task.Run(async () => await systemDNSService.GetSystemDNSAsync()); var getResult = ExecuteAsyncTask(() => systemDNSService.GetSystemDNSAsync());
var currentConfig = getTask.GetAwaiter().GetResult().System;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var currentConfig = getResult.System;
// Create updated configuration // Create updated configuration
var config = new SystemDNSConfig var config = new SystemDNSConfig
@@ -162,24 +167,29 @@ namespace PSOPNSenseAPI.Cmdlets
} }
// Update configuration // Update configuration
var updateTask = Task.Run(async () => await systemDNSService.UpdateSystemDNSAsync(config)); var updateResult = ExecuteAsyncTask(() => systemDNSService.UpdateSystemDNSAsync(config));
var updateResult = updateTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || updateResult == null)
{
return;
}
WriteVerbose($"System DNS configuration updated: {updateResult.Result}"); WriteVerbose($"System DNS configuration updated: {updateResult.Result}");
// Apply changes if requested // Apply changes if requested
if (Apply.IsPresent) if (Apply.IsPresent)
{ {
var applyTask = Task.Run(async () => await systemDNSService.ApplySystemDNSChangesAsync()); var applyResult = ExecuteAsyncTask(() => systemDNSService.ApplySystemDNSChangesAsync());
var applyResult = applyTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || applyResult == null)
{
return;
}
WriteVerbose($"System DNS changes applied: {applyResult.Status}"); WriteVerbose($"System DNS changes applied: {applyResult.Status}");
} }
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -76,15 +76,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var userService = new UserService(ApiClient, Logger); var userService = new UserService(ApiClient, Logger);
// First, get the current user // First, get the current user
var getTask = Task.Run(async () => await userService.GetUserAsync(Uuid)); var getResult = ExecuteAsyncTask(() => userService.GetUserAsync(Uuid));
var currentUser = getTask.GetAwaiter().GetResult().User;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var currentUser = getResult.User;
// Create the updated user // Create the updated user
var user = new UserConfig var user = new UserConfig
@@ -117,15 +122,15 @@ namespace PSOPNSenseAPI.Cmdlets
} }
// Update the user // Update the user
var updateTask = Task.Run(async () => await userService.UpdateUserAsync(Uuid, user)); var updateResult = ExecuteAsyncTask(() => userService.UpdateUserAsync(Uuid, user));
var updateResult = updateTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || updateResult == null)
{
return;
}
WriteVerbose($"User {Uuid} updated: {updateResult.Result}"); WriteVerbose($"User {Uuid} updated: {updateResult.Result}");
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
@@ -59,15 +59,20 @@ namespace PSOPNSenseAPI.Cmdlets
/// <summary> /// <summary>
/// Processes the cmdlet /// Processes the cmdlet
/// </summary> /// </summary>
protected override void ProcessRecord() protected override void ProcessRecordInternal()
{
try
{ {
var interfaceService = new InterfaceService(ApiClient, Logger); var interfaceService = new InterfaceService(ApiClient, Logger);
// First, get the current VLAN configuration // First, get the current VLAN configuration
var getTask = Task.Run(async () => await interfaceService.GetVLANAsync(Uuid)); var getResult = ExecuteAsyncTask(() => interfaceService.GetVLANAsync(Uuid));
var currentVlan = getTask.GetAwaiter().GetResult().Vlan;
// Only continue if no exception occurred
if (ProcessingException != null || getResult == null)
{
return;
}
var currentVlan = getResult.Vlan;
// Create the updated configuration // Create the updated configuration
var vlan = new VLANConfig var vlan = new VLANConfig
@@ -79,15 +84,15 @@ namespace PSOPNSenseAPI.Cmdlets
}; };
// Update the VLAN // Update the VLAN
var updateTask = Task.Run(async () => await interfaceService.UpdateVLANAsync(Uuid, vlan)); var updateResult = ExecuteAsyncTask(() => interfaceService.UpdateVLANAsync(Uuid, vlan));
var updateResult = updateTask.GetAwaiter().GetResult();
// Only continue if no exception occurred
if (ProcessingException != null || updateResult == null)
{
return;
}
WriteVerbose($"VLAN {Uuid} updated: {updateResult.Result}"); WriteVerbose($"VLAN {Uuid} updated: {updateResult.Result}");
} }
catch (Exception ex)
{
HandleException(ex);
}
}
} }
} }
+1 -1
View File
@@ -3,7 +3,7 @@
RootModule = 'lib\PSOPNSenseAPI.dll' RootModule = 'lib\PSOPNSenseAPI.dll'
# Version number of this module. # Version number of this module.
ModuleVersion = '2025.04.15.1257' ModuleVersion = '2025.04.15.1543'
# Supported PSEditions # Supported PSEditions
CompatiblePSEditions = @('Desktop', 'Core') CompatiblePSEditions = @('Desktop', 'Core')