Skip to content

Commit

Permalink
Merge pull request #669 from threefoldtech/development_farmerbot_vali…
Browse files Browse the repository at this point in the history
…dations

check farmer twin id
  • Loading branch information
rawdaGastan authored Jan 24, 2024
2 parents 89f8319 + 758d52b commit 4f2ebaa
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 33 deletions.
4 changes: 3 additions & 1 deletion farmerbot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Farmerbot is a service that farmers can run allowing them to automatically manag

## How to use

> :warning: **Be careful**: Make sure to run one farmerbot for each farm, otherwise the relay connection will close in all instances.
> :warning: **Be careful**: The timezone of the farmerbot will be the same as the time zone of the machine the farmerbot running inside.
- add your [configurations](#config)
Expand Down Expand Up @@ -90,7 +92,7 @@ make build

```yml
farm_id: "<your farm ID, required>"
included_nodes:
included_nodes: [optional, if no nodes are added then the farmerbot will include all nodes in the farm, farm should contain at least 2 nodes]
- "<your node ID to be included, required at least 2>"
excluded_nodes:
- "<your node ID to be excluded, optional>"
Expand Down
20 changes: 11 additions & 9 deletions farmerbot/internal/farmerbot.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type FarmerBot struct {
mnemonicOrSeed string
keyType string
identity substrate.Identity
twinID uint32
}

// NewFarmerBot generates a new farmer bot
Expand Down Expand Up @@ -55,7 +56,13 @@ func NewFarmerBot(ctx context.Context, config Config, network, mnemonicOrSeed, k
}
defer subConn.Close()

state, err := newState(ctx, subConn, farmerbot.rmbNodeClient, config)
twinID, err := subConn.GetTwinByPubKey(identity.PublicKey())
if err != nil {
return FarmerBot{}, err
}
farmerbot.twinID = twinID

state, err := newState(ctx, subConn, farmerbot.rmbNodeClient, config, twinID)
if err != nil {
return FarmerBot{}, err
}
Expand Down Expand Up @@ -122,11 +129,6 @@ func (f *FarmerBot) serve(ctx context.Context) error {
log.Warn().Float64("current balance", balance).Msgf("Recommended balance to run farmerbot is %v tft", recommendedBalanceToRun)
}

farmerTwinID, err := subConn.GetTwinByPubKey(f.identity.PublicKey())
if err != nil {
return err
}

farmRouter.WithHandler("version", func(ctx context.Context, payload []byte) (interface{}, error) {
return version.Version, nil
})
Expand All @@ -152,7 +154,7 @@ func (f *FarmerBot) serve(ctx context.Context) error {
})

powerRouter.WithHandler("includenode", func(ctx context.Context, payload []byte) (interface{}, error) {
err := authorize(ctx, farmerTwinID)
err := authorize(ctx, f.twinID)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -183,7 +185,7 @@ func (f *FarmerBot) serve(ctx context.Context) error {
})

powerRouter.WithHandler("poweroff", func(ctx context.Context, payload []byte) (interface{}, error) {
err := authorize(ctx, farmerTwinID)
err := authorize(ctx, f.twinID)
if err != nil {
return nil, err
}
Expand All @@ -209,7 +211,7 @@ func (f *FarmerBot) serve(ctx context.Context) error {
})

powerRouter.WithHandler("poweron", func(ctx context.Context, payload []byte) (interface{}, error) {
err := authorize(ctx, farmerTwinID)
err := authorize(ctx, f.twinID)
if err != nil {
return nil, err
}
Expand Down
7 changes: 5 additions & 2 deletions farmerbot/internal/farmerbot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ import (
"github.com/threefoldtech/zos/pkg/gridtypes"
)

const aliceSeed = "0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a"
const (
aliceSeed = "0xe5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a"
farmTwinID = 1
)

func TestFarmerbot(t *testing.T) {
ctrl := gomock.NewController(t)
Expand All @@ -38,7 +41,7 @@ func TestFarmerbot(t *testing.T) {
resources := gridtypes.Capacity{HRU: 1, SRU: 1, CRU: 1, MRU: 1}
mockRMBAndSubstrateCalls(ctx, sub, rmb, inputs, true, false, resources, []string{}, false, false)

state, err := newState(ctx, sub, rmb, inputs)
state, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.NoError(t, err)
farmerbot.state = state

Expand Down
2 changes: 1 addition & 1 deletion farmerbot/internal/find_node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestFindNode(t *testing.T) {
resources := gridtypes.Capacity{HRU: gridtypes.Unit(convertGBToBytes(1)), SRU: gridtypes.Unit(convertGBToBytes(1)), CRU: 1, MRU: gridtypes.Unit(convertGBToBytes(1))}
mockRMBAndSubstrateCalls(ctx, sub, rmb, inputs, true, false, resources, []string{}, false, false)

state, err := newState(ctx, sub, rmb, inputs)
state, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.NoError(t, err)
farmerbot.state = state

Expand Down
2 changes: 1 addition & 1 deletion farmerbot/internal/power_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestPower(t *testing.T) {
resources := gridtypes.Capacity{HRU: 1, SRU: 1, CRU: 1, MRU: 1}
mockRMBAndSubstrateCalls(ctx, sub, rmb, inputs, true, false, resources, []string{}, false, false)

state, err := newState(ctx, sub, rmb, inputs)
state, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.NoError(t, err)
farmerbot.state = state

Expand Down
6 changes: 5 additions & 1 deletion farmerbot/internal/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type state struct {
}

// NewState creates new state from configs
func newState(ctx context.Context, sub Substrate, rmbNodeClient RMB, cfg Config) (*state, error) {
func newState(ctx context.Context, sub Substrate, rmbNodeClient RMB, cfg Config, twinID uint32) (*state, error) {
s := state{config: cfg}

// required from power for nodes
Expand All @@ -38,6 +38,10 @@ func newState(ctx context.Context, sub Substrate, rmbNodeClient RMB, cfg Config)
return nil, err
}

if twinID != uint32(farm.TwinID) {
return nil, fmt.Errorf("you are not authorized to run the farmerbot on farm %d. your twin id is `%d`, only the farm owner with twin id `%d` is authorized", farm.ID, twinID, farm.TwinID)
}

s.farm = *farm

nodes, err := fetchNodes(ctx, sub, rmbNodeClient, cfg, farm.DedicatedFarm)
Expand Down
36 changes: 18 additions & 18 deletions farmerbot/internal/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func mockRMBAndSubstrateCalls(

// farm calls
if !noFarm {
sub.EXPECT().GetFarm(inputs.FarmID).Return(&substrate.Farm{ID: 1, DedicatedFarm: true, PublicIPs: []substrate.PublicIP{{IP: "1.1.1.1"}}}, farmErr)
sub.EXPECT().GetFarm(inputs.FarmID).Return(&substrate.Farm{ID: 1, TwinID: farmTwinID, DedicatedFarm: true, PublicIPs: []substrate.PublicIP{{IP: "1.1.1.1"}}}, farmErr)
if farmErr != nil {
return
}
Expand Down Expand Up @@ -123,7 +123,7 @@ func TestSetConfig(t *testing.T) {
t.Run("test valid state: no periodic wake up start, wakeup threshold (< min => min)", func(t *testing.T) {
mockRMBAndSubstrateCalls(ctx, sub, rmb, inputs, true, false, resources, []string{}, false, false)

state, err := newState(ctx, sub, rmb, inputs)
state, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.NoError(t, err)
assert.Equal(t, uint32(state.farm.ID), uint32(1))
assert.True(t, state.nodes[1].dedicated)
Expand All @@ -144,7 +144,7 @@ func TestSetConfig(t *testing.T) {

inputs.Power.WakeUpThreshold = 100

state, err := newState(ctx, sub, rmb, inputs)
state, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.NoError(t, err)
assert.Equal(t, state.config.Power.WakeUpThreshold, maxWakeUpThreshold)
})
Expand All @@ -154,7 +154,7 @@ func TestSetConfig(t *testing.T) {

inputs.Power.WakeUpThreshold = 0

state, err := newState(ctx, sub, rmb, inputs)
state, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.NoError(t, err)
assert.Equal(t, state.config.Power.WakeUpThreshold, defaultWakeUpThreshold)
})
Expand All @@ -163,7 +163,7 @@ func TestSetConfig(t *testing.T) {
mockRMBAndSubstrateCalls(ctx, sub, rmb, inputs, true, false, resources, []string{}, false, false)
inputs.Power.WakeUpThreshold = 110

_, err := newState(ctx, sub, rmb, inputs)
_, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.Error(t, err)

inputs.Power.WakeUpThreshold = defaultWakeUpThreshold
Expand All @@ -172,14 +172,14 @@ func TestSetConfig(t *testing.T) {
t.Run("test valid state: nodes are off in substrate", func(t *testing.T) {
mockRMBAndSubstrateCalls(ctx, sub, rmb, inputs, false, false, resources, []string{}, false, false)

_, err := newState(ctx, sub, rmb, inputs)
_, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.NoError(t, err)
})

t.Run("test invalid state: cpu provision out of range", func(t *testing.T) {
inputs.Power.OverProvisionCPU = 6

_, err := newState(ctx, sub, rmb, inputs)
_, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.Error(t, err)

inputs.Power.OverProvisionCPU = 0
Expand All @@ -191,15 +191,15 @@ func TestSetConfig(t *testing.T) {
for _, call := range calls {
mockRMBAndSubstrateCalls(ctx, sub, rmb, inputs, true, false, resources, []string{call}, false, false)

_, err := newState(ctx, sub, rmb, inputs)
_, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.Error(t, err)
}
})

t.Run("test invalid state: rent contract doesn't exist", func(t *testing.T) {
mockRMBAndSubstrateCalls(ctx, sub, rmb, inputs, true, false, resources, []string{"rentNotExist"}, false, false)

state, err := newState(ctx, sub, rmb, inputs)
state, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.NoError(t, err)
assert.False(t, state.nodes[1].hasActiveRentContract)
})
Expand All @@ -209,7 +209,7 @@ func TestSetConfig(t *testing.T) {

mockRMBAndSubstrateCalls(ctx, sub, rmb, inputs, true, false, resources, []string{}, false, false)

_, err := newState(ctx, sub, rmb, inputs)
_, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.NoError(t, err)

inputs.ExcludedNodes = []uint32{}
Expand All @@ -221,56 +221,56 @@ func TestSetConfig(t *testing.T) {

mockRMBAndSubstrateCalls(ctx, sub, rmb, inputs, true, false, resources, []string{}, false, false)

_, err := newState(ctx, sub, rmb, inputs)
_, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.Error(t, err)

inputs.ExcludedNodes = []uint32{}
inputs.IncludedNodes = []uint32{1, 2}
})

t.Run("test invalid state no farm ID", func(t *testing.T) {
sub.EXPECT().GetFarm(inputs.FarmID).Return(&substrate.Farm{ID: 0}, nil)
sub.EXPECT().GetFarm(inputs.FarmID).Return(&substrate.Farm{ID: 0, TwinID: farmTwinID}, nil)
sub.EXPECT().GetNodes(inputs.FarmID).Return([]uint32{}, nil)

_, err := newState(ctx, sub, rmb, inputs)
_, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.Error(t, err)
})

t.Run("test invalid state no node ID", func(t *testing.T) {
mockRMBAndSubstrateCalls(ctx, sub, rmb, inputs, true, false, resources, []string{}, true, false)

_, err := newState(ctx, sub, rmb, inputs)
_, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.Error(t, err)
})

t.Run("test invalid state no twin ID", func(t *testing.T) {
mockRMBAndSubstrateCalls(ctx, sub, rmb, inputs, true, false, resources, []string{}, false, true)

_, err := newState(ctx, sub, rmb, inputs)
_, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.Error(t, err)
})

t.Run("test invalid state no node sru", func(t *testing.T) {
resources := gridtypes.Capacity{HRU: 1, SRU: 0, CRU: 1, MRU: 1}
mockRMBAndSubstrateCalls(ctx, sub, rmb, inputs, true, false, resources, []string{}, false, false)

_, err := newState(ctx, sub, rmb, inputs)
_, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.Error(t, err)
})

t.Run("test invalid state no cru", func(t *testing.T) {
resources := gridtypes.Capacity{HRU: 1, SRU: 1, CRU: 0, MRU: 1}
mockRMBAndSubstrateCalls(ctx, sub, rmb, inputs, true, false, resources, []string{}, false, false)

_, err := newState(ctx, sub, rmb, inputs)
_, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.Error(t, err)
})

t.Run("test invalid state no mru", func(t *testing.T) {
resources := gridtypes.Capacity{HRU: 1, SRU: 1, CRU: 1, MRU: 0}
mockRMBAndSubstrateCalls(ctx, sub, rmb, inputs, true, false, resources, []string{}, false, false)

_, err := newState(ctx, sub, rmb, inputs)
_, err := newState(ctx, sub, rmb, inputs, farmTwinID)
assert.Error(t, err)
})
}
Expand Down

0 comments on commit 4f2ebaa

Please sign in to comment.