You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@submarine.apache.org by li...@apache.org on 2021/05/09 15:17:26 UTC

[submarine] branch master updated: SUBMARINE-816. Implement Submarine delete event handler

This is an automated email from the ASF dual-hosted git repository.

liuxun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/submarine.git


The following commit(s) were added to refs/heads/master by this push:
     new 0669b66  SUBMARINE-816. Implement Submarine delete event handler
0669b66 is described below

commit 0669b668c76dd19534fa29457265b1e34746c593
Author: Kai-Hsun Chen <b0...@ntu.edu.tw>
AuthorDate: Sat May 8 16:27:26 2021 +0800

    SUBMARINE-816. Implement Submarine delete event handler
    
    ### What is this PR for?
    This Jira aims to handle the delete events of custom resource "submarine". To elaborate, when the informer of the custom resource "submarine" receives a delete event, the submarine operator needs to delete the resources related to the "submarine" instance.
    
    Reference:
    (1) CRD: https://github.com/apache/submarine/blob/master/submarine-cloud-v2/artifacts/examples/crd.yaml
    (2) CR: https://github.com/apache/submarine/blob/master/submarine-cloud-v2/artifacts/examples/example-submarine.yaml
    ### What type of PR is it?
    [Feature]
    
    ### Todos
    * Create namespace via submarine operator
    
    ### What is the Jira issue?
    https://issues.apache.org/jira/browse/SUBMARINE-816
    
    ### How should this be tested?
    ```
    # Step1-1: In-cluster
    eval $(minikube docker-env)
    make image
    kubectl apply -f artifacts/examples/submarine-operator-service-account.yaml
    kubectl create ns submarine-operator-test
    kubectl apply -n submarine-operator-test -f artifacts/examples/example-submarine.yaml
    
    # Step1-2: Out-of-cluster
    go build -o submarine-operator
    ./submarine-operator
    kubectl create ns submarine-operator-test
    kubectl apply -n submarine-operator-test -f artifacts/examples/example-submarine.yaml
    
    # Step2: Delete Custom Resource
    kubectl delete submarine example-submarine -n submarine-operator-test
    
    # Step3: Check the result
    kubectl get ns
    kubectl get pv
    ```
    
    ### Screenshots (if appropriate)
    * Step1: Create example-submarine (custom resource) in namespace submarine-operator-test
    * Step2: Delete example-submarine
    
    https://user-images.githubusercontent.com/20109646/117336563-eeedf400-aece-11eb-8d11-aff3b146de6e.mov
    
    ### Questions:
    * Do the license files need updating? No
    * Are there breaking changes for older versions? No
    * Does this need new documentation? Yes
    
    Author: Kai-Hsun Chen <b0...@ntu.edu.tw>
    
    Signed-off-by: Liu Xun <li...@apache.org>
    
    Closes #580 from kevin85421/SUBMARINE-816 and squashes the following commits:
    
    8e6d221 [Kai-Hsun Chen] Change hardcoded string to const
    17159ff [Kai-Hsun Chen] Update README.md
    9ff0571 [Kai-Hsun Chen] SUBMARINE-816. Implement Submarine delete event handler
---
 submarine-cloud-v2/README.md     |   3 +-
 submarine-cloud-v2/controller.go | 148 +++++++++++++++++++++++++--------------
 2 files changed, 98 insertions(+), 53 deletions(-)

diff --git a/submarine-cloud-v2/README.md b/submarine-cloud-v2/README.md
index 779fedc..2bc6b28 100644
--- a/submarine-cloud-v2/README.md
+++ b/submarine-cloud-v2/README.md
@@ -62,7 +62,8 @@ make image
 kubectl apply -f artifacts/examples/submarine-operator-service-account.yaml
 
 # Step3: Deploy a submarine-operator
-kubectl apply -f artifacts/examples/submarine-operator.yaml
+kubectl create ns submarine-operator-test
+kubectl apply -n submarine-operator-test -f artifacts/examples/example-submarine.yaml
 
 # Step4: Inspect submarine-operator POD logs 
 kubectl logs ${submarine-operator POD}
