github.com/percona/percona-xtradb-cluster-operator@v1.14.0/cmd/pitr/main.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"log"
     8  	"os"
     9  	"os/signal"
    10  	"syscall"
    11  	"time"
    12  
    13  	"github.com/percona/percona-xtradb-cluster-operator/cmd/pitr/collector"
    14  	"github.com/percona/percona-xtradb-cluster-operator/cmd/pitr/recoverer"
    15  
    16  	"github.com/caarlos0/env"
    17  )
    18  
    19  func main() {
    20  	command := "collect"
    21  	if len(os.Args) > 1 {
    22  		command = os.Args[1]
    23  	}
    24  	ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM, os.Interrupt)
    25  	defer stop()
    26  	switch command {
    27  	case "collect":
    28  		runCollector(ctx)
    29  	case "recover":
    30  		runRecoverer(ctx)
    31  	default:
    32  		fmt.Fprintf(os.Stderr, "ERROR: unknown command \"%s\".\nCommands:\n  collect - collect binlogs\n  recover - recover from binlogs\n", command)
    33  		os.Exit(1)
    34  	}
    35  }
    36  
    37  func runCollector(ctx context.Context) {
    38  	config, err := getCollectorConfig()
    39  	if err != nil {
    40  		log.Fatalln("ERROR: get config:", err)
    41  	}
    42  	c, err := collector.New(ctx, config)
    43  	if err != nil {
    44  		log.Fatalln("ERROR: new controller:", err)
    45  	}
    46  	log.Println("run binlog collector")
    47  	for {
    48  		timeout, cancel := context.WithTimeout(ctx, time.Duration(config.CollectSpanSec)*time.Second)
    49  		defer cancel()
    50  
    51  		err := c.Run(timeout)
    52  		if err != nil {
    53  			log.Fatalln("ERROR:", err)
    54  		}
    55  
    56  		t := time.NewTimer(time.Duration(config.CollectSpanSec) * time.Second)
    57  		select {
    58  		case <-ctx.Done():
    59  			log.Fatalln("ERROR:", ctx.Err().Error())
    60  		case <-t.C:
    61  			break
    62  		}
    63  	}
    64  }
    65  
    66  func runRecoverer(ctx context.Context) {
    67  	config, err := getRecovererConfig()
    68  	if err != nil {
    69  		log.Fatalln("ERROR: get recoverer config:", err)
    70  	}
    71  	c, err := recoverer.New(ctx, config)
    72  	if err != nil {
    73  		log.Fatalln("ERROR: new recoverer controller:", err)
    74  	}
    75  	log.Println("run recover")
    76  	err = c.Run(ctx)
    77  	if err != nil {
    78  		log.Fatalln("ERROR: recover:", err)
    79  	}
    80  }
    81  
    82  func getCollectorConfig() (collector.Config, error) {
    83  	cfg := collector.Config{}
    84  	err := env.Parse(&cfg)
    85  	switch cfg.StorageType {
    86  	case "s3":
    87  		if err := env.Parse(&cfg.BackupStorageS3); err != nil {
    88  			return cfg, err
    89  		}
    90  	case "azure":
    91  		if err := env.Parse(&cfg.BackupStorageAzure); err != nil {
    92  			return cfg, err
    93  		}
    94  	default:
    95  		return cfg, errors.New("unknown STORAGE_TYPE")
    96  	}
    97  
    98  	return cfg, err
    99  }
   100  
   101  func getRecovererConfig() (recoverer.Config, error) {
   102  	cfg := recoverer.Config{}
   103  	if err := env.Parse(&cfg); err != nil {
   104  		return cfg, err
   105  	}
   106  	switch cfg.StorageType {
   107  	case "s3":
   108  		if err := env.Parse(&cfg.BackupStorageS3); err != nil {
   109  			return cfg, err
   110  		}
   111  		if err := env.Parse(&cfg.BinlogStorageS3); err != nil {
   112  			return cfg, err
   113  		}
   114  	case "azure":
   115  		if err := env.Parse(&cfg.BackupStorageAzure); err != nil {
   116  			return cfg, err
   117  		}
   118  		if err := env.Parse(&cfg.BinlogStorageAzure); err != nil {
   119  			return cfg, err
   120  		}
   121  	default:
   122  		return cfg, errors.New("unknown STORAGE_TYPE")
   123  	}
   124  
   125  	return cfg, nil
   126  }