diff --git a/cmd/varlogadm/cli.go b/cmd/varlogadm/cli.go index f36267bad..a9edb2218 100644 --- a/cmd/varlogadm/cli.go +++ b/cmd/varlogadm/cli.go @@ -40,6 +40,7 @@ func newStartCommand() *cli.Command { flagLogStreamGCTimeout.DurationFlag(false, admin.DefaultLogStreamGCTimeout), flagDisableAutoLogStreamSync.BoolFlag(), flagAutoUnseal.BoolFlag(), + flagReplicaSelector, flagMetadataRepository.StringSliceFlag(true, nil), flagInitMRConnRetryCount.IntFlag(false, mrmanager.DefaultInitialMRConnectRetryCount), @@ -95,10 +96,17 @@ func start(c *cli.Context) error { return err } + repfactor := c.Uint(flagReplicationFactor.Name) + repsel, err := admin.NewReplicaSelector(c.String(flagReplicaSelector.Name), mrMgr.ClusterMetadataView(), int(repfactor)) + if err != nil { + return err + } + opts := []admin.Option{ admin.WithLogger(logger), admin.WithListenAddress(c.String(flagListen.Name)), - admin.WithReplicationFactor(c.Uint(flagReplicationFactor.Name)), + admin.WithReplicationFactor(repfactor), + admin.WithReplicaSelector(repsel), admin.WithLogStreamGCTimeout(c.Duration(flagLogStreamGCTimeout.Name)), admin.WithMetadataRepositoryManager(mrMgr), admin.WithStorageNodeManager(snMgr), diff --git a/cmd/varlogadm/flags.go b/cmd/varlogadm/flags.go index 61f12ab85..3c4291d76 100644 --- a/cmd/varlogadm/flags.go +++ b/cmd/varlogadm/flags.go @@ -1,6 +1,11 @@ package main import ( + "strings" + + "github.com/urfave/cli/v2" + + "github.com/kakao/varlog/internal/admin" "github.com/kakao/varlog/internal/flags" ) @@ -30,6 +35,13 @@ var ( Aliases: []string{"enable-auto-unseal", "with-auto-unseal"}, Envs: []string{"AUTO_UNSEAL", "ENABLE_AUTO_UNSEAL", "WITH_AUTO_UNSEAL"}, } + flagReplicaSelector = &cli.StringFlag{ + Name: "replica-selector", + Aliases: []string{"repsel"}, + EnvVars: []string{"REPLICA_SELECTOR"}, + Value: admin.ReplicaSelectorNameLFU, + Usage: strings.Join([]string{admin.ReplicaSelectorNameRandom, admin.ReplicaSelectorNameLFU}, " | "), + } flagInitMRConnRetryCount = flags.FlagDesc{ Name: "init-mr-conn-retry-count", diff --git a/internal/admin/admin.go b/internal/admin/admin.go index 86db780ca..2588ee739 100644 --- a/internal/admin/admin.go +++ b/internal/admin/admin.go @@ -135,6 +135,15 @@ func (adm *Admin) Serve() error { } adm.mu.Unlock() + if ce := adm.logger.Check(zap.InfoLevel, "starting"); ce != nil { + ce.Write( + zap.String("address", adm.serverAddr), + zap.Uint("replicationFactor", adm.replicationFactor), + zap.String("replicationSelector", adm.snSelector.Name()), + zap.Duration("logStreamGCTimeout", adm.logStreamGCTimeout), + ) + } + return adm.server.Serve(lis) } diff --git a/internal/admin/config.go b/internal/admin/config.go index 4b855fada..f74b9da99 100644 --- a/internal/admin/config.go +++ b/internal/admin/config.go @@ -81,7 +81,7 @@ func (cfg config) validate() error { func (cfg *config) ensureDefault() error { if cfg.snSelector == nil { - rs, err := newReplicaSelector(replicaSelectorNameLFU, cfg.mrmgr.ClusterMetadataView(), int(cfg.replicationFactor)) + rs, err := NewReplicaSelector(ReplicaSelectorNameLFU, cfg.mrmgr.ClusterMetadataView(), int(cfg.replicationFactor)) if err != nil { return err } diff --git a/internal/admin/replica_selector.go b/internal/admin/replica_selector.go index 8baeb4de5..d2f4976db 100644 --- a/internal/admin/replica_selector.go +++ b/internal/admin/replica_selector.go @@ -31,11 +31,11 @@ type ReplicaSelector interface { } const ( - replicaSelectorNameRandom = "random" - replicaSelectorNameLFU = "lfu" // least frequently used + ReplicaSelectorNameRandom = "random" + ReplicaSelectorNameLFU = "lfu" // least frequently used ) -func newReplicaSelector(selector string, cmview mrmanager.ClusterMetadataView, repfactor int) (ReplicaSelector, error) { +func NewReplicaSelector(selector string, cmview mrmanager.ClusterMetadataView, repfactor int) (ReplicaSelector, error) { if repfactor < 1 { return nil, errors.Wrap(verrors.ErrInvalid, "replica selector: negative replication factor") } @@ -45,9 +45,9 @@ func newReplicaSelector(selector string, cmview mrmanager.ClusterMetadataView, r } switch strings.ToLower(selector) { - case replicaSelectorNameRandom: + case ReplicaSelectorNameRandom: return newRandomReplicaSelector(cmview, repfactor) - case replicaSelectorNameLFU: + case ReplicaSelectorNameLFU: return newLFUSelector(cmview, repfactor) default: return nil, fmt.Errorf("unknown selector: %s", selector) @@ -72,7 +72,7 @@ func newRandomReplicaSelector(cmview mrmanager.ClusterMetadataView, repfactor in } func (s *randomReplicaSelector) Name() string { - return replicaSelectorNameRandom + return ReplicaSelectorNameRandom } func (s *randomReplicaSelector) Select(ctx context.Context) ([]*varlogpb.ReplicaDescriptor, error) { @@ -131,7 +131,7 @@ func newLFUSelector(cmview mrmanager.ClusterMetadataView, repfactor int) (*lfuSe } func (s *lfuSelector) Name() string { - return replicaSelectorNameLFU + return ReplicaSelectorNameLFU } func (s *lfuSelector) Select(ctx context.Context) ([]*varlogpb.ReplicaDescriptor, error) { diff --git a/internal/admin/replica_selector_test.go b/internal/admin/replica_selector_test.go index 443b9ab04..15239d309 100644 --- a/internal/admin/replica_selector_test.go +++ b/internal/admin/replica_selector_test.go @@ -21,7 +21,7 @@ func TestReplicaSelector_NewUnknown(t *testing.T) { cmview := mrmanager.NewMockClusterMetadataView(ctrl) cmview.EXPECT().ClusterMetadata(gomock.Any()).Return(&varlogpb.MetadataDescriptor{}, nil).AnyTimes() - _, err := newReplicaSelector("foo", cmview, 1) + _, err := NewReplicaSelector("foo", cmview, 1) require.Error(t, err) } @@ -34,8 +34,8 @@ func TestReplicaSelector_New(t *testing.T) { cmview.EXPECT().ClusterMetadata(gomock.Any()).Return(&varlogpb.MetadataDescriptor{}, nil).AnyTimes() selectors := []string{ - replicaSelectorNameRandom, - replicaSelectorNameLFU, + ReplicaSelectorNameRandom, + ReplicaSelectorNameLFU, } tcs := []struct { name string @@ -57,7 +57,7 @@ func TestReplicaSelector_New(t *testing.T) { for _, tc := range tcs { for _, selector := range selectors { t.Run(selector+tc.name, func(t *testing.T) { - _, err := newReplicaSelector(selector, tc.cmview, tc.repfactor) + _, err := NewReplicaSelector(selector, tc.cmview, tc.repfactor) require.Error(t, err) }) } @@ -102,7 +102,7 @@ func TestReplicaSelector(t *testing.T) { tcs := []*testCase{ { name: "NotEnoughStorageNodes", - selectors: []string{replicaSelectorNameRandom, replicaSelectorNameLFU}, + selectors: []string{ReplicaSelectorNameRandom, ReplicaSelectorNameLFU}, repfactor: 1, md: &varlogpb.MetadataDescriptor{}, testf: func(t *testing.T, _ *testCase, s ReplicaSelector) { @@ -112,7 +112,7 @@ func TestReplicaSelector(t *testing.T) { }, { name: "InvalidClusterMetadataInvalidStorageNodeID", - selectors: []string{replicaSelectorNameRandom, replicaSelectorNameLFU}, + selectors: []string{ReplicaSelectorNameRandom, ReplicaSelectorNameLFU}, repfactor: 1, md: &varlogpb.MetadataDescriptor{ StorageNodes: []*varlogpb.StorageNodeDescriptor{ @@ -130,7 +130,7 @@ func TestReplicaSelector(t *testing.T) { }, { name: "InvalidClusterMetadataNoStoragePath", - selectors: []string{replicaSelectorNameRandom, replicaSelectorNameLFU}, + selectors: []string{ReplicaSelectorNameRandom, ReplicaSelectorNameLFU}, repfactor: 1, md: &varlogpb.MetadataDescriptor{ StorageNodes: []*varlogpb.StorageNodeDescriptor{ @@ -148,7 +148,7 @@ func TestReplicaSelector(t *testing.T) { }, { name: "InvalidClusterMetadataNoStorageNode", - selectors: []string{replicaSelectorNameLFU}, + selectors: []string{ReplicaSelectorNameLFU}, repfactor: 1, md: &varlogpb.MetadataDescriptor{ StorageNodes: []*varlogpb.StorageNodeDescriptor{ @@ -177,7 +177,7 @@ func TestReplicaSelector(t *testing.T) { }, { name: "InvalidClusterMetadataNoStorageNodePath", - selectors: []string{replicaSelectorNameLFU}, + selectors: []string{ReplicaSelectorNameLFU}, repfactor: 1, md: &varlogpb.MetadataDescriptor{ StorageNodes: []*varlogpb.StorageNodeDescriptor{ @@ -206,7 +206,7 @@ func TestReplicaSelector(t *testing.T) { }, { name: "Select", - selectors: []string{replicaSelectorNameRandom}, + selectors: []string{ReplicaSelectorNameRandom}, repfactor: 2, md: &varlogpb.MetadataDescriptor{ StorageNodes: []*varlogpb.StorageNodeDescriptor{ @@ -246,7 +246,7 @@ func TestReplicaSelector(t *testing.T) { }, { name: "Select", - selectors: []string{replicaSelectorNameLFU}, + selectors: []string{ReplicaSelectorNameLFU}, repfactor: 3, md: &varlogpb.MetadataDescriptor{ StorageNodes: []*varlogpb.StorageNodeDescriptor{ @@ -327,7 +327,7 @@ func TestReplicaSelector(t *testing.T) { cmview := mrmanager.NewMockClusterMetadataView(ctrl) cmview.EXPECT().ClusterMetadata(gomock.Any()).Return(tc.md, nil).AnyTimes() - s, err := newReplicaSelector(selector, cmview, tc.repfactor) + s, err := NewReplicaSelector(selector, cmview, tc.repfactor) require.NoError(t, err) require.Equal(t, selector, s.Name()) tc.testf(t, tc, s)