#!/usr/bin/env pwsh <# .SYNOPSIS Registers the locally reachable integration catalog entries for a tenant. .DESCRIPTION Uses the live Integrations API exposed by the local Docker stack to create any missing local-capable providers, then runs test and health checks for each entry so the catalog converges to a ready local lane. .PARAMETER Tenant Tenant identifier used for the catalog operations. Defaults to default; override it if your setup flow created a different tenant identifier. .PARAMETER BaseUrl Base URL for the local Integrations API. Defaults to the host-mapped integrations-web endpoint. .PARAMETER IncludeGitLab Also register the GitLab Server and GitLab CI providers. This requires authref://vault/gitlab#access-token to be populated in Vault. .PARAMETER IncludeGitLabRegistry Also register the GitLab Container Registry provider. This requires the heavy GitLab profile with registry enabled plus authref://vault/gitlab#registry-basic. .PARAMETER BootstrapGitLabSecrets When used with `-IncludeGitLab` or `-IncludeGitLabRegistry`, bootstrap or rotate the local GitLab PAT material into Vault automatically before the GitLab-backed integrations are registered. #> [CmdletBinding()] param( [string]$Tenant = 'default', [string]$BaseUrl = 'http://127.1.0.42', [switch]$IncludeGitLab, [switch]$IncludeGitLabRegistry, [switch]$BootstrapGitLabSecrets ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' $BaseUrl = $BaseUrl.TrimEnd('/') $Headers = @{ 'X-StellaOps-Tenant' = $Tenant 'X-StellaOps-Actor' = 'local-scratch-setup' } if ($BootstrapGitLabSecrets -and ($IncludeGitLab -or $IncludeGitLabRegistry)) { & (Join-Path $PSScriptRoot 'bootstrap-local-gitlab-secrets.ps1') -VerifyRegistry:$IncludeGitLabRegistry } function Invoke-IntegrationApi { param( [Parameter(Mandatory)] [ValidateSet('GET', 'POST')] [string]$Method, [Parameter(Mandatory)] [string]$Path, [object]$Body ) $invokeParameters = @{ Method = $Method Uri = "$BaseUrl$Path" Headers = $Headers TimeoutSec = 30 ErrorAction = 'Stop' } if ($null -ne $Body) { $invokeParameters['ContentType'] = 'application/json' $invokeParameters['Body'] = $Body | ConvertTo-Json -Depth 10 } return Invoke-RestMethod @invokeParameters } function Get-HealthName { param([int]$Status) switch ($Status) { 1 { return 'Healthy' } 2 { return 'Degraded' } 3 { return 'Unhealthy' } default { return 'Unknown' } } } function New-IntegrationDefinition { param( [Parameter(Mandatory)][string]$Name, [Parameter(Mandatory)][string]$Description, [Parameter(Mandatory)][int]$Type, [Parameter(Mandatory)][int]$Provider, [Parameter(Mandatory)][string]$Endpoint, [string]$AuthRefUri, [string]$OrganizationId, [hashtable]$ExtendedConfig, [string[]]$Tags ) return [ordered]@{ name = $Name description = $Description type = $Type provider = $Provider endpoint = $Endpoint authRefUri = $AuthRefUri organizationId = $OrganizationId extendedConfig = $ExtendedConfig tags = $Tags } } $definitions = @( (New-IntegrationDefinition ` -Name 'Local Harbor Fixture' ` -Description 'Local Harbor mock fixture for registry onboarding and health checks.' ` -Type 1 ` -Provider 100 ` -Endpoint 'http://harbor-fixture.stella-ops.local' ` -OrganizationId 'local-fixtures' ` -ExtendedConfig @{ scheduleType = 'manual' } ` -Tags @('local', 'scratch-setup', 'registry')), (New-IntegrationDefinition ` -Name 'Local Docker Registry' ` -Description 'Local open OCI registry for catalog and tag probe validation.' ` -Type 1 ` -Provider 104 ` -Endpoint 'http://registry.stella-ops.local:5000' ` -ExtendedConfig @{ scheduleType = 'manual' } ` -Tags @('local', 'scratch-setup', 'registry')), (New-IntegrationDefinition ` -Name 'Local Nexus Registry' ` -Description 'Local Nexus Repository Manager for registry integration checks.' ` -Type 1 ` -Provider 107 ` -Endpoint 'http://nexus.stella-ops.local:8081' ` -ExtendedConfig @{ scheduleType = 'manual' } ` -Tags @('local', 'scratch-setup', 'registry')), (New-IntegrationDefinition ` -Name 'Local GitHub App Fixture' ` -Description 'Deterministic GitHub App fixture for SCM integration checks.' ` -Type 2 ` -Provider 200 ` -Endpoint 'http://github-app-fixture.stella-ops.local' ` -OrganizationId 'local-fixtures' ` -ExtendedConfig @{ scheduleType = 'manual' } ` -Tags @('local', 'scratch-setup', 'scm')), (New-IntegrationDefinition ` -Name 'Local Gitea Server' ` -Description 'Local Gitea service for SCM connectivity and repository discovery.' ` -Type 2 ` -Provider 203 ` -Endpoint 'http://gitea.stella-ops.local:3000' ` -OrganizationId 'local' ` -ExtendedConfig @{ scheduleType = 'manual' } ` -Tags @('local', 'scratch-setup', 'scm')), (New-IntegrationDefinition ` -Name 'Local Jenkins' ` -Description 'Local Jenkins service for CI/CD integration checks.' ` -Type 3 ` -Provider 302 ` -Endpoint 'http://jenkins.stella-ops.local:8080' ` -ExtendedConfig @{ scheduleType = 'manual' } ` -Tags @('local', 'scratch-setup', 'cicd')), (New-IntegrationDefinition ` -Name 'Local eBPF Runtime Host' ` -Description 'Local runtime-host fixture exposing the eBPF agent contract.' ` -Type 5 ` -Provider 500 ` -Endpoint 'http://runtime-host-fixture.stella-ops.local' ` -ExtendedConfig @{ scheduleType = 'manual' } ` -Tags @('local', 'scratch-setup', 'runtime-host')), (New-IntegrationDefinition ` -Name 'Local StellaOps Mirror' ` -Description 'Local Concelier mirror health surface for the StellaOps mirror provider.' ` -Type 6 ` -Provider 600 ` -Endpoint 'http://concelier.stella-ops.local' ` -ExtendedConfig @{ scheduleType = 'manual' } ` -Tags @('local', 'scratch-setup', 'feed-mirror')), (New-IntegrationDefinition ` -Name 'Local NVD Mirror' ` -Description 'Local Concelier mirror health surface for the NVD mirror provider.' ` -Type 6 ` -Provider 601 ` -Endpoint 'http://concelier.stella-ops.local' ` -ExtendedConfig @{ scheduleType = 'manual' } ` -Tags @('local', 'scratch-setup', 'feed-mirror')), (New-IntegrationDefinition ` -Name 'Local OSV Mirror' ` -Description 'Local Concelier mirror health surface for the OSV mirror provider.' ` -Type 6 ` -Provider 602 ` -Endpoint 'http://concelier.stella-ops.local' ` -ExtendedConfig @{ scheduleType = 'manual' } ` -Tags @('local', 'scratch-setup', 'feed-mirror')), (New-IntegrationDefinition ` -Name 'Local Vault' ` -Description 'Local HashiCorp Vault dev server for secrets integration checks.' ` -Type 9 ` -Provider 550 ` -Endpoint 'http://vault.stella-ops.local:8200' ` -ExtendedConfig @{ scheduleType = 'manual' } ` -Tags @('local', 'scratch-setup', 'secrets')), (New-IntegrationDefinition ` -Name 'Local Consul' ` -Description 'Local Consul server for settings and service-discovery checks.' ` -Type 9 ` -Provider 551 ` -Endpoint 'http://consul.stella-ops.local:8500' ` -ExtendedConfig @{ scheduleType = 'manual' } ` -Tags @('local', 'scratch-setup', 'secrets')), (New-IntegrationDefinition ` -Name 'Local MinIO' ` -Description 'Local MinIO server for S3-compatible storage integration checks.' ` -Type 10 ` -Provider 450 ` -Endpoint 'http://minio.stella-ops.local:9000' ` -ExtendedConfig @{ scheduleType = 'manual' } ` -Tags @('local', 'scratch-setup', 'storage')) ) if ($IncludeGitLab) { $definitions += @( (New-IntegrationDefinition ` -Name 'Local GitLab Server' ` -Description 'Local GitLab server for SCM connectivity and discovery probes.' ` -Type 2 ` -Provider 201 ` -Endpoint 'http://gitlab.stella-ops.local:8929' ` -AuthRefUri 'authref://vault/gitlab#access-token' ` -ExtendedConfig @{ scheduleType = 'manual' } ` -Tags @('local', 'scratch-setup', 'scm')), (New-IntegrationDefinition ` -Name 'Local GitLab CI' ` -Description 'Local GitLab CI surface for CI/CD connectivity checks.' ` -Type 3 ` -Provider 301 ` -Endpoint 'http://gitlab.stella-ops.local:8929' ` -AuthRefUri 'authref://vault/gitlab#access-token' ` -ExtendedConfig @{ scheduleType = 'manual' } ` -Tags @('local', 'scratch-setup', 'cicd')) ) } if ($IncludeGitLabRegistry) { $definitions += New-IntegrationDefinition ` -Name 'Local GitLab Container Registry' ` -Description 'Local GitLab container registry surface. Requires authref://vault/gitlab#registry-basic.' ` -Type 1 ` -Provider 109 ` -Endpoint 'http://gitlab.stella-ops.local:5050' ` -AuthRefUri 'authref://vault/gitlab#registry-basic' ` -ExtendedConfig @{ scheduleType = 'manual' } ` -Tags @('local', 'scratch-setup', 'registry') } $existingResponse = Invoke-IntegrationApi -Method GET -Path '/api/v1/integrations?pageSize=200' $existingItems = @($existingResponse.items) $results = New-Object System.Collections.Generic.List[object] foreach ($definition in $definitions) { $match = $existingItems | Where-Object { $_.provider -eq $definition.provider -and $_.endpoint -eq $definition.endpoint } | Select-Object -First 1 if ($null -eq $match) { $created = Invoke-IntegrationApi -Method POST -Path '/api/v1/integrations/' -Body $definition $id = $created.id $action = 'created' } else { $id = $match.id $action = 'existing' } $test = Invoke-IntegrationApi -Method POST -Path "/api/v1/integrations/$id/test" $health = Invoke-IntegrationApi -Method GET -Path "/api/v1/integrations/$id/health" $results.Add([pscustomobject]@{ Name = $definition.name Provider = $definition.provider Action = $action TestSuccess = [bool]$test.success Health = Get-HealthName -Status ([int]$health.status) Endpoint = $definition.endpoint Id = "$id" }) } $results | Sort-Object Name | Format-Table Name, Action, TestSuccess, Health, Endpoint -AutoSize | Out-String | Write-Host $failures = @($results | Where-Object { -not $_.TestSuccess -or $_.Health -ne 'Healthy' }) if ($failures.Count -gt 0) { Write-Error "Local integration registration completed with $($failures.Count) failing or non-healthy entry/entries for tenant '$Tenant'." exit 1 } Write-Host "Registered and verified $($results.Count) local integration entries for tenant '$Tenant' via $BaseUrl." -ForegroundColor Green