Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Approve/Reject node membership from CLI #3594

Merged
merged 4 commits into from
Mar 15, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Add tests for node actions.
rossjones committed Mar 15, 2024
commit 37084c76b21dc823233158f12ec26d56fcf531ed
84 changes: 84 additions & 0 deletions cmd/cli/node/action_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//go:build unit || !integration

package node_test

import (
"strings"
"testing"

cmdtesting "github.com/bacalhau-project/bacalhau/cmd/testing"
"github.com/bacalhau-project/bacalhau/pkg/logger"
"github.com/bacalhau-project/bacalhau/pkg/setup"
"github.com/stretchr/testify/suite"
)

type NodeActionSuite struct {
cmdtesting.BaseNATSSuite
}

func TestNodeActionSuite(t *testing.T) {
suite.Run(t, new(NodeActionSuite))
}

func (s *NodeActionSuite) SetupSuite() {
logger.ConfigureTestLogging(s.T())
setup.SetupBacalhauRepoForTesting(s.T())
}

func (s *NodeActionSuite) TestListNodes() {
// Get default states for the test node
_, out, err := s.ExecuteTestCobraCommand(
"node",
"list",
"--output", "csv",
)
s.Require().NoError(err)

cells := getCells(out, 1)
s.Require().Equal("APPROVED", cells[2], "Expected the node to be approved")

nodeID := cells[0]

// Try to approve, expect failure
_, out, err = s.ExecuteTestCobraCommand(
"node",
"approve",
nodeID,
)
s.Require().NoError(err)
s.Require().Contains(out, "node already approved")
s.Require().Contains(out, nodeID)

// Now reject the node
_, out, err = s.ExecuteTestCobraCommand(
"node",
"reject",
nodeID,
)
s.Require().NoError(err)
s.Require().Contains(out, "Ok")

// Try to reject again - expect failure
_, out, err = s.ExecuteTestCobraCommand(
"node",
"reject",
nodeID,
)
s.Require().NoError(err)
s.Require().Contains(out, "node already rejected")

// Set it to approve again
_, out, err = s.ExecuteTestCobraCommand(
"node",
"approve",
nodeID,
)
s.Require().NoError(err)
s.Require().Contains(out, "Ok")
}

func getCells(output string, lineNo int) []string {
lines := strings.Split(output, "\n")
line := lines[lineNo]
return strings.Split(line, ",")
}
131 changes: 131 additions & 0 deletions cmd/testing/basenats.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package cmdtesting

import (
"bytes"
"context"
"fmt"
"io"
"os"
"time"

"github.com/spf13/cobra"
"golang.org/x/exp/slices"

"github.com/bacalhau-project/bacalhau/cmd/cli"
"github.com/bacalhau-project/bacalhau/cmd/util"
"github.com/bacalhau-project/bacalhau/pkg/bidstrategy/semantic"
"github.com/bacalhau-project/bacalhau/pkg/config/types"
"github.com/bacalhau-project/bacalhau/pkg/devstack"
noop_executor "github.com/bacalhau-project/bacalhau/pkg/executor/noop"
"github.com/bacalhau-project/bacalhau/pkg/logger"
"github.com/bacalhau-project/bacalhau/pkg/node"
clientv2 "github.com/bacalhau-project/bacalhau/pkg/publicapi/client/v2"
"github.com/bacalhau-project/bacalhau/pkg/test/teststack"
"github.com/stretchr/testify/suite"
)

type BaseNATSSuite struct {
suite.Suite
Node *node.Node
ClientV2 clientv2.API
Host string
Port uint16
}

// before each test
func (s *BaseNATSSuite) SetupTest() {
logger.ConfigureTestLogging(s.T())
util.Fatal = util.FakeFatalErrorHandler

computeConfig, err := node.NewComputeConfigWith(node.ComputeConfigParams{
JobSelectionPolicy: node.JobSelectionPolicy{
Locality: semantic.Anywhere,
},
LocalPublisher: types.LocalPublisherConfig{
Address: "127.0.0.1",
},
})
s.Require().NoError(err)
ctx := context.Background()
requesterConfig, err := node.NewRequesterConfigWith(
node.RequesterConfigParams{
HousekeepingBackgroundTaskInterval: 1 * time.Second,
},
)

s.Require().NoError(err)
stack := teststack.Setup(ctx, s.T(),
devstack.WithNumberOfHybridNodes(1),
devstack.WithComputeConfig(computeConfig),
devstack.WithRequesterConfig(requesterConfig),
devstack.WithNetworkType("nats"),
teststack.WithNoopExecutor(noop_executor.ExecutorConfig{}),
)
s.Node = stack.Nodes[0]
s.Host = s.Node.APIServer.Address
s.Port = s.Node.APIServer.Port
s.ClientV2 = clientv2.New(fmt.Sprintf("http://%s:%d", s.Host, s.Port))

fmt.Println(s.Host, s.Port)
}

