Files
nomad/client/fingerprint/vault_test.go
Tim Gross 8c57fd5eb0 fingerprint: initial fingerprint of Vault/Consul should be periodic (#25102)
In #24526 we updated the Consul and Vault fingerprints so that they are no
longer periodic. This fixed a problem that cluster admins reported where rolling
updates of Vault or Consul would cause a thundering herd of fingerprint updates
across the whole cluster.

But if Consul/Vault is not available during the initial fingerprint, it will
never get fingerprinted again. This is challenging for cluster updates and black
starts because the implicit service startup ordering may require
reloads. Instead, have the fingerprinter run periodically but mark that it has
made its first successful fingerprint of all Consul/Vault clusters. At that
point, we can skip further periodic updates. The `Reload` method will reset the
mark and allow the subsequent fingerprint to run normally.

Fixes: https://github.com/hashicorp/nomad/issues/25097
Ref: https://github.com/hashicorp/nomad/pull/24526
Ref: https://github.com/hashicorp/nomad/issues/24049
2025-02-13 14:26:04 -05:00

59 lines
1.6 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package fingerprint
import (
"testing"
"github.com/hashicorp/nomad/ci"
"github.com/hashicorp/nomad/client/config"
"github.com/hashicorp/nomad/helper/testlog"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/testutil"
"github.com/shoenig/test/must"
)
func TestVaultFingerprint(t *testing.T) {
ci.Parallel(t)
tv := testutil.NewTestVault(t)
defer tv.Stop()
fp := NewVaultFingerprint(testlog.HCLogger(t))
node := &structs.Node{
Attributes: make(map[string]string),
}
conf := config.DefaultConfig()
conf.VaultConfigs[structs.VaultDefaultCluster] = tv.Config
request := &FingerprintRequest{Config: conf, Node: node}
var response1 FingerprintResponse
err := fp.Fingerprint(request, &response1)
must.NoError(t, err)
must.True(t, response1.Detected)
assertNodeAttributeEquals(t, response1.Attributes, "vault.accessible", "true")
assertNodeAttributeContains(t, response1.Attributes, "vault.version")
assertNodeAttributeContains(t, response1.Attributes, "vault.cluster_id")
assertNodeAttributeContains(t, response1.Attributes, "vault.cluster_name")
// Stop Vault to simulate it being unavailable
tv.Stop()
// Fingerprint should not change without a reload
var response2 FingerprintResponse
err = fp.Fingerprint(request, &response2)
must.NoError(t, err)
must.Eq(t, response1, response2)
// Fingerprint should update after a reload
reloadable := fp.(ReloadableFingerprint)
reloadable.Reload()
var response3 FingerprintResponse
err = fp.Fingerprint(request, &response3)
must.NoError(t, err)
must.False(t, response3.Detected)
}