Skip to content

Commit

Permalink
feat: stamper (#440)
Browse files Browse the repository at this point in the history
* feat(stamp-funder): initial commit

* refactor: improve cmd package and extract stamper to pkg

* fix(operator): improve logic to use svc port

* docs: update readme.md

* feat(stamper): add stamper cmds and implement dilute

* feat: add scheduler for periodic checks

* fix(stamper): check error when dilute method invoked

* feat: add graceful shutdown

* wip: add Set and Topup

* wip: implement topup

* feat: use beekeeper cluster configuration to get nodes

* fix(stamper): unnecessary conversion

* feat: fetch block time

* feat(stamper): add topup and set calculations

* feat(funder): add periodic check

* chore: update readme.md with stamper option

* refactor(cmd): extract getStamper method

* refactor(cmd): extract withTimeoutHandler method

* feat(stamper): add batch-ids flag to filter per batchID

* fix(swap): enable use of url with path for http client

* fix(stamper): remove parallelization

* fix: calculations

* refactor(stamper): extract common functions and improve code

* fix(stamper): add missing PreRun method

* chore: add log for enable-k8s flag

* refactor(stamper): make small improvements

* chore: bump version to 0.25.0

* fix(version): format version.go file

---------

Co-authored-by: istae <[email protected]>
  • Loading branch information
gacevicljubisa and istae authored Jan 30, 2025
1 parent a02803a commit 3c7d891
Show file tree
Hide file tree
Showing 35 changed files with 1,500 additions and 328 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ RUN make binary

FROM debian:12.7-slim

ENV DEBIAN_FRONTEND noninteractive
ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y \
ca-certificates; \
Expand Down
221 changes: 192 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,28 @@
- [version](#version)
- [node-funder](#node-funder)
- [node-operator](#node-operator)
- [restart](#restart)
- [stamper](#stamper)
- [Global flags](#global-flags)
- [Public Testnet Checks](#public-testnet-checks)
- [One by one](#one-by-one)
- [All at once, sequentially](#all-at-once-sequentially)

## Introduction

**Ethereum Swarm Beekeeper** is tool used for orchestrating cluster of [Ethereum Swarm Bee](https://github.com/ethersphere/bee) and running integration tests and simulations against it in the Kubernetes.
**Ethereum Swarm Beekeeper** is an orchestration and testing tool for managing [Ethereum Swarm Bee](https://github.com/ethersphere/bee) clusters. It enables:

- **Cluster Management**: Automate creation and deletion of Bee clusters in Kubernetes.
- **Integration Checks**: Run tests (e.g., `pingpong`, `pushsync`) to validate network behavior.
- **Static Endpoints Support**: Execute checks without Kubernetes by using static Bee node endpoints.
- **Node Funding**: Automate funding Bee nodes with ETH and BZZ tokens (Kubernetes optional).
- **Dynamic Configuration**: Use flexible YAML-based configs for customizable actions.

Beekeeper simplifies managing and testing Bee nodes, whether deployed in Kubernetes or standalone environments.

## Requirements

- Kubernetes cluster (v1.19+)
- Kubernetes cluster (v1.31+)
- [Geth Swap node](https://github.com/ethersphere/helm/tree/master/charts/geth-swap)

## Installation
Expand Down Expand Up @@ -92,7 +105,10 @@ If *config-dir* is kept in a Git repo, field *config-git-repo* should point to i
Official GitHub repository with Beekeeper's configuration is **<https://github.com/ethersphere/beekeeper-config>**
NOTE: command flags can be also set through the config file
General Notes:
- command flags can be also set through the config file
- k8s client can be disabled with *enable-k8s* flag (default is true)
## Config directory
Expand Down Expand Up @@ -190,6 +206,8 @@ This setting means that pushsync check can be executed choosing *pushsync-chunks
| version | Print version number |
| node-funder | Fund (top up) Bee nodes |
| node-operator | Auto-funds (top up) Bee nodes on deployment. |
| restart | Restart Bee nodes in Kubernetes |
| stamper | Manage postage batches for nodes |
### check
Expand Down Expand Up @@ -361,22 +379,35 @@ Command **node-funder** uses <https://github.com/ethersphere/node-funder> tool t
It has following flags:

```console
--addresses strings Comma-separated list of Bee node addresses (must start with 0x). Overrides namespace and cluster name.
--geth-url string Endpoint to chain node. Required.
--cluster-name string Cluster name. Ignored if addresses or namespace are set.
--help help for node-funder
--min-native float Minimum amount of chain native coins (xDAI) nodes should have.
--min-swarm float Minimum amount of swarm tokens (xBZZ) nodes should have.
--namespace string Kubernetes namespace. Overrides cluster name if set.
--label-selector string Kubernetes label selector for filtering resources within the specified namespace. An empty string disables filtering, allowing all resources to be selected.
--timeout duration Timeout. (default 5m0s)
--wallet-key string Hex-encoded private key for the Bee node wallet. Required.
--addresses strings Comma-separated list of Bee node addresses (must start with 0x). Overrides namespace and cluster name.
--cluster-name string Name of the Beekeeper cluster to target. Ignored if a namespace is specified.
--geth-url string Endpoint to chain node. Required.
--help help for node-funder
--label-selector string Kubernetes label selector for filtering resources within the specified namespace. Use an empty string to select all resources. (default "beekeeper.ethswarm.org/node-funder=true")
--min-native float Minimum amount of chain native coins (xDAI) nodes should have.
--min-swarm float Minimum amount of swarm tokens (xBZZ) nodes should have.
--namespace string Kubernetes namespace. Overrides cluster name if set.
--periodic-check duration Periodic execution check interval.
--timeout duration Timeout. (default 5m0s)
--wallet-key string Hex-encoded private key for the Bee node wallet. Required.
```

example:
#### Fund specific addresses

```bash
beekeeper node-funder --geth-url="http://geth-swap.default.testnet.internal" --wallet-key="4663c222787e30c1994b59044aa5045377a6e79193a8ead88293926b535c722d" --namespace=default --min-swarm=180 --min-native=2.2 --log-verbosity=3
beekeeper node-funder --geth-url="http://geth-swap.default.testnet.internal" --wallet-key="4663c222787e30c1994b59044aa5045377a6e79193a8ead88293926b535c722d" --addresses=0xf176839c150e52fe30e5c2b5c648465c6fdfa532,0xebe269e07161c68a942a3a7fce6b4ed66867d6f0 --min-swarm=180 --min-native=2.2
```

#### Fund K8S namespace (use label selector to filter nodes)

```bash
beekeeper node-funder --geth-url="http://geth-swap.default.testnet.internal" --wallet-key="4663c222787e30c1994b59044aa5045377a6e79193a8ead88293926b535c722d" --namespace=default --min-swarm=180 --min-native=2.2 --label-selector="app=bee"
```

#### Fund all nodes in the cluster (beekeeper configuration)

```bash
beekeeper node-funder --geth-url="http://geth-swap.default.testnet.internal" --wallet-key="4663c222787e30c1994b59044aa5045377a6e79193a8ead88293926b535c722d" --cluster-name=default --min-swarm=180 --min-native=2.2
```

### node-operator
Expand All @@ -392,7 +423,7 @@ It has following flags:
--min-swarm float Minimum amount of swarm tokens (xBZZ) nodes should have.
--namespace string Kubernetes namespace to scan for scheduled pods.
--label-selector string Kubernetes label selector for filtering resources within the specified namespace. An empty string disables filtering, allowing all resources to be selected.
--timeout duration Timeout. Default is infinite.
--timeout duration Operation timeout (e.g., 5s, 10m, 1.5h). Default is 0, which means no timeout.
--wallet-key string Hex-encoded private key for the Bee node wallet. Required.
```

Expand Down Expand Up @@ -429,26 +460,158 @@ or
beekeeper restart -namespace=default --label-selector="app=bee" --timeout=10m
```

### stamper

Command **stamper** manage postage batches for nodes.

General Notes:

- `namespace` or `cluster-name` must be specified to locate the bee nodes.
- If both are provided, `namespace` takes precedence.
- When `namespace` is set, you can use a `label-selector` to filter specific nodes.
- Use `batch-ids` to target specific postage batches, but this is applied after finding/filtering nodes. If `batch-ids` is not provided, all batches in the filtered nodes are targeted.
- If `timeout` is set to 0 and `periodic-check` is bigger than 0, the operation will run indefinitely with periodic checks.

It has following subcommands:

- **create** - creates a postage batch for selected nodes

It has following flags:

```console
--amount uint Amount of BZZ in PLURS added that the postage batch will have. (default 100000000)
--cluster-name string Target Beekeeper cluster name.
--depth uint16 Batch depth which specifies how many chunks can be signed with the batch. It is a logarithm. Must be higher than default bucket depth (16)
--help help for create
--label-selector string Kubernetes label selector for filtering resources (use empty string for all). (default "beekeeper.ethswarm.org/node-funder=true")
--namespace string Kubernetes namespace (overrides cluster name).
--timeout duration Operation timeout (e.g., 5s, 10m, 1.5h). (default 5m0s)
```

example:

```bash
beekeeper stamper create --cluster-name=default --amount=1000 --depth=16 --timeout=5m
```

or

```bash
beekeeper stamper create --namespace=default --label-selector="app=bee" --amount=1000 --depth=16 --timeout=5m
```

- **topup** - tops up postage batch for selected nodes

It has following flags:

```console
--batch-ids strings Comma separated list of postage batch IDs to top up. If not provided, all batches are topped up.
--cluster-name string Target Beekeeper cluster name.
--geth-url string Geth URL for chain state retrieval.
--help help for topup
--label-selector string Kubernetes label selector for filtering resources (use empty string for all). (default "beekeeper.ethswarm.org/node-funder=true")
--namespace string Kubernetes namespace (overrides cluster name).
--periodic-check duration Periodic check interval. Default is 0, which means no periodic check.
--timeout duration Operation timeout (e.g., 5s, 10m, 1.5h). (default 5m0s)
--topup-to duration Duration to top up the TTL of a stamp to. (default 720h0m0s)
--ttl-threshold duration Threshold for the remaining TTL of a stamp. Actions are triggered when TTL drops below this value. (default 120h0m0s)
```

example:

```bash
beekeeper stamper topup --cluster-name=default --topup-to=720h --ttl-threshold=120h --periodic-check=1h --timeout=24h
```

or

```bash
beekeeper stamper topup --namespace=default --label-selector="app=bee" --topup-to=720h --ttl-threshold=120h --periodic-check=1h --timeout=24h
```

- **dilute** - dilutes postage batch for selected nodes

It has following flags:

```console
--batch-ids strings Comma separated list of postage batch IDs to dilute. If not provided, all batches are diluted.
--cluster-name string Target Beekeeper cluster name.
--dilution-depth uint8 Number of levels by which to increase the depth of a stamp during dilution. (default 1)
--help help for dilute
--label-selector string Kubernetes label selector for filtering resources (use empty string for all). (default "beekeeper.ethswarm.org/node-funder=true")
--namespace string Kubernetes namespace (overrides cluster name).
--periodic-check duration Periodic check interval. Default is 0, which means no periodic check.
--timeout duration Operation timeout (e.g., 5s, 10m, 1.5h). (default 5m0s)
--usage-threshold float Percentage threshold for stamp utilization. Triggers dilution when usage exceeds this value. (default 90)
```

example:

```bash
beekeeper stamper dilute --cluster-name=default --dilution-depth=1 --usage-threshold=90 --periodic-check=1h --timeout=24h
```

or

```bash
beekeeper stamper dilute --namespace=default --label-selector="app=bee" --dilution-depth=1 --usage-threshold=90 --periodic-check=1h --timeout=24h
```

- **set** - sets postage batch for selected nodes

It has following flags:

```console
--batch-ids strings Comma separated list of postage batch IDs to set. If not provided, all batches are set.
--cluster-name string Target Beekeeper cluster name.
--dilution-depth uint16 Number of levels by which to increase the depth of a stamp during dilution. (default 1)
--geth-url string Geth URL for chain state retrieval.
--help help for set
--label-selector string Kubernetes label selector for filtering resources (use empty string for all). (default "beekeeper.ethswarm.org/node-funder=true")
--namespace string Kubernetes namespace (overrides cluster name).
--periodic-check duration Periodic check interval. Default is 0, which means no periodic check.
--timeout duration Operation timeout (e.g., 5s, 10m, 1.5h). (default 5m0s)
--topup-to duration Duration to top up the TTL of a stamp to. (default 720h0m0s)
--ttl-threshold duration Threshold for the remaining TTL of a stamp. Actions are triggered when TTL drops below this value. (default 120h0m0s)
--usage-threshold float Percentage threshold for stamp utilization. Triggers dilution when usage exceeds this value. (default 90)
```

example:

```bash
beekeeper stamper set --cluster-name=default --dilution-depth=1 --usage-threshold=90 --ttl-threshold=120h --topup-to=720h --periodic-check=1h --timeout=24h
```

or

```bash
beekeeper stamper set --namespace=default --label-selector="app=bee" --dilution-depth=1 --usage-threshold=90 --ttl-threshold=120h --topup-to=720h --periodic-check=1h --timeout=24h
```

## Global flags

Global flags can be used with any command.

example:

```console
--config string config file (default is $HOME/.beekeeper.yaml)
--config-dir string config directory (default is $HOME/.beekeeper/)
--config-git-branch string Git branch (default "main")
--config-git-password string Git password or personal access tokens (needed for private repos)
--config-git-repo string Git repository with configurations (uses config directory when Git repo is not specified) (default "")
--config-git-username string Git username (needed for private repos)
--log-verbosity string log verbosity level 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=trace (default "info")
--loki-endpoint string loki http endpoint for pushing local logs (use http://loki.testnet.internal/loki/api/v1/push)
--tracing-enable enable tracing
--tracing-endpoint string endpoint to send tracing data (default "tempo-tempo-distributed-distributor.observability:6831")
--tracing-host string host to send tracing data
--tracing-port string port to send tracing data
--tracing-service-name string service name identifier for tracing (default "beekeeper")
--config string Path to the configuration file (default is $HOME/.beekeeper.yaml)
--config-dir string Directory for configuration files (default "C:\\Users\\ljubi\\.beekeeper")
--config-git-branch string Git branch to use for configuration files (default "main")
--config-git-dir string Directory within the Git repository containing configuration files. Defaults to the root directory (default ".")
--config-git-password string Git password or personal access token for authentication (required for private repositories)
--config-git-repo string URL of the Git repository containing configuration files (uses the config-dir if not specified)
--config-git-username string Git username for authentication (required for private repositories)
--enable-k8s Enable Kubernetes client functionality (default true)
--in-cluster Use the in-cluster Kubernetes client
--kubeconfig string Path to the kubeconfig file (default "~/.kube/config")
--log-verbosity string Log verbosity level (0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=trace) (default "info")
--loki-endpoint string HTTP endpoint for sending logs to Loki (e.g., http://loki.testnet.internal/loki/api/v1/push)
--tracing-enable Enable tracing for performance monitoring and debugging
--tracing-endpoint string Endpoint for sending tracing data, specified as host:port (default "127.0.0.1:6831")
--tracing-host string Host address for sending tracing data
--tracing-port string Port for sending tracing data
--tracing-service-name string Service name identifier used in tracing data (default "beekeeper")
```

## Public Testnet Checks
Expand Down
33 changes: 19 additions & 14 deletions cmd/beekeeper/cmd/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,38 +14,43 @@ import (
"github.com/spf13/cobra"
)

func (c *command) initCheckCmd() (err error) {
var errMissingClusterName = fmt.Errorf("cluster name not provided")

func (c *command) initCheckCmd() error {
const (
optionNameClusterName = "cluster-name"
optionNameCreateCluster = "create-cluster"
optionNameChecks = "checks"
optionNameMetricsEnabled = "metrics-enabled"
optionNameSeed = "seed"
optionNameTimeout = "timeout"
optionNameMetricsPusherAddress = "metrics-pusher-address"
// TODO: optionNameStages = "stages"
)

cmd := &cobra.Command{
Use: "check",
Short: "runs integration tests on a Bee cluster",
Long: `runs integration tests on a Bee cluster.`,
RunE: func(cmd *cobra.Command, args []string) (err error) {
RunE: func(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(cmd.Context(), c.globalConfig.GetDuration(optionNameTimeout))
defer cancel()

checks := c.globalConfig.GetStringSlice(optionNameChecks)
if len(checks) == 0 {
return fmt.Errorf("no checks provided")
}

clusterName := c.globalConfig.GetString(optionNameClusterName)
if clusterName == "" {
return errMissingClusterName
}

// set cluster config
cfgCluster, ok := c.config.Clusters[c.globalConfig.GetString(optionNameClusterName)]
cfgCluster, ok := c.config.Clusters[clusterName]
if !ok {
return fmt.Errorf("cluster %s not defined", c.globalConfig.GetString(optionNameClusterName))
return fmt.Errorf("cluster %s not defined", clusterName)
}

// setup cluster
cluster, err := c.setupCluster(ctx,
c.globalConfig.GetString(optionNameClusterName),
c.config,
c.globalConfig.GetBool(optionNameCreateCluster),
)
cluster, err := c.setupCluster(ctx, clusterName, c.globalConfig.GetBool(optionNameCreateCluster))
if err != nil {
return fmt.Errorf("cluster setup: %w", err)
}
Expand Down Expand Up @@ -88,7 +93,7 @@ func (c *command) initCheckCmd() (err error) {
}

// run checks
for _, checkName := range c.globalConfig.GetStringSlice(optionNameChecks) {
for _, checkName := range checks {
checkName = strings.TrimSpace(checkName)
// get configuration
checkConfig, ok := c.config.Checks[checkName]
Expand Down Expand Up @@ -145,7 +150,7 @@ func (c *command) initCheckCmd() (err error) {
PreRunE: c.preRunE,
}

cmd.Flags().String(optionNameClusterName, "default", "cluster name")
cmd.Flags().String(optionNameClusterName, "", "cluster name. Required")
cmd.Flags().String(optionNameMetricsPusherAddress, "pushgateway.staging.internal", "prometheus metrics pusher address")
cmd.Flags().Bool(optionNameCreateCluster, false, "creates cluster before executing checks")
cmd.Flags().StringSlice(optionNameChecks, []string{"pingpong"}, "list of checks to execute")
Expand Down
Loading

0 comments on commit 3c7d891

Please sign in to comment.