Merge pull request #9356 from hashicorp/b-bridgefp-upgrade-path

scheduler: enable upgrade path for bridge network finger print
This commit is contained in:
Seth Hoenig 2020-11-16 09:29:03 -06:00 committed by GitHub
commit 6eda03fd62
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 7 deletions

View file

@ -28,6 +28,21 @@ const (
FilterConstraintDevices = "missing devices"
)
var (
// predatesBridgeFingerprint returns true if the constraint matches a version
// of nomad that predates the addition of the bridge network finger-printer,
// which was added in Nomad v0.12
predatesBridgeFingerprint = mustBridgeConstraint()
)
func mustBridgeConstraint() version.Constraints {
versionC, err := version.NewConstraint("< 0.12")
if err != nil {
panic(err)
}
return versionC
}
// FeasibleIterator is used to iteratively yield nodes that
// match feasibility constraints. The iterators may manage
// some state for performance optimizations.
@ -343,6 +358,18 @@ func (c *NetworkChecker) SetNetwork(network *structs.NetworkResource) {
func (c *NetworkChecker) Feasible(option *structs.Node) bool {
if !c.hasNetwork(option) {
// special case - if the client is running a version older than 0.12 but
// the server is 0.12 or newer, we need to maintain an upgrade path for
// jobs looking for a bridge network that will not have been fingerprinted
// on the client (which was added in 0.12)
if c.networkMode == "bridge" {
sv, err := version.NewSemver(option.Attributes["nomad.version"])
if err == nil && predatesBridgeFingerprint.Check(sv) {
return true
}
}
c.ctx.Metrics().FilterNode(option, "missing network")
return false
}

View file

@ -399,14 +399,19 @@ func TestCSIVolumeChecker(t *testing.T) {
func TestNetworkChecker(t *testing.T) {
_, ctx := testContext(t)
nodes := []*structs.Node{
mock.Node(),
mock.Node(),
mock.Node(),
node := func(mode string) *structs.Node {
n := mock.Node()
n.NodeResources.Networks = append(n.NodeResources.Networks, &structs.NetworkResource{Mode: mode})
n.Attributes["nomad.version"] = "0.12.0" // mock version is 0.5.0
return n
}
nodes := []*structs.Node{
node("bridge"),
node("bridge"),
node("cni/mynet"),
}
nodes[0].NodeResources.Networks = append(nodes[0].NodeResources.Networks, &structs.NetworkResource{Mode: "bridge"})
nodes[1].NodeResources.Networks = append(nodes[1].NodeResources.Networks, &structs.NetworkResource{Mode: "bridge"})
nodes[2].NodeResources.Networks = append(nodes[2].NodeResources.Networks, &structs.NetworkResource{Mode: "cni/mynet"})
checker := NewNetworkChecker(ctx)
cases := []struct {
@ -439,6 +444,36 @@ func TestNetworkChecker(t *testing.T) {
}
}
func TestNetworkChecker_bridge_upgrade_path(t *testing.T) {
_, ctx := testContext(t)
t.Run("older client", func(t *testing.T) {
// Create a client that is still on v0.11, which does not have the bridge
// network finger-printer (and thus no bridge network resource)
oldClient := mock.Node()
oldClient.Attributes["nomad.version"] = "0.11.0"
checker := NewNetworkChecker(ctx)
checker.SetNetwork(&structs.NetworkResource{Mode: "bridge"})
ok := checker.Feasible(oldClient)
require.True(t, ok)
})
t.Run("updated client", func(t *testing.T) {
// Create a client that is updated to 0.12, but did not detect a bridge
// network resource.
oldClient := mock.Node()
oldClient.Attributes["nomad.version"] = "0.12.0"
checker := NewNetworkChecker(ctx)
checker.SetNetwork(&structs.NetworkResource{Mode: "bridge"})
ok := checker.Feasible(oldClient)
require.False(t, ok)
})
}
func TestDriverChecker_DriverInfo(t *testing.T) {
_, ctx := testContext(t)
nodes := []*structs.Node{