diff options
author | Patrick Steinhardt <psteinhardt@gitlab.com> | 2021-06-11 16:20:06 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2021-06-14 12:36:24 +0300 |
commit | deea559a231d32e1892f720882023f93a0885d20 (patch) | |
tree | 1941f8be13ec8bff597fddaaa68485588f5e7ee8 | |
parent | 92ab0786cc926e7f76db513ed3ccead9c8bc1c02 (diff) |
txinfo: Remove Praefect server info
Givven that all transactional voting nowadays happens via the
backchannel ID, there is no need anymore for the old Praefect server
structure. Let's delete it.
-rw-r--r-- | internal/transaction/txinfo/server.go | 247 | ||||
-rw-r--r-- | internal/transaction/txinfo/server_test.go | 204 | ||||
-rw-r--r-- | internal/transaction/txinfo/transaction.go | 19 |
3 files changed, 0 insertions, 470 deletions
diff --git a/internal/transaction/txinfo/server.go b/internal/transaction/txinfo/server.go deleted file mode 100644 index 8e824728d..000000000 --- a/internal/transaction/txinfo/server.go +++ /dev/null @@ -1,247 +0,0 @@ -package txinfo - -import ( - "context" - "encoding/base64" - "encoding/json" - "errors" - "fmt" - "net" - "net/url" - - "gitlab.com/gitlab-org/gitaly/v14/internal/backchannel" - "gitlab.com/gitlab-org/gitaly/v14/internal/bootstrap/starter" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/config" - "google.golang.org/grpc/credentials" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/peer" -) - -const ( - // PraefectMetadataKey is the key used to store Praefect server - // information in the gRPC metadata. - PraefectMetadataKey = "gitaly-praefect-server" -) - -var ( - // ErrPraefectServerNotFound indicates the Praefect server metadata - // could not be found - ErrPraefectServerNotFound = errors.New("metadata for Praefect server not found") -) - -// PraefectServer stores parameters required to connect to a Praefect server -type PraefectServer struct { - // BackchannelID identifies the backchannel that corresponds to the Praefect server - // that sent the request and should receive the vote. This field is actually filled - // in by the Gitaly. - BackchannelID backchannel.ID `json:"backchannel_id,omitempty"` - // ListenAddr is the TCP listen address of the Praefect server - ListenAddr string `json:"listen_addr"` - // TLSListenAddr is the TCP listen address of the Praefect server with TLS support - TLSListenAddr string `json:"tls_listen_addr"` - // SocketPath is the Unix socket path of the Praefect server - SocketPath string `json:"socket_path"` - // Token is the token required to authenticate with the Praefect server - Token string `json:"token"` -} - -// PraefectFromConfig creates a Praefect server for a given configuration. -func PraefectFromConfig(conf config.Config) (*PraefectServer, error) { - praefectServer := PraefectServer{Token: conf.Auth.Token} - - addrBySchema := map[string]*string{ - starter.TCP: &praefectServer.ListenAddr, - starter.TLS: &praefectServer.TLSListenAddr, - starter.Unix: &praefectServer.SocketPath, - } - - for _, endpoint := range []struct { - schema string - addr string - }{ - {schema: starter.TCP, addr: conf.ListenAddr}, - {schema: starter.TLS, addr: conf.TLSListenAddr}, - {schema: starter.Unix, addr: conf.SocketPath}, - } { - if endpoint.addr == "" { - continue - } - - parsed, err := starter.ParseEndpoint(endpoint.addr) - if err != nil { - if !errors.Is(err, starter.ErrEmptySchema) { - return nil, err - } - parsed = starter.Config{Name: endpoint.schema, Addr: endpoint.addr} - } - - addr, err := parsed.Endpoint() - if err != nil { - return nil, fmt.Errorf("processing of %s: %w", endpoint.schema, err) - } - - *addrBySchema[endpoint.schema] = addr - } - - return &praefectServer, nil -} - -// Inject injects Praefect connection metadata into an incoming context -func (p *PraefectServer) Inject(ctx context.Context) (context.Context, error) { - serialized, err := p.serialize() - if err != nil { - return nil, err - } - - md, ok := metadata.FromIncomingContext(ctx) - if !ok { - md = metadata.New(map[string]string{}) - } else { - md = md.Copy() - } - md.Set(PraefectMetadataKey, serialized) - - return metadata.NewIncomingContext(ctx, md), nil -} - -// Resolve Praefect address based on its peer information. Depending on how -// Praefect reached out to us, we'll adjust the PraefectServer to contain -// either its Unix or TCP address. -func (p *PraefectServer) resolvePraefectAddress(peer *peer.Peer) error { - switch addr := peer.Addr.(type) { - case *net.UnixAddr: - if p.SocketPath == "" { - return errors.New("resolvePraefectAddress: got Unix peer but no socket path") - } - - p.ListenAddr = "" - p.TLSListenAddr = "" - - return nil - case *net.TCPAddr: - var authType string - if peer.AuthInfo != nil { - authType = peer.AuthInfo.AuthType() - } - - switch authType { - case "", backchannel.Insecure().Info().SecurityProtocol: - // no transport security being used - addr, err := substituteListeningWithIP(p.ListenAddr, addr.IP.String()) - if err != nil { - return fmt.Errorf("resolvePraefectAddress: for ListenAddr: %w", err) - } - - p.ListenAddr = addr - p.TLSListenAddr = "" - p.SocketPath = "" - - return nil - default: - authType := peer.AuthInfo.AuthType() - if authType != (credentials.TLSInfo{}).AuthType() { - return fmt.Errorf("resolvePraefectAddress: got TCP peer but with unknown transport security type %q", authType) - } - - addr, err := substituteListeningWithIP(p.TLSListenAddr, addr.IP.String()) - if err != nil { - return fmt.Errorf("resolvePraefectAddress: for TLSListenAddr: %w", err) - } - - p.TLSListenAddr = addr - p.ListenAddr = "" - p.SocketPath = "" - - return nil - } - default: - return fmt.Errorf("resolvePraefectAddress: unknown peer address scheme: %s", peer.Addr.Network()) - } -} - -func substituteListeningWithIP(listenAddr, ip string) (string, error) { - if listenAddr == "" { - return "", errors.New("listening address is empty") - } - - // We need to replace Praefect's IP address with the peer's - // address as the value we have is from Praefect's configuration, - // which may be a wildcard IP address ("0.0.0.0"). - listenURL, err := url.Parse(listenAddr) - if err != nil { - return "", fmt.Errorf("parse listening address %q: %w", listenAddr, err) - } - - listenURL.Host = net.JoinHostPort(ip, listenURL.Port()) - return listenURL.String(), nil -} - -// PraefectFromContext extracts `PraefectServer` from an incoming context. In -// case the metadata key is not set, the function will return `ErrPraefectServerNotFound`. -func PraefectFromContext(ctx context.Context) (*PraefectServer, error) { - md, ok := metadata.FromIncomingContext(ctx) - if !ok { - return nil, ErrPraefectServerNotFound - } - - serialized := md[PraefectMetadataKey] - if len(serialized) == 0 { - return nil, ErrPraefectServerNotFound - } - - praefect, err := praefectFromSerialized(serialized[0]) - if err != nil { - return nil, err - } - - peer, ok := peer.FromContext(ctx) - if !ok { - return nil, fmt.Errorf("PraefectFromContext: could not get peer") - } - - if err := praefect.resolvePraefectAddress(peer); err != nil { - return nil, err - } - - praefect.BackchannelID, err = backchannel.GetPeerID(ctx) - if err != nil && !errors.Is(err, backchannel.ErrNonMultiplexedConnection) { - return nil, fmt.Errorf("get peer id: %w", err) - } - - return praefect, nil -} - -func (p *PraefectServer) serialize() (string, error) { - marshalled, err := json.Marshal(p) - if err != nil { - return "", err - } - - return base64.StdEncoding.EncodeToString(marshalled), nil -} - -// praefectFromSerialized creates a Praefect server from a `serialize()`d string. -func praefectFromSerialized(serialized string) (*PraefectServer, error) { - decoded, err := base64.StdEncoding.DecodeString(serialized) - if err != nil { - return nil, err - } - - var server PraefectServer - if err := json.Unmarshal(decoded, &server); err != nil { - return nil, err - } - - return &server, nil -} - -// Address returns the address of the Praefect server which can be used to connect to it. -func (p *PraefectServer) Address() (string, error) { - for _, addr := range []string{p.SocketPath, p.TLSListenAddr, p.ListenAddr} { - if addr != "" { - return addr, nil - } - } - - return "", errors.New("no address configured") -} diff --git a/internal/transaction/txinfo/server_test.go b/internal/transaction/txinfo/server_test.go deleted file mode 100644 index 5b4356035..000000000 --- a/internal/transaction/txinfo/server_test.go +++ /dev/null @@ -1,204 +0,0 @@ -package txinfo - -import ( - "net" - "testing" - - "github.com/stretchr/testify/require" - "gitlab.com/gitlab-org/gitaly/v14/internal/backchannel" - "gitlab.com/gitlab-org/gitaly/v14/internal/praefect/config" - "gitlab.com/gitlab-org/gitaly/v14/internal/testhelper" - "google.golang.org/grpc/credentials" - "google.golang.org/grpc/peer" -) - -func muxedPeer(t testing.TB, p *peer.Peer) *peer.Peer { - t.Helper() - - authInfo := p.AuthInfo - if authInfo == nil { - var err error - _, authInfo, err = backchannel.Insecure().ServerHandshake(nil) - require.NoError(t, err) - } - - p.AuthInfo = backchannel.WithID(authInfo, 1) - return p -} - -func tcpPeer(t *testing.T, ip string, port int) *peer.Peer { - parsedAddress := net.ParseIP(ip) - require.NotNil(t, parsedAddress) - - return &peer.Peer{ - Addr: &net.TCPAddr{ - IP: parsedAddress, - Port: port, - }, - } -} - -func tlsPeer(t *testing.T, ip string, port int) *peer.Peer { - parsedAddress := net.ParseIP(ip) - require.NotNil(t, parsedAddress) - - return &peer.Peer{ - Addr: &net.TCPAddr{ - IP: parsedAddress, - Port: port, - }, - AuthInfo: credentials.TLSInfo{}, - } -} - -func unixPeer(t *testing.T, socket string) *peer.Peer { - return &peer.Peer{ - Addr: &net.UnixAddr{ - Name: socket, - }, - } -} - -func TestPraefect_InjectMetadata(t *testing.T) { - testcases := []struct { - desc string - listenAddress string - tlsListenAddress string - socketPath string - peer *peer.Peer - expectedAddress string - }{ - { - desc: "wildcard listen address", - listenAddress: "0.0.0.0:1234", - peer: tcpPeer(t, "1.2.3.4", 4321), - expectedAddress: "tcp://1.2.3.4:1234", - }, - { - desc: "explicit listen address", - listenAddress: "127.0.0.1:1234", - peer: tcpPeer(t, "1.2.3.4", 4321), - expectedAddress: "tcp://1.2.3.4:1234", - }, - { - desc: "explicit listen address with explicit prefix", - listenAddress: "tcp://127.0.0.1:1234", - peer: tcpPeer(t, "1.2.3.4", 4321), - expectedAddress: "tcp://1.2.3.4:1234", - }, - { - desc: "explicit TLS listen address", - tlsListenAddress: "127.0.0.1:1234", - peer: tlsPeer(t, "1.2.3.4", 4321), - expectedAddress: "tls://1.2.3.4:1234", - }, - { - desc: "explicit TLS listen address with explicit prefix", - tlsListenAddress: "tls://127.0.0.1:1234", - peer: tlsPeer(t, "1.2.3.4", 4321), - expectedAddress: "tls://1.2.3.4:1234", - }, - { - desc: "named host listen address", - listenAddress: "example.com:1234", - peer: tcpPeer(t, "1.2.3.4", 4321), - expectedAddress: "tcp://1.2.3.4:1234", - }, - { - desc: "named host listen address with IPv6 peer", - listenAddress: "example.com:1234", - peer: tcpPeer(t, "2001:1db8:ac10:fe01::", 4321), - expectedAddress: "tcp://[2001:1db8:ac10:fe01::]:1234", - }, - { - desc: "Unix socket path", - socketPath: "/tmp/socket", - peer: unixPeer(t, "@"), - expectedAddress: "unix:///tmp/socket", - }, - { - desc: "Unix socket path with explicit prefix", - socketPath: "unix:///tmp/socket", - peer: unixPeer(t, "@"), - expectedAddress: "unix:///tmp/socket", - }, - { - desc: "both addresses configured with TCP peer", - listenAddress: "0.0.0.0:1234", - socketPath: "/tmp/socket", - peer: tcpPeer(t, "1.2.3.4", 4321), - expectedAddress: "tcp://1.2.3.4:1234", - }, - { - desc: "both addresses configured with Unix peer", - listenAddress: "0.0.0.0:1234", - socketPath: "/tmp/socket", - peer: unixPeer(t, "@"), - expectedAddress: "unix:///tmp/socket", - }, - { - desc: "listen address with Unix peer", - listenAddress: "0.0.0.0:1234", - peer: unixPeer(t, "@"), - expectedAddress: "", - }, - { - desc: "socket path with TCP peer", - socketPath: "/tmp/socket", - peer: tcpPeer(t, "1.2.3.4", 4321), - expectedAddress: "", - }, - { - desc: "socket path with TLS peer", - socketPath: "/tmp/socket", - peer: tlsPeer(t, "1.2.3.4", 4321), - expectedAddress: "", - }, - } - - for _, tc := range testcases { - t.Run(tc.desc, func(t *testing.T) { - ctx, cancel := testhelper.Context() - defer cancel() - - cfg := config.Config{ - ListenAddr: tc.listenAddress, - TLSListenAddr: tc.tlsListenAddress, - SocketPath: tc.socketPath, - } - - for _, muxed := range []bool{false, true} { - desc := "unmuxed" - if muxed { - desc = "muxed" - } - - t.Run(desc, func(t *testing.T) { - p := tc.peer - if muxed { - p = muxedPeer(t, tc.peer) - } - - ctx = peer.NewContext(ctx, p) - - praefectServer, err := PraefectFromConfig(cfg) - require.NoError(t, err) - - ctx, err = praefectServer.Inject(ctx) - require.NoError(t, err) - - server, err := PraefectFromContext(ctx) - if tc.expectedAddress == "" { - require.Error(t, err) - } else { - require.NoError(t, err) - - address, err := server.Address() - require.NoError(t, err) - require.Equal(t, tc.expectedAddress, address) - } - }) - } - }) - } -} diff --git a/internal/transaction/txinfo/transaction.go b/internal/transaction/txinfo/transaction.go index 0661dfbd8..bfd0010c0 100644 --- a/internal/transaction/txinfo/transaction.go +++ b/internal/transaction/txinfo/transaction.go @@ -114,22 +114,3 @@ func TransactionFromContext(ctx context.Context) (Transaction, error) { return transaction, nil } - -// FromContext extracts transaction-related metadata from the given context. No error is returned in -// case no transaction was found. -func FromContext(ctx context.Context) (*Transaction, *PraefectServer, error) { - transaction, err := TransactionFromContext(ctx) - if err != nil { - if err != ErrTransactionNotFound { - return nil, nil, err - } - return nil, nil, nil - } - - praefect, err := PraefectFromContext(ctx) - if err != nil { - return nil, nil, err - } - - return &transaction, praefect, nil -} |