Skip to content

Commit 41dee21

Browse files
gacevicljubisaakrem-chabchoubnugaon
authored
refactor: introduce NodeProvider interface for unified node management (#512)
* refactor: introduce NodeProvider interface for unified node management * fix: do not check for deployment type in node-funder and improve logs * refactor: enhance restart command to utilize NodeProvider (#516) * refactor: enhance restart command to utilize NodeProvider * refactor: add deployment-type flag to restart command * docs: update restart command docs in README * refactor: simplify restart command by removing unused cluster name and namespace checks * fix: adjust node name handling for Ingress and IngressRoute nodes * fix: change Service Port type to interface{} for better handling of string and number values (temp) * lint: remove unnecessary blank line * fix: update node discovery * feat: smoke file sizes (#505) * feat: fize-sizes param for smoke * ci: file-sizes in configs * ci: file-sizes in staging * refactor: comments * refactor: backward compatibility for ContentSize * fix: comments * fix(load): use content-size for load check (#522) --------- Co-authored-by: Ljubiša Gačević <[email protected]> * refactor: add new config file and split nodes setup for create cluster (#487) * chore: add new config file and split nodes setup for create cluster * chore: update config to use latest docker image * fix: add image flag to restart cmd * refactor: add node groups support for filtering nodes * refactor: enhance Client structure to include NodeGroupName and update filtering logic for beekeeper deployments * refactor(node): improve filterClientsByNodeGroups method --------- Co-authored-by: Ljubisa Gacevic <[email protected]> Co-authored-by: nugaon <[email protected]> Co-authored-by: Ljubiša Gačević <[email protected]> * fix: minor changes * fix: use node-grups for filtering --------- Co-authored-by: Akrem Chabchoub <[email protected]> Co-authored-by: nugaon <[email protected]>
1 parent d7a92d8 commit 41dee21

File tree

20 files changed

+271
-308
lines changed

20 files changed

+271
-308
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@ beekeeper node-operator --geth-url="http://geth-swap.default.testnet.internal" -
539539

540540
### restart
541541

542-
Command **restart** restarts bee nodes in Kubernetes, with optional targeting by namespace, label selectors, and node groups.
542+
Command **restart** restarts bee nodes in Kubernetes using a unified node management interface, with optional targeting by cluster name, namespace, label selectors, and node groups.
543543

544544
It has following flags:
545545

@@ -550,6 +550,7 @@ It has following flags:
550550
--image string Container image to use when restarting pods (defaults to current image if not set).
551551
--node-groups strings Comma-separated list of node groups to target for restarts (applies to all groups if not set).
552552
--timeout duration Operation timeout (e.g., 5s, 10m, 1.5h). (default 5m0s)
553+
--deployment-type string Indicates how the cluster was deployed: 'beekeeper' or 'helm'. (default "beekeeper")
553554
```
554555

555556
example:

cmd/beekeeper/cmd/cmd.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ import (
1212
"strings"
1313
"time"
1414

15+
"github.com/ethersphere/beekeeper/pkg/bee"
1516
"github.com/ethersphere/beekeeper/pkg/config"
1617
"github.com/ethersphere/beekeeper/pkg/httpx"
1718
"github.com/ethersphere/beekeeper/pkg/k8s"
1819
"github.com/ethersphere/beekeeper/pkg/logging"
20+
"github.com/ethersphere/beekeeper/pkg/node"
1921
"github.com/ethersphere/beekeeper/pkg/scheduler"
2022
"github.com/ethersphere/beekeeper/pkg/swap"
2123
"github.com/go-git/go-billy/v5/memfs"
@@ -433,6 +435,58 @@ func (c *command) executePeriodically(ctx context.Context, action func(ctx conte
433435
return ctx.Err()
434436
}
435437

438+
func (c *command) createNodeClient(ctx context.Context, useDeploymentType bool) (*node.Client, error) {
439+
namespace := c.globalConfig.GetString(optionNameNamespace)
440+
clusterName := c.globalConfig.GetString(optionNameClusterName)
441+
442+
if clusterName == "" && namespace == "" {
443+
return nil, errors.New("either cluster name or namespace must be provided")
444+
}
445+
446+
if c.globalConfig.IsSet(optionNameNamespace) && namespace == "" {
447+
return nil, errors.New("namespace cannot be empty if set")
448+
}
449+
450+
if namespace == "" && useDeploymentType && !isValidDeploymentType(c.globalConfig.GetString(optionNameDeploymentType)) {
451+
return nil, errors.New("unsupported deployment type: must be 'beekeeper' or 'helm'")
452+
}
453+
454+
if useDeploymentType {
455+
c.log.Infof("using deployment type %s", c.globalConfig.GetString(optionNameDeploymentType))
456+
}
457+
458+
var beeClients map[string]*bee.Client
459+
460+
if clusterName != "" {
461+
cluster, err := c.setupCluster(ctx, clusterName, false)
462+
if err != nil {
463+
return nil, fmt.Errorf("setting up cluster %s: %w", clusterName, err)
464+
}
465+
466+
beeClients, err = cluster.NodesClients(ctx)
467+
if err != nil {
468+
return nil, fmt.Errorf("failed to retrieve node clients: %w", err)
469+
}
470+
471+
namespace = cluster.Namespace()
472+
}
473+
474+
nodeClient := node.New(&node.ClientConfig{
475+
Log: c.log,
476+
HTTPClient: c.httpClient,
477+
K8sClient: c.k8sClient,
478+
BeeClients: beeClients,
479+
Namespace: namespace,
480+
LabelSelector: c.globalConfig.GetString(optionNameLabelSelector),
481+
DeploymentType: node.DeploymentType(c.globalConfig.GetString(optionNameDeploymentType)),
482+
InCluster: c.globalConfig.GetBool(optionNameInCluster),
483+
UseNamespace: c.globalConfig.IsSet(optionNameNamespace),
484+
NodeGroups: c.globalConfig.GetStringSlice(optionNameNodeGroups),
485+
})
486+
487+
return nodeClient, nil
488+
}
489+
436490
func (c *command) setSwapClient() (err error) {
437491
if c.globalConfig.IsSet(optionNameGethURL) {
438492
gethUrl, err := url.Parse(c.globalConfig.GetString(optionNameGethURL))

cmd/beekeeper/cmd/node_funder.go

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -73,40 +73,33 @@ Requires --wallet-key for the funding account and --geth-url for blockchain acce
7373
})
7474
}
7575

76-
namespace := c.globalConfig.GetString(optionNameNamespace)
77-
if namespace != "" {
78-
label := c.globalConfig.GetString(optionNameLabelSelector)
79-
funderClient := nodefunder.NewClient(c.k8sClient, c.globalConfig.GetBool(optionNameInCluster), label, c.log)
76+
nodeClient, err := c.createNodeClient(ctx, false)
77+
if err != nil {
78+
return fmt.Errorf("creating node client: %w", err)
79+
}
8080

81-
cfg.Namespace = namespace
81+
if c.globalConfig.IsSet(optionNameNamespace) {
82+
cfg.Namespace = nodeClient.Namespace()
8283
return c.executePeriodically(ctx, func(ctx context.Context) error {
84+
funderClient := nodefunder.NewClient(nodeClient, c.log)
8385
return funder.Fund(ctx, cfg, funderClient, nil, logOpt)
8486
})
8587
}
8688

87-
clusterName := c.globalConfig.GetString(optionNameClusterName)
88-
if clusterName != "" {
89-
cluster, err := c.setupCluster(ctx, clusterName, false)
89+
if c.globalConfig.IsSet(optionNameClusterName) {
90+
nodes, err := nodeClient.GetNodes(ctx)
9091
if err != nil {
91-
return fmt.Errorf("setting up cluster %s: %w", clusterName, err)
92+
return fmt.Errorf("failed to retrieve nodes: %w", err)
9293
}
9394

94-
clients, err := cluster.NodesClients(ctx)
95-
if err != nil {
96-
return fmt.Errorf("failed to retrieve node clients: %w", err)
97-
}
98-
99-
for _, node := range clients {
100-
c.log.Debugf("adding node address %s", node.Name())
101-
addr, err := node.Addresses(ctx)
95+
for _, node := range nodes {
96+
addr, err := node.Client().Node.Addresses(ctx)
10297
if err != nil {
10398
return fmt.Errorf("error fetching addresses for node %s: %w", node.Name(), err)
10499
}
105100
cfg.Addresses = append(cfg.Addresses, addr.Ethereum)
106101
}
107102

108-
c.log.Infof("funding %d nodes in cluster %s", len(cfg.Addresses), clusterName)
109-
110103
return c.executePeriodically(ctx, func(ctx context.Context) error {
111104
return funder.Fund(ctx, cfg, nil, nil, logOpt)
112105
})
@@ -130,6 +123,7 @@ Requires --wallet-key for the funding account and --geth-url for blockchain acce
130123
cmd.Flags().Float64(optionNameMinNative, 0, "Minimum amount of chain native coins (xDAI) nodes should have.")
131124
cmd.Flags().Float64(optionNameMinSwarm, 0, "Minimum amount of swarm tokens (xBZZ) nodes should have.")
132125
cmd.Flags().String(optionNameLabelSelector, nodeFunderLabelSelector, "Kubernetes label selector for filtering resources within the specified namespace. Use an empty string to select all resources.")
126+
cmd.Flags().StringSlice(optionNameNodeGroups, nil, "List of node groups to target for node-funder (applies to all groups if not set). Only used with --cluster-name.")
133127
cmd.Flags().Duration(optionNameTimeout, 5*time.Minute, "Operation timeout (e.g., 5s, 10m, 1.5h).")
134128
cmd.Flags().Duration(optionNamePeriodicCheck, 0*time.Minute, "Periodic execution check interval.")
135129

cmd/beekeeper/cmd/nuke.go

Lines changed: 8 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ package cmd
22

33
import (
44
"context"
5-
"errors"
65
"fmt"
76
"time"
87

9-
"github.com/ethersphere/beekeeper/pkg/bee"
108
"github.com/ethersphere/beekeeper/pkg/node"
119
"github.com/ethersphere/beekeeper/pkg/nuker"
1210
"github.com/spf13/cobra"
@@ -28,59 +26,24 @@ func (c *command) initNukeCmd() (err error) {
2826
This command provides StatefulSet update and rollback procedures to maintain cluster stability during the nuke process, ensuring safe and coordinated resets of node state.`,
2927
RunE: func(cmd *cobra.Command, args []string) (err error) {
3028
return c.withTimeoutHandler(cmd, func(ctx context.Context) error {
31-
namespace := c.globalConfig.GetString(optionNameNamespace)
32-
clusterName := c.globalConfig.GetString(optionNameClusterName)
33-
34-
if clusterName == "" && namespace == "" {
35-
return errors.New("either cluster name or namespace must be provided")
36-
}
37-
38-
if !isValidDeploymentType(c.globalConfig.GetString(optionNameDeploymentType)) {
39-
return errors.New("unsupported deployment type: must be 'beekeeper' or 'helm'")
40-
}
41-
42-
var beeClients map[string]*bee.Client
43-
44-
if clusterName != "" {
45-
cluster, err := c.setupCluster(ctx, clusterName, false)
46-
if err != nil {
47-
return fmt.Errorf("setting up cluster %s: %w", clusterName, err)
48-
}
49-
50-
beeClients, err = cluster.NodesClients(ctx)
51-
if err != nil {
52-
return fmt.Errorf("failed to retrieve node clients: %w", err)
53-
}
54-
55-
namespace = cluster.Namespace()
29+
if !c.globalConfig.GetBool(optionNameEnableK8S) {
30+
return fmt.Errorf("kubernetes support must be enabled for nuke command")
5631
}
5732

58-
nodeClient := node.New(&node.ClientConfig{
59-
Log: c.log,
60-
HTTPClient: c.httpClient,
61-
K8sClient: c.k8sClient,
62-
BeeClients: beeClients,
63-
Namespace: namespace,
64-
LabelSelector: c.globalConfig.GetString(optionNameLabelSelector),
65-
DeploymentType: node.DeploymentType(c.globalConfig.GetString(optionNameDeploymentType)),
66-
InCluster: c.globalConfig.GetBool(optionNameInCluster),
67-
UseNamespace: c.globalConfig.IsSet(optionNameNamespace),
68-
})
69-
70-
nodes, err := nodeClient.GetNodes(ctx)
33+
nodeClient, err := c.createNodeClient(ctx, true)
7134
if err != nil {
72-
return fmt.Errorf("getting nodes: %w", err)
35+
return fmt.Errorf("creating node client: %w", err)
7336
}
7437

7538
nukerClient := nuker.New(&nuker.ClientConfig{
7639
Log: c.log,
7740
K8sClient: c.k8sClient,
78-
Nodes: nodes,
41+
NodeProvider: nodeClient,
7942
UseRandomNeighborhood: c.globalConfig.GetBool(optionNameUseRandomNeighboorhood),
8043
})
8144

82-
if err := nukerClient.Run(ctx, namespace, c.globalConfig.GetStringSlice(optionNameRestartArgs)); err != nil {
83-
return fmt.Errorf("updating Bee cluster %s: %w", clusterName, err)
45+
if err := nukerClient.Run(ctx, c.globalConfig.GetStringSlice(optionNameRestartArgs)); err != nil {
46+
return fmt.Errorf("running nuke command: %w", err)
8447
}
8548

8649
return nil
@@ -92,6 +55,7 @@ func (c *command) initNukeCmd() (err error) {
9255
cmd.Flags().String(optionNameClusterName, "", "Target Beekeeper cluster name.")
9356
cmd.Flags().StringP(optionNameNamespace, "n", "", "Kubernetes namespace (overrides cluster name).")
9457
cmd.Flags().String(optionNameLabelSelector, beeLabelSelector, "Kubernetes label selector for filtering resources when namespace is set (use empty string for all).")
58+
cmd.Flags().StringSlice(optionNameNodeGroups, nil, "List of node groups to target for nuke (applies to all groups if not set). Only used with --cluster-name.")
9559
cmd.Flags().Duration(optionNameTimeout, 30*time.Minute, "Timeout")
9660
cmd.Flags().StringSlice(optionNameRestartArgs, []string{"bee", "start", "--config=.bee.yaml"}, "Command to run in the Bee cluster, e.g. 'db,nuke,--config=.bee.yaml'")
9761
cmd.Flags().Bool(optionNameUseRandomNeighboorhood, false, "Use random neighborhood for Bee nodes (default: false)")

cmd/beekeeper/cmd/operator.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cmd
33
import (
44
"context"
55
"errors"
6+
"fmt"
67
"time"
78

89
"github.com/ethersphere/beekeeper/pkg/funder/operator"
@@ -39,6 +40,10 @@ but this can be customized with --label-selector. Runs indefinitely until manual
3940
Requires --namespace, --wallet-key, and --geth-url for operation.`,
4041
RunE: func(cmd *cobra.Command, args []string) (err error) {
4142
return c.withTimeoutHandler(cmd, func(ctx context.Context) error {
43+
if !c.globalConfig.GetBool(optionNameEnableK8S) {
44+
return fmt.Errorf("kubernetes support must be enabled for nuke command")
45+
}
46+
4247
namespace := c.globalConfig.GetString(optionNameNamespace)
4348
if namespace == "" {
4449
return errors.New("namespace not provided")

cmd/beekeeper/cmd/restart.go

Lines changed: 18 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package cmd
22

33
import (
44
"context"
5-
"errors"
65
"fmt"
76
"time"
87

@@ -12,11 +11,12 @@ import (
1211

1312
func (c *command) initRestartCmd() (err error) {
1413
const (
15-
optionNameLabelSelector = "label-selector"
16-
optionNameNamespace = "namespace"
17-
optionNameImage = "image"
18-
optionNameNodeGroups = "node-groups"
19-
optionNameTimeout = "timeout"
14+
optionNameLabelSelector = "label-selector"
15+
optionNameNamespace = "namespace"
16+
optionNameImage = "image"
17+
optionNameNodeGroups = "node-groups"
18+
optionNameTimeout = "timeout"
19+
optionNameDeploymentType = "deployment-type"
2020
)
2121

2222
cmd := &cobra.Command{
@@ -41,58 +41,35 @@ This command is useful for:
4141
4242
Requires either --cluster-name or --namespace to be specified.`,
4343
RunE: func(cmd *cobra.Command, args []string) (err error) {
44-
ctx, cancel := context.WithTimeout(cmd.Context(), c.globalConfig.GetDuration(optionNameTimeout))
45-
defer cancel()
46-
47-
clusterName := c.globalConfig.GetString(optionNameClusterName)
48-
namespace := c.globalConfig.GetString(optionNameNamespace)
49-
50-
if clusterName == "" && namespace == "" {
51-
return errors.New("either cluster name or namespace must be provided")
52-
}
53-
54-
restartClient := restart.NewClient(c.k8sClient, c.log)
55-
56-
if clusterName != "" {
57-
clusterConfig, ok := c.config.Clusters[clusterName]
58-
if !ok {
59-
return fmt.Errorf("cluster config %s not defined", clusterName)
44+
return c.withTimeoutHandler(cmd, func(ctx context.Context) error {
45+
if !c.globalConfig.GetBool(optionNameEnableK8S) {
46+
return fmt.Errorf("kubernetes support must be enabled for nuke command")
6047
}
6148

62-
cluster, err := c.setupCluster(ctx, clusterName, false)
49+
nodeClient, err := c.createNodeClient(ctx, true)
6350
if err != nil {
64-
return fmt.Errorf("setting up cluster %s: %w", clusterName, err)
51+
return fmt.Errorf("creating node client: %w", err)
6552
}
6653

67-
c.log.Infof("restarting cluster %s", clusterName)
54+
restartClient := restart.NewClient(nodeClient, c.k8sClient, c.log)
6855

69-
if err := restartClient.RestartCluster(ctx,
70-
cluster,
71-
clusterConfig.GetNamespace(),
72-
c.globalConfig.GetString(optionNameImage),
73-
c.globalConfig.GetStringSlice(optionNameNodeGroups),
74-
); err != nil {
75-
return fmt.Errorf("restarting cluster %s: %w", clusterName, err)
56+
if err := restartClient.Restart(ctx, c.globalConfig.GetString(optionNameImage)); err != nil {
57+
return fmt.Errorf("restarting pods: %w", err)
7658
}
7759

7860
return nil
79-
}
80-
81-
if err := restartClient.RestartPods(ctx, namespace, c.globalConfig.GetString(optionNameLabelSelector)); err != nil {
82-
return fmt.Errorf("restarting pods in namespace %s: %w", namespace, err)
83-
}
84-
85-
return nil
61+
})
8662
},
8763
PreRunE: c.preRunE,
8864
}
8965

9066
cmd.Flags().String(optionNameClusterName, "", "Kubernetes cluster to operate on (overrides namespace and label selector).")
9167
cmd.Flags().StringP(optionNameNamespace, "n", "", "Namespace to delete pods from (only used if cluster name is not set).")
92-
cmd.Flags().String(optionNameLabelSelector, "", "Label selector for resources in the namespace (only used with namespace).")
68+
cmd.Flags().String(optionNameLabelSelector, beeLabelSelector, "Label selector for resources in the namespace (only used with namespace).")
9369
cmd.Flags().String(optionNameImage, "", "Container image to use when restarting pods (defaults to current image if not set).")
94-
cmd.Flags().StringSlice(optionNameNodeGroups, nil, "List of node groups to target for restarts (applies to all groups if not set).")
70+
cmd.Flags().StringSlice(optionNameNodeGroups, nil, "List of node groups to target for restarts (applies to all groups if not set). Only used with --cluster-name.")
9571
cmd.Flags().Duration(optionNameTimeout, 5*time.Minute, "Operation timeout (e.g., 5s, 10m, 1.5h).")
72+
cmd.Flags().String(optionNameDeploymentType, "beekeeper", "Indicates how the cluster was deployed: 'beekeeper' or 'helm'.")
9673

9774
c.root.AddCommand(cmd)
9875

0 commit comments

Comments
 (0)