...

Source file src/github.com/cybertec-postgresql/pgwatch/v6/internal/cmdopts/cmdsource.go

Documentation: github.com/cybertec-postgresql/pgwatch/v6/internal/cmdopts

     1  package cmdopts
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"net/url"
     8  
     9  	"github.com/cybertec-postgresql/pgwatch/v6/internal/log"
    10  	"github.com/cybertec-postgresql/pgwatch/v6/internal/sources"
    11  )
    12  
    13  type SourceCommand struct {
    14  	owner   *Options
    15  	Ping    SourcePingCommand    `command:"ping" description:"Try to connect to configured sources, report errors if any and then exit"`
    16  	Resolve SourceResolveCommand `command:"resolve" description:"Connect to the configured source(s) and return resolved connection strings for the monitoring targets discovered"`
    17  	// PrintSQL  SourcePrintCommand `command:"print" description:"Get and print SQL for a given Source"`
    18  }
    19  
    20  func NewSourceCommand(owner *Options) *SourceCommand {
    21  	return &SourceCommand{
    22  		owner:   owner,
    23  		Ping:    SourcePingCommand{owner: owner},
    24  		Resolve: SourceResolveCommand{owner: owner},
    25  	}
    26  }
    27  
    28  type SourcePingCommand struct {
    29  	owner *Options
    30  }
    31  
    32  func (cmd *SourcePingCommand) Execute(args []string) error {
    33  	err := cmd.owner.InitSourceReader(context.Background())
    34  	if err != nil {
    35  		return err
    36  	}
    37  	srcs, err := cmd.owner.SourcesReaderWriter.GetSources()
    38  	if err != nil {
    39  		return err
    40  	}
    41  	var foundSources sources.Sources
    42  	if len(args) == 0 {
    43  		foundSources = srcs
    44  	} else {
    45  		for _, name := range args {
    46  			for _, s := range srcs {
    47  				if s.Name == name {
    48  					foundSources = append(foundSources, s)
    49  				}
    50  			}
    51  		}
    52  	}
    53  	var e error
    54  	resolver := sources.NewResolver()
    55  	for _, s := range foundSources {
    56  		switch s.Kind {
    57  		case sources.SourcePatroniDiscovery:
    58  			_, e = resolver.ResolveDatabasesFromPatroni(s)
    59  		case sources.SourcePostgresDiscovery:
    60  			_, e = resolver.ResolveDatabasesFromPostgres(s)
    61  		default:
    62  			mdb := sources.NewSourceConn(s)
    63  			// we don't want to log connection errors here, so we use a noop logger in the context
    64  			ctx := log.WithLogger(context.Background(), log.NewNoopLogger())
    65  			if e = mdb.Connect(ctx, cmd.owner.Sources); e == nil {
    66  				e = mdb.Ping(ctx)
    67  			}
    68  		}
    69  		if e != nil {
    70  			fmt.Printf("FAIL:\t%s (%s)\n", s.Name, e)
    71  		} else {
    72  			fmt.Printf("OK:\t%s\n", s.Name)
    73  		}
    74  		err = errors.Join(err, e)
    75  	}
    76  	// err here specifies execution error, not configuration error
    77  	// so we indicate it with a special exit code
    78  	// but we still return nil to indicate that the command was executed
    79  	cmd.owner.CompleteCommand(map[bool]int32{true: ExitCodeCmdError, false: ExitCodeOK}[err != nil])
    80  	return nil
    81  }
    82  
    83  type SourceResolveCommand struct {
    84  	owner *Options
    85  }
    86  
    87  func (cmd *SourceResolveCommand) Execute(args []string) error {
    88  	err := cmd.owner.InitSourceReader(context.Background())
    89  	if err != nil {
    90  		return err
    91  	}
    92  	srcs, err := cmd.owner.SourcesReaderWriter.GetSources()
    93  	if err != nil {
    94  		return err
    95  	}
    96  	var foundSources sources.Sources
    97  	if len(args) == 0 {
    98  		foundSources = srcs
    99  	} else {
   100  		for _, name := range args {
   101  			for _, s := range srcs {
   102  				if s.Name == name {
   103  					foundSources = append(foundSources, s)
   104  				}
   105  			}
   106  		}
   107  	}
   108  	conns, err := foundSources.ResolveDatabases(nil)
   109  	if err != nil {
   110  		return err
   111  	}
   112  	var connstr url.URL
   113  	connstr.Scheme = "postgresql"
   114  	for _, conn := range conns {
   115  		s, ok := conn.(*sources.DbConn)
   116  		if !ok {
   117  			continue
   118  		}
   119  		src := s.GetSource()
   120  		if src.ConnStr > "" {
   121  			fmt.Printf("%s=%s\n", src.Name, src.ConnStr)
   122  		} else {
   123  			connstr.Host = fmt.Sprintf("%s:%d", s.ConnConfig.ConnConfig.Host, s.ConnConfig.ConnConfig.Port)
   124  			connstr.User = url.UserPassword(s.ConnConfig.ConnConfig.User, s.ConnConfig.ConnConfig.Password)
   125  			connstr.Path = s.ConnConfig.ConnConfig.Database
   126  			fmt.Printf("%s=%s\n", src.Name, connstr.String())
   127  		}
   128  	}
   129  	cmd.owner.CompleteCommand(ExitCodeOK)
   130  	return nil
   131  }
   132