1279 lines
38 KiB
Go
1279 lines
38 KiB
Go
/*
|
|
Copyright 2020 The Kubernetes Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package clusterapi
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path"
|
|
"reflect"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/labels"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
fakediscovery "k8s.io/client-go/discovery/fake"
|
|
fakedynamic "k8s.io/client-go/dynamic/fake"
|
|
fakekube "k8s.io/client-go/kubernetes/fake"
|
|
clientgotesting "k8s.io/client-go/testing"
|
|
"k8s.io/utils/pointer"
|
|
)
|
|
|
|
type testControllerShutdownFunc func()
|
|
|
|
type testConfig struct {
|
|
spec *testSpec
|
|
machineDeployment *MachineDeployment
|
|
machineSet *MachineSet
|
|
machines []*Machine
|
|
nodes []*corev1.Node
|
|
}
|
|
|
|
type testSpec struct {
|
|
annotations map[string]string
|
|
machineDeploymentName string
|
|
machineSetName string
|
|
namespace string
|
|
nodeCount int
|
|
rootIsMachineDeployment bool
|
|
}
|
|
|
|
const customCAPIGroup = "custom.x-k8s.io"
|
|
|
|
func mustCreateTestController(t *testing.T, testConfigs ...*testConfig) (*machineController, testControllerShutdownFunc) {
|
|
t.Helper()
|
|
|
|
nodeObjects := make([]runtime.Object, 0)
|
|
machineObjects := make([]runtime.Object, 0)
|
|
|
|
for _, config := range testConfigs {
|
|
for i := range config.nodes {
|
|
nodeObjects = append(nodeObjects, config.nodes[i])
|
|
}
|
|
|
|
for i := range config.machines {
|
|
machineObjects = append(machineObjects, newUnstructuredFromMachine(config.machines[i]))
|
|
}
|
|
|
|
machineObjects = append(machineObjects, newUnstructuredFromMachineSet(config.machineSet))
|
|
if config.machineDeployment != nil {
|
|
machineObjects = append(machineObjects, newUnstructuredFromMachineDeployment(config.machineDeployment))
|
|
}
|
|
}
|
|
|
|
kubeclientSet := fakekube.NewSimpleClientset(nodeObjects...)
|
|
dynamicClientset := fakedynamic.NewSimpleDynamicClient(runtime.NewScheme(), machineObjects...)
|
|
discoveryClient := &fakediscovery.FakeDiscovery{
|
|
Fake: &clientgotesting.Fake{
|
|
Resources: []*v1.APIResourceList{
|
|
{
|
|
GroupVersion: fmt.Sprintf("%s/v1beta1", customCAPIGroup),
|
|
APIResources: []v1.APIResource{
|
|
{
|
|
Name: resourceNameMachineDeployment,
|
|
},
|
|
{
|
|
Name: resourceNameMachineSet,
|
|
},
|
|
{
|
|
Name: resourceNameMachine,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
GroupVersion: fmt.Sprintf("%s/v1alpha3", defaultCAPIGroup),
|
|
APIResources: []v1.APIResource{
|
|
{
|
|
Name: resourceNameMachineDeployment,
|
|
},
|
|
{
|
|
Name: resourceNameMachineSet,
|
|
},
|
|
{
|
|
Name: resourceNameMachine,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
controller, err := newMachineController(dynamicClientset, kubeclientSet, discoveryClient)
|
|
if err != nil {
|
|
t.Fatal("failed to create test controller")
|
|
}
|
|
|
|
stopCh := make(chan struct{})
|
|
if err := controller.run(stopCh); err != nil {
|
|
t.Fatalf("failed to run controller: %v", err)
|
|
}
|
|
|
|
return controller, func() {
|
|
close(stopCh)
|
|
}
|
|
}
|
|
|
|
func createMachineSetTestConfig(namespace string, nodeCount int, annotations map[string]string) *testConfig {
|
|
return createTestConfigs(createTestSpecs(namespace, 1, nodeCount, false, annotations)...)[0]
|
|
}
|
|
|
|
func createMachineSetTestConfigs(namespace string, configCount, nodeCount int, annotations map[string]string) []*testConfig {
|
|
return createTestConfigs(createTestSpecs(namespace, configCount, nodeCount, false, annotations)...)
|
|
}
|
|
|
|
func createMachineDeploymentTestConfig(namespace string, nodeCount int, annotations map[string]string) *testConfig {
|
|
return createTestConfigs(createTestSpecs(namespace, 1, nodeCount, true, annotations)...)[0]
|
|
}
|
|
|
|
func createMachineDeploymentTestConfigs(namespace string, configCount, nodeCount int, annotations map[string]string) []*testConfig {
|
|
return createTestConfigs(createTestSpecs(namespace, configCount, nodeCount, true, annotations)...)
|
|
}
|
|
|
|
func createTestSpecs(namespace string, scalableResourceCount, nodeCount int, isMachineDeployment bool, annotations map[string]string) []testSpec {
|
|
var specs []testSpec
|
|
|
|
for i := 0; i < scalableResourceCount; i++ {
|
|
specs = append(specs, testSpec{
|
|
annotations: annotations,
|
|
machineDeploymentName: fmt.Sprintf("machinedeployment-%d", i),
|
|
machineSetName: fmt.Sprintf("machineset-%d", i),
|
|
namespace: strings.ToLower(namespace),
|
|
nodeCount: nodeCount,
|
|
rootIsMachineDeployment: isMachineDeployment,
|
|
})
|
|
}
|
|
|
|
return specs
|
|
}
|
|
|
|
func createTestConfigs(specs ...testSpec) []*testConfig {
|
|
var result []*testConfig
|
|
|
|
for i, spec := range specs {
|
|
config := &testConfig{
|
|
spec: &specs[i],
|
|
nodes: make([]*corev1.Node, spec.nodeCount),
|
|
machines: make([]*Machine, spec.nodeCount),
|
|
}
|
|
|
|
config.machineSet = &MachineSet{
|
|
TypeMeta: v1.TypeMeta{
|
|
APIVersion: fmt.Sprintf("%s/v1alpha3", defaultCAPIGroup),
|
|
Kind: "MachineSet",
|
|
},
|
|
ObjectMeta: v1.ObjectMeta{
|
|
Name: spec.machineSetName,
|
|
Namespace: spec.namespace,
|
|
UID: types.UID(spec.machineSetName),
|
|
},
|
|
}
|
|
|
|
if !spec.rootIsMachineDeployment {
|
|
config.machineSet.ObjectMeta.Annotations = spec.annotations
|
|
config.machineSet.Spec.Replicas = int32ptr(int32(spec.nodeCount))
|
|
} else {
|
|
config.machineDeployment = &MachineDeployment{
|
|
TypeMeta: v1.TypeMeta{
|
|
APIVersion: fmt.Sprintf("%s/v1alpha3", defaultCAPIGroup),
|
|
Kind: "MachineDeployment",
|
|
},
|
|
ObjectMeta: v1.ObjectMeta{
|
|
Name: spec.machineDeploymentName,
|
|
Namespace: spec.namespace,
|
|
UID: types.UID(spec.machineDeploymentName),
|
|
Annotations: spec.annotations,
|
|
},
|
|
Spec: MachineDeploymentSpec{
|
|
Replicas: int32ptr(int32(spec.nodeCount)),
|
|
},
|
|
}
|
|
|
|
config.machineSet.OwnerReferences = make([]v1.OwnerReference, 1)
|
|
config.machineSet.OwnerReferences[0] = v1.OwnerReference{
|
|
Name: config.machineDeployment.Name,
|
|
Kind: config.machineDeployment.Kind,
|
|
UID: config.machineDeployment.UID,
|
|
}
|
|
}
|
|
|
|
machineOwner := v1.OwnerReference{
|
|
Name: config.machineSet.Name,
|
|
Kind: config.machineSet.Kind,
|
|
UID: config.machineSet.UID,
|
|
}
|
|
|
|
for j := 0; j < spec.nodeCount; j++ {
|
|
config.nodes[j], config.machines[j] = makeLinkedNodeAndMachine(j, spec.namespace, machineOwner)
|
|
}
|
|
|
|
result = append(result, config)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// makeLinkedNodeAndMachine creates a node and machine. The machine
|
|
// has its NodeRef set to the new node and the new machine's owner
|
|
// reference is set to owner.
|
|
func makeLinkedNodeAndMachine(i int, namespace string, owner v1.OwnerReference) (*corev1.Node, *Machine) {
|
|
node := &corev1.Node{
|
|
TypeMeta: v1.TypeMeta{
|
|
Kind: "Node",
|
|
},
|
|
ObjectMeta: v1.ObjectMeta{
|
|
Name: fmt.Sprintf("%s-%s-node-%d", namespace, owner.Name, i),
|
|
Annotations: map[string]string{
|
|
machineAnnotationKey: fmt.Sprintf("%s/%s-%s-machine-%d", namespace, namespace, owner.Name, i),
|
|
},
|
|
},
|
|
Spec: corev1.NodeSpec{
|
|
ProviderID: fmt.Sprintf("test:////%s-%s-nodeid-%d", namespace, owner.Name, i),
|
|
},
|
|
}
|
|
|
|
machine := &Machine{
|
|
TypeMeta: v1.TypeMeta{
|
|
APIVersion: fmt.Sprintf("%s/v1alpha3", defaultCAPIGroup),
|
|
Kind: "Machine",
|
|
},
|
|
ObjectMeta: v1.ObjectMeta{
|
|
Name: fmt.Sprintf("%s-%s-machine-%d", namespace, owner.Name, i),
|
|
Namespace: namespace,
|
|
OwnerReferences: []v1.OwnerReference{{
|
|
Name: owner.Name,
|
|
Kind: owner.Kind,
|
|
UID: owner.UID,
|
|
}},
|
|
},
|
|
Spec: MachineSpec{
|
|
ProviderID: pointer.StringPtr(fmt.Sprintf("test:////%s-%s-nodeid-%d", namespace, owner.Name, i)),
|
|
},
|
|
Status: MachineStatus{
|
|
NodeRef: &corev1.ObjectReference{
|
|
Kind: node.Kind,
|
|
Name: node.Name,
|
|
},
|
|
},
|
|
}
|
|
|
|
return node, machine
|
|
}
|
|
|
|
func int32ptr(v int32) *int32 {
|
|
return &v
|
|
}
|
|
|
|
func addTestConfigs(t *testing.T, controller *machineController, testConfigs ...*testConfig) error {
|
|
t.Helper()
|
|
|
|
for _, config := range testConfigs {
|
|
if config.machineDeployment != nil {
|
|
|
|
if err := controller.machineDeploymentInformer.Informer().GetStore().Add(newUnstructuredFromMachineDeployment(config.machineDeployment)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if err := controller.machineSetInformer.Informer().GetStore().Add(newUnstructuredFromMachineSet(config.machineSet)); err != nil {
|
|
return err
|
|
}
|
|
for i := range config.machines {
|
|
if err := controller.machineInformer.Informer().GetStore().Add(newUnstructuredFromMachine(config.machines[i])); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
for i := range config.nodes {
|
|
if err := controller.nodeInformer.GetStore().Add(config.nodes[i]); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func deleteTestConfigs(t *testing.T, controller *machineController, testConfigs ...*testConfig) error {
|
|
t.Helper()
|
|
|
|
for _, config := range testConfigs {
|
|
for i := range config.nodes {
|
|
if err := controller.nodeInformer.GetStore().Delete(config.nodes[i]); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
for i := range config.machines {
|
|
if err := controller.machineInformer.Informer().GetStore().Delete(config.machines[i]); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if err := controller.machineSetInformer.Informer().GetStore().Delete(config.machineSet); err != nil {
|
|
return err
|
|
}
|
|
if config.machineDeployment != nil {
|
|
if err := controller.machineDeploymentInformer.Informer().GetStore().Delete(config.machineDeployment); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func TestControllerFindMachineByID(t *testing.T) {
|
|
type testCase struct {
|
|
description string
|
|
name string
|
|
namespace string
|
|
lookupSucceeds bool
|
|
}
|
|
|
|
var testCases = []testCase{{
|
|
description: "lookup fails",
|
|
lookupSucceeds: false,
|
|
name: "machine-does-not-exist",
|
|
namespace: "namespace-does-not-exist",
|
|
}, {
|
|
description: "lookup fails in valid namespace",
|
|
lookupSucceeds: false,
|
|
name: "machine-does-not-exist-in-existing-namespace",
|
|
}, {
|
|
description: "lookup succeeds",
|
|
lookupSucceeds: true,
|
|
}}
|
|
|
|
test := func(t *testing.T, tc testCase, testConfig *testConfig) {
|
|
controller, stop := mustCreateTestController(t, testConfig)
|
|
defer stop()
|
|
|
|
machine, err := controller.findMachine(path.Join(tc.namespace, tc.name))
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if tc.lookupSucceeds && machine == nil {
|
|
t.Error("expected success, findMachine failed")
|
|
}
|
|
|
|
if tc.lookupSucceeds && machine != nil {
|
|
if machine.Name != tc.name {
|
|
t.Errorf("expected %q, got %q", tc.name, machine.Name)
|
|
}
|
|
if machine.Namespace != tc.namespace {
|
|
t.Errorf("expected %q, got %q", tc.namespace, machine.Namespace)
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.description, func(t *testing.T) {
|
|
testConfig := createMachineSetTestConfig(testNamespace, 1, map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "10",
|
|
})
|
|
if tc.name == "" {
|
|
tc.name = testConfig.machines[0].Name
|
|
}
|
|
if tc.namespace == "" {
|
|
tc.namespace = testConfig.machines[0].Namespace
|
|
}
|
|
test(t, tc, testConfig)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestControllerFindMachineOwner(t *testing.T) {
|
|
testConfig := createMachineSetTestConfig(testNamespace, 1, map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "10",
|
|
})
|
|
|
|
controller, stop := mustCreateTestController(t, testConfig)
|
|
defer stop()
|
|
|
|
// Test #1: Lookup succeeds
|
|
testResult1, err := controller.findMachineOwner(testConfig.machines[0].DeepCopy())
|
|
if err != nil {
|
|
t.Fatalf("unexpected error, got %v", err)
|
|
}
|
|
if testResult1 == nil {
|
|
t.Fatal("expected non-nil result")
|
|
}
|
|
if testConfig.spec.machineSetName != testResult1.Name {
|
|
t.Errorf("expected %q, got %q", testConfig.spec.machineSetName, testResult1.Name)
|
|
}
|
|
|
|
// Test #2: Lookup fails as the machine UUID != machineset UUID
|
|
testMachine2 := testConfig.machines[0].DeepCopy()
|
|
testMachine2.OwnerReferences[0].UID = "does-not-match-machineset"
|
|
testResult2, err := controller.findMachineOwner(testMachine2)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error, got %v", err)
|
|
}
|
|
if testResult2 != nil {
|
|
t.Fatal("expected nil result")
|
|
}
|
|
|
|
// Test #3: Delete the MachineSet and lookup should fail
|
|
if err := controller.machineSetInformer.Informer().GetStore().Delete(testResult1); err != nil {
|
|
t.Fatalf("unexpected error, got %v", err)
|
|
}
|
|
testResult3, err := controller.findMachineOwner(testConfig.machines[0].DeepCopy())
|
|
if err != nil {
|
|
t.Fatalf("unexpected error, got %v", err)
|
|
}
|
|
if testResult3 != nil {
|
|
t.Fatal("expected lookup to fail")
|
|
}
|
|
}
|
|
|
|
func TestControllerFindMachineByProviderID(t *testing.T) {
|
|
testConfig := createMachineSetTestConfig(testNamespace, 1, map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "10",
|
|
})
|
|
|
|
controller, stop := mustCreateTestController(t, testConfig)
|
|
defer stop()
|
|
|
|
// Remove all the "machine" annotation values on all the
|
|
// nodes. We want to force findMachineByProviderID() to only
|
|
// be successful by searching on provider ID.
|
|
for _, node := range testConfig.nodes {
|
|
delete(node.Annotations, machineAnnotationKey)
|
|
if err := controller.nodeInformer.GetStore().Update(node); err != nil {
|
|
t.Fatalf("unexpected error updating node, got %v", err)
|
|
}
|
|
}
|
|
|
|
// Test #1: Verify underlying machine provider ID matches
|
|
machine, err := controller.findMachineByProviderID(normalizedProviderString(testConfig.nodes[0].Spec.ProviderID))
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if machine == nil {
|
|
t.Fatal("expected to find machine")
|
|
}
|
|
|
|
if !reflect.DeepEqual(machine, testConfig.machines[0]) {
|
|
t.Fatalf("expected machines to be equal - expected %+v, got %+v", testConfig.machines[0], machine)
|
|
}
|
|
|
|
// Test #2: Verify machine returned by fake provider ID is correct machine
|
|
fakeProviderID := fmt.Sprintf("%s$s/%s", testConfig.machines[0].Namespace, testConfig.machines[0].Name)
|
|
machine, err = controller.findMachineByProviderID(normalizedProviderID(fakeProviderID))
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if machine != nil {
|
|
t.Fatal("expected find to fail")
|
|
}
|
|
|
|
// Test #3: Verify machine is not found if it has a
|
|
// non-existent or different provider ID.
|
|
machine = testConfig.machines[0].DeepCopy()
|
|
machine.Spec.ProviderID = pointer.StringPtr("does-not-match")
|
|
if err := controller.machineInformer.Informer().GetStore().Update(machine); err != nil {
|
|
t.Fatalf("unexpected error updating machine, got %v", err)
|
|
}
|
|
machine, err = controller.findMachineByProviderID(normalizedProviderString(testConfig.nodes[0].Spec.ProviderID))
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if machine != nil {
|
|
t.Fatal("expected find to fail")
|
|
}
|
|
}
|
|
|
|
func TestControllerFindNodeByNodeName(t *testing.T) {
|
|
testConfig := createMachineSetTestConfig(testNamespace, 1, map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "10",
|
|
})
|
|
|
|
controller, stop := mustCreateTestController(t, testConfig)
|
|
defer stop()
|
|
|
|
// Test #1: Verify known node can be found
|
|
node, err := controller.findNodeByNodeName(testConfig.nodes[0].Name)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if node == nil {
|
|
t.Fatal("expected lookup to be successful")
|
|
}
|
|
|
|
// Test #2: Verify non-existent node cannot be found
|
|
node, err = controller.findNodeByNodeName(testConfig.nodes[0].Name + "non-existent")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if node != nil {
|
|
t.Fatal("expected lookup to fail")
|
|
}
|
|
}
|
|
|
|
func TestControllerMachinesInMachineSet(t *testing.T) {
|
|
testConfig1 := createMachineSetTestConfig("testConfig1", 5, map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "10",
|
|
})
|
|
|
|
controller, stop := mustCreateTestController(t, testConfig1)
|
|
defer stop()
|
|
|
|
// Construct a second set of objects and add the machines,
|
|
// nodes and the additional machineset to the existing set of
|
|
// test objects in the controller. This gives us two
|
|
// machinesets, each with their own machines and linked nodes.
|
|
testConfig2 := createMachineSetTestConfig("testConfig2", 5, map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "10",
|
|
})
|
|
|
|
if err := addTestConfigs(t, controller, testConfig2); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
machinesInTestObjs1, err := controller.listMachines(testConfig1.spec.namespace, labels.Everything())
|
|
if err != nil {
|
|
t.Fatalf("error listing machines: %v", err)
|
|
}
|
|
|
|
machinesInTestObjs2, err := controller.listMachines(testConfig2.spec.namespace, labels.Everything())
|
|
if err != nil {
|
|
t.Fatalf("error listing machines: %v", err)
|
|
}
|
|
|
|
actual := len(machinesInTestObjs1) + len(machinesInTestObjs2)
|
|
expected := len(testConfig1.machines) + len(testConfig2.machines)
|
|
if actual != expected {
|
|
t.Fatalf("expected %d machines, got %d", expected, actual)
|
|
}
|
|
|
|
// Sort results as order is not guaranteed.
|
|
sort.Slice(machinesInTestObjs1, func(i, j int) bool {
|
|
return machinesInTestObjs1[i].Name < machinesInTestObjs1[j].Name
|
|
})
|
|
sort.Slice(machinesInTestObjs2, func(i, j int) bool {
|
|
return machinesInTestObjs2[i].Name < machinesInTestObjs2[j].Name
|
|
})
|
|
|
|
for i, m := range machinesInTestObjs1 {
|
|
if m.Name != testConfig1.machines[i].Name {
|
|
t.Errorf("expected %q, got %q", testConfig1.machines[i].Name, m.Name)
|
|
}
|
|
if m.Namespace != testConfig1.machines[i].Namespace {
|
|
t.Errorf("expected %q, got %q", testConfig1.machines[i].Namespace, m.Namespace)
|
|
}
|
|
}
|
|
|
|
for i, m := range machinesInTestObjs2 {
|
|
if m.Name != testConfig2.machines[i].Name {
|
|
t.Errorf("expected %q, got %q", testConfig2.machines[i].Name, m.Name)
|
|
}
|
|
if m.Namespace != testConfig2.machines[i].Namespace {
|
|
t.Errorf("expected %q, got %q", testConfig2.machines[i].Namespace, m.Namespace)
|
|
}
|
|
}
|
|
|
|
// Finally everything in the respective objects should be equal.
|
|
if !reflect.DeepEqual(testConfig1.machines, machinesInTestObjs1) {
|
|
t.Fatalf("expected %+v, got %+v", testConfig1.machines, machinesInTestObjs1)
|
|
}
|
|
if !reflect.DeepEqual(testConfig2.machines, machinesInTestObjs2) {
|
|
t.Fatalf("expected %+v, got %+v", testConfig2.machines, machinesInTestObjs2)
|
|
}
|
|
}
|
|
|
|
func TestControllerLookupNodeGroupForNonExistentNode(t *testing.T) {
|
|
testConfig := createMachineSetTestConfig(testNamespace, 1, map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "10",
|
|
})
|
|
|
|
controller, stop := mustCreateTestController(t, testConfig)
|
|
defer stop()
|
|
|
|
node := testConfig.nodes[0].DeepCopy()
|
|
node.Spec.ProviderID = "does-not-exist"
|
|
|
|
ng, err := controller.nodeGroupForNode(node)
|
|
|
|
// Looking up a node that doesn't exist doesn't generate an
|
|
// error. But, equally, the ng should actually be nil.
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if ng != nil {
|
|
t.Fatalf("unexpected nodegroup: %v", ng)
|
|
}
|
|
}
|
|
|
|
func TestControllerNodeGroupForNodeWithMissingMachineOwner(t *testing.T) {
|
|
test := func(t *testing.T, testConfig *testConfig) {
|
|
controller, stop := mustCreateTestController(t, testConfig)
|
|
defer stop()
|
|
|
|
machine := testConfig.machines[0].DeepCopy()
|
|
machine.OwnerReferences = []v1.OwnerReference{}
|
|
if err := controller.machineInformer.Informer().GetStore().Update(newUnstructuredFromMachine(machine)); err != nil {
|
|
t.Fatalf("unexpected error updating machine, got %v", err)
|
|
}
|
|
|
|
ng, err := controller.nodeGroupForNode(testConfig.nodes[0])
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if ng != nil {
|
|
t.Fatalf("unexpected nodegroup: %v", ng)
|
|
}
|
|
}
|
|
|
|
t.Run("MachineSet", func(t *testing.T) {
|
|
testConfig := createMachineSetTestConfig(testNamespace, 1, map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "10",
|
|
})
|
|
test(t, testConfig)
|
|
})
|
|
|
|
t.Run("MachineDeployment", func(t *testing.T) {
|
|
testConfig := createMachineDeploymentTestConfig(testNamespace, 1, map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "10",
|
|
})
|
|
test(t, testConfig)
|
|
})
|
|
}
|
|
|
|
func TestControllerNodeGroupForNodeWithPositiveScalingBounds(t *testing.T) {
|
|
test := func(t *testing.T, testConfig *testConfig) {
|
|
controller, stop := mustCreateTestController(t, testConfig)
|
|
defer stop()
|
|
|
|
ng, err := controller.nodeGroupForNode(testConfig.nodes[0])
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
// We don't scale from 0 so nodes must belong to a
|
|
// nodegroup that has a scale size of at least 1.
|
|
if ng != nil {
|
|
t.Fatalf("unexpected nodegroup: %v", ng)
|
|
}
|
|
}
|
|
|
|
t.Run("MachineSet", func(t *testing.T) {
|
|
testConfig := createMachineSetTestConfig(testNamespace, 1, map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "1",
|
|
})
|
|
test(t, testConfig)
|
|
})
|
|
|
|
t.Run("MachineDeployment", func(t *testing.T) {
|
|
testConfig := createMachineDeploymentTestConfig(testNamespace, 1, map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "1",
|
|
})
|
|
test(t, testConfig)
|
|
})
|
|
}
|
|
|
|
func TestControllerNodeGroups(t *testing.T) {
|
|
assertNodegroupLen := func(t *testing.T, controller *machineController, expected int) {
|
|
t.Helper()
|
|
nodegroups, err := controller.nodeGroups()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if got := len(nodegroups); got != expected {
|
|
t.Fatalf("expected %d, got %d", expected, got)
|
|
}
|
|
}
|
|
|
|
annotations := map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "2",
|
|
}
|
|
|
|
controller, stop := mustCreateTestController(t)
|
|
defer stop()
|
|
|
|
// Test #1: zero nodegroups
|
|
assertNodegroupLen(t, controller, 0)
|
|
|
|
// Test #2: add 5 machineset-based nodegroups
|
|
machineSetConfigs := createMachineSetTestConfigs("MachineSet", 5, 1, annotations)
|
|
if err := addTestConfigs(t, controller, machineSetConfigs...); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
assertNodegroupLen(t, controller, 5)
|
|
|
|
// Test #2: add 2 machinedeployment-based nodegroups
|
|
machineDeploymentConfigs := createMachineDeploymentTestConfigs("MachineDeployment", 2, 1, annotations)
|
|
if err := addTestConfigs(t, controller, machineDeploymentConfigs...); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
assertNodegroupLen(t, controller, 7)
|
|
|
|
// Test #3: delete 5 machineset-backed objects
|
|
if err := deleteTestConfigs(t, controller, machineSetConfigs...); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
assertNodegroupLen(t, controller, 2)
|
|
|
|
// Test #4: delete 2 machinedeployment-backed objects
|
|
if err := deleteTestConfigs(t, controller, machineDeploymentConfigs...); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
assertNodegroupLen(t, controller, 0)
|
|
|
|
annotations = map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "1",
|
|
}
|
|
|
|
// Test #5: machineset with no scaling bounds results in no nodegroups
|
|
machineSetConfigs = createMachineSetTestConfigs("MachineSet", 5, 1, annotations)
|
|
if err := addTestConfigs(t, controller, machineSetConfigs...); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
assertNodegroupLen(t, controller, 0)
|
|
|
|
// Test #6: machinedeployment with no scaling bounds results in no nodegroups
|
|
machineDeploymentConfigs = createMachineDeploymentTestConfigs("MachineDeployment", 2, 1, annotations)
|
|
if err := addTestConfigs(t, controller, machineDeploymentConfigs...); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
assertNodegroupLen(t, controller, 0)
|
|
|
|
annotations = map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "-1",
|
|
nodeGroupMaxSizeAnnotationKey: "1",
|
|
}
|
|
|
|
// Test #7: machineset with bad scaling bounds results in an error and no nodegroups
|
|
machineSetConfigs = createMachineSetTestConfigs("MachineSet", 5, 1, annotations)
|
|
if err := addTestConfigs(t, controller, machineSetConfigs...); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if _, err := controller.nodeGroups(); err == nil {
|
|
t.Fatalf("expected an error")
|
|
}
|
|
|
|
// Test #8: machinedeployment with bad scaling bounds results in an error and no nodegroups
|
|
machineDeploymentConfigs = createMachineDeploymentTestConfigs("MachineDeployment", 2, 1, annotations)
|
|
if err := addTestConfigs(t, controller, machineDeploymentConfigs...); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if _, err := controller.nodeGroups(); err == nil {
|
|
t.Fatalf("expected an error")
|
|
}
|
|
}
|
|
|
|
func TestControllerNodeGroupsNodeCount(t *testing.T) {
|
|
type testCase struct {
|
|
nodeGroups int
|
|
nodesPerGroup int
|
|
expectedNodeGroups int
|
|
expectedNodesPerGroup int
|
|
}
|
|
|
|
var testCases = []testCase{{
|
|
nodeGroups: 0,
|
|
nodesPerGroup: 0,
|
|
expectedNodeGroups: 0,
|
|
expectedNodesPerGroup: 0,
|
|
}, {
|
|
nodeGroups: 1,
|
|
nodesPerGroup: 0,
|
|
expectedNodeGroups: 0,
|
|
expectedNodesPerGroup: 0,
|
|
}, {
|
|
nodeGroups: 2,
|
|
nodesPerGroup: 10,
|
|
expectedNodeGroups: 2,
|
|
expectedNodesPerGroup: 10,
|
|
}}
|
|
|
|
test := func(t *testing.T, tc testCase, testConfigs []*testConfig) {
|
|
controller, stop := mustCreateTestController(t, testConfigs...)
|
|
defer stop()
|
|
|
|
nodegroups, err := controller.nodeGroups()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if got := len(nodegroups); got != tc.expectedNodeGroups {
|
|
t.Fatalf("expected %d, got %d", tc.expectedNodeGroups, got)
|
|
}
|
|
|
|
for i := range nodegroups {
|
|
nodes, err := nodegroups[i].Nodes()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if got := len(nodes); got != tc.expectedNodesPerGroup {
|
|
t.Fatalf("expected %d, got %d", tc.expectedNodesPerGroup, got)
|
|
}
|
|
}
|
|
}
|
|
|
|
annotations := map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "10",
|
|
}
|
|
|
|
t.Run("MachineSet", func(t *testing.T) {
|
|
for _, tc := range testCases {
|
|
test(t, tc, createMachineSetTestConfigs(testNamespace, tc.nodeGroups, tc.nodesPerGroup, annotations))
|
|
}
|
|
})
|
|
|
|
t.Run("MachineDeployment", func(t *testing.T) {
|
|
for _, tc := range testCases {
|
|
test(t, tc, createMachineDeploymentTestConfigs(testNamespace, tc.nodeGroups, tc.nodesPerGroup, annotations))
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestControllerFindMachineFromNodeAnnotation(t *testing.T) {
|
|
testConfig := createMachineSetTestConfig(testNamespace, 1, map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "10",
|
|
})
|
|
|
|
controller, stop := mustCreateTestController(t, testConfig)
|
|
defer stop()
|
|
|
|
// Remove all the provider ID values on all the machines. We
|
|
// want to force findMachineByProviderID() to fallback to
|
|
// searching using the annotation on the node object.
|
|
for _, machine := range testConfig.machines {
|
|
machine.Spec.ProviderID = nil
|
|
if err := controller.machineInformer.Informer().GetStore().Update(newUnstructuredFromMachine(machine)); err != nil {
|
|
t.Fatalf("unexpected error updating machine, got %v", err)
|
|
}
|
|
}
|
|
|
|
// Test #1: Verify machine can be found from node annotation
|
|
machine, err := controller.findMachineByProviderID(normalizedProviderString(testConfig.nodes[0].Spec.ProviderID))
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if machine == nil {
|
|
t.Fatal("expected to find machine")
|
|
}
|
|
if !reflect.DeepEqual(machine, testConfig.machines[0]) {
|
|
t.Fatalf("expected machines to be equal - expected %+v, got %+v", testConfig.machines[0], machine)
|
|
}
|
|
|
|
// Test #2: Verify machine is not found if it has no
|
|
// corresponding machine annotation.
|
|
node := testConfig.nodes[0].DeepCopy()
|
|
delete(node.Annotations, machineAnnotationKey)
|
|
if err := controller.nodeInformer.GetStore().Update(node); err != nil {
|
|
t.Fatalf("unexpected error updating node, got %v", err)
|
|
}
|
|
machine, err = controller.findMachineByProviderID(normalizedProviderString(testConfig.nodes[0].Spec.ProviderID))
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if machine != nil {
|
|
t.Fatal("expected find to fail")
|
|
}
|
|
}
|
|
|
|
func TestControllerMachineSetNodeNamesWithoutLinkage(t *testing.T) {
|
|
testConfig := createMachineSetTestConfig(testNamespace, 3, map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "10",
|
|
})
|
|
|
|
controller, stop := mustCreateTestController(t, testConfig)
|
|
defer stop()
|
|
|
|
// Remove all linkage between node and machine.
|
|
for _, machine := range testConfig.machines {
|
|
machine.Spec.ProviderID = nil
|
|
if err := controller.machineInformer.Informer().GetStore().Update(newUnstructuredFromMachine(machine)); err != nil {
|
|
t.Fatalf("unexpected error updating machine, got %v", err)
|
|
}
|
|
}
|
|
for _, machine := range testConfig.machines {
|
|
machine.Status.NodeRef = nil
|
|
if err := controller.machineInformer.Informer().GetStore().Update(newUnstructuredFromMachine(machine)); err != nil {
|
|
t.Fatalf("unexpected error updating machine, got %v", err)
|
|
}
|
|
}
|
|
|
|
nodegroups, err := controller.nodeGroups()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if l := len(nodegroups); l != 1 {
|
|
t.Fatalf("expected 1 nodegroup, got %d", l)
|
|
}
|
|
|
|
ng := nodegroups[0]
|
|
nodeNames, err := ng.Nodes()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
// We removed all linkage - so we should get 0 nodes back.
|
|
if len(nodeNames) != 0 {
|
|
t.Fatalf("expected len=0, got len=%v", len(nodeNames))
|
|
}
|
|
}
|
|
|
|
func TestControllerMachineSetNodeNamesUsingProviderID(t *testing.T) {
|
|
testConfig := createMachineSetTestConfig(testNamespace, 3, map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "10",
|
|
})
|
|
|
|
controller, stop := mustCreateTestController(t, testConfig)
|
|
defer stop()
|
|
|
|
// Remove Status.NodeRef.Name on all the machines. We want to
|
|
// force machineSetNodeNames() to only consider the provider
|
|
// ID for lookups.
|
|
for _, machine := range testConfig.machines {
|
|
machine.Status.NodeRef = nil
|
|
if err := controller.machineInformer.Informer().GetStore().Update(newUnstructuredFromMachine(machine)); err != nil {
|
|
t.Fatalf("unexpected error updating machine, got %v", err)
|
|
}
|
|
}
|
|
|
|
nodegroups, err := controller.nodeGroups()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if l := len(nodegroups); l != 1 {
|
|
t.Fatalf("expected 1 nodegroup, got %d", l)
|
|
}
|
|
|
|
ng := nodegroups[0]
|
|
nodeNames, err := ng.Nodes()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if len(nodeNames) != len(testConfig.nodes) {
|
|
t.Fatalf("expected len=%v, got len=%v", len(testConfig.nodes), len(nodeNames))
|
|
}
|
|
|
|
sort.Slice(nodeNames, func(i, j int) bool {
|
|
return nodeNames[i].Id < nodeNames[j].Id
|
|
})
|
|
|
|
for i := range testConfig.nodes {
|
|
if nodeNames[i].Id != testConfig.nodes[i].Spec.ProviderID {
|
|
t.Fatalf("expected %q, got %q", testConfig.nodes[i].Spec.ProviderID, nodeNames[i].Id)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestControllerMachineSetNodeNamesUsingStatusNodeRefName(t *testing.T) {
|
|
testConfig := createMachineSetTestConfig(testNamespace, 3, map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "10",
|
|
})
|
|
|
|
controller, stop := mustCreateTestController(t, testConfig)
|
|
defer stop()
|
|
|
|
// Remove all the provider ID values on all the machines. We
|
|
// want to force machineSetNodeNames() to fallback to
|
|
// searching using Status.NodeRef.Name.
|
|
for _, machine := range testConfig.machines {
|
|
machine.Spec.ProviderID = nil
|
|
if err := controller.machineInformer.Informer().GetStore().Update(newUnstructuredFromMachine(machine)); err != nil {
|
|
t.Fatalf("unexpected error updating machine, got %v", err)
|
|
}
|
|
}
|
|
|
|
nodegroups, err := controller.nodeGroups()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if l := len(nodegroups); l != 1 {
|
|
t.Fatalf("expected 1 nodegroup, got %d", l)
|
|
}
|
|
|
|
nodeNames, err := nodegroups[0].Nodes()
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
if len(nodeNames) != len(testConfig.nodes) {
|
|
t.Fatalf("expected len=%v, got len=%v", len(testConfig.nodes), len(nodeNames))
|
|
}
|
|
|
|
sort.Slice(nodeNames, func(i, j int) bool {
|
|
return nodeNames[i].Id < nodeNames[j].Id
|
|
})
|
|
|
|
for i := range testConfig.nodes {
|
|
if nodeNames[i].Id != testConfig.nodes[i].Spec.ProviderID {
|
|
t.Fatalf("expected %q, got %q", testConfig.nodes[i].Spec.ProviderID, nodeNames[i].Id)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestControllerGetAPIVersionGroup(t *testing.T) {
|
|
expected := "mygroup"
|
|
if err := os.Setenv(CAPIGroupEnvVar, expected); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
observed := getCAPIGroup()
|
|
if observed != expected {
|
|
t.Fatalf("Wrong Version Group detected, expected %q, got %q", expected, observed)
|
|
}
|
|
|
|
expected = defaultCAPIGroup
|
|
if err := os.Setenv(CAPIGroupEnvVar, ""); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
observed = getCAPIGroup()
|
|
if observed != expected {
|
|
t.Fatalf("Wrong Version Group detected, expected %q, got %q", expected, observed)
|
|
}
|
|
}
|
|
|
|
func TestControllerGetAPIVersionGroupWithMachineDeployments(t *testing.T) {
|
|
testConfig := createMachineDeploymentTestConfig(testNamespace, 1, map[string]string{
|
|
nodeGroupMinSizeAnnotationKey: "1",
|
|
nodeGroupMaxSizeAnnotationKey: "1",
|
|
})
|
|
if err := os.Setenv(CAPIGroupEnvVar, customCAPIGroup); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
|
|
testConfig.machineDeployment.TypeMeta.APIVersion = fmt.Sprintf("%s/v1beta1", customCAPIGroup)
|
|
testConfig.machineSet.TypeMeta.APIVersion = fmt.Sprintf("%s/v1beta1", customCAPIGroup)
|
|
for _, machine := range testConfig.machines {
|
|
machine.TypeMeta.APIVersion = fmt.Sprintf("%s/v1beta1", customCAPIGroup)
|
|
}
|
|
controller, stop := mustCreateTestController(t, testConfig)
|
|
defer stop()
|
|
|
|
machineDeployments, err := controller.listMachineDeployments(testNamespace, labels.Everything())
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if l := len(machineDeployments); l != 1 {
|
|
t.Fatalf("Incorrect number of MachineDeployments, expected 1, got %d", l)
|
|
}
|
|
|
|
machineSets, err := controller.listMachineSets(testNamespace, labels.Everything())
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if l := len(machineSets); l != 1 {
|
|
t.Fatalf("Incorrect number of MachineSets, expected 1, got %d", l)
|
|
}
|
|
|
|
machines, err := controller.listMachines(testNamespace, labels.Everything())
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if l := len(machines); l != 1 {
|
|
t.Fatalf("Incorrect number of Machines, expected 1, got %d", l)
|
|
}
|
|
|
|
if err := os.Unsetenv(CAPIGroupEnvVar); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestGetAPIGroupPreferredVersion(t *testing.T) {
|
|
testCases := []struct {
|
|
description string
|
|
APIGroup string
|
|
preferredVersion string
|
|
error bool
|
|
}{
|
|
{
|
|
description: "find version for default API group",
|
|
APIGroup: defaultCAPIGroup,
|
|
preferredVersion: "v1alpha3",
|
|
error: false,
|
|
},
|
|
{
|
|
description: "find version for another API group",
|
|
APIGroup: customCAPIGroup,
|
|
preferredVersion: "v1beta1",
|
|
error: false,
|
|
},
|
|
{
|
|
description: "API group does not exist",
|
|
APIGroup: "does.not.exist",
|
|
preferredVersion: "",
|
|
error: true,
|
|
},
|
|
}
|
|
|
|
discoveryClient := &fakediscovery.FakeDiscovery{
|
|
Fake: &clientgotesting.Fake{
|
|
Resources: []*v1.APIResourceList{
|
|
{
|
|
GroupVersion: fmt.Sprintf("%s/v1beta1", customCAPIGroup),
|
|
},
|
|
{
|
|
GroupVersion: fmt.Sprintf("%s/v1alpha3", defaultCAPIGroup),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
t.Run(tc.description, func(t *testing.T) {
|
|
version, err := getAPIGroupPreferredVersion(discoveryClient, tc.APIGroup)
|
|
if (err != nil) != tc.error {
|
|
t.Errorf("expected to have error: %t. Had an error: %t", tc.error, err != nil)
|
|
}
|
|
if version != tc.preferredVersion {
|
|
t.Errorf("expected %v, got: %v", tc.preferredVersion, version)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGroupVersionHasResource(t *testing.T) {
|
|
testCases := []struct {
|
|
description string
|
|
APIGroup string
|
|
resourceName string
|
|
expected bool
|
|
error bool
|
|
}{
|
|
{
|
|
description: "true when it finds resource",
|
|
resourceName: resourceNameMachineDeployment,
|
|
APIGroup: fmt.Sprintf("%s/v1alpha3", defaultCAPIGroup),
|
|
expected: true,
|
|
error: false,
|
|
},
|
|
{
|
|
description: "false when it does not find resource",
|
|
resourceName: "resourceDoesNotExist",
|
|
APIGroup: fmt.Sprintf("%s/v1alpha3", defaultCAPIGroup),
|
|
expected: false,
|
|
error: false,
|
|
},
|
|
{
|
|
description: "error when invalid groupVersion",
|
|
resourceName: resourceNameMachineDeployment,
|
|
APIGroup: "APIGroupDoesNotExist",
|
|
expected: false,
|
|
error: true,
|
|
},
|
|
}
|
|
|
|
discoveryClient := &fakediscovery.FakeDiscovery{
|
|
Fake: &clientgotesting.Fake{
|
|
Resources: []*v1.APIResourceList{
|
|
{
|
|
GroupVersion: fmt.Sprintf("%s/v1alpha3", defaultCAPIGroup),
|
|
APIResources: []v1.APIResource{
|
|
{
|
|
Name: resourceNameMachineDeployment,
|
|
},
|
|
{
|
|
Name: resourceNameMachineSet,
|
|
},
|
|
{
|
|
Name: resourceNameMachine,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
t.Run(tc.description, func(t *testing.T) {
|
|
got, err := groupVersionHasResource(discoveryClient, tc.APIGroup, tc.resourceName)
|
|
if (err != nil) != tc.error {
|
|
t.Errorf("expected to have error: %t. Had an error: %t", tc.error, err != nil)
|
|
}
|
|
if got != tc.expected {
|
|
t.Errorf("expected %v, got: %v", tc.expected, got)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsFailedMachineProviderID(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
providerID normalizedProviderID
|
|
expected bool
|
|
}{
|
|
{
|
|
name: "with the failed machine prefix",
|
|
providerID: normalizedProviderID(fmt.Sprintf("%sfoo", failedMachinePrefix)),
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "without the failed machine prefix",
|
|
providerID: normalizedProviderID("foo"),
|
|
expected: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
if got := isFailedMachineProviderID(tc.providerID); got != tc.expected {
|
|
t.Errorf("test case: %s, expected: %v, got: %v", tc.name, tc.expected, got)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMachineKeyFromFailedProviderID(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
providerID normalizedProviderID
|
|
expected string
|
|
}{
|
|
{
|
|
name: "with a valid failed machine prefix",
|
|
providerID: normalizedProviderID(fmt.Sprintf("%stest-namespace_foo", failedMachinePrefix)),
|
|
expected: "test-namespace/foo",
|
|
},
|
|
{
|
|
name: "with a machine with an underscore in the name",
|
|
providerID: normalizedProviderID(fmt.Sprintf("%stest-namespace_foo_bar", failedMachinePrefix)),
|
|
expected: "test-namespace/foo_bar",
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
if got := machineKeyFromFailedProviderID(tc.providerID); got != tc.expected {
|
|
t.Errorf("test case: %s, expected: %q, got: %q", tc.name, tc.expected, got)
|
|
}
|
|
})
|
|
}
|
|
}
|