// After each test
func (s *BaseNATSSuite) TearDownTest() {
util.Fatal = util.FakeFatalErrorHandler
if s.Node != nil {
s.Node.CleanupManager.Cleanup(context.Background())
}
}

// ExecuteTestCobraCommand executes a cobra command with the given arguments. The api-host and api-port
// flags are automatically added if they are not provided in `args`. They are set to the values of
// `s.Host` and `s.Port` respectively.
func (s *BaseNATSSuite) ExecuteTestCobraCommand(args ...string) (c *cobra.Command, output string, err error) {
return s.ExecuteTestCobraCommandWithStdin(nil, args...)
}

// ExecuteTestCobraCommandWithStdin executes a cobra command with the given arguments and with a specific
// stdin. The api-host and api-port flags are automatically added if they are not provided in `args`. They
// are set to the values of `s.Host` and `s.Port` respectively.
func (s *BaseNATSSuite) ExecuteTestCobraCommandWithStdin(stdin io.Reader, args ...string) (c *cobra.Command, output string, err error) {
buf := new(bytes.Buffer)
root := cli.NewRootCmd()
root.SetOut(buf)
root.SetErr(buf)
root.SetIn(stdin)

arguments := []string{}
if !slices.Contains(args, "--api-host") {
arguments = append(arguments, "--api-host", s.Host)
}

if !slices.Contains(args, "--api-port") {
arguments = append(arguments, "--api-port", fmt.Sprintf("%d", s.Port))
}
arguments = append(arguments, args...)

root.SetArgs(arguments)

// Need to check if we're running in debug mode for VSCode
// Empty them if they exist
if (len(os.Args) > 2) && (os.Args[1] == "-test.run") {
os.Args[1] = ""
os.Args[2] = ""
}

s.T().Logf("Command to execute: %v", arguments)

util.TestError = nil
c, err = root.ExecuteC()
if err == nil {
err = util.TestError
}
return c, buf.String(), err
}

// ExecuteTestCobraCommandWithStdinBytes executes a cobra command with the given arguments and with a specific
// stdin bytes. The api-host and api-port flags are automatically added if they are not provided in `args`. They
// are set to the values of `s.Host` and `s.Port` respectively.
func (s *BaseNATSSuite) ExecuteTestCobraCommandWithStdinBytes(stdin []byte, args ...string) (c *cobra.Command, output string, err error) {
return s.ExecuteTestCobraCommandWithStdin(bytes.NewReader(stdin), args...)
}
2 changes: 2 additions & 0 deletions pkg/node/compute.go
Original file line number Diff line number Diff line change
@@ -238,6 +238,8 @@ func NewComputeNode(
// TODO: When we no longer use libP2P for management, we should remove this
// as the managementProxy will always be set.
if managementProxy != nil {
// TODO: Make the registration lock folder a config option so that we have it
// available and don't have to depend on getting the repo folder.
repo, _ := pkgconfig.Get[string]("repo")
regFilename := fmt.Sprintf("%s.registration.lock", nodeID)
regFilename = filepath.Join(repo, pkgconfig.ComputeStorePath, regFilename)
6 changes: 6 additions & 0 deletions pkg/test/teststack/stack.go
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ import (

"github.com/stretchr/testify/require"

"github.com/bacalhau-project/bacalhau/pkg/config"
"github.com/bacalhau-project/bacalhau/pkg/lib/provider"
"github.com/bacalhau-project/bacalhau/pkg/models"
"github.com/bacalhau-project/bacalhau/pkg/repo"
@@ -62,9 +63,14 @@ func Setup(
if err := fsRepo.Open(); err != nil {
t.Fatal(err)
}

// TODO(ross) - Remove this once compute node registration lock does not rely on
// this config for finding it's storage path.
config.SetValue("repo", repoPath)
} else {
fsRepo = setup.SetupBacalhauRepoForTesting(t)
}

cm := system.NewCleanupManager()
t.Cleanup(func() {
cm.Cleanup(ctx)