diff --git a/submarine-cloud-v2/controller.go b/submarine-cloud-v2/controller.go
index 18c5aad..bd64f10 100644
--- a/submarine-cloud-v2/controller.go
+++ b/submarine-cloud-v2/controller.go
@@ -95,6 +95,17 @@ type Controller struct {
 	recorder record.EventRecorder
 }
 
+const (
+	ADD = iota
+	UPDATE
+	DELETE
+)
+
+type WorkQueueItem struct {
+	key    string
+	action int
+}
+
 // NewController returns a new sample controller
 func NewController(
 	kubeclientset kubernetes.Interface,
@@ -144,9 +155,14 @@ func NewController(
 	// Setting up event handler for Submarine
 	klog.Info("Setting up event handlers")
 	submarineInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
-		AddFunc: controller.enqueueSubmarine,
+		AddFunc: func(toAdd interface{}) {
+			controller.enqueueSubmarine(toAdd, ADD)
+		},
 		UpdateFunc: func(old, new interface{}) {
-			controller.enqueueSubmarine(new)
+			controller.enqueueSubmarine(new, UPDATE)
+		},
+		DeleteFunc: func(toDelete interface{}) {
+			controller.enqueueSubmarine(toDelete, DELETE)
 		},
 	})
 
@@ -201,10 +217,12 @@ func (c *Controller) processNextWorkItem() bool {
 	err := func(obj interface{}) error {
 		// TODO: Maintain workqueue
 		defer c.workqueue.Done(obj)
-		key, _ := obj.(string)
-		c.syncHandler(key)
+		var item WorkQueueItem
+
+		item, _ = obj.(WorkQueueItem)
+		c.syncHandler(item)
 		c.workqueue.Forget(obj)
-		klog.Infof("Successfully synced '%s'", key)
+		klog.Infof("Successfully synced '%s'", item.key)
 		return nil
 	}(obj)
 
@@ -1036,8 +1054,10 @@ func (c *Controller) newSubmarineTensorboard(namespace string, spec *v1alpha1.Su
 // syncHandler compares the actual state with the desired, and attempts to
 // converge the two. It then updates the Status block of the Foo resource
 // with the current status of the resource.
-func (c *Controller) syncHandler(key string) error {
+func (c *Controller) syncHandler(workqueueItem WorkQueueItem) error {
 	// TODO: business logic
+	key := workqueueItem.key
+	action := workqueueItem.action
 
 	// Convert the namespace/name string into a distinct namespace and name
 	namespace, name, err := cache.SplitMetaNamespaceKey(key)
@@ -1046,59 +1066,80 @@ func (c *Controller) syncHandler(key string) error {
 		return nil
 	}
 
-	// Get the Submarine resource with this namespace/name
-	submarine, err := c.submarinesLister.Submarines(namespace).Get(name)
-	if err != nil {
-		// The Submarine resource may no longer exist, in which case we stop
-		// processing
-		if errors.IsNotFound(err) {
-			utilruntime.HandleError(fmt.Errorf("submarine '%s' in work queue no longer exists", key))
-			return nil
+	klog.Info("syncHandler: ", key, " / ", action)
+
+	if action != DELETE { // Case: ADD & UPDATE
+		klog.Info("Add / Update: ", key)
+		// Get the Submarine resource with this namespace/name
+		submarine, err := c.submarinesLister.Submarines(namespace).Get(name)
+		if err != nil {
+			// The Submarine resource may no longer exist, in which case we stop
+			// processing
+			if errors.IsNotFound(err) {
+				utilruntime.HandleError(fmt.Errorf("submarine '%s' in work queue no longer exists", key))
+				return nil
+			}
 		}
-	}
 
-	klog.Info("syncHandler: ", key)
+		// Print out the spec of the Submarine resource
+		b, err := json.MarshalIndent(submarine.Spec, "", "  ")
+		fmt.Println(string(b))
 
-	// Print out the spec of the Submarine resource
-	b, err := json.MarshalIndent(submarine.Spec, "", "  ")
-	fmt.Println(string(b))
+		// Install subcharts
+		c.newSubCharts(namespace)
 
-	// Install subcharts
-	c.newSubCharts(namespace)
+		// Create submarine-server
+		serverImage := submarine.Spec.Server.Image
+		serverReplicas := *submarine.Spec.Server.Replicas
+		if serverImage == "" {
+			serverImage = "apache/submarine:server-" + submarine.Spec.Version
+		}
+		err = c.newSubmarineServer(namespace, serverImage, serverReplicas)
+		if err != nil {
+			return err
+		}
 
-	// Create submarine-server
-	serverImage := submarine.Spec.Server.Image
-	serverReplicas := *submarine.Spec.Server.Replicas
-	if serverImage == "" {
-		serverImage = "apache/submarine:server-" + submarine.Spec.Version
-	}
-	err = c.newSubmarineServer(namespace, serverImage, serverReplicas)
-	if err != nil {
-		return err
-	}
+		// Create Submarine Database
+		err = c.newSubmarineDatabase(namespace, &submarine.Spec)
+		if err != nil {
+			return err
+		}
 
-	// Create Submarine Database
-	err = c.newSubmarineDatabase(namespace, &submarine.Spec)
-	if err != nil {
-		return err
-	}
+		// Create ingress
+		err = c.newIngress(namespace)
+		if err != nil {
+			return err
+		}
 
-	// Create ingress
-	err = c.newIngress(namespace)
-	if err != nil {
-		return err
-	}
+		// Create RBAC
+		err = c.newSubmarineServerRBAC(namespace)
+		if err != nil {
+			return err
+		}
 
-	// Create RBAC
-	err = c.newSubmarineServerRBAC(namespace)
-	if err != nil {
-		return err
-	}
+		// Create Submarine Tensorboard
+		err = c.newSubmarineTensorboard(namespace, &submarine.Spec)
+		if err != nil {
+			return err
+		}
+	} else {
+		// DELETE
+		err = c.kubeclientset.CoreV1().Namespaces().Delete(context.TODO(), namespace, metav1.DeleteOptions{})
+		if err != nil {
+			return err
+		}
 
-	// Create Submarine Tensorboard
-	err = c.newSubmarineTensorboard(namespace, &submarine.Spec)
-	if err != nil {
-		return err
+		err = c.kubeclientset.CoreV1().PersistentVolumes().Delete(context.TODO(), "submarine-database-pv--"+namespace, metav1.DeleteOptions{})
+		if err != nil {
+			return err
+		}
+
+		err = c.kubeclientset.CoreV1().PersistentVolumes().Delete(context.TODO(), "submarine-tensorboard-pv--"+namespace, metav1.DeleteOptions{})
+		if err != nil {
+			return err
+		}
+
+		klog.Info("Delete Namespace: ", namespace)
 	}
 
 	return nil
@@ -1107,7 +1148,7 @@ func (c *Controller) syncHandler(key string) error {
 // enqueueFoo takes a Submarine resource and converts it into a namespace/name
 // string which is then put onto the work queue. This method should *not* be
 // passed resources of any type other than Submarine.
-func (c *Controller) enqueueSubmarine(obj interface{}) {
+func (c *Controller) enqueueSubmarine(obj interface{}, action int) {
 	var key string
 	var err error
 	if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil {
@@ -1117,5 +1158,8 @@ func (c *Controller) enqueueSubmarine(obj interface{}) {
 
 	// key: [namespace]/[CR name]
 	// Example: default/example-submarine
-	c.workqueue.Add(key)
+	c.workqueue.Add(WorkQueueItem{
+		key:    key,
+		action: action,
+	})
 }

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@submarine.apache.org
For additional commands, e-mail: dev-help@submarine.apache.org