Repository: gardener/machine-controller-manager (go)

Issue:
Deletion of node object once VM is deleted
## Issue
Currently, the KCM seems to be having a bug where sometimes it is not able to delete the node object when the VM is deleted. 

## Possible solutions
1. Trace back the issue with the community and fix it there on Kubernetes upstream
2. Force MCM for node object deletion once VM deletion returns successfully.


Pull request:
Deletes nodes object on machine deletion
**What this PR does / why we need it**:
Deletes node object once the machine object is deleted. This removes any hanging node objects in the cluster. 

**Which issue(s) this PR fixes**:
Fixes #186 

**Special notes for your reviewer**:

**Release note**:
<!--  Write your release note:
1. Enter your release note in the below block.
2. If no release note is required, just write "NONE" within the block.

Format of block header: <category> <target_group>
Possible values:
- category:       improvement|noteworthy
- target_group:   user|operator|developer
-->
```improvement user
Deletes nodes object on machine (object) deletion
```


Patch:
diff --git a/pkg/controller/machine.go b/pkg/controller/machine.go
index cbf040969..1c54fb5d0 100644
--- a/pkg/controller/machine.go
+++ b/pkg/controller/machine.go
@@ -451,6 +451,7 @@ func (c *controller) machineUpdate(machine *v1alpha1.Machine, actualProviderID s
 
 func (c *controller) machineDelete(machine *v1alpha1.Machine, driver driver.Driver) error {
 	var err error
+	nodeName := machine.Status.Node
 
 	if finalizers := sets.NewString(machine.Finalizers...); finalizers.Has(DeleteFinalizerName) {
 		glog.V(2).Infof("Deleting Machine %q", machine.Name)
@@ -503,7 +504,6 @@ func (c *controller) machineDelete(machine *v1alpha1.Machine, driver driver.Driv
 			buf := bytes.NewBuffer([]byte{})
 			errBuf := bytes.NewBuffer([]byte{})
 
-			nodeName := machine.Status.Node
 			drainOptions := NewDrainOptions(
 				c.targetCoreClient,
 				timeOutDuration,
@@ -566,11 +566,22 @@ func (c *controller) machineDelete(machine *v1alpha1.Machine, driver driver.Driv
 			return err
 		}
 
+		// Delete node object
+		err = c.targetCoreClient.CoreV1().Nodes().Delete(nodeName, &metav1.DeleteOptions{})
+		if err != nil && !apierrors.IsNotFound(err) {
+			// If its an error, and anyother error than object not found
+			glog.Errorf("Deletion of Node Object %q failed due to error: %s", nodeName, err)
+			return err
+		}
+
+		// Remove finalizers from machine object
 		c.deleteMachineFinalizers(machine)
+
+		// Delete machine object
 		err = c.controlMachineClient.Machines(machine.Namespace).Delete(machine.Name, &metav1.DeleteOptions{})
 		if err != nil && !apierrors.IsNotFound(err) {
 			// If its an error, and anyother error than object not found
-			glog.Errorf("Deletion of Machine Object %s failed due to error: %s", machine.Name, err)
+			glog.Errorf("Deletion of Machine Object %q failed due to error: %s", machine.Name, err)
 			return err
 		}
 


Test patch:
diff --git a/pkg/controller/machine_test.go b/pkg/controller/machine_test.go
index 85c2b44a7..0e2e79c1b 100644
--- a/pkg/controller/machine_test.go
+++ b/pkg/controller/machine_test.go
@@ -731,12 +731,18 @@ var _ = Describe("machine", func() {
 					Expect(err).ToNot(HaveOccurred())
 				}
 
-				machine, err = controller.controlMachineClient.Machines(machine.Namespace).Get(machine.Name, metav1.GetOptions{})
+				node, nodeErr := controller.targetCoreClient.CoreV1().Nodes().Get(machine.Status.Node, metav1.GetOptions{})
+				machine, machineErr := controller.controlMachineClient.Machines(machine.Namespace).Get(machine.Name, metav1.GetOptions{})
+
 				if data.expect.machineDeleted {
-					Expect(err).To(HaveOccurred())
+					Expect(machineErr).To(HaveOccurred())
+					Expect(nodeErr).To(HaveOccurred())
 				} else {
-					Expect(err).ToNot(HaveOccurred())
+					Expect(machineErr).ToNot(HaveOccurred())
 					Expect(machine).ToNot(BeNil())
+
+					Expect(nodeErr).ToNot(HaveOccurred())
+					Expect(node).ToNot(BeNil())
 				}
 			},
 			Entry("Machine deletion", &data{