Public/kubebuddy.ps1

$Global:MakeReport = $false  # Global flag to control report mode

$moduleVersion = 'v0.0.16'

function Invoke-KubeBuddy {
    param (
        [switch]$HtmlReport,
        [switch]$txtReport,
        [switch]$jsonReport,
        [switch]$Aks,
        [switch]$ExcludeNamespaces,
        [switch]$yes,
        [string]$SubscriptionId,
        [string]$ResourceGroup,
        [string]$ClusterName,
        [string]$outputpath,
        [switch]$UseAksRestApi  # Flag for AKS REST API mode
    )

    # Assign default value if $outputpath is not set
    if (-not $outputpath) {
        $outputpath = Join-Path -Path $HOME -ChildPath "kubebuddy-report"
    }

    # Detect if outputpath is a FILE or DIRECTORY
    $fileExtension = [System.IO.Path]::GetExtension($outputpath)

    if ($fileExtension -in @(".html", ".txt")) {
        $reportDir = Split-Path -Parent $outputpath
        $reportBaseName = [System.IO.Path]::GetFileNameWithoutExtension($outputpath)
    } else {
        $reportDir = $outputpath
        $timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
        $reportBaseName = "kubebuddy-report-$timestamp"
    }

    # Ensure the output directory exists
    if (!(Test-Path -Path $reportDir)) {
        Write-Host "📂 Creating directory: $reportDir" -ForegroundColor Yellow
        New-Item -ItemType Directory -Path $reportDir -Force | Out-Null
    }

    # Define report file paths
    $htmlReportFile = Join-Path -Path $reportDir -ChildPath "$reportBaseName.html"
    $txtReportFile = Join-Path -Path $reportDir -ChildPath "$reportBaseName.txt"
    $jsonReportFile = Join-Path -Path $reportDir -ChildPath "$reportBaseName.json"
    Clear-Host

    # KubeBuddy ASCII Art
    $banner = @"
██╗ ██╗██╗ ██║██████╗ ███████╗██████╗ ██╗ ██╗██████╗ ██████╗ ██╗ ██╗
██║ ██╔╝██║ ██║██╔══██╗██╔════╝██╔══██╗██║ ██║██╔══██╗██╔══██╗╚██╗ ██╔╝
█████╔╝ ██║ ██║██████╔╝█████╗ ██████╔╝██║ ██║██║ ██║██║ ██║ ╚████╔╝
██╔═██╗ ██║ ██║██╔══██╗██╔══╝ ██╔══██╗██║ ██║██║ ██║██║ ██║ ╚██╔╝
██║ ██╗╚██████╔╝██████╔╝███████╗██████╔╝╚██████╔╝██████╔╝██████╔╝ ██║
╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝
"@

    Write-Host ""
    Write-Host -NoNewline $banner -ForegroundColor Cyan
    Write-Host "$moduleVersion" -ForegroundColor Magenta
    Write-Host "-------------------------------------------------------------" -ForegroundColor DarkGray
    Write-Host "Your Kubernetes Assistant" -ForegroundColor Cyan
    Write-Host "-------------------------------------------------------------" -ForegroundColor DarkGray

    # Get current context
    $context = kubectl config view --minify -o jsonpath="{.current-context}" 2>$null
    if (-not $context) {
        Write-Host "`n🚫 Failed to get Kubernetes context. Ensure kubeconfig is valid and cluster is accessible." -ForegroundColor Red
        return
    }
    Write-Host "`n🤖 Connected to Kubernetes context: '$context'" -ForegroundColor Cyan

    # Confirm context
    if ($yes) {
        Write-Host "`n🤖 Skipping context confirmation." -ForegroundColor Red
    } else {
        $confirmation = Read-Host "🤖 Is this the correct context? (y/n)"
        if ($confirmation.Trim().ToLower() -ne 'y') {
            Write-Host "🤖 Exiting. Please switch context and try again." -ForegroundColor Yellow
            return
        }
    }

    # Validate cluster access for AKS
    if ($Aks) {
        Write-Host -NoNewline "`n🤖 Validating AKS cluster access..." -ForegroundColor Yellow
        $spnProvided = $env:AZURE_CLIENT_ID -and $env:AZURE_CLIENT_SECRET -and $env:AZURE_TENANT_ID
        $isContainer = Test-IsContainer

        if (-not $isContainer) {
            # Local run: Use az aks show
            try {
                if ($spnProvided) {
                    az login --service-principal -u $env:AZURE_CLIENT_ID -p $env:AZURE_CLIENT_SECRET --tenant $env:AZURE_TENANT_ID --only-show-errors 2>&1 | Out-Null
                    $aksOutput = az aks show --resource-group $ResourceGroup --name $ClusterName --subscription $SubscriptionId --only-show-errors 2>&1
                    az logout --only-show-errors 2>&1 | Out-Null
                }
                else {
                    if (-not (Get-Command az -ErrorAction SilentlyContinue)) {
                        Write-Host "`r🤖 ❌ Azure CLI not found and no SPN credentials provided." -ForegroundColor Red
                        return
                    }
                    $aksOutput = az aks show --resource-group $ResourceGroup --name $ClusterName --subscription $SubscriptionId --only-show-errors 2>&1
                }
                if ($LASTEXITCODE -ne 0 -or -not $aksOutput) {
                    Write-Host "`r🤖 ❌ Failed to access AKS cluster '$ClusterName' in '$ResourceGroup'" -ForegroundColor Red
                    Write-Host "🤖 Ensure you're logged in to Azure with 'az login' or provide SPN credentials." -ForegroundColor Red
                    Write-Host "🧾 Error: $aksOutput" -ForegroundColor DarkGray
                    return
                }
                $aksInfo = $aksOutput | ConvertFrom-Json
                Write-Host "`r🤖 ✅ Connected to AKS Cluster: $($aksInfo.name) in $($aksInfo.location)`n" -ForegroundColor Green
            }
            catch {
                Write-Host "`r🤖 ❌ Failed to access AKS cluster: $_" -ForegroundColor Red
                return
            }
        }
        else {
            # Container run: Use kubectl check
            try {
                $kubectlOutput = kubectl get nodes --no-headers 2>&1
                if (
                    $LASTEXITCODE -ne 0 -or
                    $kubectlOutput -match "Unable to connect to the server" -or
                    $kubectlOutput -match "no such host" -or
                    $kubectlOutput -match "couldn't get current server API group list" -or
                    $kubectlOutput -match "get token" -or
                    $kubectlOutput -match "credentials"
                ) {
                    Write-Host "`r🤖 ❌ Failed to access AKS cluster. Check DNS resolution, SPN permissions, or kubeconfig auth." -ForegroundColor Red
                    Write-Host "🧾 Error: $kubectlOutput" -ForegroundColor DarkGray
                    return
                }
            
                Write-Host "`r🤖 ✅ Connected to AKS cluster. `n" -ForegroundColor Green
            }
            catch {
                Write-Host "`r🤖 ❌ Exception occurred while validating cluster access: $_" -ForegroundColor Red
                return
            }            
        }
    }

    # Report modes
    if ($HtmlReport) {
        Write-Host "📄 Generating HTML report: $htmlReportFile" -ForegroundColor Cyan
        if ($Aks -and (-not $SubscriptionId -or -not $ResourceGroup -or -not $ClusterName)) {
            Write-Host "⚠️ ERROR: -Aks requires -SubscriptionId, -ResourceGroup, and -ClusterName" -ForegroundColor Red
            return
        }
        $KubeData = Get-KubeData -SubscriptionId $SubscriptionId -ResourceGroup $ResourceGroup -ClusterName $ClusterName -ExcludeNamespaces:$ExcludeNamespaces -Aks:$Aks -UseAksRestApi:$UseAksRestApi
        if ($KubeData -eq $false) {
            Write-Host "`n🚫 Script terminated due to a connection error. Please ensure you can connect to your Kubernetes Cluster" -ForegroundColor Red
            return
        }
        Generate-K8sHTMLReport `
            -version $moduleVersion `
            -outputPath $htmlReportFile `
            -aks:$Aks `
            -SubscriptionId $SubscriptionId `
            -ResourceGroup $ResourceGroup `
            -ClusterName $ClusterName `
            -ExcludeNamespaces:$ExcludeNamespaces `
            -KubeData $KubeData
        Write-Host "`n🤖 ✅ HTML report saved at: $htmlReportFile" -ForegroundColor Green
        return
    }

    if ($txtReport) {
        Write-Host "📄 Generating Text report: $txtReportFile" -ForegroundColor Cyan
        if ($Aks -and (-not $SubscriptionId -or -not $ResourceGroup -or -not $ClusterName)) {
            Write-Host "⚠️ ERROR: -Aks requires -SubscriptionId, -ResourceGroup, and -ClusterName" -ForegroundColor Red
            return
        }
        $KubeData = Get-KubeData -SubscriptionId $SubscriptionId -ResourceGroup $ResourceGroup -ClusterName $ClusterName -ExcludeNamespaces:$ExcludeNamespaces -Aks:$Aks -UseAksRestApi:$UseAksRestApi
        if ($KubeData -eq $false) {
            Write-Host "`n🚫 Script terminated due to a connection error. Please ensure you can connect to your Kubernetes Cluster" -ForegroundColor Red
            return
        }
        Generate-K8sTextReport `
            -ReportFile $txtReportFile `
            -ExcludeNamespaces:$ExcludeNamespaces `
            -aks:$Aks `
            -SubscriptionId $SubscriptionId `
            -ResourceGroup $ResourceGroup `
            -ClusterName $ClusterName `
            -KubeData $KubeData
        Write-Host "`n🤖 ✅ Text report saved at: $txtReportFile" -ForegroundColor Green
        return
    }

    if ($jsonReport) {
        Write-Host "📄 Generating Json report: $jsonReportFile" -ForegroundColor Cyan
        if ($Aks -and (-not $SubscriptionId -or -not $ResourceGroup -or -not $ClusterName)) {
            Write-Host "⚠️ ERROR: -Aks requires -SubscriptionId, -ResourceGroup, and -ClusterName" -ForegroundColor Red
            return
        }
        $KubeData = Get-KubeData -SubscriptionId $SubscriptionId -ResourceGroup $ResourceGroup -ClusterName $ClusterName -ExcludeNamespaces:$ExcludeNamespaces -Aks:$Aks -UseAksRestApi:$UseAksRestApi
        if ($KubeData -eq $false) {
            Write-Host "`n🚫 Script terminated due to a connection error. Please ensure you can connect to your Kubernetes Cluster" -ForegroundColor Red
            return
        }
        Create-jsonReport `
            -outputpath $jsonReportFile `
            -KubeData $KubeData `
            -aks:$Aks `
            -SubscriptionId $SubscriptionId `
            -ResourceGroup $ResourceGroup `
            -ClusterName $ClusterName
        Write-Host "`n🤖 ✅ Json report saved at: $jsonReportFile" -ForegroundColor Green
        return
    }

    # Interactive mode
    Write-Host -NoNewline "`n`r🤖 Initializing KubeBuddy..." -ForegroundColor Yellow
    Start-Sleep -Seconds 2
    Write-Host "`r✅ KubeBuddy is ready to assist you! " -ForegroundColor Green
    $msg = @(
        "🤖 Hello, I'm KubeBuddy—your Kubernetes assistant!",
        "",
        " - I can check node health, workload status, networking, storage, RBAC security, and more.",
        " - You're currently connected to the '$context' context. All actions will run on this cluster.",
        "",
        " ** WARNING: PLEASE VERIFY YOUR CONTEXT! **",
        "",
        " - If this is NOT the correct CONTEXT, please EXIT and connect to the correct one.",
        " - Actions performed here may impact the wrong Kubernetes cluster!",
        "",
        " - Choose an option from the menu below to get started."
    )
    Write-SpeechBubble -msg $msg -color "Cyan" -icon "🤖" -lastColor "Green" -delay 50
    $firstRun = $true
    show-mainMenu -ExcludeNamespaces:$ExcludeNamespaces -KubeData $KubeData
}