Skip to content

Commit

Permalink
lib: move url parsing to connect package
Browse files Browse the repository at this point in the history
Moves the common URL parsing logic from the `cmd` package to the
`connect` package.

Part of #TNTP-1081
  • Loading branch information
dmyger committed Jan 20, 2025
1 parent 0d17f18 commit 9012678
Show file tree
Hide file tree
Showing 12 changed files with 280 additions and 253 deletions.
12 changes: 6 additions & 6 deletions cli/cluster/cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ type connectOpts struct {
}

// connectTarantool establishes a connection to Tarantool.
func connectTarantool(uriOpts UriOpts, connOpts connectOpts) (tarantool.Connector, error) {
addr, connectorOpts := MakeConnectOptsFromUriOpts(uriOpts)
func connectTarantool(uriOpts connect.UriOpts, connOpts connectOpts) (tarantool.Connector, error) {
addr, connectorOpts := connect.MakeConnectOptsFromUriOpts(uriOpts)
if connectorOpts.User == "" && connectorOpts.Pass == "" {
connectorOpts.User = connOpts.Username
connectorOpts.Pass = connOpts.Password
Expand All @@ -164,8 +164,8 @@ func connectTarantool(uriOpts UriOpts, connOpts connectOpts) (tarantool.Connecto
}

// connectEtcd establishes a connection to etcd.
func connectEtcd(uriOpts UriOpts, connOpts connectOpts) (*clientv3.Client, error) {
etcdOpts := MakeEtcdOptsFromUriOpts(uriOpts)
func connectEtcd(uriOpts connect.UriOpts, connOpts connectOpts) (*clientv3.Client, error) {
etcdOpts := connect.MakeEtcdOptsFromUriOpts(uriOpts)
if etcdOpts.Username == "" && etcdOpts.Password == "" {
etcdOpts.Username = connOpts.Username
etcdOpts.Password = connOpts.Password
Expand All @@ -185,7 +185,7 @@ func connectEtcd(uriOpts UriOpts, connOpts connectOpts) (*clientv3.Client, error
}

// doOnStorage determines a storage based on the opts.
func doOnStorage(connOpts connectOpts, opts UriOpts,
func doOnStorage(connOpts connectOpts, opts connect.UriOpts,
tarantoolFunc func(tarantool.Connector) error, etcdFunc func(*clientv3.Client) error) error {
etcdcli, errEtcd := connectEtcd(opts, connOpts)
if errEtcd == nil {
Expand All @@ -206,7 +206,7 @@ func createPublisherAndCollector(
publishers libcluster.DataPublisherFactory,
collectors libcluster.CollectorFactory,
connOpts connectOpts,
opts UriOpts) (libcluster.DataPublisher, libcluster.Collector, func(), error) {
opts connect.UriOpts) (libcluster.DataPublisher, libcluster.Collector, func(), error) {
prefix, key, timeout := opts.Prefix, opts.Key, opts.Timeout

var (
Expand Down
7 changes: 4 additions & 3 deletions cli/cluster/cmd/failover.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/apex/log"
"github.com/google/uuid"
libcluster "github.com/tarantool/tt/lib/cluster"
"github.com/tarantool/tt/lib/connect"
"go.etcd.io/etcd/api/v3/mvccpb"
clientv3 "go.etcd.io/etcd/client/v3"
"gopkg.in/yaml.v2"
Expand Down Expand Up @@ -63,7 +64,7 @@ type SwitchStatusCtx struct {
TaskID string
}

func makeEtcdOpts(uriOpts UriOpts) libcluster.EtcdOpts {
func makeEtcdOpts(uriOpts connect.UriOpts) libcluster.EtcdOpts {
opts := libcluster.EtcdOpts{
Endpoints: []string{uriOpts.Endpoint},
Username: uriOpts.Username,
Expand All @@ -81,7 +82,7 @@ func makeEtcdOpts(uriOpts UriOpts) libcluster.EtcdOpts {

// Switch master instance.
func Switch(uri *url.URL, switchCtx SwitchCtx) error {
uriOpts, err := ParseUriOpts(uri)
uriOpts, err := connect.ParseUriOpts(uri)
if err != nil {
return fmt.Errorf("invalid URL %q: %w", uri, err)
}
Expand Down Expand Up @@ -173,7 +174,7 @@ func Switch(uri *url.URL, switchCtx SwitchCtx) error {

// SwitchStatus shows master switching status.
func SwitchStatus(uri *url.URL, switchCtx SwitchStatusCtx) error {
uriOpts, err := ParseUriOpts(uri)
uriOpts, err := connect.ParseUriOpts(uri)
if err != nil {
return fmt.Errorf("invalid URL %q: %w", uri, err)
}
Expand Down
3 changes: 2 additions & 1 deletion cli/cluster/cmd/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"net/url"

libcluster "github.com/tarantool/tt/lib/cluster"
"github.com/tarantool/tt/lib/connect"
)

// PublishCtx contains information abould cluster publish command execution
Expand Down Expand Up @@ -33,7 +34,7 @@ type PublishCtx struct {

// PublishUri publishes a configuration to URI.
func PublishUri(publishCtx PublishCtx, uri *url.URL) error {
uriOpts, err := ParseUriOpts(uri)
uriOpts, err := connect.ParseUriOpts(uri)
if err != nil {
return fmt.Errorf("invalid URL %q: %w", uri, err)
}
Expand Down
11 changes: 6 additions & 5 deletions cli/cluster/cmd/replicaset.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/tarantool/go-tarantool"
"github.com/tarantool/tt/cli/replicaset"
libcluster "github.com/tarantool/tt/lib/cluster"
"github.com/tarantool/tt/lib/connect"
clientv3 "go.etcd.io/etcd/client/v3"
)

Expand Down Expand Up @@ -107,7 +108,7 @@ func pickPatchKey(keys []string, force bool, pathMsg string) (int, error) {
func createDataCollectorAndKeyPublisher(
collectors libcluster.DataCollectorFactory,
publishers libcluster.DataPublisherFactory,
opts UriOpts, connOpts connectOpts) (
opts connect.UriOpts, connOpts connectOpts) (
libcluster.DataCollector, replicaset.DataPublisher, func(), error) {
prefix, key, timeout := opts.Prefix, opts.Key, opts.Timeout
var (
Expand Down Expand Up @@ -154,7 +155,7 @@ func createDataCollectorAndKeyPublisher(

// Promote promotes an instance by patching the cluster config.
func Promote(uri *url.URL, ctx PromoteCtx) error {
opts, err := ParseUriOpts(uri)
opts, err := connect.ParseUriOpts(uri)
if err != nil {
return fmt.Errorf("invalid URL %q: %w", uri, err)
}
Expand Down Expand Up @@ -201,7 +202,7 @@ type DemoteCtx struct {

// Demote demotes an instance by patching the cluster config.
func Demote(uri *url.URL, ctx DemoteCtx) error {
opts, err := ParseUriOpts(uri)
opts, err := connect.ParseUriOpts(uri)
if err != nil {
return fmt.Errorf("invalid URL %q: %w", uri, err)
}
Expand Down Expand Up @@ -248,7 +249,7 @@ type ExpelCtx struct {

// Expel expels an instance by patching the cluster config.
func Expel(uri *url.URL, ctx ExpelCtx) error {
opts, err := ParseUriOpts(uri)
opts, err := connect.ParseUriOpts(uri)
if err != nil {
return fmt.Errorf("invalid URL %q: %w", uri, err)
}
Expand Down Expand Up @@ -302,7 +303,7 @@ type RolesChangeCtx struct {

// ChangeRole adds/removes a role by patching the cluster config.
func ChangeRole(uri *url.URL, ctx RolesChangeCtx, action replicaset.RolesChangerAction) error {
opts, err := ParseUriOpts(uri)
opts, err := connect.ParseUriOpts(uri)
if err != nil {
return fmt.Errorf("invalid URL %q: %w", uri, err)
}
Expand Down
3 changes: 2 additions & 1 deletion cli/cluster/cmd/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/tarantool/tt/cli/cluster"
libcluster "github.com/tarantool/tt/lib/cluster"
"github.com/tarantool/tt/lib/connect"
)

// ShowCtx contains information about cluster show command execution context.
Expand All @@ -23,7 +24,7 @@ type ShowCtx struct {

// ShowUri shows a configuration from URI.
func ShowUri(showCtx ShowCtx, uri *url.URL) error {
uriOpts, err := ParseUriOpts(uri)
uriOpts, err := connect.ParseUriOpts(uri)
if err != nil {
return fmt.Errorf("invalid URL %q: %w", uri, err)
}
Expand Down
4 changes: 2 additions & 2 deletions cli/cmd/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ You could also specify etcd/tarantool username and password with environment var
The priority of credentials:
environment variables < command flags < URL credentials.
`, float64(clustercmd.DefaultUriTimeout)/float64(time.Second),
`, float64(libconnect.DefaultUriTimeout)/float64(time.Second),
libconnect.EtcdUsernameEnv, libconnect.EtcdPasswordEnv,
libconnect.TarantoolUsernameEnv, libconnect.TarantoolPasswordEnv)
failoverUriHelp = fmt.Sprintf(
Expand Down Expand Up @@ -129,7 +129,7 @@ You could also specify etcd/tarantool username and password with environment var
The priority of credentials:
environment variables < command flags < URL credentials.
`, float64(clustercmd.DefaultUriTimeout)/float64(time.Second),
`, float64(libconnect.DefaultUriTimeout)/float64(time.Second),
libconnect.EtcdUsernameEnv, libconnect.EtcdPasswordEnv,
libconnect.TarantoolUsernameEnv, libconnect.TarantoolPasswordEnv)
)
Expand Down
23 changes: 23 additions & 0 deletions lib/connect/opts_etcd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package connect

import libcluster "github.com/tarantool/tt/lib/cluster"

// MakeEtcdOptsFromUriOpts create etcd connect options from URI options.
func MakeEtcdOptsFromUriOpts(src UriOpts) libcluster.EtcdOpts {
var endpoints []string
if src.Endpoint != "" {
endpoints = []string{src.Endpoint}
}

return libcluster.EtcdOpts{
Endpoints: endpoints,
Username: src.Username,
Password: src.Password,
KeyFile: src.KeyFile,
CertFile: src.CertFile,
CaPath: src.CaPath,
CaFile: src.CaFile,
SkipHostVerify: src.SkipHostVerify || src.SkipPeerVerify,
Timeout: src.Timeout,
}
}
91 changes: 91 additions & 0 deletions lib/connect/opts_etcd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package connect_test

import (
"testing"
"time"

"github.com/stretchr/testify/assert"
libcluster "github.com/tarantool/tt/lib/cluster"
"github.com/tarantool/tt/lib/connect"
)

func TestMakeEtcdOptsFromUriOpts(t *testing.T) {
cases := []struct {
Name string
UriOpts connect.UriOpts
Expected libcluster.EtcdOpts
}{
{
Name: "empty",
UriOpts: connect.UriOpts{},
Expected: libcluster.EtcdOpts{},
},
{
Name: "ignored",
UriOpts: connect.UriOpts{
Host: "foo",
Prefix: "foo",
Key: "bar",
Instance: "zoo",
Ciphers: "foo:bar:ciphers",
},
Expected: libcluster.EtcdOpts{},
},
{
Name: "skip_host_verify",
UriOpts: connect.UriOpts{
SkipHostVerify: true,
},
Expected: libcluster.EtcdOpts{
SkipHostVerify: true,
},
},
{
Name: "skip_peer_verify",
UriOpts: connect.UriOpts{
SkipPeerVerify: true,
},
Expected: libcluster.EtcdOpts{
SkipHostVerify: true,
},
},
{
Name: "full",
UriOpts: connect.UriOpts{
Endpoint: "foo",
Host: "host",
Prefix: "prefix",
Key: "key",
Instance: "instance",
Username: "username",
Password: "password",
KeyFile: "key_file",
CertFile: "cert_file",
CaPath: "ca_path",
CaFile: "ca_file",
SkipHostVerify: true,
SkipPeerVerify: true,
Timeout: 2 * time.Second,
},
Expected: libcluster.EtcdOpts{
Endpoints: []string{"foo"},
Username: "username",
Password: "password",
KeyFile: "key_file",
CertFile: "cert_file",
CaPath: "ca_path",
CaFile: "ca_file",
SkipHostVerify: true,
Timeout: 2 * time.Second,
},
},
}

for _, tc := range cases {
t.Run(tc.Name, func(t *testing.T) {
etcdOpts := connect.MakeEtcdOptsFromUriOpts(tc.UriOpts)

assert.Equal(t, tc.Expected, etcdOpts)
})
}
}
29 changes: 29 additions & 0 deletions lib/connect/opts_tarantool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package connect

import (
"fmt"

"github.com/tarantool/go-tarantool"
)

// MakeConnectOptsFromUriOpts create Tarantool connect options from
// URI options.
func MakeConnectOptsFromUriOpts(src UriOpts) (string, tarantool.Opts) {
opts := tarantool.Opts{
User: src.Username,
Pass: src.Password,
Ssl: tarantool.SslOpts{
KeyFile: src.KeyFile,
CertFile: src.CertFile,
CaFile: src.CaFile,
Ciphers: src.Ciphers,
},
Timeout: src.Timeout,
}

if opts.Ssl != (tarantool.SslOpts{}) {
opts.Transport = "ssl"
}

return fmt.Sprintf("tcp://%s", src.Host), opts
}
Loading

0 comments on commit 9012678

Please sign in to comment.