Skip to content

Commit

Permalink
cmd/storagenode: refactor main.go
Browse files Browse the repository at this point in the history
The cmd/storagenode/main.go is a big mess right now with so many
unneeded config structures initialized and shared by several
subcommands.

There are many instances where the config structure of one subcommand
is mistakenly used for another subcommand.

This changes is an attempt to clean up the main.go by moving the
subcommands to a separate `cmd_*.go` files with separate config structures
for each subcommand.

Resolves #5756

Change-Id: I85adf2439acba271c023c269739f7fa3c6d49f9d
  • Loading branch information
profclems committed Apr 6, 2023
1 parent 45a8ac7 commit 3cf8963
Show file tree
Hide file tree
Showing 14 changed files with 736 additions and 479 deletions.
52 changes: 52 additions & 0 deletions cmd/storagenode/cmd_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.

package main

import (
"os"
"path/filepath"

"github.com/spf13/cobra"

"storj.io/common/fpath"
"storj.io/private/cfgstruct"
"storj.io/private/process"
)

func newConfigCmd(f *Factory) *cobra.Command {
var cfg setupCfg

cmd := &cobra.Command{
Use: "config",
Short: "Edit config files",
RunE: func(cmd *cobra.Command, args []string) error {
setupDir, err := filepath.Abs(f.ConfDir)
if err != nil {
return err
}

cfg.SetupDir = setupDir
return cmdConfig(cmd, &cfg)
},
Annotations: map[string]string{"type": "setup"},
}

process.Bind(cmd, &cfg, f.Defaults, cfgstruct.ConfDir(f.ConfDir), cfgstruct.IdentityDir(f.IdentityDir), cfgstruct.SetupMode())

return cmd
}

func cmdConfig(cmd *cobra.Command, cfg *setupCfg) (err error) {
setupDir, err := filepath.Abs(cfg.SetupDir)
if err != nil {
return err
}
// run setup if we can't access the config file
conf := filepath.Join(setupDir, "config.yaml")
if _, err := os.Stat(conf); err != nil {
return cmdSetup(cmd, cfg)
}

return fpath.EditFile(conf)
}
44 changes: 36 additions & 8 deletions cmd/storagenode/dashboard.go → cmd/storagenode/cmd_dashboard.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2019 Storj Labs, Inc.
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.

