Classes/GceSshTunnel.ps1
|
# PowerShell class for GCE SSH Tunnel objects # This class represents an IAP tunnel to a GCE VM instance class GceSshTunnel { # Properties [int]$Id # Tunnel ID is the Process ID (PID) [string]$InstanceName [string]$Project [string]$Zone [int]$LocalPort [int]$RemotePort [System.Diagnostics.Process]$TunnelProcess [DateTime]$Created # Status method that checks process and port status dynamically [string] GetStatus() { try { # Check if process exists and is running if ($null -eq $this.TunnelProcess) { return 'Error' } # Refresh process object try { $process = Get-Process -Id $this.TunnelProcess.Id -ErrorAction SilentlyContinue if (-not $process) { return 'Stopped' } } catch { # Process check failed - check if it has exited if ($this.TunnelProcess.HasExited) { return 'Stopped' } return 'Error' } # Process is running, now check if port is open $TcpClient = $null try { $TcpClient = New-Object System.Net.Sockets.TcpClient $ConnectResult = $TcpClient.BeginConnect("localhost", $this.LocalPort, $null, $null) $WaitResult = $ConnectResult.AsyncWaitHandle.WaitOne(1000, $false) if ($WaitResult -and $TcpClient.Connected) { $TcpClient.Close() return 'Active' } else { $TcpClient.Close() return 'Error' } } catch { # Port check failed if ($null -ne $TcpClient) { try { $TcpClient.Close() } catch { } } return 'Error' } } catch { return 'Error' } } # Constructor GceSshTunnel( [int]$Id, [string]$InstanceName, [string]$Project, [string]$Zone, [int]$LocalPort, [int]$RemotePort, [System.Diagnostics.Process]$TunnelProcess ) { $this.Id = $Id $this.InstanceName = $InstanceName $this.Project = $Project $this.Zone = $Zone $this.LocalPort = $LocalPort $this.RemotePort = $RemotePort $this.TunnelProcess = $TunnelProcess $this.Created = Get-Date } # Method to stop the tunnel process [void] Stop([bool]$Force = $false) { if ($null -eq $this.TunnelProcess) { return } if ($this.TunnelProcess.HasExited) { return } try { $this.TunnelProcess.Kill() $this.TunnelProcess.WaitForExit(5000) if (-not $this.TunnelProcess.HasExited -and $Force) { $this.TunnelProcess.Kill() $this.TunnelProcess.WaitForExit(2000) } } catch { if ($Force) { try { $this.TunnelProcess.Kill() } catch { # Ignore errors when force killing } } } } # Override ToString for better display [string] ToString() { return "GceSshTunnel [Id=$($this.Id), Instance=$($this.InstanceName), Status=$($this.GetStatus()), Port=$($this.LocalPort)]" } } |