Skip to content

Commit 0c1ceff

Browse files
authored
bmh: add wait until annotation exists and tests (rh-ecosystem-edge#588)
This adds a method to wait until an annotation exists on the BMH along with unit tests for it.
1 parent 6457043 commit 0c1ceff

File tree

3 files changed

+142
-11
lines changed

3 files changed

+142
-11
lines changed

pkg/bmh/baremetalhost.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,51 @@ func (builder *BmhBuilder) WaitUntilDeleted(timeout time.Duration) error {
649649
return err
650650
}
651651

652+
// WaitUntilAnnotationExists waits up to the specified timeout until the annotation exists.
653+
func (builder *BmhBuilder) WaitUntilAnnotationExists(annotation string, timeout time.Duration) (*BmhBuilder, error) {
654+
if valid, err := builder.validate(); !valid {
655+
return nil, err
656+
}
657+
658+
if annotation == "" {
659+
glog.V(100).Info("BMH annotation key cannot be empty")
660+
661+
return nil, fmt.Errorf("bmh annotation key cannot be empty")
662+
}
663+
664+
glog.V(100).Infof(
665+
"Waiting until BMH %s in namespace %s has annotation %s",
666+
builder.Definition.Name, builder.Definition.Namespace, annotation)
667+
668+
if !builder.Exists() {
669+
return nil, fmt.Errorf(
670+
"baremetalhost object %s does not exist in namespace %s", builder.Definition.Name, builder.Definition.Namespace)
671+
}
672+
673+
var err error
674+
err = wait.PollUntilContextTimeout(
675+
context.TODO(), time.Second, timeout, true, func(ctx context.Context) (bool, error) {
676+
builder.Object, err = builder.Get()
677+
if err != nil {
678+
glog.V(100).Infof("failed to get bmh %s/%s: %v", builder.Definition.Namespace, builder.Definition.Name, err)
679+
680+
return false, nil
681+
}
682+
683+
if _, ok := builder.Object.Annotations[annotation]; !ok {
684+
return false, nil
685+
}
686+
687+
return true, nil
688+
})
689+
690+
if err != nil {
691+
return nil, err
692+
}
693+
694+
return builder, nil
695+
}
696+
652697
// validate will check that the builder and builder definition are properly initialized before
653698
// accessing any member fields.
654699
func (builder *BmhBuilder) validate() (bool, error) {

pkg/bmh/baremetalhost_test.go

Lines changed: 95 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ var (
2020
defaultBmHostSecretName = "testsecret"
2121
defaultBmHostMacAddress = "AA:BB:CC:11:22:33"
2222
defaultBmHostBootMode = "UEFISecureBoot"
23+
defaultBmHostAnnotation = "annotation.openshift.io/test-annotation"
2324
testSchemes = []clients.SchemeAttacher{
2425
bmhv1alpha1.AddToScheme,
2526
}
@@ -966,6 +967,86 @@ func TestBareMetalHostDeleteAndWaitUntilDeleted(t *testing.T) {
966967
}
967968
}
968969

970+
func TestBareMetalHostWaitUntilAnnotationExists(t *testing.T) {
971+
testCases := []struct {
972+
annotation string
973+
exists bool
974+
valid bool
975+
annotated bool
976+
expectedError error
977+
}{
978+
{
979+
annotation: defaultBmHostAnnotation,
980+
exists: true,
981+
valid: true,
982+
annotated: true,
983+
expectedError: nil,
984+
},
985+
{
986+
annotation: "",
987+
exists: true,
988+
valid: true,
989+
annotated: true,
990+
expectedError: fmt.Errorf("bmh annotation key cannot be empty"),
991+
},
992+
{
993+
annotation: defaultBmHostAnnotation,
994+
exists: false,
995+
valid: true,
996+
annotated: true,
997+
expectedError: fmt.Errorf(
998+
"baremetalhost object %s does not exist in namespace %s", defaultBmHostName, defaultBmHostNsName),
999+
},
1000+
{
1001+
annotation: defaultBmHostAnnotation,
1002+
exists: true,
1003+
valid: false,
1004+
annotated: true,
1005+
expectedError: fmt.Errorf("not acceptable 'bootMode' value"),
1006+
},
1007+
{
1008+
annotation: defaultBmHostAnnotation,
1009+
exists: true,
1010+
valid: true,
1011+
annotated: false,
1012+
expectedError: context.DeadlineExceeded,
1013+
},
1014+
}
1015+
1016+
for _, testCase := range testCases {
1017+
var (
1018+
runtimeObjects []runtime.Object
1019+
builder *BmhBuilder
1020+
)
1021+
1022+
if testCase.exists {
1023+
bmh := buildDummyBmHost(bmhv1alpha1.StateProvisioned, bmhv1alpha1.OperationalStatusOK)
1024+
1025+
if testCase.annotated {
1026+
bmh.Annotations = map[string]string{
1027+
defaultBmHostAnnotation: "",
1028+
}
1029+
}
1030+
1031+
runtimeObjects = append(runtimeObjects, bmh)
1032+
}
1033+
1034+
testSettings := clients.GetTestClients(clients.TestClientParams{
1035+
K8sMockObjects: runtimeObjects,
1036+
SchemeAttachers: testSchemes,
1037+
})
1038+
1039+
if testCase.valid {
1040+
builder = buildValidBmHostBuilder(testSettings)
1041+
} else {
1042+
builder = buildInValidBmHostBuilder(testSettings)
1043+
}
1044+
1045+
_, err := builder.WaitUntilAnnotationExists(testCase.annotation, time.Second)
1046+
assert.Equal(t, testCase.expectedError, err)
1047+
}
1048+
}
1049+
9691050
func TestBareMetalHostWaitUntilDeleted(t *testing.T) {
9701051
testCases := []struct {
9711052
testBmHost *BmhBuilder
@@ -1026,19 +1107,14 @@ func buildBareMetalHostTestClientWithDummyObject(state ...bmhv1alpha1.Provisioni
10261107
}
10271108

10281109
return clients.GetTestClients(clients.TestClientParams{
1029-
K8sMockObjects: buildDummyBmHost(provisionState),
1110+
K8sMockObjects: buildDummyBmHostObject(provisionState),
10301111
SchemeAttachers: testSchemes,
10311112
})
10321113
}
10331114

10341115
func buildDummyBmHost(
1035-
state bmhv1alpha1.ProvisioningState, operationalStatus ...bmhv1alpha1.OperationalStatus) []runtime.Object {
1036-
operState := bmhv1alpha1.OperationalStatusOK
1037-
if len(operationalStatus) > 0 {
1038-
operState = operationalStatus[0]
1039-
}
1040-
1041-
return append([]runtime.Object{}, &bmhv1alpha1.BareMetalHost{
1116+
state bmhv1alpha1.ProvisioningState, operState bmhv1alpha1.OperationalStatus) *bmhv1alpha1.BareMetalHost {
1117+
return &bmhv1alpha1.BareMetalHost{
10421118
Spec: bmhv1alpha1.BareMetalHostSpec{
10431119
BMC: bmhv1alpha1.BMCDetails{
10441120
Address: defaultBmHostAddress,
@@ -1061,5 +1137,15 @@ func buildDummyBmHost(
10611137
State: state,
10621138
},
10631139
},
1064-
})
1140+
}
1141+
}
1142+
1143+
func buildDummyBmHostObject(
1144+
state bmhv1alpha1.ProvisioningState, operationalStatus ...bmhv1alpha1.OperationalStatus) []runtime.Object {
1145+
operState := bmhv1alpha1.OperationalStatusOK
1146+
if len(operationalStatus) > 0 {
1147+
operState = operationalStatus[0]
1148+
}
1149+
1150+
return append([]runtime.Object{}, buildDummyBmHost(state, operState))
10651151
}

pkg/bmh/list_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func TestBareMetalHostList(t *testing.T) {
6060

6161
if testCase.client {
6262
testSettings = clients.GetTestClients(clients.TestClientParams{
63-
K8sMockObjects: buildDummyBmHost(bmhv1alpha1.StateProvisioned),
63+
K8sMockObjects: buildDummyBmHostObject(bmhv1alpha1.StateProvisioned),
6464
SchemeAttachers: testSchemes,
6565
})
6666
}
@@ -194,7 +194,7 @@ func TestBareMetalWaitForAllBareMetalHostsInGoodOperationalState(t *testing.T) {
194194

195195
if testCase.client {
196196
testSettings = clients.GetTestClients(clients.TestClientParams{
197-
K8sMockObjects: buildDummyBmHost(bmhv1alpha1.StateProvisioned, testCase.operationalState),
197+
K8sMockObjects: buildDummyBmHostObject(bmhv1alpha1.StateProvisioned, testCase.operationalState),
198198
SchemeAttachers: testSchemes,
199199
})
200200
}

0 commit comments

Comments
 (0)