package main
Expand All @@ -17,8 +17,10 @@ import (
"github.com/spf13/cobra"
"go.uber.org/zap"

"storj.io/common/identity"
"storj.io/common/memory"
"storj.io/common/rpc"
"storj.io/private/cfgstruct"
"storj.io/private/process"
"storj.io/private/version"
"storj.io/storj/storagenode/internalpb"
Expand All @@ -30,6 +32,29 @@ type dashboardClient struct {
conn *rpc.Conn
}

type dashboardCfg struct {
Address string `default:"127.0.0.1:7778" help:"address for dashboard service"`

UseColor bool `internal:"true"`
}

func newDashboardCmd(f *Factory) *cobra.Command {
var cfg dashboardCfg

cmd := &cobra.Command{
Use: "dashboard",
Short: "Run the dashboard",
RunE: func(cmd *cobra.Command, args []string) error {
cfg.UseColor = f.UseColor
return cmdDashboard(cmd, &cfg)
},
}

process.Bind(cmd, &cfg, cfgstruct.ConfDir(f.ConfDir), cfgstruct.IdentityDir(f.IdentityDir))

return cmd
}

func dialDashboardClient(ctx context.Context, address string) (*dashboardClient, error) {
conn, err := rpc.NewDefaultDialer(nil).DialAddressUnencrypted(ctx, address)
if err != nil {
Expand All @@ -46,17 +71,20 @@ func (dash *dashboardClient) close() error {
return dash.conn.Close()
}

func cmdDashboard(cmd *cobra.Command, args []string) (err error) {
func cmdDashboard(cmd *cobra.Command, cfg *dashboardCfg) (err error) {
ctx, _ := process.Ctx(cmd)

ident, err := runCfg.Identity.Load()
// TDDO: move to dashboardCfg to allow setting CertPath and KeyPath
var identityCfg identity.Config

ident, err := identityCfg.Load()
if err != nil {
zap.L().Fatal("Failed to load identity.", zap.Error(err))
} else {
zap.L().Info("Identity loaded.", zap.Stringer("Node ID", ident.ID))
}

client, err := dialDashboardClient(ctx, dashboardCfg.Address)
client, err := dialDashboardClient(ctx, cfg.Address)
if err != nil {
return err
}
Expand All @@ -72,7 +100,7 @@ func cmdDashboard(cmd *cobra.Command, args []string) (err error) {
return err
}

if err := printDashboard(data); err != nil {
if err := printDashboard(cfg, data); err != nil {
return err
}

Expand All @@ -81,10 +109,10 @@ func cmdDashboard(cmd *cobra.Command, args []string) (err error) {
}
}

func printDashboard(data *internalpb.DashboardResponse) error {
func printDashboard(cfg *dashboardCfg, data *internalpb.DashboardResponse) error {
clearScreen()
var warnFlag bool
color.NoColor = !useColor
color.NoColor = !cfg.UseColor

heading := color.New(color.FgGreen, color.Bold)
_, _ = heading.Printf("\nStorage Node Dashboard ( Node Version: %s )\n", version.Build.Version.String())
Expand Down Expand Up @@ -130,7 +158,7 @@ func printDashboard(data *internalpb.DashboardResponse) error {

w = tabwriter.NewWriter(color.Output, 0, 0, 1, ' ', 0)
// TODO: Get addresses from server data
fmt.Fprintf(w, "Internal\t%s\n", color.WhiteString(dashboardCfg.Address))
fmt.Fprintf(w, "Internal\t%s\n", color.WhiteString(cfg.Address))
fmt.Fprintf(w, "External\t%s\n", color.WhiteString(data.GetExternalAddress()))
// Disabling the Link to the Dashboard as its not working yet
// fmt.Fprintf(w, "Dashboard\t%s\n", color.WhiteString(data.GetDashboardAddress()))
Expand Down
103 changes: 103 additions & 0 deletions cmd/storagenode/cmd_diag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.

package main

import (
"fmt"
"os"
"path/filepath"
"sort"
"text/tabwriter"
"time"

"github.com/spf13/cobra"
"github.com/zeebo/errs"
"go.uber.org/zap"

"storj.io/common/memory"
"storj.io/common/storj"
"storj.io/private/cfgstruct"
"storj.io/private/process"
"storj.io/storj/storagenode"
"storj.io/storj/storagenode/storagenodedb"
)

type diagCfg struct {
storagenode.Config

DiagDir string `internal:"true"`
}

func newDiagCmd(f *Factory) *cobra.Command {
var diagCfg diagCfg
cmd := &cobra.Command{
Use: "diag",
Short: "Diagnostic Tool support",
RunE: func(cmd *cobra.Command, args []string) error {
diagDir, err := filepath.Abs(f.ConfDir)
if err != nil {
return err
}
diagCfg.DiagDir = diagDir
return cmdDiag(cmd, &diagCfg)
},
Annotations: map[string]string{"type": "helper"},
}

process.Bind(cmd, &diagCfg, f.Defaults, cfgstruct.ConfDir(f.ConfDir), cfgstruct.IdentityDir(f.IdentityDir))

return cmd
}

func cmdDiag(cmd *cobra.Command, cfg *diagCfg) (err error) {
ctx, _ := process.Ctx(cmd)

// check if the directory exists
_, err = os.Stat(cfg.DiagDir)
if err != nil {
fmt.Println("storage node directory doesn't exist", cfg.DiagDir)
return err
}

db, err := storagenodedb.OpenExisting(ctx, zap.L().Named("db"), cfg.DatabaseConfig())
if err != nil {
return errs.New("Error starting master database on storage node: %v", err)
}
defer func() {
err = errs.Combine(err, db.Close())
}()

summaries, err := db.Bandwidth().SummaryBySatellite(ctx, time.Time{}, time.Now())
if err != nil {
fmt.Printf("unable to get bandwidth summary: %v\n", err)
return err
}

satellites := storj.NodeIDList{}
for id := range summaries {
satellites = append(satellites, id)
}
sort.Sort(satellites)

w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', tabwriter.AlignRight|tabwriter.Debug)
defer func() { err = errs.Combine(err, w.Flush()) }()

fmt.Fprint(w, "Satellite\tTotal\tPut\tGet\tDelete\tAudit Get\tRepair Get\tRepair Put\n")

for _, id := range satellites {
summary := summaries[id]
fmt.Fprintf(w, "%v\t%v\t%v\t%v\t%v\t%v\t%v\t%v\n",
id,
memory.Size(summary.Total()),
memory.Size(summary.Put),
memory.Size(summary.Get),
memory.Size(summary.Delete),
memory.Size(summary.GetAudit),
memory.Size(summary.GetRepair),
memory.Size(summary.PutRepair),
)
}

return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,53 @@ import (
"storj.io/common/memory"
"storj.io/common/rpc"
"storj.io/common/storj"
"storj.io/private/cfgstruct"
"storj.io/private/process"
"storj.io/storj/private/date"
"storj.io/storj/private/prompt"
"storj.io/storj/storagenode"
"storj.io/storj/storagenode/internalpb"
)

type gracefulExitCfg struct {
storagenode.Config
}

func newGracefulExitInitCmd(f *Factory) *cobra.Command {
var cfg gracefulExitCfg
cmd := &cobra.Command{
Use: "exit-satellite",
Short: "Initiate graceful exit",
Long: "Initiate gracefule exit.\n" +
"The command shows the list of the available satellites that can be exited " +
"and ask for choosing one.",
RunE: func(cmd *cobra.Command, args []string) error {
return cmdGracefulExitInit(cmd, &cfg)
},
Annotations: map[string]string{"type": "helper"},
}

process.Bind(cmd, &cfg, f.Defaults, cfgstruct.ConfDir(f.ConfDir))

return cmd
}

func newGracefulExitStatusCmd(f *Factory) *cobra.Command {
var cfg gracefulExitCfg
cmd := &cobra.Command{
Use: "exit-status",
Short: "Display graceful exit status",
RunE: func(cmd *cobra.Command, args []string) error {
return cmdGracefulExitStatus(cmd, &cfg)
},
Annotations: map[string]string{"type": "helper"},
}

process.Bind(cmd, &cfg, f.Defaults, cfgstruct.ConfDir(f.ConfDir))

return cmd
}

type gracefulExitClient struct {
conn *rpc.Conn
}
Expand Down Expand Up @@ -62,10 +103,10 @@ func (client *gracefulExitClient) close() error {
return client.conn.Close()
}

func cmdGracefulExitInit(cmd *cobra.Command, args []string) error {
func cmdGracefulExitInit(cmd *cobra.Command, cfg *gracefulExitCfg) error {
ctx, _ := process.Ctx(cmd)

ident, err := runCfg.Identity.Load()
ident, err := cfg.Identity.Load()
if err != nil {
zap.L().Fatal("Failed to load identity.", zap.Error(err))
} else {
Expand All @@ -81,7 +122,7 @@ func cmdGracefulExitInit(cmd *cobra.Command, args []string) error {
return nil
}

client, err := dialGracefulExitClient(ctx, diagCfg.Server.PrivateAddress)
client, err := dialGracefulExitClient(ctx, cfg.Server.PrivateAddress)
if err != nil {
return errs.Wrap(err)
}
Expand Down Expand Up @@ -139,17 +180,17 @@ func cmdGracefulExitInit(cmd *cobra.Command, args []string) error {
return gracefulExitInit(ctx, satelliteIDs, w, client)
}

func cmdGracefulExitStatus(cmd *cobra.Command, args []string) (err error) {
func cmdGracefulExitStatus(cmd *cobra.Command, cfg *gracefulExitCfg) (err error) {
ctx, _ := process.Ctx(cmd)

ident, err := runCfg.Identity.Load()
ident, err := cfg.Identity.Load()
if err != nil {
zap.L().Fatal("Failed to load identity.", zap.Error(err))
} else {
zap.L().Info("Identity loaded.", zap.Stringer("Node ID", ident.ID))
}

client, err := dialGracefulExitClient(ctx, diagCfg.Server.PrivateAddress)
client, err := dialGracefulExitClient(ctx, cfg.Server.PrivateAddress)
if err != nil {
return errs.Wrap(err)
}
Expand Down
File renamed without changes.
Loading

1 comment on commit 3cf8963

@storjrobot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit has been mentioned on Storj Community Forum (official). There might be relevant details there:

https://forum.storj.io/t/error-dashboard-sh-v1-77-2/22374/4

Please sign in to comment.