testutil: add ACL bootstrapping to test server configuration (#18811)

Some of our `api` package tests have ACLs enabled, but none of those tests also
run clients and the "wait for the clients to be live" code reads from the Node
API. The caller can't bootstrap ACLs until `NewTestServer` returns, and this
makes for a circular dependency.

Allow developers to provide a bootstrap token to the test server config, and
if it's available, have the server bootstrap the ACL system with it before
checking for live clients.
This commit is contained in:
Tim Gross
2023-10-19 16:50:38 -04:00
committed by GitHub
parent 83720740f5
commit f5c5035fde

View File

@@ -93,7 +93,8 @@ type VaultConfig struct {
// ACLConfig is used to configure ACLs
type ACLConfig struct {
Enabled bool `json:"enabled"`
Enabled bool `json:"enabled"`
BootstrapToken string `json:"-"` // not in the real config
}
// ServerConfigCallback is a function interface which can be
@@ -195,6 +196,7 @@ func NewTestServer(t testing.T, cb ServerConfigCallback) *TestServer {
if nomadConfig.Stderr != nil {
stderr = nomadConfig.Stderr
}
t.Logf("CONFIG JSON: %s", string(configContent))
args := []string{"agent", "-config", configFile.Name()}
if nomadConfig.DevMode {
@@ -228,6 +230,10 @@ func NewTestServer(t testing.T, cb ServerConfigCallback) *TestServer {
server.waitForAPI()
}
if nomadConfig.ACL.Enabled && nomadConfig.ACL.BootstrapToken != "" {
server.bootstrapSelf()
}
// Wait for the client to be ready
if nomadConfig.DevMode {
server.waitForClient()
@@ -272,6 +278,28 @@ func (s *TestServer) Stop() {
}
// bootstrapSelf bootstraps the ACL system from the provided token.
func (s *TestServer) bootstrapSelf() {
contentType := "application/json"
rootToken := s.Config.ACL.BootstrapToken
body := struct{ BootstrapSecret string }{rootToken}
buf, err := json.Marshal(body)
if err != nil {
s.t.Fatalf("err: %s", err)
}
resp, err := s.HTTPClient.Post(s.url("/v1/acl/bootstrap"), contentType, bytes.NewBuffer(buf))
if err != nil {
s.t.Fatalf("err: %s", err)
}
defer resp.Body.Close()
if err := s.requireOK(resp); err != nil {
s.t.Fatalf("err: %s", err)
}
}
// waitForAPI waits for only the agent HTTP endpoint to start
// responding. This is an indication that the agent has started,
// but will likely return before a leader is elected.
@@ -324,7 +352,14 @@ func (s *TestServer) waitForClient() {
}
WaitForResult(func() (bool, error) {
resp, err := s.HTTPClient.Get(s.url("/v1/nodes"))
req, err := http.NewRequest(http.MethodGet, s.url("/v1/nodes"), nil)
if err != nil {
return false, err
}
if s.Config.ACL.BootstrapToken != "" {
req.Header.Set("X-Nomad-Token", s.Config.ACL.BootstrapToken)
}
resp, err := s.HTTPClient.Do(req)
if err != nil {
return false, err
}