Skip to content

Commit

Permalink
Add tests for fetching Machine from NodeName
Browse files Browse the repository at this point in the history
  • Loading branch information
JoelSpeed committed Mar 23, 2020
1 parent 90eaab2 commit bd52ac7
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 7 deletions.
16 changes: 16 additions & 0 deletions pkg/termination/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"github.com/go-logr/logr"
machinev1 "github.com/openshift/machine-api-operator/pkg/apis/machine/v1beta1"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/client"
)
Expand Down Expand Up @@ -35,6 +36,8 @@ func NewHandler(logger logr.Logger, cfg *rest.Config, pollInterval time.Duration
panic(err)
}

logger = logger.WithValues("node", nodeName)

return &handler{
client: c,
pollURL: pollURL,
Expand Down Expand Up @@ -80,5 +83,18 @@ func (h *handler) Run(stop <-chan struct{}) error {
func (h *handler) run(ctx context.Context, wg *sync.WaitGroup) error {
defer wg.Done()

machine, err := h.getMachineForNode(ctx)
if err != nil {
return fmt.Errorf("error fetching machine for node (%q): %v", h.nodeName, err)
}

logger := h.log.WithValues("namespace", machine.Namespace, "machine", machine.Name)
logger.V(1).Info("Monitoring node for machine")

return fmt.Errorf("not implemented")
}

// getMachineForNodeName finds the Machine associated with the Node name given
func (h *handler) getMachineForNode(ctx context.Context) (*machinev1.Machine, error) {
return nil, fmt.Errorf("machine not found for node %q", h.nodeName)
}
130 changes: 123 additions & 7 deletions pkg/termination/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,26 @@ limitations under the License.
package termination

import (
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"time"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
machinev1 "github.com/openshift/machine-api-operator/pkg/apis/machine/v1beta1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/klogr"
"sigs.k8s.io/controller-runtime/pkg/client"
)

var notFoundFunc = func(rw http.ResponseWriter, req *http.Request) {
rw.WriteHeader(404)
}

var _ = Describe("Handler Suite", func() {
var terminationServer *httptest.Server
var httpHandler http.Handler
Expand All @@ -36,7 +46,8 @@ var _ = Describe("Handler Suite", func() {
// Reset test vars
terminationServer = nil
httpHandler = nil
nodeName = "testNode"
nodeName = "test-node"
httpHandler = newMockHTTPHandler(notFoundFunc)

h = &handler{
client: k8sClient,
Expand All @@ -62,15 +73,11 @@ var _ = Describe("Handler Suite", func() {
close(stop)
}
terminationServer.Close()

Expect(deleteAllMachines(k8sClient)).To(Succeed())
})

Context("when the handler is stopped", func() {
BeforeEach(func() {
httpHandler = newMockHTTPHandler(func(rw http.ResponseWriter, req *http.Request) {
rw.WriteHeader(404)
})
})

JustBeforeEach(func() {
close(stop)
})
Expand All @@ -79,6 +86,65 @@ var _ = Describe("Handler Suite", func() {
Eventually(errs).Should(Receive(BeNil()))
})
})

Context("when no machine exists for the node", func() {
It("should return an error upon starting", func() {
Eventually(errs).Should(Receive(MatchError("error fetching machine for node (\"test-node\"): machine not found for node \"test-node\"")))
})
})

Context("getMachineForNode", func() {
var machine *machinev1.Machine
var err error

JustBeforeEach(func() {
machine, err = h.getMachineForNode(ctx)
})

Context("with a broken client", func() {
BeforeEach(func() {
brokenClient, err := client.New(cfg, client.Options{Scheme: runtime.NewScheme()})
Expect(err).ToNot(HaveOccurred())
h.client = brokenClient
})

It("should return an error", func() {
Expect(err).ToNot(BeNil())
Expect(err.Error()).To(HavePrefix("error listing machines: no kind is registered for the type v1beta1.MachineList in scheme"))
})

It("should not return a machine", func() {
Expect(machine).To(BeNil())
})
})

Context("with no machine for the node name", func() {
It("should return an error", func() {
Expect(err).To(MatchError("machine not found for node \"test-node\""))
})

It("should not return a machine", func() {
Expect(machine).To(BeNil())
})
})

Context("with a machine matching the node name", func() {
var testMachine *machinev1.Machine

BeforeEach(func() {
testMachine = newTestMachine("test-machine", "test-namespace", nodeName)
createMachine(testMachine)
})

It("should not return an error", func() {
Expect(err).ToNot(HaveOccurred())
})

It("should return a machine", func() {
Expect(machine).To(Equal(testMachine))
})
})
})
})

// mockHTTPHandler is used to mock the pollURL responses during tests
Expand Down Expand Up @@ -106,3 +172,53 @@ func isClosed(ch <-chan struct{}) bool {

return false
}

func deleteAllMachines(c client.Client) error {
machineList := &machinev1.MachineList{}
err := c.List(ctx, machineList)
if err != nil {
return fmt.Errorf("error listing machines: %v", err)
}

// Delete all machines found
for _, machine := range machineList.Items {
m := machine
err := c.Delete(ctx, &m)
if err != nil {
return err
}
}
return nil
}

func newTestMachine(name, namespace, nodeName string) *machinev1.Machine {
return &machinev1.Machine{
TypeMeta: metav1.TypeMeta{
Kind: "Machine",
APIVersion: machinev1.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Status: machinev1.MachineStatus{
NodeRef: &corev1.ObjectReference{
Name: nodeName,
},
},
}
}

func createMachine(m *machinev1.Machine) {
typeMeta := m.TypeMeta
status := m.Status
Expect(k8sClient.Create(ctx, m)).To(Succeed())
m.Status = status
Expect(k8sClient.Status().Update(ctx, m)).To(Succeed())

// Fetch object to sync back to latest changes
key := client.ObjectKey{Namespace: m.Namespace, Name: m.Name}
Expect(k8sClient.Get(ctx, key, m)).To(Succeed())
// Restore TypeMeta as not restored by Get
m.TypeMeta = typeMeta
}

0 comments on commit bd52ac7

Please sign in to comment.