featurebase/ctl/common.go
Matthew Jaffee 254bacc40c remove http subpackage and bring implementations into core
remove interfaces as necessary
2022-02-03 21:04:04 -06:00

77 lines
3.4 KiB
Go

// Copyright 2021 Molecula Corp. All rights reserved.
package ctl
import (
"time"
pilosa "github.com/molecula/featurebase/v3"
"github.com/molecula/featurebase/v3/encoding/proto"
"github.com/molecula/featurebase/v3/logger"
"github.com/molecula/featurebase/v3/server"
"github.com/pkg/errors"
"github.com/spf13/pflag"
)
// CommandWithTLSSupport is the interface for commands which has TLS settings
type CommandWithTLSSupport interface {
TLSHost() string
TLSConfiguration() server.TLSConfig
Logger() logger.Logger
}
// SetTLSConfig creates common TLS flags
func SetTLSConfig(flags *pflag.FlagSet, prefix string, certificatePath *string, certificateKeyPath *string, caCertPath *string, skipVerify *bool, enableClientVerification *bool) {
flags.StringVarP(certificatePath, prefix+"tls.certificate", "", "", "TLS certificate path (usually has the .crt or .pem extension)")
flags.StringVarP(certificateKeyPath, prefix+"tls.key", "", "", "TLS certificate key path (usually has the .key extension)")
flags.StringVarP(caCertPath, prefix+"tls.ca-certificate", "", "", "TLS CA certificate path (usually has the .pem extension)")
flags.BoolVarP(skipVerify, prefix+"tls.skip-verify", "", false, "Skip TLS certificate server verification (not secure)")
flags.BoolVarP(enableClientVerification, prefix+"tls.enable-client-verification", "", false, "Enable TLS certificate client verification for incoming connections")
}
// AnyClientOption can be either pilosa.InternalClientOption or
// pilosa.ClientOption. The internal options are specific to the
// featurebase client, whereas the client options are applied to the
// Go HTTP client that gets used under the hood.
type AnyClientOption interface{}
// commandClient returns a pilosa.InternalHTTPClient for the command
func commandClient(cmd CommandWithTLSSupport, opts ...AnyClientOption) (*pilosa.InternalClient, error) {
internalopts, clientopts, err := separateOptions(opts...)
if err != nil {
return nil, errors.Wrap(err, "separating client options")
}
// we default dial timeout to 3s in commandClient, but prepend it
// to the option list so other options can override it.
clientopts = append([]pilosa.ClientOption{pilosa.ClientDialTimeoutOption(time.Second * 3)}, clientopts...)
internalopts = append([]pilosa.InternalClientOption{pilosa.WithSerializer(proto.Serializer{})}, internalopts...)
tls := cmd.TLSConfiguration()
tlsConfig, err := server.GetTLSConfig(&tls, cmd.Logger())
if err != nil {
return nil, errors.Wrap(err, "getting tls config")
}
client, err := pilosa.NewInternalClient(cmd.TLSHost(), pilosa.GetHTTPClient(tlsConfig, clientopts...), internalopts...)
if err != nil {
return nil, errors.Wrap(err, "getting internal client")
}
return client, err
}
// separateOptions splits the list of AnyClientOption into the two
// possible types.
func separateOptions(opts ...AnyClientOption) ([]pilosa.InternalClientOption, []pilosa.ClientOption, error) {
internalopts := []pilosa.InternalClientOption{}
clientopts := []pilosa.ClientOption{}
for _, opt := range opts {
if iopt, ok := opt.(pilosa.InternalClientOption); ok {
internalopts = append(internalopts, iopt)
continue
}
if copt, ok := opt.(pilosa.ClientOption); ok {
clientopts = append(clientopts, copt)
continue
}
return nil, nil, errors.Errorf("opt: %+v of type %[1]T must be an InternalClientOption or a ClientOption", opt)
}
return internalopts, clientopts, nil
}