Add mutual exclusivity to manager host selectors

Using a label selector and name when creating a manager will produce the
union of all host documents that match the criteria. While this is not
inherently a problem, it's not expected behavior. This change makes
using the label selector and name property mutually exclusive. When
creating a manger using both selectors, the manager will contain the
intersection of hosts, rather than the union.

Change-Id: I791e0460cea2ae3d60ea2cc24f900b925c36d9af
Signed-off-by: Drew Walters <andrew.walters@att.com>
This commit is contained in:
Drew Walters 2020-05-01 18:14:40 +00:00
parent d126615f8b
commit bbb823306d
2 changed files with 47 additions and 2 deletions

View File

@ -78,15 +78,18 @@ func ByLabel(label string) HostSelector {
return document.ErrDocNotFound{Selector: selector}
}
var matchingHosts []baremetalHost
for _, doc := range docs {
host, err := newBaremetalHost(mgmtCfg, doc, docBundle)
if err != nil {
return err
}
a.Hosts = append(a.Hosts, host)
matchingHosts = append(matchingHosts, host)
}
a.Hosts = reconcileHosts(a.Hosts, matchingHosts...)
return nil
}
}
@ -105,7 +108,7 @@ func ByName(name string) HostSelector {
return err
}
a.Hosts = append(a.Hosts, host)
a.Hosts = reconcileHosts(a.Hosts, host)
return nil
}
@ -202,3 +205,25 @@ func newBaremetalHost(mgmtCfg config.ManagementConfiguration,
return host, nil
}
// reconcileHosts produces the intersection of two baremetal host arrays.
func reconcileHosts(existingHosts []baremetalHost, newHosts ...baremetalHost) []baremetalHost {
if len(existingHosts) == 0 {
return newHosts
}
// Create a map of host document names for efficient filtering
hostMap := make(map[string]bool)
for _, host := range existingHosts {
hostMap[host.HostName] = true
}
var reconciledHosts []baremetalHost
for _, host := range newHosts {
if _, exists := hostMap[host.HostName]; exists {
reconciledHosts = append(reconciledHosts, host)
}
}
return reconciledHosts
}

View File

@ -95,6 +95,26 @@ func TestNewManagerMultipleNodes(t *testing.T) {
assert.Equal(t, "node-master-2", manager.Hosts[1].NodeID())
}
func TestNewManagerMultipleSelectors(t *testing.T) {
settings := initSettings(t, withTestDataPath("base"))
manager, err := NewManager(settings, config.BootstrapPhase, ByName("master-1"),
ByLabel("airshipit.org/test-node=true"))
require.NoError(t, err)
require.Equal(t, 1, len(manager.Hosts))
assert.Equal(t, "node-master-1", manager.Hosts[0].NodeID())
}
func TestNewManagerMultipleSelectorsNoMatch(t *testing.T) {
settings := initSettings(t, withTestDataPath("base"))
manager, err := NewManager(settings, config.BootstrapPhase, ByName("master-2"),
ByLabel(document.EphemeralHostSelector))
require.Equal(t, 0, len(manager.Hosts))
assert.Error(t, err)
}
func TestNewManagerByNameNoHostFound(t *testing.T) {
settings := initSettings(t, withTestDataPath("base"))