open-nomad/client/meta_endpoint_test.go
Michael Schurter 35d65c7c7e
Dynamic Node Metadata (#15844)
Fixes #14617
Dynamic Node Metadata allows Nomad users, and their jobs, to update Node metadata through an API. Currently Node metadata is only reloaded when a Client agent is restarted.

Includes new UI for editing metadata as well.

---------

Co-authored-by: Phil Renaud <phil.renaud@hashicorp.com>
2023-02-07 14:42:25 -08:00

96 lines
2.5 KiB
Go

package client
import (
"testing"
"github.com/hashicorp/nomad/acl"
"github.com/hashicorp/nomad/ci"
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/helper/pointer"
"github.com/hashicorp/nomad/nomad"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/testutil"
"github.com/shoenig/test/must"
)
func TestNodeMeta_ACL(t *testing.T) {
ci.Parallel(t)
s, _, cleanupS := nomad.TestACLServer(t, nil)
defer cleanupS()
testutil.WaitForLeader(t, s.RPC)
c1, cleanup := TestClient(t, func(c *config.Config) {
c.ACLEnabled = true
c.Servers = []string{s.GetConfig().RPCAddr.String()}
})
defer cleanup()
// Dynamic node metadata endpoints should fail without auth
applyReq := &structs.NodeMetaApplyRequest{
NodeID: c1.NodeID(),
Meta: map[string]*string{
"foo": pointer.Of("bar"),
},
}
resp := structs.NodeMetaResponse{}
err := c1.ClientRPC("NodeMeta.Apply", applyReq, &resp)
must.ErrorContains(t, err, structs.ErrPermissionDenied.Error())
readReq := &structs.NodeSpecificRequest{
NodeID: c1.NodeID(),
}
err = c1.ClientRPC("NodeMeta.Read", readReq, &resp)
must.ErrorContains(t, err, structs.ErrPermissionDenied.Error())
// Create a token to make it work
policyGood := mock.NodePolicy(acl.PolicyWrite)
tokenGood := mock.CreatePolicyAndToken(t, s.State(), 1009, "meta", policyGood)
applyReq.AuthToken = tokenGood.SecretID
err = c1.ClientRPC("NodeMeta.Apply", applyReq, &resp)
must.NoError(t, err)
must.Eq(t, "bar", resp.Meta["foo"])
readReq.AuthToken = tokenGood.SecretID
err = c1.ClientRPC("NodeMeta.Read", readReq, &resp)
must.NoError(t, err)
}
func TestNodeMeta_Validation(t *testing.T) {
ci.Parallel(t)
s, cleanupS := nomad.TestServer(t, nil)
defer cleanupS()
testutil.WaitForLeader(t, s.RPC)
c1, cleanup := TestClient(t, func(c *config.Config) {
c.Servers = []string{s.GetConfig().RPCAddr.String()}
})
defer cleanup()
applyReq := &structs.NodeMetaApplyRequest{
NodeID: c1.NodeID(),
Meta: map[string]*string{},
}
resp := struct{}{}
// An empty map is an error
err := c1.ClientRPC("NodeMeta.Apply", applyReq, &resp)
must.ErrorContains(t, err, "missing required Meta")
// empty keys are prohibited
applyReq.Meta[""] = pointer.Of("bad")
err = c1.ClientRPC("NodeMeta.Apply", applyReq, &resp)
must.ErrorContains(t, err, "empty")
// * is prohibited in keys
delete(applyReq.Meta, "")
applyReq.Meta["*"] = pointer.Of("bad")
err = c1.ClientRPC("NodeMeta.Apply", applyReq, &resp)
must.ErrorContains(t, err, "*")
}