@@ -282,6 +282,9 @@ Collecting networkpolicies...
282
282
Collecting limitranges...
283
283
Collecting events...
284
284
Collecting Postgres logs...
285
+ Collecting pgBackRest logs...
286
+ Collecting Patroni logs...
287
+ Collecting pgBackRest Repo Host logs...
285
288
Collecting PostgresCluster pod logs...
286
289
Collecting monitoring pod logs...
287
290
Collecting operator pod logs...
@@ -471,6 +474,12 @@ Collecting PGO CLI logs...
471
474
writeInfo (cmd , fmt .Sprintf ("Error gathering pgBackRest DB Hosts Logs: %s" , err ))
472
475
}
473
476
477
+ // Patroni Logs that are stored on the Postgres Instances
478
+ err = gatherPatroniLogs (ctx , clientset , restConfig , namespace , clusterName , tw , cmd )
479
+ if err != nil {
480
+ writeInfo (cmd , fmt .Sprintf ("Error gathering Patroni Logs from Instance Pods: %s" , err ))
481
+ }
482
+
474
483
// All pgBackRest Logs on the Repo Host
475
484
err = gatherRepoHostLogs (ctx , clientset , restConfig , namespace , clusterName , tw , cmd )
476
485
if err != nil {
@@ -1308,6 +1317,113 @@ func gatherDbBackrestLogs(ctx context.Context,
1308
1317
return nil
1309
1318
}
1310
1319
1320
+ // gatherPatroniLogs gathers all the file-based Patroni logs on the DB instance,
1321
+ // if configured. By default, these logs will be sent to stdout and captured as
1322
+ // Pod logs instead.
1323
+ func gatherPatroniLogs (ctx context.Context ,
1324
+ clientset * kubernetes.Clientset ,
1325
+ config * rest.Config ,
1326
+ namespace string ,
1327
+ clusterName string ,
1328
+ tw * tar.Writer ,
1329
+ cmd * cobra.Command ,
1330
+ ) error {
1331
+ writeInfo (cmd , "Collecting Patroni logs..." )
1332
+
1333
+ dbPods , err := clientset .CoreV1 ().Pods (namespace ).List (ctx , metav1.ListOptions {
1334
+ LabelSelector : util .DBInstanceLabels (clusterName ),
1335
+ })
1336
+
1337
+ if err != nil {
1338
+ if apierrors .IsForbidden (err ) {
1339
+ writeInfo (cmd , err .Error ())
1340
+ return nil
1341
+ }
1342
+ return err
1343
+ }
1344
+
1345
+ if len (dbPods .Items ) == 0 {
1346
+ writeInfo (cmd , "No database instance pod found for gathering logs" )
1347
+ return nil
1348
+ }
1349
+
1350
+ writeDebug (cmd , fmt .Sprintf ("Found %d Pods\n " , len (dbPods .Items )))
1351
+
1352
+ podExec , err := util .NewPodExecutor (config )
1353
+ if err != nil {
1354
+ return err
1355
+ }
1356
+
1357
+ for _ , pod := range dbPods .Items {
1358
+ writeDebug (cmd , fmt .Sprintf ("Pod Name is %s\n " , pod .Name ))
1359
+
1360
+ exec := func (stdin io.Reader , stdout , stderr io.Writer , command ... string ,
1361
+ ) error {
1362
+ return podExec (namespace , pod .Name , util .ContainerDatabase ,
1363
+ stdin , stdout , stderr , command ... )
1364
+ }
1365
+
1366
+ // Get Patroni Log Files
1367
+ stdout , stderr , err := Executor (exec ).listPatroniLogFiles ()
1368
+
1369
+ // Depending upon the list* function above:
1370
+ // An error may happen when err is non-nil or stderr is non-empty.
1371
+ // In both cases, we want to print helpful information and continue to the
1372
+ // next iteration.
1373
+ if err != nil || stderr != "" {
1374
+
1375
+ if apierrors .IsForbidden (err ) {
1376
+ writeInfo (cmd , err .Error ())
1377
+ return nil
1378
+ }
1379
+
1380
+ writeDebug (cmd , "Error getting Patroni logs\n " )
1381
+
1382
+ if err != nil {
1383
+ writeDebug (cmd , fmt .Sprintf ("%s\n " , err .Error ()))
1384
+ }
1385
+ if stderr != "" {
1386
+ writeDebug (cmd , stderr )
1387
+ }
1388
+
1389
+ if strings .Contains (stderr , "No such file or directory" ) {
1390
+ writeDebug (cmd , "Cannot find any Patroni log files. This is acceptable in some configurations.\n " )
1391
+ }
1392
+ continue
1393
+ }
1394
+
1395
+ logFiles := strings .Split (strings .TrimSpace (stdout ), "\n " )
1396
+ for _ , logFile := range logFiles {
1397
+ writeDebug (cmd , fmt .Sprintf ("LOG FILE: %s\n " , logFile ))
1398
+ var buf bytes.Buffer
1399
+
1400
+ stdout , stderr , err := Executor (exec ).catFile (logFile )
1401
+ if err != nil {
1402
+ if apierrors .IsForbidden (err ) {
1403
+ writeInfo (cmd , err .Error ())
1404
+ // Continue and output errors for each log file
1405
+ // Allow the user to see and address all issues at once
1406
+ continue
1407
+ }
1408
+ return err
1409
+ }
1410
+
1411
+ buf .Write ([]byte (stdout ))
1412
+ if stderr != "" {
1413
+ str := fmt .Sprintf ("\n Error returned: %s\n " , stderr )
1414
+ buf .Write ([]byte (str ))
1415
+ }
1416
+
1417
+ path := clusterName + fmt .Sprintf ("/pods/%s/" , pod .Name ) + logFile
1418
+ if err := writeTar (tw , buf .Bytes (), path , cmd ); err != nil {
1419
+ return err
1420
+ }
1421
+ }
1422
+
1423
+ }
1424
+ return nil
1425
+ }
1426
+
1311
1427
// gatherRepoHostLogs gathers all the file-based pgBackRest logs on the repo host.
1312
1428
// There may not be any logs depending upon pgBackRest's log-level-file.
1313
1429
func gatherRepoHostLogs (ctx context.Context ,
0 commit comments