scripts/demo-setup.ps1
|
# demo-setup.ps1 # Injects fake multi-cloud data into the PSCumulus module scope for demo purposes. # # ── From PSGallery (talk demo) ──────────────────────────────────────────────── # # Install-Module PSCumulus -Scope CurrentUser # Import-Module PSCumulus # Invoke-WebRequest https://raw.githubusercontent.com/adilio/PSCumulus/main/scripts/demo-setup.ps1 -OutFile demo-setup.ps1 # . ./demo-setup.ps1 # # ── From source (development) ───────────────────────────────────────────────── # # Import-Module ./PSCumulus.psd1 -Force # . ./scripts/demo-setup.ps1 # # ── Demo commands ───────────────────────────────────────────────────────────── # # Get-CloudContext # # Connect-Cloud -Provider AWS, Azure, GCP # Get-CloudInstance -All # Get-CloudInstance -All | Where-Object { $_.Tags['environment'] -eq 'prod' } # Get-CloudInstance -All | Group-Object Provider | Select-Object Name, Count # # # Pre-built query functions (tab-complete Find-* / Show-*) # Find-UntaggedInstances # tagging compliance: missing owner tag # Find-StaleInstances # cost waste: stopped/terminated > 30 days # Show-FleetHealth # running vs not-running by provider # Show-CostCenterRollup # instance count per cost-center tag # Find-OldestInstances # oldest five instances across all clouds # Invoke-AllDemoQueries # run all of the above in sequence # # # Cleanup # Remove-DemoSetup # unload module, remove demo functions # Remove-DemoSetup -Uninstall # also uninstalls PSCumulus from the system # # Get-CloudInstance -Provider Azure -ResourceGroup prod-rg # Get-CloudInstance -Provider AWS -Region us-east-1 # Get-CloudInstance -Provider GCP -Project contoso-prod # # Get-CloudStorage -Provider Azure -ResourceGroup prod-rg # Get-CloudStorage -Provider AWS -Region us-east-1 # Get-CloudStorage -Provider GCP -Project contoso-prod # # Get-CloudDisk -Provider Azure -ResourceGroup prod-rg # Get-CloudDisk -Provider AWS -Region us-east-1 # Get-CloudDisk -Provider GCP -Project contoso-prod # # Get-CloudNetwork -Provider Azure -ResourceGroup prod-rg # Get-CloudNetwork -Provider AWS -Region us-east-1 # Get-CloudNetwork -Provider GCP -Project contoso-prod # # Get-CloudFunction -Provider Azure -ResourceGroup prod-rg # Get-CloudFunction -Provider AWS -Region us-east-1 # Get-CloudFunction -Provider GCP -Project contoso-prod # # Get-CloudTag -Provider Azure -ResourceId '/subscriptions/00000000/resourceGroups/prod-rg/providers/Microsoft.Compute/virtualMachines/web-server-01' # Get-CloudTag -Provider AWS -ResourceId 'i-0a1b2c3d4e5f00001' # Get-CloudTag -Provider GCP -Project contoso-prod -Resource 'instances/prod-web-01' # # Start-CloudInstance -Provider Azure -Name web-server-01 -ResourceGroup prod-rg # Start-CloudInstance -Provider AWS -InstanceId i-0a1b2c3d4e5f00003 -Region us-east-1 # Start-CloudInstance -Provider GCP -Name prod-worker-01 -Zone us-central1-c -Project contoso-prod # # Stop-CloudInstance -Provider Azure -Name api-server-01 -ResourceGroup prod-rg # Stop-CloudInstance -Provider AWS -InstanceId i-0a1b2c3d4e5f00002 -Region us-east-1 # Stop-CloudInstance -Provider GCP -Name prod-api-01 -Zone us-central1-b -Project contoso-prod # # ───────────────────────────────────────────────────────────────────────────── $module = Get-Module PSCumulus if (-not $module) { Write-Error "PSCumulus is not loaded. Run: Import-Module ./PSCumulus.psd1 -Force" return } $module.Invoke({ # ── Connect backends ────────────────────────────────────────────────────── Set-Item -Path 'Function:Connect-AzureBackend' -Value { [pscustomobject]@{ PSTypeName = 'PSCumulus.ConnectionResult' Provider = 'Azure' Connected = $true ContextName = 'contoso-production (00000000-0000-0000-0000-000000000001)' TenantId = '00000000-0000-0000-0000-000000000002' Subscription = 'contoso-production' Account = 'adil@contoso.com' Region = 'eastus' } } Set-Item -Path 'Function:Connect-AWSBackend' -Value { param([string]$Region) [pscustomobject]@{ PSTypeName = 'PSCumulus.ConnectionResult' Provider = 'AWS' Connected = $true Account = '123456789012' ProfileName = 'default' Region = if ($Region) { $Region } else { 'us-east-1' } } } Set-Item -Path 'Function:Connect-GCPBackend' -Value { param([string]$Project) [pscustomobject]@{ PSTypeName = 'PSCumulus.ConnectionResult' Provider = 'GCP' Connected = $true Account = 'adil@contoso-prod.iam.gserviceaccount.com' Project = if ($Project) { $Project } else { 'contoso-prod' } Region = 'us-central1' } } # ── Instances ───────────────────────────────────────────────────────────── Set-Item -Path 'Function:Get-AzureInstanceData' -Value { param([string]$ResourceGroup) ConvertTo-CloudRecord -Name 'web-server-01' -Provider Azure -Region 'eastus' -Status 'Running' -Size 'Standard_D2s_v3' -CreatedAt ([datetime]'2025-03-15') -Tags @{ environment = 'prod'; team = 'platform'; 'cost-center' = 'eng-001'; owner = 'platform-team' } -Metadata @{ ResourceGroup = 'prod-rg'; VmId = 'aaaaaaaa-0001-0001-0001-aaaaaaaaaaaa'; OsType = 'Linux' } ConvertTo-CloudRecord -Name 'api-server-01' -Provider Azure -Region 'eastus' -Status 'Running' -Size 'Standard_D4s_v3' -CreatedAt ([datetime]'2024-11-01') -Tags @{ environment = 'prod'; team = 'platform'; 'cost-center' = 'eng-001'; owner = 'platform-team' } -Metadata @{ ResourceGroup = 'prod-rg'; VmId = 'aaaaaaaa-0002-0002-0002-aaaaaaaaaaaa'; OsType = 'Linux' } ConvertTo-CloudRecord -Name 'db-server-01' -Provider Azure -Region 'eastus2' -Status 'Stopped' -Size 'Standard_E8s_v3' -CreatedAt ([datetime]'2024-08-20') -Tags @{ environment = 'staging'; team = 'data'; 'cost-center' = 'eng-002' } -Metadata @{ ResourceGroup = 'prod-rg'; VmId = 'aaaaaaaa-0003-0003-0003-aaaaaaaaaaaa'; OsType = 'Windows' } } Set-Item -Path 'Function:Get-AWSInstanceData' -Value { param([string]$Region) ConvertTo-CloudRecord -Name 'prod-web-01' -Provider AWS -Region 'us-east-1a' -Status 'Running' -Size 't3.medium' -CreatedAt ([datetime]'2026-01-10') -Tags @{ environment = 'prod'; team = 'platform'; 'cost-center' = 'eng-001'; owner = 'platform-team' } -Metadata @{ InstanceId = 'i-0a1b2c3d4e5f00001'; PrivateIpAddress = '10.0.1.10'; PublicIpAddress = '54.210.10.1'; VpcId = 'vpc-0a1b2c3d'; SubnetId = 'subnet-0a1b2c3d' } ConvertTo-CloudRecord -Name 'prod-api-01' -Provider AWS -Region 'us-east-1b' -Status 'Running' -Size 't3.large' -CreatedAt ([datetime]'2025-06-01') -Tags @{ environment = 'prod'; team = 'platform'; 'cost-center' = 'eng-001'; owner = 'platform-team' } -Metadata @{ InstanceId = 'i-0a1b2c3d4e5f00002'; PrivateIpAddress = '10.0.2.10'; PublicIpAddress = '54.210.10.2'; VpcId = 'vpc-0a1b2c3d'; SubnetId = 'subnet-1a2b3c4d' } ConvertTo-CloudRecord -Name 'prod-worker-01' -Provider AWS -Region 'us-east-1c' -Status 'Stopped' -Size 't3.xlarge' -CreatedAt ([datetime]'2024-09-30') -Tags @{ environment = 'staging'; team = 'workers'; 'cost-center' = 'eng-003' } -Metadata @{ InstanceId = 'i-0a1b2c3d4e5f00003'; PrivateIpAddress = '10.0.3.10'; PublicIpAddress = $null; VpcId = 'vpc-0a1b2c3d'; SubnetId = 'subnet-2a3b4c5d' } } Set-Item -Path 'Function:Get-GCPInstanceData' -Value { param([string]$Project) ConvertTo-CloudRecord -Name 'prod-web-01' -Provider GCP -Region 'us-central1-a' -Status 'Running' -Size 'n2-standard-2' -CreatedAt ([datetime]'2025-11-20') -Tags @{ environment = 'prod'; team = 'platform'; 'cost-center' = 'eng-001'; owner = 'platform-team' } -Metadata @{ Project = 'contoso-prod'; Id = '1234567890000001'; Zone = 'us-central1-a'; PrivateIpAddress = '10.128.0.10'; PublicIpAddress = '34.72.10.1'; Labels = @{ env = 'production'; team = 'platform' } } ConvertTo-CloudRecord -Name 'prod-api-01' -Provider GCP -Region 'us-central1-b' -Status 'Running' -Size 'n2-standard-4' -CreatedAt ([datetime]'2025-04-08') -Tags @{ environment = 'prod'; team = 'platform'; 'cost-center' = 'eng-001'; owner = 'platform-team' } -Metadata @{ Project = 'contoso-prod'; Id = '1234567890000002'; Zone = 'us-central1-b'; PrivateIpAddress = '10.128.0.11'; PublicIpAddress = '34.72.10.2'; Labels = @{ env = 'production'; team = 'platform' } } ConvertTo-CloudRecord -Name 'prod-worker-01' -Provider GCP -Region 'us-central1-c' -Status 'Terminated' -Size 'n2-standard-8' -CreatedAt ([datetime]'2024-07-14') -Tags @{ environment = 'staging'; team = 'workers'; 'cost-center' = 'eng-003' } -Metadata @{ Project = 'contoso-prod'; Id = '1234567890000003'; Zone = 'us-central1-c'; PrivateIpAddress = '10.128.0.12'; PublicIpAddress = $null; Labels = @{ env = 'production'; team = 'workers' } } } # ── Storage ─────────────────────────────────────────────────────────────── Set-Item -Path 'Function:Get-AzureStorageData' -Value { param([string]$ResourceGroup) ConvertTo-CloudRecord -Name 'contosoproddata' -Provider Azure -Region 'eastus' -Status 'available' -Size 'Standard_LRS' -CreatedAt ([datetime]'2024-09-01') -Metadata @{ ResourceGroup = 'prod-rg'; Kind = 'StorageV2'; AccessTier = 'Hot' } ConvertTo-CloudRecord -Name 'contosobackups' -Provider Azure -Region 'eastus2' -Status 'available' -Size 'Standard_GRS' -CreatedAt ([datetime]'2024-09-01') -Metadata @{ ResourceGroup = 'prod-rg'; Kind = 'BlobStorage'; AccessTier = 'Cool' } } Set-Item -Path 'Function:Get-AWSStorageData' -Value { param([string]$Region) ConvertTo-CloudRecord -Name 'contoso-prod-assets' -Provider AWS -Region 'us-east-1' -Status 'Available' -CreatedAt ([datetime]'2024-09-01') -Metadata @{ BucketName = 'contoso-prod-assets' } ConvertTo-CloudRecord -Name 'contoso-prod-backups' -Provider AWS -Region 'us-west-2' -Status 'Available' -CreatedAt ([datetime]'2024-09-01') -Metadata @{ BucketName = 'contoso-prod-backups' } } Set-Item -Path 'Function:Get-GCPStorageData' -Value { param([string]$Project) ConvertTo-CloudRecord -Name 'contoso-prod-assets' -Provider GCP -Region 'US-CENTRAL1' -Status 'Available' -Size 'STANDARD' -CreatedAt ([datetime]'2024-09-01') -Metadata @{ Project = 'contoso-prod'; StorageClass = 'STANDARD'; Location = 'US-CENTRAL1' } ConvertTo-CloudRecord -Name 'contoso-prod-backups' -Provider GCP -Region 'US' -Status 'Available' -Size 'NEARLINE' -CreatedAt ([datetime]'2024-09-01') -Metadata @{ Project = 'contoso-prod'; StorageClass = 'NEARLINE'; Location = 'US' } } # ── Disks ───────────────────────────────────────────────────────────────── Set-Item -Path 'Function:Get-AzureDiskData' -Value { param([string]$ResourceGroup) ConvertTo-CloudRecord -Name 'web-server-01_OsDisk_1' -Provider Azure -Region 'eastus' -Status 'Attached' -Size '128 GB' -CreatedAt ([datetime]'2024-11-01') -Metadata @{ ResourceGroup = 'prod-rg'; DiskSizeGB = 128; OsType = 'Linux'; Sku = 'Premium_LRS' } ConvertTo-CloudRecord -Name 'api-server-01_OsDisk_1' -Provider Azure -Region 'eastus' -Status 'Attached' -Size '128 GB' -CreatedAt ([datetime]'2024-11-01') -Metadata @{ ResourceGroup = 'prod-rg'; DiskSizeGB = 128; OsType = 'Linux'; Sku = 'Premium_LRS' } ConvertTo-CloudRecord -Name 'data-disk-prod-01' -Provider Azure -Region 'eastus' -Status 'Attached' -Size '512 GB' -CreatedAt ([datetime]'2024-10-01') -Metadata @{ ResourceGroup = 'prod-rg'; DiskSizeGB = 512; OsType = $null; Sku = 'Premium_LRS' } ConvertTo-CloudRecord -Name 'db-server-01_OsDisk_1' -Provider Azure -Region 'eastus2' -Status 'Unattached' -Size '256 GB' -CreatedAt ([datetime]'2024-10-15') -Metadata @{ ResourceGroup = 'prod-rg'; DiskSizeGB = 256; OsType = 'Windows'; Sku = 'Premium_LRS' } } Set-Item -Path 'Function:Get-AWSDiskData' -Value { param([string]$Region) ConvertTo-CloudRecord -Name 'prod-web-root' -Provider AWS -Region 'us-east-1a' -Status 'in-use' -Size '100 GB' -CreatedAt ([datetime]'2024-11-01') -Metadata @{ VolumeId = 'vol-0a1b2c3d00000001'; VolumeType = 'gp3'; Encrypted = $true; InstanceId = 'i-0a1b2c3d4e5f00001' } ConvertTo-CloudRecord -Name 'prod-api-root' -Provider AWS -Region 'us-east-1b' -Status 'in-use' -Size '100 GB' -CreatedAt ([datetime]'2024-11-01') -Metadata @{ VolumeId = 'vol-0a1b2c3d00000002'; VolumeType = 'gp3'; Encrypted = $true; InstanceId = 'i-0a1b2c3d4e5f00002' } ConvertTo-CloudRecord -Name 'prod-data-store' -Provider AWS -Region 'us-east-1a' -Status 'in-use' -Size '500 GB' -CreatedAt ([datetime]'2024-10-01') -Metadata @{ VolumeId = 'vol-0a1b2c3d00000003'; VolumeType = 'io1'; Encrypted = $true; InstanceId = 'i-0a1b2c3d4e5f00001' } ConvertTo-CloudRecord -Name 'vol-0a1b2c3d00000004' -Provider AWS -Region 'us-east-1c' -Status 'available' -Size '100 GB' -CreatedAt ([datetime]'2024-10-15') -Metadata @{ VolumeId = 'vol-0a1b2c3d00000004'; VolumeType = 'gp3'; Encrypted = $false; InstanceId = $null } } Set-Item -Path 'Function:Get-GCPDiskData' -Value { param([string]$Project) ConvertTo-CloudRecord -Name 'prod-web-01' -Provider GCP -Region 'us-central1-a' -Status 'Ready' -Size '100 GB' -CreatedAt ([datetime]'2024-11-01') -Metadata @{ Project = 'contoso-prod'; Zone = 'us-central1-a'; DiskType = 'pd-balanced'; SizeGb = '100' } ConvertTo-CloudRecord -Name 'prod-api-01' -Provider GCP -Region 'us-central1-b' -Status 'Ready' -Size '100 GB' -CreatedAt ([datetime]'2024-11-01') -Metadata @{ Project = 'contoso-prod'; Zone = 'us-central1-b'; DiskType = 'pd-balanced'; SizeGb = '100' } ConvertTo-CloudRecord -Name 'prod-data-disk' -Provider GCP -Region 'us-central1-a' -Status 'Ready' -Size '500 GB' -CreatedAt ([datetime]'2024-10-01') -Metadata @{ Project = 'contoso-prod'; Zone = 'us-central1-a'; DiskType = 'pd-ssd'; SizeGb = '500' } } # ── Networks ────────────────────────────────────────────────────────────── Set-Item -Path 'Function:Get-AzureNetworkData' -Value { param([string]$ResourceGroup) ConvertTo-CloudRecord -Name 'prod-vnet' -Provider Azure -Region 'eastus' -Status 'Succeeded' -Size '10.0.0.0/16' -Metadata @{ ResourceGroup = 'prod-rg'; AddressSpace = @('10.0.0.0/16'); SubnetCount = 3 } ConvertTo-CloudRecord -Name 'dev-vnet' -Provider Azure -Region 'eastus' -Status 'Succeeded' -Size '10.1.0.0/16' -Metadata @{ ResourceGroup = 'dev-rg'; AddressSpace = @('10.1.0.0/16'); SubnetCount = 2 } } Set-Item -Path 'Function:Get-AWSNetworkData' -Value { param([string]$Region) ConvertTo-CloudRecord -Name 'prod-vpc' -Provider AWS -Region $Region -Status 'available' -Size '10.0.0.0/16' -Metadata @{ VpcId = 'vpc-0a1b2c3d4e5f0001'; IsDefault = $false; CidrBlock = '10.0.0.0/16' } ConvertTo-CloudRecord -Name 'default' -Provider AWS -Region $Region -Status 'available' -Size '172.31.0.0/16' -Metadata @{ VpcId = 'vpc-0a1b2c3d4e5f0002'; IsDefault = $true; CidrBlock = '172.31.0.0/16' } } Set-Item -Path 'Function:Get-GCPNetworkData' -Value { param([string]$Project) ConvertTo-CloudRecord -Name 'prod-network' -Provider GCP -Region 'global' -Status 'Available' -Metadata @{ Project = 'contoso-prod'; AutoCreateSubnetworks = $false; SubnetworkMode = 'custom' } ConvertTo-CloudRecord -Name 'default' -Provider GCP -Region 'global' -Status 'Available' -Metadata @{ Project = 'contoso-prod'; AutoCreateSubnetworks = $true; SubnetworkMode = 'auto' } } # ── Tags / Labels ───────────────────────────────────────────────────────── Set-Item -Path 'Function:Get-AzureTagData' -Value { param([string]$ResourceId) $name = ($ResourceId -split '/')[-1] ConvertTo-CloudRecord -Name $name -Provider Azure -Metadata @{ ResourceId = $ResourceId Tags = @{ env = 'production'; team = 'platform'; 'cost-center' = 'eng-001'; app = 'contoso-web' } } } Set-Item -Path 'Function:Get-AWSTagData' -Value { param([string]$ResourceId) ConvertTo-CloudRecord -Name $ResourceId -Provider AWS -Metadata @{ ResourceId = $ResourceId Tags = @{ Name = 'prod-web-01'; env = 'production'; team = 'platform'; 'cost-center' = 'eng-001' } } } Set-Item -Path 'Function:Get-GCPTagData' -Value { param([string]$Project, [string]$Resource) $resourceName = ($Resource -split '/')[-1] ConvertTo-CloudRecord -Name $resourceName -Provider GCP -Metadata @{ Project = if ($Project) { $Project } else { 'contoso-prod' } Resource = $Resource Labels = @{ env = 'production'; team = 'platform'; 'cost-center' = 'eng-001' } } } # ── Functions ───────────────────────────────────────────────────────────── Set-Item -Path 'Function:Get-AzureFunctionData' -Value { param([string]$ResourceGroup) ConvertTo-CloudRecord -Name 'process-orders' -Provider Azure -Region 'eastus' -Status 'Running' -Size 'dotnet' -CreatedAt ([datetime]'2024-12-01') -Metadata @{ ResourceGroup = 'prod-rg'; Runtime = 'dotnet'; RuntimeVersion = '8'; OSType = 'Linux'; Kind = 'functionapp' } ConvertTo-CloudRecord -Name 'send-notifications' -Provider Azure -Region 'eastus' -Status 'Running' -Size 'node' -CreatedAt ([datetime]'2024-12-01') -Metadata @{ ResourceGroup = 'prod-rg'; Runtime = 'node'; RuntimeVersion = '20'; OSType = 'Linux'; Kind = 'functionapp' } ConvertTo-CloudRecord -Name 'resize-images' -Provider Azure -Region 'eastus' -Status 'Running' -Size 'python' -CreatedAt ([datetime]'2025-01-10') -Metadata @{ ResourceGroup = 'prod-rg'; Runtime = 'python'; RuntimeVersion = '3.11'; OSType = 'Linux'; Kind = 'functionapp' } } Set-Item -Path 'Function:Get-AWSFunctionData' -Value { param([string]$Region) $r = if ($Region) { $Region } else { 'us-east-1' } ConvertTo-CloudRecord -Name 'ProcessOrders' -Provider AWS -Region $r -Status 'Active' -Size 'nodejs18.x' -CreatedAt ([datetime]'2024-12-01') -Metadata @{ FunctionArn = "arn:aws:lambda:${r}:123456789012:function:ProcessOrders"; Runtime = 'nodejs18.x'; Handler = 'index.handler'; MemorySize = 512; Timeout = 30 } ConvertTo-CloudRecord -Name 'SendNotifications' -Provider AWS -Region $r -Status 'Active' -Size 'python3.11' -CreatedAt ([datetime]'2024-12-01') -Metadata @{ FunctionArn = "arn:aws:lambda:${r}:123456789012:function:SendNotifications"; Runtime = 'python3.11'; Handler = 'main.handler'; MemorySize = 256; Timeout = 15 } ConvertTo-CloudRecord -Name 'ResizeImages' -Provider AWS -Region $r -Status 'Active' -Size 'python3.11' -CreatedAt ([datetime]'2025-01-10') -Metadata @{ FunctionArn = "arn:aws:lambda:${r}:123456789012:function:ResizeImages"; Runtime = 'python3.11'; Handler = 'resize.handler'; MemorySize = 1024; Timeout = 60 } } Set-Item -Path 'Function:Get-GCPFunctionData' -Value { param([string]$Project) $p = if ($Project) { $Project } else { 'contoso-prod' } ConvertTo-CloudRecord -Name 'process-orders' -Provider GCP -Region 'us-central1' -Status 'Active' -Size 'nodejs18' -CreatedAt ([datetime]'2024-12-01') -Metadata @{ Project = $p; Runtime = 'nodejs18'; EntryPoint = 'processOrders'; FullName = "projects/$p/locations/us-central1/functions/process-orders" } ConvertTo-CloudRecord -Name 'send-notifications' -Provider GCP -Region 'us-central1' -Status 'Active' -Size 'python311' -CreatedAt ([datetime]'2024-12-01') -Metadata @{ Project = $p; Runtime = 'python311'; EntryPoint = 'send_notifications'; FullName = "projects/$p/locations/us-central1/functions/send-notifications" } ConvertTo-CloudRecord -Name 'resize-images' -Provider GCP -Region 'us-central1' -Status 'Active' -Size 'python311' -CreatedAt ([datetime]'2025-01-10') -Metadata @{ Project = $p; Runtime = 'python311'; EntryPoint = 'resize_image'; FullName = "projects/$p/locations/us-central1/functions/resize-images" } } # ── Start / Stop ────────────────────────────────────────────────────────── Set-Item -Path 'Function:Start-AzureInstance' -Value { param([Parameter(Mandatory)][string]$Name, [Parameter(Mandatory)][string]$ResourceGroup) Start-Sleep -Milliseconds 600 ConvertTo-CloudRecord -Name $Name -Provider Azure -Status 'Starting' -Metadata @{ ResourceGroup = $ResourceGroup } } Set-Item -Path 'Function:Stop-AzureInstance' -Value { param([Parameter(Mandatory)][string]$Name, [Parameter(Mandatory)][string]$ResourceGroup) Start-Sleep -Milliseconds 600 ConvertTo-CloudRecord -Name $Name -Provider Azure -Status 'Stopping' -Metadata @{ ResourceGroup = $ResourceGroup } } Set-Item -Path 'Function:Start-AWSInstance' -Value { param([Parameter(Mandatory)][string]$InstanceId, [string]$Region) Start-Sleep -Milliseconds 600 ConvertTo-CloudRecord -Name $InstanceId -Provider AWS -Region $Region -Status 'Starting' -Metadata @{ InstanceId = $InstanceId } } Set-Item -Path 'Function:Stop-AWSInstance' -Value { param([Parameter(Mandatory)][string]$InstanceId, [string]$Region) Start-Sleep -Milliseconds 600 ConvertTo-CloudRecord -Name $InstanceId -Provider AWS -Region $Region -Status 'Stopping' -Metadata @{ InstanceId = $InstanceId } } Set-Item -Path 'Function:Start-GCPInstance' -Value { param([Parameter(Mandatory)][string]$Name, [Parameter(Mandatory)][string]$Zone, [string]$Project) Start-Sleep -Milliseconds 600 ConvertTo-CloudRecord -Name $Name -Provider GCP -Region $Zone -Status 'Starting' -Metadata @{ Project = $Project; Zone = $Zone } } Set-Item -Path 'Function:Stop-GCPInstance' -Value { param([Parameter(Mandatory)][string]$Name, [Parameter(Mandatory)][string]$Zone, [string]$Project) Start-Sleep -Milliseconds 600 ConvertTo-CloudRecord -Name $Name -Provider GCP -Region $Zone -Status 'Stopping' -Metadata @{ Project = $Project; Zone = $Zone } } # ── Seed context via Connect-Cloud ─────────────────────────────────────────── # Call the real command so context is established the same way a user would. # Suppress pipeline output -- the demo presenter calls it interactively. $null = Connect-Cloud -Provider Azure, AWS, GCP }) Write-Host "PSCumulus demo mode active. All commands return simulated data." -ForegroundColor Cyan Write-Host "Demo queries: Find-UntaggedInstances, Find-StaleInstances, Show-FleetHealth, Show-CostCenterRollup, Find-OldestInstances, Invoke-AllDemoQueries" -ForegroundColor DarkCyan Write-Host "Cleanup: Remove-DemoSetup [-Uninstall]" -ForegroundColor DarkCyan # ── Demo query functions ─────────────────────────────────────────────────────── # Pre-built queries for the talk. Each can be called individually or run all # at once with Invoke-AllDemoQueries. function Find-UntaggedInstances { # Tagging compliance -- instances missing a required owner tag Get-CloudInstance -All | Where-Object { -not $_.Tags['owner'] } } function Find-StaleInstances { # Cost waste candidates -- stopped/terminated instances older than 30 days $cutoff = (Get-Date).AddDays(-30) Get-CloudInstance -All | Where-Object { $_.Status -ne 'Running' -and $_.CreatedAt -lt $cutoff } | Select-Object Name, Provider, Status, CreatedAt | Format-Table -AutoSize } function Show-FleetHealth { # Fleet health -- running vs not-running breakdown by provider Get-CloudInstance -All | Group-Object Provider, Status | Select-Object Name, Count | Sort-Object Count -Descending | Format-Table -AutoSize } function Show-CostCenterRollup { # Cost-center rollup -- instance count per cost center across all clouds Get-CloudInstance -All | Group-Object { $_.Tags['cost-center'] } | Select-Object Name, Count | Sort-Object Count -Descending | Format-Table -AutoSize } function Find-OldestInstances { # Legacy/forgotten VM candidates -- oldest five instances across all clouds Get-CloudInstance -All | Where-Object { $_.CreatedAt } | Sort-Object CreatedAt | Select-Object Name, Provider, Region, CreatedAt -First 5 | Format-Table -AutoSize } function Remove-DemoSetup { # Removes all demo functions, unloads the module, and optionally uninstalls it. param( [switch]$Uninstall ) $demoFunctions = @( 'Find-UntaggedInstances' 'Find-StaleInstances' 'Show-FleetHealth' 'Show-CostCenterRollup' 'Find-OldestInstances' 'Invoke-AllDemoQueries' 'Remove-DemoSetup' ) foreach ($fn in $demoFunctions) { if (Get-Item -Path "Function:$fn" -ErrorAction SilentlyContinue) { Remove-Item -Path "Function:$fn" } } Remove-Module PSCumulus -Force -ErrorAction SilentlyContinue if ($Uninstall) { Uninstall-Module PSCumulus -AllVersions -Force -ErrorAction SilentlyContinue Write-Host "PSCumulus uninstalled." -ForegroundColor Yellow } else { Write-Host "PSCumulus unloaded. Run 'Uninstall-Module PSCumulus' to remove it fully." -ForegroundColor Yellow } } function Invoke-AllDemoQueries { Write-Host "`n── Tagging compliance ──────────────────────────────────" -ForegroundColor Cyan Find-UntaggedInstances Write-Host "`n── Stale instances (stopped/terminated > 30 days) ─────" -ForegroundColor Cyan Find-StaleInstances Write-Host "`n── Fleet health ────────────────────────────────────────" -ForegroundColor Cyan Show-FleetHealth Write-Host "`n── Cost-center rollup ──────────────────────────────────" -ForegroundColor Cyan Show-CostCenterRollup Write-Host "`n── Oldest instances ────────────────────────────────────" -ForegroundColor Cyan Find-OldestInstances } |