@@ -366,10 +366,6 @@ export async function deploySonataflow(namespace: string): Promise<void> {
366366 console . warn (
367367 `[deploy-sonataflow] WARNING: OS (${ osMajorMinor } ) and OSL (${ oslMajorMinor } ) major.minor versions differ — this may cause Knative API incompatibilities` ,
368368 ) ;
369- } else {
370- console . warn (
371- `[deploy-sonataflow] Operator versions: OS=${ osFullVersion || "unknown" } , OSL=${ oslFullVersion || "unknown" } ` ,
372- ) ;
373369 }
374370
375371 hardenSonataFlowPlatform ( namespace ) ;
@@ -682,28 +678,26 @@ function formatOcFailure(err: unknown): string {
682678}
683679
684680/**
685- * Best-effort diagnostics bundle for CI when `rhdh.deploy()` fails waiting for RHDH.
686- * Keep this intentionally stderr-heavy: it should only run on failure paths.
681+ * Best-effort snapshot when `rhdh.deploy()` fails (pods, hub describe/logs, recent events).
687682 */
688683export function logOrchestratorDeployFailureDiagnostics (
689684 namespace : string ,
690685) : void {
691686 const banner = ( title : string ) => {
692- console . error ( `\n===== [orchestrator-e2e diagnostics ] ${ title } =====\n` ) ;
687+ console . error ( `\n===== [orchestrator-e2e deploy failure ] ${ title } =====\n` ) ;
693688 } ;
694689
695690 const safeOc = ( args : string [ ] , timeoutMs = 120_000 ) : string | undefined => {
696691 try {
697692 return runOc ( args , timeoutMs ) ;
698693 } catch ( err ) {
699694 console . error (
700- `[orchestrator-e2e diagnostics ] oc ${ args . join ( " " ) } failed: ${ formatOcFailure ( err ) } ` ,
695+ `[orchestrator-e2e deploy failure ] oc ${ args . join ( " " ) } failed: ${ formatOcFailure ( err ) } ` ,
701696 ) ;
702697 return undefined ;
703698 }
704699 } ;
705700
706- /** Print `oc` stdout; empty string usually means “no matches” (message on stderr). */
707701 const dumpOc = ( out : string | undefined , emptyHint : string ) => {
708702 if ( out === undefined ) return ;
709703 if ( out . trim ( ) . length > 0 ) {
@@ -715,6 +709,11 @@ export function logOrchestratorDeployFailureDiagnostics(
715709
716710 banner ( `namespace=${ namespace } ` ) ;
717711
712+ dumpOc (
713+ safeOc ( [ "get" , "pods" , "-n" , namespace , "-o" , "wide" ] , 60_000 ) ,
714+ "(get pods — empty stdout)" ,
715+ ) ;
716+
718717 const hubPod = safeOc ( [
719718 "get" ,
720719 "pods" ,
@@ -724,263 +723,37 @@ export function logOrchestratorDeployFailureDiagnostics(
724723 "app.kubernetes.io/instance=redhat-developer-hub" ,
725724 "-o" ,
726725 "jsonpath={.items[0].metadata.name}" ,
727- ] ) ;
726+ ] ) ?. trim ( ) ;
728727
729728 if ( hubPod ) {
730729 banner ( `redhat-developer-hub pod describe (${ hubPod } )` ) ;
731730 dumpOc (
732731 safeOc ( [ "describe" , "pod" , "-n" , namespace , hubPod ] , 120_000 ) ,
733732 "(describe produced no stdout)" ,
734733 ) ;
735-
736734 banner ( `redhat-developer-hub pod logs (${ hubPod } ) --all-containers` ) ;
737735 dumpOc (
738736 safeOc (
739- [ "logs" , "-n" , namespace , hubPod , "--all-containers" , "--tail=400 " ] ,
740- 180_000 ,
737+ [ "logs" , "-n" , namespace , hubPod , "--all-containers" , "--tail=300 " ] ,
738+ 120_000 ,
741739 ) ,
742- "(no current container logs on stdout)" ,
743- ) ;
744-
745- banner (
746- `redhat-developer-hub previous pod logs (${ hubPod } ) --all-containers` ,
740+ "(no container logs on stdout)" ,
747741 ) ;
748- try {
749- console . error (
750- runOc (
751- [
752- "logs" ,
753- "-n" ,
754- namespace ,
755- hubPod ,
756- "--all-containers" ,
757- "--previous" ,
758- "--tail=400" ,
759- ] ,
760- 180_000 ,
761- ) ,
762- ) ;
763- } catch ( err ) {
764- const msg = formatOcFailure ( err ) ;
765- if ( / B a d R e q u e s t | n o t f o u n d | n o p r e v i o u s / i. test ( msg ) ) {
766- console . error (
767- "(no previous pod/container logs — single revision or init never restarted)" ,
768- ) ;
769- } else {
770- console . error ( `previous logs unavailable: ${ msg } ` ) ;
771- }
772- }
773742 } else {
774743 banner ( "redhat-developer-hub pod not found via label selector" ) ;
775- dumpOc (
776- safeOc ( [ "get" , "pods" , "-n" , namespace , "-o" , "wide" ] , 120_000 ) ,
777- "(get pods — empty stdout)" ,
778- ) ;
779- }
780-
781- banner (
782- "SonataFlow / workflow / data-index pods (namespace-wide — label selectors vary by OSL version)" ,
783- ) ;
784- dumpOc (
785- safeOc ( [ "get" , "pods" , "-n" , namespace , "-o" , "wide" ] , 120_000 ) ,
786- "(no pods listed in namespace)" ,
787- ) ;
788-
789- banner (
790- "sonataflow workflow pods (label selectors — may be empty on some OSL builds)" ,
791- ) ;
792- dumpOc (
793- safeOc (
794- [
795- "get" ,
796- "pods" ,
797- "-n" ,
798- namespace ,
799- "-l" ,
800- "sonataflow.org/workflowName=failswitch" ,
801- "-o" ,
802- "wide" ,
803- ] ,
804- 120_000 ,
805- ) ,
806- "(no pods with sonataflow.org/workflowName=failswitch — see namespace-wide list above)" ,
807- ) ;
808- dumpOc (
809- safeOc (
810- [
811- "get" ,
812- "pods" ,
813- "-n" ,
814- namespace ,
815- "-l" ,
816- "sonataflow.org/workflowName=greeting" ,
817- "-o" ,
818- "wide" ,
819- ] ,
820- 120_000 ,
821- ) ,
822- "(no pods with sonataflow.org/workflowName=greeting — see namespace-wide list above)" ,
823- ) ;
824-
825- banner (
826- "SonataFlow CRs (oc get sonataflow … -o yaml — persistence vs operator reconcile)" ,
827- ) ;
828- for ( const workflow of WORKFLOWS ) {
829- banner ( `sonataflow/${ workflow } (full YAML)` ) ;
830- dumpOc (
831- safeOc (
832- [ "get" , "sonataflow" , workflow , "-n" , namespace , "-o" , "yaml" ] ,
833- 120_000 ,
834- ) ,
835- `(get sonataflow/${ workflow } returned empty stdout)` ,
836- ) ;
837744 }
838745
839- banner (
840- "workflow Deployments (oc describe deployment … — secret/volume mounts on pod template)" ,
746+ banner ( "recent namespace events (last 40 lines)" ) ;
747+ const events = safeOc (
748+ [ "get" , "events" , "-n" , namespace , "--sort-by=.lastTimestamp" ] ,
749+ 60_000 ,
841750 ) ;
842- for ( const workflow of WORKFLOWS ) {
843- banner ( `deployment/${ workflow } (describe)` ) ;
844- dumpOc (
845- safeOc ( [ "describe" , "deployment" , workflow , "-n" , namespace ] , 120_000 ) ,
846- `(describe deployment/${ workflow } returned empty stdout)` ,
847- ) ;
848- }
849-
850- banner (
851- "Services + Endpoints (workflow — empty endpoints => DNS ok but no ready backends)" ,
852- ) ;
853- dumpOc (
854- safeOc (
855- [ "get" , "svc" , "failswitch" , "greeting" , "-n" , namespace , "-o" , "wide" ] ,
856- 60_000 ,
857- ) ,
858- "(get svc failswitch greeting — empty stdout)" ,
859- ) ;
860- dumpOc (
861- safeOc (
862- [
863- "get" ,
864- "endpoints" ,
865- "failswitch" ,
866- "greeting" ,
867- "-n" ,
868- namespace ,
869- "-o" ,
870- "wide" ,
871- ] ,
872- 60_000 ,
873- ) ,
874- "(get endpoints — empty stdout)" ,
875- ) ;
876- for ( const svc of [ "failswitch" , "greeting" ] as const ) {
877- dumpOc (
878- safeOc (
879- [
880- "get" ,
881- "endpointslices.discovery.k8s.io" ,
882- "-n" ,
883- namespace ,
884- "-l" ,
885- `kubernetes.io/service-name=${ svc } ` ,
886- "-o" ,
887- "wide" ,
888- ] ,
889- 60_000 ,
890- ) ,
891- `(no EndpointSlices for service ${ svc } — empty stdout)` ,
892- ) ;
893- }
894-
895- banner ( "NetworkPolicy (can block pod-to-pod traffic to workflow Services)" ) ;
896- dumpOc (
897- safeOc ( [ "get" , "networkpolicy" , "-n" , namespace , "-o" , "wide" ] , 60_000 ) ,
898- "(no NetworkPolicies in namespace)" ,
899- ) ;
900-
901- banner (
902- "Postgres-related Secrets (existence only — compare to Deployment volume/env refs)" ,
903- ) ;
904- banner ( "secret/backstage-psql-secret" ) ;
905- dumpOc (
906- safeOc ( [ "get" , "secret" , "backstage-psql-secret" , "-n" , namespace ] , 30_000 ) ,
907- "(get secret backstage-psql-secret — empty stdout)" ,
908- ) ;
909- banner (
910- "secret/sonataflow-psql-postgresql (upstream default; often absent in e2e)" ,
911- ) ;
912- try {
913- dumpOc (
914- runOc (
915- [ "get" , "secret" , "sonataflow-psql-postgresql" , "-n" , namespace ] ,
916- 30_000 ,
917- ) ,
918- "(secret absent — expected when workflows use backstage-psql-secret)" ,
919- ) ;
920- } catch ( err ) {
921- const msg = formatOcFailure ( err ) ;
922- if ( / N o t F o u n d / i. test ( msg ) ) {
923- console . error (
924- "(not found — expected when workflows are patched to backstage-psql-secret)" ,
925- ) ;
926- } else {
927- console . error ( `unexpected error: ${ msg } ` ) ;
928- }
929- }
930-
931- banner (
932- "ReplicaSets in namespace (workflow — multiple RS generations / stale templates)" ,
933- ) ;
934- dumpOc (
935- safeOc ( [ "get" , "rs" , "-n" , namespace , "-o" , "wide" ] , 120_000 ) ,
936- "(get rs — empty stdout)" ,
937- ) ;
938-
939- banner (
940- "SonataFlow reconcile hints (generation / observedGeneration when present)" ,
941- ) ;
942- for ( const workflow of WORKFLOWS ) {
943- banner ( `sonataflow/${ workflow } (generation line)` ) ;
944- const gen = safeOc (
945- [
946- "get" ,
947- "sonataflow" ,
948- workflow ,
949- "-n" ,
950- namespace ,
951- "-o" ,
952- "jsonpath={.metadata.generation}" ,
953- ] ,
954- 30_000 ,
955- ) ;
956- if ( gen !== undefined ) {
957- console . error ( ` metadata.generation=${ gen . trim ( ) } ` ) ;
958- }
959- const observed = safeOc (
960- [
961- "get" ,
962- "sonataflow" ,
963- workflow ,
964- "-n" ,
965- namespace ,
966- "-o" ,
967- "jsonpath={.status.observedGeneration}" ,
968- ] ,
969- 30_000 ,
970- ) ;
971- if ( observed !== undefined && observed . trim ( ) !== "" ) {
972- console . error ( ` status.observedGeneration=${ observed . trim ( ) } ` ) ;
973- }
751+ if ( events ?. trim ( ) ) {
752+ const lines = events . trim ( ) . split ( "\n" ) ;
753+ console . error ( lines . slice ( - 40 ) . join ( "\n" ) ) ;
754+ } else {
755+ console . error ( "(no events or oc get events failed)" ) ;
974756 }
975-
976- banner ( "recent namespace warnings/errors (last 200 events)" ) ;
977- dumpOc (
978- safeOc (
979- [ "get" , "events" , "-n" , namespace , "--sort-by=.lastTimestamp" ] ,
980- 120_000 ,
981- ) ,
982- "(get events — empty stdout)" ,
983- ) ;
984757}
985758
986759function detectOperatorVersion ( ...labels : string [ ] ) : string {
0 commit comments