You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by zh...@apache.org on 2023/04/21 02:33:59 UTC

[apisix-ingress-controller] branch master updated: fix: secret reference update Ingress (#1780)

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

zhangjintao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-ingress-controller.git


The following commit(s) were added to refs/heads/master by this push:
     new a414df75 fix: secret reference update Ingress (#1780)
a414df75 is described below

commit a414df7531f904481afccce44f5436f3d45d2c86
Author: Sarasa Kisaragi <li...@gmail.com>
AuthorDate: Fri Apr 21 10:33:52 2023 +0800

    fix: secret reference update Ingress (#1780)
---
 pkg/providers/apisix/apisix_tls.go                 | 248 +++---------
 pkg/providers/ingress/ingress.go                   | 170 +++-----
 pkg/providers/ingress/translation/translator.go    |  27 +-
 pkg/providers/k8s/namespace/namespace.go           |   3 +
 test/e2e/scaffold/scaffold.go                      |   2 +-
 .../suite-ingress-features/namespace.go            |   3 +
 .../suite-ingress/suite-ingress-features/secret.go | 439 ++++++++++++++++++++-
 7 files changed, 563 insertions(+), 329 deletions(-)

diff --git a/pkg/providers/apisix/apisix_tls.go b/pkg/providers/apisix/apisix_tls.go
index 7fa219c8..bb6cf420 100644
--- a/pkg/providers/apisix/apisix_tls.go
+++ b/pkg/providers/apisix/apisix_tls.go
@@ -36,10 +36,8 @@ import (
 	configv2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
 	configv2beta3 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2beta3"
 	"github.com/apache/apisix-ingress-controller/pkg/log"
-	"github.com/apache/apisix-ingress-controller/pkg/providers/translation"
 	"github.com/apache/apisix-ingress-controller/pkg/providers/utils"
 	"github.com/apache/apisix-ingress-controller/pkg/types"
-	v1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
 )
 
 type apisixTlsController struct {
@@ -49,11 +47,11 @@ type apisixTlsController struct {
 	workers   int
 	pool      pool.Pool
 
-	// secretSSLMap stores reference from K8s secret to ApisixTls
-	// type: Map<SecretKey, Map<ApisixTlsKey, SSL object in APISIX>>
-	// SecretKey -> ApisixTlsKey -> SSL object in APISIX
+	// secretRefMap stores reference from K8s secret to ApisixTls
+	// type: Map<SecretKey, Map<ApisixTlsKey, empty struct>>
+	// SecretKey -> ApisixTlsKey -> empty object in APISIX
 	// SecretKey and ApisixTlsKey are kube-style meta key: `namespace/name`
-	secretSSLMap *sync.Map
+	secretRefMap *sync.Map
 }
 
 func newApisixTlsController(common *apisixCommon) *apisixTlsController {
@@ -63,7 +61,7 @@ func newApisixTlsController(common *apisixCommon) *apisixTlsController {
 		workers:      1,
 		pool:         pool.NewLimited(2),
 
-		secretSSLMap: new(sync.Map),
+		secretRefMap: new(sync.Map),
 	}
 
 	c.ApisixTlsInformer.AddEventHandler(
@@ -156,18 +154,16 @@ func (c *apisixTlsController) sync(ctx context.Context, ev *types.Event) error {
 	switch event.GroupVersion {
 	case config.ApisixV2beta3:
 		tls := multiVersionedTls.V2beta3()
-		ssl, err := c.translator.TranslateSSLV2Beta3(tls)
-
-		// We should cache the relations regardless the translation succeed or not
 		secretKey := tls.Spec.Secret.Namespace + "/" + tls.Spec.Secret.Name
-		c.storeSecretCache(secretKey, apisixTlsKey, ssl, ev.Type)
+		c.storeSecretCache(secretKey, apisixTlsKey, ev.Type)
 		if tls.Spec.Client != nil {
 			caSecretKey := tls.Spec.Client.CASecret.Namespace + "/" + tls.Spec.Client.CASecret.Name
 			if caSecretKey != secretKey {
-				c.storeSecretCache(caSecretKey, apisixTlsKey, ssl, ev.Type)
+				c.storeSecretCache(caSecretKey, apisixTlsKey, ev.Type)
 			}
 		}
 
+		ssl, err := c.translator.TranslateSSLV2Beta3(tls)
 		if err != nil {
 			log.Errorw("failed to translate ApisixTls",
 				zap.Error(err),
@@ -191,18 +187,16 @@ func (c *apisixTlsController) sync(ctx context.Context, ev *types.Event) error {
 		}
 	case config.ApisixV2:
 		tls := multiVersionedTls.V2()
-		ssl, err := c.translator.TranslateSSLV2(tls)
-
-		// We should cache the relations regardless the translation succeed or not
 		secretKey := tls.Spec.Secret.Namespace + "/" + tls.Spec.Secret.Name
-		c.storeSecretCache(secretKey, apisixTlsKey, ssl, ev.Type)
+		c.storeSecretCache(secretKey, apisixTlsKey, ev.Type)
 		if tls.Spec.Client != nil {
 			caSecretKey := tls.Spec.Client.CASecret.Namespace + "/" + tls.Spec.Client.CASecret.Name
 			if caSecretKey != secretKey {
-				c.storeSecretCache(caSecretKey, apisixTlsKey, ssl, ev.Type)
+				c.storeSecretCache(caSecretKey, apisixTlsKey, ev.Type)
 			}
 		}
 
+		ssl, err := c.translator.TranslateSSLV2(tls)
 		if err != nil {
 			log.Errorw("failed to translate ApisixTls",
 				zap.Error(err),
@@ -286,21 +280,21 @@ func (c *apisixTlsController) updateStatus(obj kube.ApisixTls, statusErr error)
 	}
 }
 
-func (c *apisixTlsController) storeSecretCache(secretKey string, apisixTlsKey string, ssl *v1.Ssl, evType types.EventType) {
-	if ssls, ok := c.secretSSLMap.Load(secretKey); ok {
-		sslMap := ssls.(*sync.Map)
+func (c *apisixTlsController) storeSecretCache(secretKey string, apisixTlsKey string, evType types.EventType) {
+	if refs, ok := c.secretRefMap.Load(secretKey); ok {
+		refMap := refs.(*sync.Map)
 		switch evType {
 		case types.EventDelete:
-			sslMap.Delete(apisixTlsKey)
-			c.secretSSLMap.Store(secretKey, sslMap)
+			refMap.Delete(apisixTlsKey)
+			c.secretRefMap.Store(secretKey, refMap)
 		default:
-			sslMap.Store(apisixTlsKey, ssl)
-			c.secretSSLMap.Store(secretKey, sslMap)
+			refMap.Store(apisixTlsKey, struct{}{})
+			c.secretRefMap.Store(secretKey, refMap)
 		}
 	} else if evType != types.EventDelete {
-		sslMap := new(sync.Map)
-		sslMap.Store(apisixTlsKey, ssl)
-		c.secretSSLMap.Store(secretKey, sslMap)
+		refMap := new(sync.Map)
+		refMap.Store(apisixTlsKey, struct{}{})
+		c.secretRefMap.Store(secretKey, refMap)
 	}
 }
 
@@ -552,14 +546,14 @@ func (c *apisixTlsController) recordStatus(at interface{}, reason string, err er
 }
 
 func (c *apisixTlsController) SyncSecretChange(ctx context.Context, ev *types.Event, secret *corev1.Secret, secretKey string) {
-	ssls, ok := c.secretSSLMap.Load(secretKey)
+	refs, ok := c.secretRefMap.Load(secretKey)
 	if !ok {
 		log.Debugw("ApisixTls: sync secret change, not concerned", zap.String("key", secretKey))
 		// This secret is not concerned.
 		return
 	}
 
-	sslMap, ok := ssls.(*sync.Map) // apisix tls key -> SSLs
+	refMap, ok := refs.(*sync.Map) // apisix tls key -> empty struct
 	if !ok {
 		log.Debugw("ApisixTls: sync secret change, not such SSls map", zap.String("key", secretKey))
 		return
@@ -568,183 +562,29 @@ func (c *apisixTlsController) SyncSecretChange(ctx context.Context, ev *types.Ev
 	log.Debugw("ApisixTls: sync secret change", zap.String("key", secretKey))
 	switch c.Config.Kubernetes.APIVersion {
 	case config.ApisixV2beta3:
-		sslMap.Range(c.syncSSLsAndUpdateStatusV2beta3(ctx, ev, secret, secretKey))
-	case config.ApisixV2:
-		sslMap.Range(c.syncSSLsAndUpdateStatusV2(ctx, ev, secret, secretKey))
-	}
-}
-
-func (c *apisixTlsController) syncSSLsAndUpdateStatusV2beta3(ctx context.Context, ev *types.Event, secret *corev1.Secret, secretKey string) func(k, v interface{}) bool {
-	return func(k, v interface{}) bool {
-		ssl := v.(*v1.Ssl)
-		tlsMetaKey := k.(string)
-		tlsNamespace, tlsName, err := cache.SplitMetaNamespaceKey(tlsMetaKey)
-		if err != nil {
-			log.Errorf("invalid cached ApisixTls key: %s", tlsMetaKey)
-			return true
-		}
-
-		multiVersioned, err := c.ApisixTlsLister.V2beta3(tlsNamespace, tlsName)
-		if err != nil {
-			log.Warnw("secret related ApisixTls resource not found, skip",
-				zap.String("ApisixTls", tlsMetaKey),
-			)
-			return true
-		}
-		tls := multiVersioned.V2beta3()
-
-		// We don't expect a secret to be used as both SSL and mTLS in ApisixTls
-		if tls.Spec.Secret.Namespace == secret.Namespace && tls.Spec.Secret.Name == secret.Name {
-			cert, pkey, err := translation.ExtractKeyPair(secret, true)
-			if err != nil {
-				log.Errorw("secret required by ApisixTls invalid",
-					zap.String("ApisixTls", tlsMetaKey),
-					zap.String("secret", secretKey),
-					zap.Error(err),
-				)
-				go func(tls *configv2beta3.ApisixTls) {
-					c.RecordEventS(tls, corev1.EventTypeWarning, utils.ResourceSyncAborted,
-						fmt.Sprintf("sync from secret %s changes failed, error: %s", secretKey, err.Error()))
-					c.recordStatus(tls, utils.ResourceSyncAborted, err, metav1.ConditionFalse, tls.GetGeneration())
-				}(tls)
-				return true
-			}
-			// sync ssl
-			ssl.Cert = string(cert)
-			ssl.Key = string(pkey)
-		} else if tls.Spec.Client != nil &&
-			tls.Spec.Client.CASecret.Namespace == secret.Namespace && tls.Spec.Client.CASecret.Name == secret.Name {
-			ca, _, err := translation.ExtractKeyPair(secret, false)
-			if err != nil {
-				log.Errorw("ca secret required by ApisixTls invalid",
-					zap.String("ApisixTls", tlsMetaKey),
-					zap.String("secret", secretKey),
-					zap.Error(err),
-				)
-				go func(tls *configv2beta3.ApisixTls) {
-					c.RecordEventS(tls, corev1.EventTypeWarning, utils.ResourceSyncAborted,
-						fmt.Sprintf("sync from ca secret %s changes failed, error: %s", secretKey, err.Error()))
-					c.recordStatus(tls, utils.ResourceSyncAborted, err, metav1.ConditionFalse, tls.GetGeneration())
-				}(tls)
-				return true
-			}
-			ssl.Client = &v1.MutualTLSClientConfig{
-				CA: string(ca),
-			}
-		} else {
-			log.Warnw("stale secret cache, ApisixTls doesn't requires target secret",
-				zap.String("ApisixTls", tlsMetaKey),
-				zap.String("secret", secretKey),
-			)
+		refMap.Range(func(k, v interface{}) bool {
+			tlsMetaKey := k.(string)
+			c.workqueue.Add(&types.Event{
+				Type: types.EventSync,
+				Object: kube.ApisixTlsEvent{
+					Key:          tlsMetaKey,
+					GroupVersion: config.ApisixV2beta3,
+				},
+			})
 			return true
-		}
-		// Use another goroutine to send requests, to avoid
-		// long time lock occupying.
-		go func(ssl *v1.Ssl, tls *configv2beta3.ApisixTls) {
-			err := c.SyncSSL(ctx, ssl, ev.Type)
-			if err != nil {
-				log.Errorw("failed to sync ssl to APISIX",
-					zap.Error(err),
-					zap.Any("ssl", ssl),
-					zap.Any("secret", secret),
-				)
-				c.RecordEventS(tls, corev1.EventTypeWarning, utils.ResourceSyncAborted,
-					fmt.Sprintf("sync from secret %s changes failed, error: %s", secretKey, err.Error()))
-				c.recordStatus(tls, utils.ResourceSyncAborted, err, metav1.ConditionFalse, tls.GetGeneration())
-			} else {
-				c.RecordEventS(tls, corev1.EventTypeNormal, utils.ResourceSynced,
-					fmt.Sprintf("sync from secret %s changes", secretKey))
-				c.recordStatus(tls, utils.ResourceSynced, nil, metav1.ConditionTrue, tls.GetGeneration())
-			}
-		}(ssl, tls)
-		return true
-	}
-}
-
-func (c *apisixTlsController) syncSSLsAndUpdateStatusV2(ctx context.Context, ev *types.Event, secret *corev1.Secret, secretKey string) func(k, v interface{}) bool {
-	return func(k, v interface{}) bool {
-		ssl := v.(*v1.Ssl)
-		tlsMetaKey := k.(string)
-		tlsNamespace, tlsName, err := cache.SplitMetaNamespaceKey(tlsMetaKey)
-		if err != nil {
-			log.Errorf("invalid cached ApisixTls key: %s", tlsMetaKey)
-			return true
-		}
-
-		multiVersioned, err := c.ApisixTlsLister.V2(tlsNamespace, tlsName)
-		if err != nil {
-			log.Warnw("secret related ApisixTls resource not found, skip",
-				zap.String("ApisixTls", tlsMetaKey),
-			)
-			return true
-		}
-		tls := multiVersioned.V2()
-
-		// We don't expect a secret to be used as both SSL and mTLS in ApisixTls
-		if tls.Spec.Secret.Namespace == secret.Namespace && tls.Spec.Secret.Name == secret.Name {
-			cert, pkey, err := translation.ExtractKeyPair(secret, true)
-			if err != nil {
-				log.Errorw("secret required by ApisixTls invalid",
-					zap.String("ApisixTls", tlsMetaKey),
-					zap.String("secret", secretKey),
-					zap.Error(err),
-				)
-				go func(tls *configv2.ApisixTls) {
-					c.RecordEventS(tls, corev1.EventTypeWarning, utils.ResourceSyncAborted,
-						fmt.Sprintf("sync from secret %s changes failed, error: %s", secretKey, err.Error()))
-					c.recordStatus(tls, utils.ResourceSyncAborted, err, metav1.ConditionFalse, tls.GetGeneration())
-				}(tls)
-				return true
-			}
-			// sync ssl
-			ssl.Cert = string(cert)
-			ssl.Key = string(pkey)
-		} else if tls.Spec.Client != nil &&
-			tls.Spec.Client.CASecret.Namespace == secret.Namespace && tls.Spec.Client.CASecret.Name == secret.Name {
-			ca, _, err := translation.ExtractKeyPair(secret, false)
-			if err != nil {
-				log.Errorw("ca secret required by ApisixTls invalid",
-					zap.String("ApisixTls", tlsMetaKey),
-					zap.String("secret", secretKey),
-					zap.Error(err),
-				)
-				go func(tls *configv2.ApisixTls) {
-					c.RecordEventS(tls, corev1.EventTypeWarning, utils.ResourceSyncAborted,
-						fmt.Sprintf("sync from ca secret %s changes failed, error: %s", secretKey, err.Error()))
-					c.recordStatus(tls, utils.ResourceSyncAborted, err, metav1.ConditionFalse, tls.GetGeneration())
-				}(tls)
-				return true
-			}
-			ssl.Client = &v1.MutualTLSClientConfig{
-				CA: string(ca),
-			}
-		} else {
-			log.Warnw("stale secret cache, ApisixTls doesn't requires target secret",
-				zap.String("ApisixTls", tlsMetaKey),
-				zap.String("secret", secretKey),
-			)
+		})
+	case config.ApisixV2:
+		refMap.Range(func(k, v interface{}) bool {
+			tlsMetaKey := k.(string)
+			c.workqueue.Add(&types.Event{
+				Type: types.EventSync,
+				Object: kube.ApisixTlsEvent{
+					Key:          tlsMetaKey,
+					GroupVersion: config.ApisixV2,
+				},
+			})
 			return true
-		}
-		// Use another goroutine to send requests, to avoid
-		// long time lock occupying.
-		go func(ssl *v1.Ssl, tls *configv2.ApisixTls) {
-			err := c.SyncSSL(ctx, ssl, ev.Type)
-			if err != nil {
-				log.Errorw("failed to sync ssl to APISIX",
-					zap.Error(err),
-					zap.Any("ssl", ssl),
-					zap.Any("secret", secret),
-				)
-				c.RecordEventS(tls, corev1.EventTypeWarning, utils.ResourceSyncAborted,
-					fmt.Sprintf("sync from secret %s changes failed, error: %s", secretKey, err.Error()))
-				c.recordStatus(tls, utils.ResourceSyncAborted, err, metav1.ConditionFalse, tls.GetGeneration())
-			} else {
-				c.RecordEventS(tls, corev1.EventTypeNormal, utils.ResourceSynced,
-					fmt.Sprintf("sync from secret %s changes", secretKey))
-				c.recordStatus(tls, utils.ResourceSynced, nil, metav1.ConditionTrue, tls.GetGeneration())
-			}
-		}(ssl, tls)
-		return true
+		})
 	}
 }
 
diff --git a/pkg/providers/ingress/ingress.go b/pkg/providers/ingress/ingress.go
index 35d9da1d..49bb1d17 100644
--- a/pkg/providers/ingress/ingress.go
+++ b/pkg/providers/ingress/ingress.go
@@ -40,7 +40,6 @@ import (
 	"github.com/apache/apisix-ingress-controller/pkg/providers/translation"
 	"github.com/apache/apisix-ingress-controller/pkg/providers/utils"
 	"github.com/apache/apisix-ingress-controller/pkg/types"
-	v1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
 )
 
 const (
@@ -55,12 +54,12 @@ type ingressController struct {
 
 	pool pool.Pool
 
-	// secretSSLMap stores reference from K8s secret to Ingress
-	// type: Map<SecretKey, Map<IngressVersionKey, SSL in APISIX>>
-	// SecretKey -> IngressVersionKey -> []string
+	// secretRefMap stores reference from K8s secret to Ingress
+	// type: Map<SecretKey, Map<IngressVersionKey, empty struct>>
+	// SecretKey -> IngressVersionKey -> empty struct
 	// Secret key is kube-style meta key: `namespace/name`
 	// Ingress Version Key is: `namespace/name_groupVersion`
-	secretSSLMap *sync.Map
+	secretRefMap *sync.Map
 }
 
 func newIngressController(common *ingressCommon) *ingressController {
@@ -71,7 +70,7 @@ func newIngressController(common *ingressCommon) *ingressController {
 		workers:   1,
 		pool:      pool.NewLimited(2),
 
-		secretSSLMap: new(sync.Map),
+		secretRefMap: new(sync.Map),
 	}
 
 	c.IngressInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
@@ -142,6 +141,7 @@ func (c *ingressController) sync(ctx context.Context, ev *types.Event) error {
 			return nil
 		}
 	}
+
 	if ev.Type == types.EventDelete {
 		if ing != nil {
 			// We still find the resource while we are processing the DELETE event,
@@ -152,6 +152,29 @@ func (c *ingressController) sync(ctx context.Context, ev *types.Event) error {
 		}
 		ing = ev.Tombstone.(kube.Ingress)
 	}
+
+	var secrets []string
+	switch ingEv.GroupVersion {
+	case kube.IngressV1:
+		for _, tls := range ing.V1().Spec.TLS {
+			secrets = append(secrets, tls.SecretName)
+		}
+	case kube.IngressV1beta1:
+		for _, tls := range ing.V1beta1().Spec.TLS {
+			secrets = append(secrets, tls.SecretName)
+		}
+	case kube.IngressExtensionsV1beta1:
+		for _, tls := range ing.ExtensionsV1beta1().Spec.TLS {
+			secrets = append(secrets, tls.SecretName)
+		}
+	}
+
+	for _, secret := range secrets {
+		// We don't support annotation in Ingress
+		// 	_caAnnotation = "nginx.ingress.kubernetes.io/auth-tls-secret"
+		c.storeSecretReference(namespace+"/"+secret, ingEv.Key+"_"+ingEv.GroupVersion, ev.Type)
+	}
+
 	{
 		if ev.Type == types.EventDelete {
 			tctx, err = c.translator.TranslateIngressDeleteEvent(ing)
@@ -166,16 +189,6 @@ func (c *ingressController) sync(ctx context.Context, ev *types.Event) error {
 			goto updateStatus
 		}
 
-		for _, ssl := range tctx.SSL {
-			ns, ok1 := ssl.Labels[translation.MetaSecretNamespace]
-			sec, ok2 := ssl.Labels[translation.MetaSecretName]
-			if ok1 && ok2 {
-				// We don't support annotation in Ingress
-				// 	_caAnnotation = "nginx.ingress.kubernetes.io/auth-tls-secret"
-				c.storeSecretReference(ns+"/"+sec, ingEv.Key, ev.Type, ssl)
-			}
-		}
-
 		log.Debugw("translated ingress resource to a couple of routes, upstreams and pluginConfigs",
 			zap.Any("ingress", ing),
 			zap.Any("routes", tctx.Routes),
@@ -573,118 +586,59 @@ func (c *ingressController) ingressLBStatusIPs() ([]corev1.LoadBalancerIngress,
 	return utils.IngressLBStatusIPs(c.IngressPublishService, c.IngressStatusAddress, c.SvcLister)
 }
 
-func (c *ingressController) storeSecretReference(secretKey string, ingressKey string, evType types.EventType, ssl *v1.Ssl) {
-	if ssls, ok := c.secretSSLMap.Load(secretKey); ok {
-		sslMap := ssls.(*sync.Map)
+func (c *ingressController) storeSecretReference(secretKey string, ingressKey string, evType types.EventType) {
+	if refs, ok := c.secretRefMap.Load(secretKey); ok {
+		refMap := refs.(*sync.Map)
 		switch evType {
 		case types.EventDelete:
-			sslMap.Delete(ingressKey)
-			c.secretSSLMap.Store(secretKey, sslMap)
+			refMap.Delete(ingressKey)
+			c.secretRefMap.Store(secretKey, refMap)
 		default:
-			sslMap.Store(ingressKey, ssl)
-			c.secretSSLMap.Store(secretKey, sslMap)
+			refMap.Store(ingressKey, struct{}{})
+			c.secretRefMap.Store(secretKey, refMap)
 		}
 	} else if evType != types.EventDelete {
-		sslMap := new(sync.Map)
-		sslMap.Store(ingressKey, ssl)
-		c.secretSSLMap.Store(secretKey, sslMap)
+		refMap := new(sync.Map)
+		refMap.Store(ingressKey, struct{}{})
+		c.secretRefMap.Store(secretKey, refMap)
 	}
 }
 
 func (c *ingressController) SyncSecretChange(ctx context.Context, ev *types.Event, secret *corev1.Secret, secretKey string) {
-	ssls, ok := c.secretSSLMap.Load(secretKey)
+	refs, ok := c.secretRefMap.Load(secretKey)
 	if !ok {
+		log.Debugw("Ingress: sync secret change, not concerned", zap.String("key", secretKey))
+		// This secret is not concerned.
 		return
 	}
 
-	sslMap, ok := ssls.(*sync.Map) // ingress version key -> SSL
+	refMap, ok := refs.(*sync.Map) // ingress version key -> empty struct
 	if !ok {
+		log.Debugw("Ingress: sync secret change, not such key map", zap.String("key", secretKey))
 		return
 	}
 
-	sslMap.Range(func(k, v interface{}) bool {
+	refMap.Range(func(k, v interface{}) bool {
 		ingressVersionKey := k.(string)
-		ssl := v.(*v1.Ssl)
-		return c.syncSSLs(ctx, ev.Type, secret, secretKey, ingressVersionKey, ssl)
-	})
-}
-
-func (c *ingressController) syncSSLs(ctx context.Context, evType types.EventType, secret *corev1.Secret, secretKey, ingressVersionKey string, ssl *v1.Ssl) bool {
-	vals := strings.Split(ingressVersionKey, "_")
-	if len(vals) != 2 {
-		log.Errorw("cache recorded invalid ingress version key",
-			zap.String("key", ingressVersionKey),
-		)
-	}
-	ingressKey := vals[0]
-	ingressVersion := vals[1]
 
-	ingressNamespace, ingressName, err := cache.SplitMetaNamespaceKey(ingressKey)
-	if err != nil {
-		log.Errorf("invalid cached ApisixTls key: %s", ingressKey)
-		return true
-	}
+		vals := strings.Split(ingressVersionKey, "_")
+		if len(vals) != 2 {
+			log.Errorw("cache recorded invalid ingress version key",
+				zap.String("key", ingressVersionKey),
+			)
+			return true
+		}
+		ingressKey := vals[0]
+		ingressVersion := vals[1]
 
-	var (
-		obj metav1.Object
-		ing kube.Ingress
-	)
-	switch ingressVersion {
-	case kube.IngressV1:
-		ing, err = c.IngressLister.V1(ingressNamespace, ingressName)
-		obj = ing.V1()
-	case kube.IngressV1beta1:
-		ing, err = c.IngressLister.V1(ingressNamespace, ingressName)
-		obj = ing.V1beta1()
-	case kube.IngressExtensionsV1beta1:
-		ing, err = c.IngressLister.V1(ingressNamespace, ingressName)
-		obj = ing.ExtensionsV1beta1()
-	}
-	if err != nil {
-		log.Warnw("secret related ingress resource not found, skip",
-			zap.String("ingress", ingressKey),
-		)
-		return true
-	}
+		c.workqueue.Add(&types.Event{
+			Type: types.EventSync,
+			Object: kube.IngressEvent{
+				Key:          ingressKey,
+				GroupVersion: ingressVersion,
+			},
+		})
 
-	cert, pkey, err := translation.ExtractKeyPair(secret, true)
-	if err != nil {
-		log.Errorw("secret required by Ingress invalid",
-			zap.String("ingress", ingressKey),
-			zap.String("secret", secretKey),
-			zap.Error(err),
-		)
-		go func(obj metav1.Object) {
-			runtimeObj := obj.(runtime.Object)
-			c.RecordEventS(runtimeObj, corev1.EventTypeWarning, utils.ResourceSyncAborted,
-				fmt.Sprintf("sync from secret %s changes failed, error: %s", secretKey, err.Error()))
-			c.recordStatus(runtimeObj)
-		}(obj)
 		return true
-	}
-
-	// update ssl
-	ssl.Cert = string(cert)
-	ssl.Key = string(pkey)
-
-	go func(ssl *v1.Ssl, obj metav1.Object) {
-		runtimeObj := obj.(runtime.Object)
-
-		err := c.SyncSSL(ctx, ssl, evType)
-		if err != nil {
-			log.Errorw("failed to sync ssl to APISIX",
-				zap.Error(err),
-				zap.Any("ssl", ssl),
-				zap.Any("secret", secret),
-			)
-			c.RecordEventS(runtimeObj, corev1.EventTypeWarning, utils.ResourceSyncAborted,
-				fmt.Sprintf("sync from secret %s changes failed, error: %s", secretKey, err.Error()))
-			c.recordStatus(runtimeObj)
-		} else {
-			c.RecordEventS(runtimeObj, corev1.EventTypeNormal, utils.ResourceSynced,
-				fmt.Sprintf("sync from secret %s changes", secretKey))
-			c.recordStatus(runtimeObj)
-		}
-	}(ssl, obj)
-	return true
+	})
 }
diff --git a/pkg/providers/ingress/translation/translator.go b/pkg/providers/ingress/translation/translator.go
index ea8f31e6..92545a46 100644
--- a/pkg/providers/ingress/translation/translator.go
+++ b/pkg/providers/ingress/translation/translator.go
@@ -26,6 +26,7 @@ import (
 	extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
 	networkingv1 "k8s.io/api/networking/v1"
 	networkingv1beta1 "k8s.io/api/networking/v1beta1"
+	k8serrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/intstr"
 	listerscorev1 "k8s.io/client-go/listers/core/v1"
@@ -580,13 +581,23 @@ func (t *translator) TranslateOldIngress(ing kube.Ingress) (*translation.Transla
 	}
 }
 
+func (t *translator) translateOldIngressTLS(namespace, ingName, secretName string, hosts []string) (*apisixv1.Ssl, error) {
+	ssl, err := t.TranslateIngressTLS(namespace, ingName, secretName, hosts)
+	if err != nil && k8serrors.IsNotFound(err) {
+		return &apisixv1.Ssl{
+			ID: id.GenID(namespace + "_" + fmt.Sprintf("%v-%v", ingName, "tls")),
+		}, nil
+	}
+	return ssl, err
+}
+
 func (t *translator) translateOldIngressV1(ing *networkingv1.Ingress) (*translation.TranslateContext, error) {
 	oldCtx := translation.DefaultEmptyTranslateContext()
 
 	for _, tls := range ing.Spec.TLS {
-		ssl, err := t.TranslateIngressTLS(ing.Namespace, ing.Name, tls.SecretName, tls.Hosts)
+		ssl, err := t.translateOldIngressTLS(ing.Namespace, ing.Name, tls.SecretName, tls.Hosts)
 		if err != nil {
-			log.Debugw("failed to translate ingress tls to apisix tls",
+			log.Errorw("failed to translate ingress tls to apisix tls",
 				zap.Error(err),
 				zap.Any("ingress", ing),
 			)
@@ -621,8 +632,12 @@ func (t *translator) translateOldIngressV1beta1(ing *networkingv1beta1.Ingress)
 	oldCtx := translation.DefaultEmptyTranslateContext()
 
 	for _, tls := range ing.Spec.TLS {
-		ssl, err := t.TranslateIngressTLS(ing.Namespace, ing.Name, tls.SecretName, tls.Hosts)
+		ssl, err := t.translateOldIngressTLS(ing.Namespace, ing.Name, tls.SecretName, tls.Hosts)
 		if err != nil {
+			log.Errorw("failed to translate ingress tls to apisix tls",
+				zap.Error(err),
+				zap.Any("ingress", ing),
+			)
 			continue
 		}
 		oldCtx.AddSSL(ssl)
@@ -654,8 +669,12 @@ func (t *translator) translateOldIngressExtensionsv1beta1(ing *extensionsv1beta1
 	oldCtx := translation.DefaultEmptyTranslateContext()
 
 	for _, tls := range ing.Spec.TLS {
-		ssl, err := t.TranslateIngressTLS(ing.Namespace, ing.Name, tls.SecretName, tls.Hosts)
+		ssl, err := t.translateOldIngressTLS(ing.Namespace, ing.Name, tls.SecretName, tls.Hosts)
 		if err != nil {
+			log.Errorw("failed to translate ingress tls to apisix tls",
+				zap.Error(err),
+				zap.Any("ingress", ing),
+			)
 			continue
 		}
 		oldCtx.AddSSL(ssl)
diff --git a/pkg/providers/k8s/namespace/namespace.go b/pkg/providers/k8s/namespace/namespace.go
index d4b268e6..05f886b5 100644
--- a/pkg/providers/k8s/namespace/namespace.go
+++ b/pkg/providers/k8s/namespace/namespace.go
@@ -94,14 +94,17 @@ func (c *namespaceController) sync(ctx context.Context, ev *types.Event) error {
 
 		// if labels of namespace contains the watchingLabels, the namespace should be set to controller.watchingNamespaces
 		if c.controller.watchingLabels.IsSubsetOf(namespace.Labels) {
+			log.Infow("watching namespace", zap.String("name", namespace.Name))
 			c.controller.watchingNamespaces.Store(namespace.Name, struct{}{})
 		} else {
+			log.Infow("un-watching namespace", zap.String("name", namespace.Name))
 			c.controller.watchingNamespaces.Delete(namespace.Name)
 		}
 
 	} else { // type == types.EventDelete
 		namespace := ev.Tombstone.(*corev1.Namespace)
 		if _, ok := c.controller.watchingNamespaces.Load(namespace.Name); ok {
+			log.Infow("un-watching namespace", zap.String("name", namespace.Name))
 			c.controller.watchingNamespaces.Delete(namespace.Name)
 		}
 		// do nothing, if the namespace did not in controller.watchingNamespaces
diff --git a/test/e2e/scaffold/scaffold.go b/test/e2e/scaffold/scaffold.go
index 0033441d..e979f3b5 100644
--- a/test/e2e/scaffold/scaffold.go
+++ b/test/e2e/scaffold/scaffold.go
@@ -506,7 +506,7 @@ func (s *Scaffold) afterEach() {
 	if ginkgo.CurrentSpecReport().Failed() {
 		// dump and delete related resource
 		env := os.Getenv("E2E_ENV")
-		if env == "ci" || env == "debug" {
+		if env == "ci" {
 			_, _ = fmt.Fprintln(ginkgo.GinkgoWriter, "Dumping namespace contents")
 			output, _ := k8s.RunKubectlAndGetOutputE(ginkgo.GinkgoT(), s.kubectlOptions, "get", "deploy,sts,svc,pods")
 			if output != "" {
diff --git a/test/e2e/suite-ingress/suite-ingress-features/namespace.go b/test/e2e/suite-ingress/suite-ingress-features/namespace.go
index a41b6fb4..033873dc 100644
--- a/test/e2e/suite-ingress/suite-ingress-features/namespace.go
+++ b/test/e2e/suite-ingress/suite-ingress-features/namespace.go
@@ -327,6 +327,9 @@ spec:
 		_ = s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.com").Expect().Status(http.StatusOK).Body().Raw()
 
 		assert.Nil(ginkgo.GinkgoT(), s.DeleteResourceFromStringWithNamespace(route1, namespace1), "deleting ingress")
+
+		time.Sleep(6 * time.Second)
+
 		// un-label
 		_, err = client.CoreV1().Namespaces().Update(
 			context.Background(),
diff --git a/test/e2e/suite-ingress/suite-ingress-features/secret.go b/test/e2e/suite-ingress/suite-ingress-features/secret.go
index 9b054e38..6c856916 100644
--- a/test/e2e/suite-ingress/suite-ingress-features/secret.go
+++ b/test/e2e/suite-ingress/suite-ingress-features/secret.go
@@ -630,6 +630,8 @@ UnBVSIGJ/c0AhVSDuOAJiF36pvsDysTZXMTFE/9i5bkGOiwtzRNe4Hym/SEZUCpn
 	ingressSuites := func(s *scaffold.Scaffold) {
 		ginkgo.It("should update SSL if secret referenced by Ingress is updated", func() {
 			backendSvc, backendSvcPort := s.DefaultHTTPBackend()
+			secretName := "test-apisix-tls"
+
 			ingress := fmt.Sprintf(`
 apiVersion: networking.k8s.io/v1
 kind: Ingress
@@ -638,6 +640,10 @@ metadata:
     kubernetes.io/ingress.class: apisix
   name: ingress-route
 spec:
+  tls:
+  - hosts:
+    - api6.com
+    secretName: %s
   rules:
   - host: api6.com
     http:
@@ -649,10 +655,12 @@ spec:
             name: %s
             port:
               number: %d
-`, backendSvc, backendSvcPort[0])
+`, secretName, backendSvc, backendSvcPort[0])
 			assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ingress))
+			routes, err := s.ListApisixRoutes()
+			assert.Nil(ginkgo.GinkgoT(), err, "list routes error")
+			assert.Len(ginkgo.GinkgoT(), routes, 0, "routes number not expect")
 
-			secretName := "test-apisix-tls"
 			cert := `-----BEGIN CERTIFICATE-----
 MIIFcjCCA1qgAwIBAgIJALDqPppBVXQ3MA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNV
 BAYTAkNOMRAwDgYDVQQIDAdKaWFuZ3N1MQ8wDQYDVQQHDAZTdXpob3UxEDAOBgNV
@@ -739,15 +747,14 @@ jW4KB95bGOTa7r7DM1Up0MbAIwWoeLBGhOIXk7inurZGg+FNjZMA5Lzm6qo=
 			// key compare
 			keyCompare := "HrMHUvE9Esvn7GnZ+vAynaIg/8wlB3r0zm0htmnwofaOw61M98WSdvoWLaQa8YKSdemgQUz2W4MYk2rRZcVSzHfJOLRG7g4ieZau6peDYOmPmp/0ZZFpOzBKoWHN3QP/8i/7SF+JX+EDLD2JO2+GM6iR3f2Zj7v0vx+CcoQ1rjxaXNETSSHo8yvW6pdFZOLgJk4rOHKGypnqzygxxamM8Hq7WSPrWhNe47y1QAfz42kBQXRUJpNNd7W749cTsMWCqBlR+8klTlnSFHkjyijBZjg5ihqZsi/8JzHGrmAixZ54ugPgbufD0/ZJdo3w7opJc4WTnUI2GhiBL+ENCA0X1s/6H8JG8zsC50PvxOBpRgK455TTvejm1JHyt0GTh7c4WFEeQSrbEFzS89BpVrPtre2enO38pkILI8ty8r6tIbZzuOJhM6ZpxQQcAe8OUvFuIIlx21yBvlljbu3eH5Hg7X+wtJ [...]
 			// create secret
-			err := s.NewSecret(secretName, cert, key)
+			err = s.NewSecret(secretName, cert, key)
 			assert.Nil(ginkgo.GinkgoT(), err, "create secret error")
-			// create ApisixTls resource
-			tlsName := "tls-name"
 			host := "api6.com"
-			err = s.NewApisixTls(tlsName, host, secretName)
-			assert.Nil(ginkgo.GinkgoT(), err, "create tls error")
 			// check ssl in APISIX
 			time.Sleep(10 * time.Second)
+			routes, err = s.ListApisixRoutes()
+			assert.Nil(ginkgo.GinkgoT(), err, "list routes error")
+			assert.Len(ginkgo.GinkgoT(), routes, 1, "routes number not expect")
 			tls, err := s.ListApisixSsl()
 			assert.Nil(ginkgo.GinkgoT(), err, "list tls error")
 			assert.Len(ginkgo.GinkgoT(), tls, 1, "tls number not expect")
@@ -853,15 +860,423 @@ UnBVSIGJ/c0AhVSDuOAJiF36pvsDysTZXMTFE/9i5bkGOiwtzRNe4Hym/SEZUCpn
 			assert.Equal(ginkgo.GinkgoT(), keyCompareUpdate, tlsUpdate[0].Key, "tls key not expect")
 			// check DP
 			s.NewAPISIXHttpsClient(host).GET("/ip").WithHeader("Host", host).Expect().Status(http.StatusOK).Body().Raw()
+		})
+
+		ginkgo.It("should delete SSL if secret and Ingress are deleted", func() {
+			backendSvc, backendSvcPort := s.DefaultHTTPBackend()
+			secretName := "test-apisix-tls"
+			// create secret
+			cert := `-----BEGIN CERTIFICATE-----
+MIIFcjCCA1qgAwIBAgIJALDqPppBVXQ3MA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNV
+BAYTAkNOMRAwDgYDVQQIDAdKaWFuZ3N1MQ8wDQYDVQQHDAZTdXpob3UxEDAOBgNV
+BAoMB2FwaTcuYWkxEDAOBgNVBAsMB2FwaTcuYWkxDzANBgNVBAMMBmp3LmNvbTAg
+Fw0yMTA0MDkwNzEyMDBaGA8yMDUxMDQwMjA3MTIwMFowZTELMAkGA1UEBhMCQ04x
+EDAOBgNVBAgMB0ppYW5nc3UxDzANBgNVBAcMBlN1emhvdTEQMA4GA1UECgwHYXBp
+Ny5haTEQMA4GA1UECwwHYXBpNy5haTEPMA0GA1UEAwwGancuY29tMIICIjANBgkq
+hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuEPPnUMlSw41CTdxUNxkQ4gAZ7cPotwY
+Y6sVLGtWoR8gKFSZImQIor3UF+8HhN/ZOFRv5tSeeQ/MTE72cs2T5mp6eRU8OrSV
+0npk/TpZfaCx7zobsfXB4YU1NZcVWKthFF5X8p//l5gxUMU8V4a01P0aDTmZ67wG
+3Fhr0AC067GVYvdwp1yRt6TUUk8ha7JsiySchUIFhX5QMWmrSNhc1bDnHetejMFl
+itFFPZkeYG89O/7Ca1K3ca/VVu+/IJ4h7fbF3rt4uP182cJdHl1L94dQSKCJukaW
+v+xauWnm4hxOzBK7ImpYB/2eP2D33tmuCLeSv4S+bTG1l7hIN9C/xrYPzfun415h
+M2jMK69aAkQL71xa+66kVxioJyNYogYz3ss5ruzDL8K/7bkdO0Zzqldd2+j8lkTl
+X4csA+aMHF3v/U7hL/4Wdwi8ziwToRMq9KK9vuh+mPgcdtFGFml+sU+NQfJNm/BN
+7fRMZKDIHLacSPE0GUkfW+x3dXOP2lWSZe/iOBZ0NOGNdrOnxTRTr7IH7DYU8aXF
+w2GqfAFEQbD4wazCh1AI8lkZr6mPGB1q+HnF2IF7kkgXBHtI5U2KErgcX5BirIVe
+v0Yg/OxbbymeTh/hNCcY1kJ1YUCbm9U3U6ZV+d8lj7dQHtugcAzWxSTwpBLVUPrO
+eFuhSMLVblUCAwEAAaMjMCEwHwYDVR0RBBgwFoIIYXBpNi5jb22CCiouYXBpNi5j
+b20wDQYJKoZIhvcNAQELBQADggIBAFgeSuMPpriYUrQByO3taiY1+56s+KoAmsyA
+LH15n2+thAgorusX2g1Zd7UNBHBtVO8c+ihpQb+2PnmgTTGT70ndpRbV5F6124Mt
+Hui/X0kjm76RYd1QKN1VFp0Zo+JVdRa+VhDsXWjO0VetINmFhNINFEJctyeHB8oi
+aaDL0wZrevHh47hBqtnrmLl+QVG34aLBRhZ5953leiNvXHUJNaT0nLgf0j9p4esS
+b2bx9uP4pFI1T9wcv/TE3K0rQbu/uqGY6MgznXHyi4qIK/I+WCa3fF2UZ5P/5EUM
+k2ptQneYkLLUVwwmj8C04bYhYe7Z6jkYYp17ojxIP+ejOY1eiE8SYKNjKinmphrM
+5aceqIyfbE4TPqvicNzIggA4yEMPbTA0PC/wqbCf61oMc15hwacdeIaQGiwsM+pf
+DTk+GBxp3megx/+0XwTQbguleTlHnaaES+ma0vbl6a1rUK0YAUDUrcfFLv6EFtGD
+6EHxFf7gH9sTfc2RiGhKxUhRbyEree+6INAvXy+AymVYmQmKuAFqkDQJ+09bTfm8
+bDs+00FijzHFBvC8cIhNffj0qqiv35g+9FTwnE9qpunlrtKG/sMgEXX6m8kL1YQ8
+m5DPGhyEZyt5Js2kzzo8TyINPKmrqriYuiD4p4EH13eSRs3ayanQh6ckC7lb+WXq
+3IrSc5hO
+-----END CERTIFICATE-----`
+			key := `-----BEGIN RSA PRIVATE KEY-----
+MIIJKAIBAAKCAgEAuEPPnUMlSw41CTdxUNxkQ4gAZ7cPotwYY6sVLGtWoR8gKFSZ
+ImQIor3UF+8HhN/ZOFRv5tSeeQ/MTE72cs2T5mp6eRU8OrSV0npk/TpZfaCx7zob
+sfXB4YU1NZcVWKthFF5X8p//l5gxUMU8V4a01P0aDTmZ67wG3Fhr0AC067GVYvdw
+p1yRt6TUUk8ha7JsiySchUIFhX5QMWmrSNhc1bDnHetejMFlitFFPZkeYG89O/7C
+a1K3ca/VVu+/IJ4h7fbF3rt4uP182cJdHl1L94dQSKCJukaWv+xauWnm4hxOzBK7
+ImpYB/2eP2D33tmuCLeSv4S+bTG1l7hIN9C/xrYPzfun415hM2jMK69aAkQL71xa
++66kVxioJyNYogYz3ss5ruzDL8K/7bkdO0Zzqldd2+j8lkTlX4csA+aMHF3v/U7h
+L/4Wdwi8ziwToRMq9KK9vuh+mPgcdtFGFml+sU+NQfJNm/BN7fRMZKDIHLacSPE0
+GUkfW+x3dXOP2lWSZe/iOBZ0NOGNdrOnxTRTr7IH7DYU8aXFw2GqfAFEQbD4wazC
+h1AI8lkZr6mPGB1q+HnF2IF7kkgXBHtI5U2KErgcX5BirIVev0Yg/OxbbymeTh/h
+NCcY1kJ1YUCbm9U3U6ZV+d8lj7dQHtugcAzWxSTwpBLVUPrOeFuhSMLVblUCAwEA
+AQKCAgApTupoMvlVTiYNnuREYGQJz59noN5cgELndR8WCiotjLDE2dJKp2pYMX4u
+r2NcImKsAiHj+Z5dPXFrWfhd3EBf01cJdf0+m+VKfi3NpxsQ0smQ+9Hhn1qLmDVJ
+gklCy4jD7DKDLeM6tN+5X74bUROQ+/yvIk6jTk+rbhcdVks422LGAPq8SkBQjx8a
+JKs1XZZ/ywFbzmU2fA62RR4lAnwtW680QeO8Yk7FRAzltkHdFJMBtCcZsD13uxd0
+meKbCVhJ5JyPRi/WKN2oY65EdF3na+pPnc3CeLiq5e2gy2D7J6VyknBpUrXRdMXZ
+J3/p8ZrWUXEQhk26ZP50uNdXy/Bx1jYe+U8mpkTMYVYxgu5K4Zea3yJyRn2piiE/
+9LnKNy/KsINt/0QE55ldvtciyP8RDA/08eQX0gvtKWWC/UFVRZCeL48bpqLmdAfE
+cMwlk1b0Lmo2PxULFLMAjaTKmcMAbwl53YRit0MtvaIOwiZBUVHE0blRiKC2DMKi
+SA6xLbaYJVDaMcfix8kZkKbC0xBNmL4123qX4RF6IUTPufyUTz/tpjzH6eKDw/88
+LmSx227d7/qWp5gROCDhZOPhtr4rj70JKNqcXUX9iFga+dhloOwfHYjdKndKOLUI
+Gp3K9YkPT/fCfesrguUx8BoleO5pC6RQJhRsemkRGlSY8U1ZsQKCAQEA5FepCn1f
+A46GsBSQ+/pbaHlbsR2syN3J5RmAFLFozYUrqyHE/cbNUlaYq397Ax7xwQkiN3F2
+z/whTxOh4Sk/HdDF4d+I0PZeoxINxgfzyYkx8Xpzn2loxsRO8fb3g+mOxZidjjXv
+vxqUBaj3Y01Ig0UXuw7YqCwys+xg3ELtvcGLBW/7NWMo8zqk2nUjhfcwp4e4AwBt
+Xcsc2aShUlr/RUrJH4adjha6Yaqc/8xTXHW8gZi5L2lucwB0LA+CBe4ES9BZLZdX
+N575/ohXRdjadHKYceYHiamt2326DzaxVJu2EIXU8dgdgOZ/6krITzuePRQHLPHX
+6bDfdg/WSpFrtwKCAQEAzpVqBcJ1fAI7bOkt89j2zZb1r5uD2f9sp/lA/Dj65QKV
+ShWR7Y6Jr4ShXmFvIenWtjwsl86PflMgtsJefOmLyv8o7PL154XD8SnNbBlds6IM
+MyNKkOJFa5NOrsal7TitaTvtYdKq8Zpqtxe+2kg80wi+tPVQNQS/drOpR3rDiLIE
+La/ty8XDYZsSowlzBX+uoFq7GuMct1Uh2T0/I4Kf0ZLXwYjkRlRk4LrU0BRPhRMu
+MHugOTYFKXShE2a3OEcxqCgvQ/3pn2TV92pPVKBIBGL6uKUwmXQYKaV3G4u10pJ4
+axq/avBOErcKZOReb0SNiOjiIsth8o+hnpYPU5COUwKCAQBksVNV0NtpUhyK4Ube
+FxTgCUQp4pAjM8qoQIp+lY1FtAgBuy6HSneYa59/YQP56FdrbH+uO1bNeL2nhVzJ
+UcsHdt0MMeq/WyV4e6mfPjp/EQT5G6qJDY6quD6n7ORRQ1k2QYqY/6fteeb0aAJP
+w/DKElnYnz9jSbpCJWbBOrJkD0ki6LK6ZDPWrnGr9CPqG4tVFUBL8pBH4B2kzDhn
+fME86TGvuUkZM2SVVQtOsefAyhqKe7KN+cw+4mBYXa5UtxUl6Yap2CcZ2/0aBT2X
+C32qBC69a1a/mheUxuiZdODWEqRCvQGedFLuWLbntnqGlh+9h2tyomM4JkskYO96
+io4ZAoIBAFouLW9AOUseKlTb4dx+DRcoXC4BpGhIsWUOUQkJ0rSgEQ2bJu3d+Erv
+igYKYJocW0eIMys917Qck75UUS0UQpsmEfaGBUTBRw0C45LZ6+abydmVAVsH+6f/
+USzIuOw6frDeoTy/2zHG5+jva7gcKrkxKxcRs6bBYNdvjGkQtUT5+Qr8rsDyntz/
+9f3IBTcUSuXjVaRiGkoJ1tHfg617u0qgYKEyofv1oWfdB0Oiaig8fEBb51CyPUSg
+jiRLBZaCtbGjgSacNB0JxsHP3buikG2hy7NJIVMLs/SSL9GNhpzapciTj5YeOua+
+ksICUxsdgO+QQg9QW3yoqLPy69Pd2dMCggEBANDLoUf3ZE7Dews6cfIa0WC33NCV
+FkyECaF2MNOp5Q9y/T35FyeA7UeDsTZ6Dy++XGW4uNStrSI6dCyQARqJw+i7gCst
+2m5lIde01ptzDQ9iO1Dv1XasxX/589CyLq6CxLfRgPMJPDeUEg0X7+a0lBT5Hpwk
+gNnZmws4l3i7RlVMtACCenmof9VtOcMK/9Qr502WHEoGkQR1r6HZFb25841cehL2
+do+oXlr8db++r87a8QQUkizzc6wXD9JffBNo9AO9Ed4HVOukpEA0gqVGBu85N3xW
+jW4KB95bGOTa7r7DM1Up0MbAIwWoeLBGhOIXk7inurZGg+FNjZMA5Lzm6qo=
+-----END RSA PRIVATE KEY-----`
+			err := s.NewSecret(secretName, cert, key)
+			assert.Nil(ginkgo.GinkgoT(), err, "create secret error")
+			host := "api6.com"
+
+			// create ingress
+			ingress := fmt.Sprintf(`
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  annotations:
+    kubernetes.io/ingress.class: apisix
+  name: ingress-route
+spec:
+  tls:
+  - hosts:
+    - api6.com
+    secretName: %s
+  rules:
+  - host: api6.com
+    http:
+      paths:
+      - path: /ip
+        pathType: Exact
+        backend:
+          service:
+            name: %s
+            port:
+              number: %d
+`, secretName, backendSvc, backendSvcPort[0])
+			assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ingress))
+
+			// key compare
+			keyCompare := "HrMHUvE9Esvn7GnZ+vAynaIg/8wlB3r0zm0htmnwofaOw61M98WSdvoWLaQa8YKSdemgQUz2W4MYk2rRZcVSzHfJOLRG7g4ieZau6peDYOmPmp/0ZZFpOzBKoWHN3QP/8i/7SF+JX+EDLD2JO2+GM6iR3f2Zj7v0vx+CcoQ1rjxaXNETSSHo8yvW6pdFZOLgJk4rOHKGypnqzygxxamM8Hq7WSPrWhNe47y1QAfz42kBQXRUJpNNd7W749cTsMWCqBlR+8klTlnSFHkjyijBZjg5ihqZsi/8JzHGrmAixZ54ugPgbufD0/ZJdo3w7opJc4WTnUI2GhiBL+ENCA0X1s/6H8JG8zsC50PvxOBpRgK455TTvejm1JHyt0GTh7c4WFEeQSrbEFzS89BpVrPtre2enO38pkILI8ty8r6tIbZzuOJhM6ZpxQQcAe8OUvFuIIlx21yBvlljbu3eH5Hg7X+wtJ [...]
 
-			// delete ApisixTls
-			err = s.DeleteApisixTls(tlsName, host, secretName)
-			assert.Nil(ginkgo.GinkgoT(), err, "delete tls error")
 			// check ssl in APISIX
 			time.Sleep(10 * time.Second)
-			tls, err = s.ListApisixSsl()
+			routes, err := s.ListApisixRoutes()
+			assert.Nil(ginkgo.GinkgoT(), err, "list routes error")
+			assert.Len(ginkgo.GinkgoT(), routes, 1, "routes number not expect")
+			ssls, err := s.ListApisixSsl()
 			assert.Nil(ginkgo.GinkgoT(), err, "list tls error")
-			assert.Len(ginkgo.GinkgoT(), tls, 0, "tls number not expect")
+			assert.Len(ginkgo.GinkgoT(), ssls, 1, "tls number not expect")
+			assert.Equal(ginkgo.GinkgoT(), cert, ssls[0].Cert, "tls cert not expect")
+			assert.Equal(ginkgo.GinkgoT(), keyCompare, ssls[0].Key, "tls key not expect")
+
+			// check DP
+			s.NewAPISIXHttpsClient(host).GET("/ip").WithHeader("Host", host).Expect().Status(http.StatusOK).Body().Raw()
+
+			// delete secret
+			err = s.DeleteResource("secret", secretName)
+			assert.Nil(ginkgo.GinkgoT(), err, "delete secret error")
+			// check routes
+			routes, err = s.ListApisixRoutes()
+			assert.Nil(ginkgo.GinkgoT(), err, "list routes error")
+			assert.Len(ginkgo.GinkgoT(), routes, 1, "routes number not expect")
+			// check ssl in APISIX
+			time.Sleep(10 * time.Second)
+			ssls, err = s.ListApisixSsl()
+			assert.Nil(ginkgo.GinkgoT(), err, "list tlsUpdate error")
+			assert.Len(ginkgo.GinkgoT(), ssls, 1, "tls number not expect")
+			assert.Equal(ginkgo.GinkgoT(), cert, ssls[0].Cert, "tls cert not expect")
+			assert.Equal(ginkgo.GinkgoT(), keyCompare, ssls[0].Key, "tls key not expect")
+			// check DP
+			s.NewAPISIXHttpsClient(host).GET("/ip").WithHeader("Host", host).Expect().Status(http.StatusOK).Body().Raw()
+
+			// delete ingress
+			err = s.DeleteResource("ingress", "ingress-route")
+			assert.Nil(ginkgo.GinkgoT(), err, "delete ingress error")
+			// check routes
+			routes, err = s.ListApisixRoutes()
+			assert.Nil(ginkgo.GinkgoT(), err, "list routes error")
+			assert.Len(ginkgo.GinkgoT(), routes, 0, "routes number not expect")
+			// check ssl in APISIX
+			time.Sleep(10 * time.Second)
+			ssls, err = s.ListApisixSsl()
+			assert.Nil(ginkgo.GinkgoT(), err, "list tlsUpdate error")
+			assert.Len(ginkgo.GinkgoT(), ssls, 0, "tls number not expect")
+		})
+
+		ginkgo.It("should update SSL if secret is deleted then re-create", func() {
+			backendSvc, backendSvcPort := s.DefaultHTTPBackend()
+			secretName := "test-apisix-tls"
+			// create secret
+			cert := `-----BEGIN CERTIFICATE-----
+MIIFcjCCA1qgAwIBAgIJALDqPppBVXQ3MA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNV
+BAYTAkNOMRAwDgYDVQQIDAdKaWFuZ3N1MQ8wDQYDVQQHDAZTdXpob3UxEDAOBgNV
+BAoMB2FwaTcuYWkxEDAOBgNVBAsMB2FwaTcuYWkxDzANBgNVBAMMBmp3LmNvbTAg
+Fw0yMTA0MDkwNzEyMDBaGA8yMDUxMDQwMjA3MTIwMFowZTELMAkGA1UEBhMCQ04x
+EDAOBgNVBAgMB0ppYW5nc3UxDzANBgNVBAcMBlN1emhvdTEQMA4GA1UECgwHYXBp
+Ny5haTEQMA4GA1UECwwHYXBpNy5haTEPMA0GA1UEAwwGancuY29tMIICIjANBgkq
+hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuEPPnUMlSw41CTdxUNxkQ4gAZ7cPotwY
+Y6sVLGtWoR8gKFSZImQIor3UF+8HhN/ZOFRv5tSeeQ/MTE72cs2T5mp6eRU8OrSV
+0npk/TpZfaCx7zobsfXB4YU1NZcVWKthFF5X8p//l5gxUMU8V4a01P0aDTmZ67wG
+3Fhr0AC067GVYvdwp1yRt6TUUk8ha7JsiySchUIFhX5QMWmrSNhc1bDnHetejMFl
+itFFPZkeYG89O/7Ca1K3ca/VVu+/IJ4h7fbF3rt4uP182cJdHl1L94dQSKCJukaW
+v+xauWnm4hxOzBK7ImpYB/2eP2D33tmuCLeSv4S+bTG1l7hIN9C/xrYPzfun415h
+M2jMK69aAkQL71xa+66kVxioJyNYogYz3ss5ruzDL8K/7bkdO0Zzqldd2+j8lkTl
+X4csA+aMHF3v/U7hL/4Wdwi8ziwToRMq9KK9vuh+mPgcdtFGFml+sU+NQfJNm/BN
+7fRMZKDIHLacSPE0GUkfW+x3dXOP2lWSZe/iOBZ0NOGNdrOnxTRTr7IH7DYU8aXF
+w2GqfAFEQbD4wazCh1AI8lkZr6mPGB1q+HnF2IF7kkgXBHtI5U2KErgcX5BirIVe
+v0Yg/OxbbymeTh/hNCcY1kJ1YUCbm9U3U6ZV+d8lj7dQHtugcAzWxSTwpBLVUPrO
+eFuhSMLVblUCAwEAAaMjMCEwHwYDVR0RBBgwFoIIYXBpNi5jb22CCiouYXBpNi5j
+b20wDQYJKoZIhvcNAQELBQADggIBAFgeSuMPpriYUrQByO3taiY1+56s+KoAmsyA
+LH15n2+thAgorusX2g1Zd7UNBHBtVO8c+ihpQb+2PnmgTTGT70ndpRbV5F6124Mt
+Hui/X0kjm76RYd1QKN1VFp0Zo+JVdRa+VhDsXWjO0VetINmFhNINFEJctyeHB8oi
+aaDL0wZrevHh47hBqtnrmLl+QVG34aLBRhZ5953leiNvXHUJNaT0nLgf0j9p4esS
+b2bx9uP4pFI1T9wcv/TE3K0rQbu/uqGY6MgznXHyi4qIK/I+WCa3fF2UZ5P/5EUM
+k2ptQneYkLLUVwwmj8C04bYhYe7Z6jkYYp17ojxIP+ejOY1eiE8SYKNjKinmphrM
+5aceqIyfbE4TPqvicNzIggA4yEMPbTA0PC/wqbCf61oMc15hwacdeIaQGiwsM+pf
+DTk+GBxp3megx/+0XwTQbguleTlHnaaES+ma0vbl6a1rUK0YAUDUrcfFLv6EFtGD
+6EHxFf7gH9sTfc2RiGhKxUhRbyEree+6INAvXy+AymVYmQmKuAFqkDQJ+09bTfm8
+bDs+00FijzHFBvC8cIhNffj0qqiv35g+9FTwnE9qpunlrtKG/sMgEXX6m8kL1YQ8
+m5DPGhyEZyt5Js2kzzo8TyINPKmrqriYuiD4p4EH13eSRs3ayanQh6ckC7lb+WXq
+3IrSc5hO
+-----END CERTIFICATE-----`
+			key := `-----BEGIN RSA PRIVATE KEY-----
+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
+-----END RSA PRIVATE KEY-----`
+			err := s.NewSecret(secretName, cert, key)
+			assert.Nil(ginkgo.GinkgoT(), err, "create secret error")
+			host := "api6.com"
+
+			// create ingress
+			ingress := fmt.Sprintf(`
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  annotations:
+    kubernetes.io/ingress.class: apisix
+  name: ingress-route
+spec:
+  tls:
+  - hosts:
+    - api6.com
+    secretName: %s
+  rules:
+  - host: api6.com
+    http:
+      paths:
+      - path: /ip
+        pathType: Exact
+        backend:
+          service:
+            name: %s
+            port:
+              number: %d
+`, secretName, backendSvc, backendSvcPort[0])
+			assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ingress))
+
+			// key compare
+			keyCompare := "HrMHUvE9Esvn7GnZ+vAynaIg/8wlB3r0zm0htmnwofaOw61M98WSdvoWLaQa8YKSdemgQUz2W4MYk2rRZcVSzHfJOLRG7g4ieZau6peDYOmPmp/0ZZFpOzBKoWHN3QP/8i/7SF+JX+EDLD2JO2+GM6iR3f2Zj7v0vx+CcoQ1rjxaXNETSSHo8yvW6pdFZOLgJk4rOHKGypnqzygxxamM8Hq7WSPrWhNe47y1QAfz42kBQXRUJpNNd7W749cTsMWCqBlR+8klTlnSFHkjyijBZjg5ihqZsi/8JzHGrmAixZ54ugPgbufD0/ZJdo3w7opJc4WTnUI2GhiBL+ENCA0X1s/6H8JG8zsC50PvxOBpRgK455TTvejm1JHyt0GTh7c4WFEeQSrbEFzS89BpVrPtre2enO38pkILI8ty8r6tIbZzuOJhM6ZpxQQcAe8OUvFuIIlx21yBvlljbu3eH5Hg7X+wtJ [...]
+
+			// check ssl in APISIX
+			time.Sleep(10 * time.Second)
+			routes, err := s.ListApisixRoutes()
+			assert.Nil(ginkgo.GinkgoT(), err, "list routes error")
+			assert.Len(ginkgo.GinkgoT(), routes, 1, "routes number not expect")
+			ssls, err := s.ListApisixSsl()
+			assert.Nil(ginkgo.GinkgoT(), err, "list tls error")
+			assert.Len(ginkgo.GinkgoT(), ssls, 1, "tls number not expect")
+			assert.Equal(ginkgo.GinkgoT(), cert, ssls[0].Cert, "tls cert not expect")
+			assert.Equal(ginkgo.GinkgoT(), keyCompare, ssls[0].Key, "tls key not expect")
+
+			// check DP
+			s.NewAPISIXHttpsClient(host).GET("/ip").WithHeader("Host", host).Expect().Status(http.StatusOK).Body().Raw()
+
+			// delete secret
+			err = s.DeleteResource("secret", secretName)
+			assert.Nil(ginkgo.GinkgoT(), err, "delete secret error")
+			// check routes
+			routes, err = s.ListApisixRoutes()
+			assert.Nil(ginkgo.GinkgoT(), err, "list routes error")
+			assert.Len(ginkgo.GinkgoT(), routes, 1, "routes number not expect")
+			// check ssl in APISIX
+			time.Sleep(10 * time.Second)
+			ssls, err = s.ListApisixSsl()
+			assert.Nil(ginkgo.GinkgoT(), err, "list tlsUpdate error")
+			assert.Len(ginkgo.GinkgoT(), ssls, 1, "tls number not expect")
+			assert.Equal(ginkgo.GinkgoT(), cert, ssls[0].Cert, "tls cert not expect")
+			assert.Equal(ginkgo.GinkgoT(), keyCompare, ssls[0].Key, "tls key not expect")
+			// check DP
+			s.NewAPISIXHttpsClient(host).GET("/ip").WithHeader("Host", host).Expect().Status(http.StatusOK).Body().Raw()
+
+			// re-create secret
+			certUpdate := `-----BEGIN CERTIFICATE-----
+MIIFcjCCA1qgAwIBAgIJAM7zkxmhGdNEMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNV
+BAYTAkNOMRAwDgYDVQQIDAdKaWFuZ3N1MQ8wDQYDVQQHDAZTdXpob3UxEDAOBgNV
+BAoMB2FwaTcuYWkxEDAOBgNVBAsMB2FwaTcuYWkxDzANBgNVBAMMBmp3LmNvbTAg
+Fw0yMTA0MDkwNzE1MzNaGA8yMDUxMDQwMjA3MTUzM1owZTELMAkGA1UEBhMCQ04x
+EDAOBgNVBAgMB0ppYW5nc3UxDzANBgNVBAcMBlN1emhvdTEQMA4GA1UECgwHYXBp
+Ny5haTEQMA4GA1UECwwHYXBpNy5haTEPMA0GA1UEAwwGancuY29tMIICIjANBgkq
+hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlXGEL4P5+mjllbb4VxkpqjsHny2wY7QZ
+NbA0INfLdBq3B5avL0Gp/nHk1iOMq+RkUu+DDb9i0wKw0j1ygaaN4WNXCa7/LZ7E
+IVDKcCKF7JQUi5za9A36nTBMLb7ZbFwxnxGkCK2AwdIbUIB6Ciq/d+WEbZelspPQ
+PtG9e8pVYTbNhRublGgVD+LEUHYdvSneveFQxdmHhNQMPXNbh+Qmgz48n7cLMEHh
+NwRyrWOb3zhdDeKlTm/yfPAQwvQNet+Ol3g19tKhS7WzDndrPfPNYAsoOdXZ5TTY
+AlXzwsbVYSOW4gMW39p68ZnoseQHBVZkiTfN2CGvWbzd9gUXOiQship+xRfSoVEY
+5FN1KsTIA5fdDbgqCTM4Ed1FTq39hJSBnsQObzQtfjgz0Sivwp9q0NoXX+YM6eBJ
+1kzVx6r70UMq+NJbs7mvAW9Ehzv2m2GsinMq3lyvVwSbsJWX9vOHKxmuWympmOw1
+7sUcH4DNHCxnzLK0L0oDV2atpNyKFvmMWSSmw09wOvuE+G+CLwILvgiSiTRPe1Gm
+cgaTC92nZsafA5d8r2uxxJRHD7PAQSE5YnsdLsXAFSegYyHss2jq8lzVFwWhTk4t
+A/8si8qUHh/hHKt71dYrSRmYTTyj834P8KDwQAMYBGcThtZa7PudOR22toohyte7
+Y7j4V6li2mkCAwEAAaMjMCEwHwYDVR0RBBgwFoIIYXBpNi5jb22CCiouYXBpNi5j
+b20wDQYJKoZIhvcNAQELBQADggIBAGmueLf8FFxVCgKKPQbHgPJ8/bTBQfBXi4cG
+eg46QT3j4r8cw05CM64NXQs51q8kWa4aIhGzXweZPZZcnLppIZX31HguAsaOTWEv
+2T3v9nqacMdujdyB+ll/bkwBoVudF47/JqQvHkevE0W43EZGgtmaPWki6psXK0C7
+Fwx95FeUizYrbsDDKbPKQ2iv70oES2bhhKi6K3o6uV6cFuUTxoNsjv9mjMM93xL/
+r5HhOAg7/voXwkvYAkOoehGRF4pwsfmjCJMF9k3BqDOZM+8087EHZFiWCPOvseA/
+FNxtEiDeUt86BGO9wzTv4ZN0gkJOrxATIw15wRemxnXJ8GUweiZh+U2nvDSklZq4
+Z4Wj2tWfa/yIqRBOZyqcAOS6jCnz/pYEGRniO6DMZSN1VX8A5pH8HNMnREW8Sze+
+c9cNZwquESqGFfKMAHOzuyxJhqEvuwwT/JNCLUgtQICPtdAQmNJQEwDAIdmS8VrX
+XNsBIYSloIopKd7IY3V7Y8yASs7jKLrtJN4AE+SpssWuTa4p2LSO08sW3NP8r86G
+1cs5R6Mckmqaqk5ES9gRbKmhm4goamb2fe2HJ/PTFyOrWtucA6OU3AdrQNXY+qbK
+FskpOMlyl8WZo6JMsbOjd+tVygf9QuhvH9MxYDvppfeHxS0B7mYGZDOV/4G2vn2A
+C1K1xkvo
+-----END CERTIFICATE-----`
+			keyUpdate := `-----BEGIN RSA PRIVATE KEY-----
+MIIJKQIBAAKCAgEAlXGEL4P5+mjllbb4VxkpqjsHny2wY7QZNbA0INfLdBq3B5av
+L0Gp/nHk1iOMq+RkUu+DDb9i0wKw0j1ygaaN4WNXCa7/LZ7EIVDKcCKF7JQUi5za
+9A36nTBMLb7ZbFwxnxGkCK2AwdIbUIB6Ciq/d+WEbZelspPQPtG9e8pVYTbNhRub
+lGgVD+LEUHYdvSneveFQxdmHhNQMPXNbh+Qmgz48n7cLMEHhNwRyrWOb3zhdDeKl
+Tm/yfPAQwvQNet+Ol3g19tKhS7WzDndrPfPNYAsoOdXZ5TTYAlXzwsbVYSOW4gMW
+39p68ZnoseQHBVZkiTfN2CGvWbzd9gUXOiQship+xRfSoVEY5FN1KsTIA5fdDbgq
+CTM4Ed1FTq39hJSBnsQObzQtfjgz0Sivwp9q0NoXX+YM6eBJ1kzVx6r70UMq+NJb
+s7mvAW9Ehzv2m2GsinMq3lyvVwSbsJWX9vOHKxmuWympmOw17sUcH4DNHCxnzLK0
+L0oDV2atpNyKFvmMWSSmw09wOvuE+G+CLwILvgiSiTRPe1GmcgaTC92nZsafA5d8
+r2uxxJRHD7PAQSE5YnsdLsXAFSegYyHss2jq8lzVFwWhTk4tA/8si8qUHh/hHKt7
+1dYrSRmYTTyj834P8KDwQAMYBGcThtZa7PudOR22toohyte7Y7j4V6li2mkCAwEA
+AQKCAgEAipLCQdUdHWfbS6JoUUtR6TnnbWDOaQV9Qt1q2PGBBN4oze6Z7zXyTbCK
+w04fiNy1cnoJidvn5UZfc/Pqk/I/KboV4TLWCBVqRIJH1QcOLDt7eaIvHZNAyjUY
+zmpj7ijnElsnQayw8gjDrzgS8g6FkMXQsFaoHRkXRsjx7THHTeelV0IsV8bTkPFz
+nDCKjveeRXACmBOHqFGAMBMh0rZqR9SUHn168HqGPZ/wPntY8/mtv8xkAIGp1tQ8
+lqn7Pe7CqA2d7IuPaUbJDCcL2FyUGfT+jfKQpAsGKdRNvlTlU7fOlzDKKzTKP/G5
+ZgrNv9NGUj7erwU9Nfb90r0RtqYIac2CQnBDNx6snsSLx+QlO5wEQ8+xZ3zjKkGi
+VazSaSqpkK2MV7KwyxJD5WEMqyHuUufQGU8TVywi4RkH21VXiwxwCbRLpF/gdBMi
+2015JF1qd/t4GSHc6CtxqKslSxvNpr2cG6c/5Tx2gC3X6ARMr01YDFdKKI/FrsTQ
+w3/E/WNKoPNgAXy361oaT5QVGOyBbL8h9mmDW6vD3R0aLLzdZKsQU+DNs6tcAl10
+mboKMBDVyg2Qew5QsumD89EpA3Da9VkyMxcPmOJ7oOJqscNF3Ejyx8ePlF+jS3dR
+467uaXERVCGep2WDuYcv5Y14uUYAVj+P9aH85YjozA2KzG0aiqECggEBAMZvZwwd
+fgub7RrU/0sHWw50JupVaRIjVIgopTmUw6MWDcpjn6BiCsMCJlabHxeN8XJYn3+E
+aro8TZMvMYvjQQ0yrdKbPw8VLoTNfu++Bn/HPQ8gHFV+wzk33xfKRlRqxXic+MlG
+SQ33IV+xr7JoW4fiMjSvOpp3kJj459mSOBLjhcXW7N4sMPhY6O72g2pqa8ncmOJT
+ZU94VlssAxL3B1P1wsH8HsjhIluDHT+9qwsHhq/prIGLs4ydQSNB0m1oDT21zK/R
+jC7fDbTT4oTZzy8QYiLDwW4ugct53HMQCnJfOdX4F6aOxt7k4d8VwoGuliKyjHii
+VX4C+LZfT/64XiUCggEBAMDLyfqY8PK4ULNPrpSh92IOX5iwCcwGmOYDwGIeIbO6
+S1Pp7WGhA6Ryap/+F5gIdhB0qfnhAslMrQNRFfo3EcHF86UiCsfIRbPh7fwC2s0F
+4G+tST6TsPyCddjWiQsvsmT1eYPNDgPj6JDl3d0mzboVsVge46RORTAhm4k2pobZ
+EUDl+bljWM4LTf+pjN4DTRptwwueSqLVfxdkMhrHSG/NAYFerUKozxJGZeavnUcL
+c+WUCtPJvyQrx2CBhn8LQ7xsPJJPYjNwSf6joMNXPyGvfPYQaxaK1NM0y/7KfuYN
+N8DoBwwnpZIvcznjHDWY0P/cIZFKC2mmq6N062z/bfUCggEAey2oQAMGvVobgy55
+EzALvBsqFQjT4miADs18UxQfpVsJUHsrGboCiC8LcXN1h3+bQ6nzyIqAXf8VAKqp
+DPcS6IhvEm9AY7J4YAPYKiZBjow1QPBj5kZ8FUaze+caZUiqMEbwwLCapMqlsutv
+70WMm/szwzSLIlvaLLtF4O89U6xc3ASgoQG5nFBEuCHaTfKl2nbPiJ7QItbGdG4L
+sngZ2mqSbSx+R6BJXZk0TN8GECCp4QUjCn+YA0+Sobo4T6Xpokb6OqHPbUEVFwz4
+bhNu4v4+jOoLZsQD2jVZPSvV8E1gb4xD0iaLGM3n0D2HskyX8g332OKcQ07A6SSd
+WbdE6QKCAQEAiC2pzgNHdfowrmcjBkNdLHrAlWYKlX03dIjD08o6vethl7UNAj+s
+BfT3UWk1myKm2jq9cQ25XRx2vHgC0Qki1r8OuN5RxQm2CjgUVERj7hsvi1JYAQZr
+JgC0YuQuSqN3G460NR+ava62r9pdmv70o3L9ICQ5YO4UOsoSRZo/h9I9OJz4hjUh
+HfCoOGS3Zn3ocTmEYml9iITKz2fraDTI+odQf+Oy9/mqwdrN0WLL8cmqJEgsWaoQ
+A+mUW5tBt+zp/GZrZmECGRlAesdzH2c55X5CAsBYE8UeTMznJmI7vh0p+20oxTIf
+5iDz/7hmTYlSXtdLMoedhhO++qb0P7owHQKCAQBbjTZSMRiqevr3JlEouxioZ+XD
+yol9hMGQEquLWzqWlvP/LvgNT0PNRcE/qrMlPo7kzoq0r8PbL22tBl2C7C0e+BIv
+UnBVSIGJ/c0AhVSDuOAJiF36pvsDysTZXMTFE/9i5bkGOiwtzRNe4Hym/SEZUCpn
+4hL3iPXCYEWz5hDeoucgdZQjHv2JeQQ3NR9OokwQOwvzlx8uYwgV/6ZT9dJJ3AZL
+8Z1U5/a5LhrDtIKAsCCpRx99P++Eqt2M2YV7jZcTfEbEvxP4XBYcdh30nbq1uEhs
+4zEnK1pMx5PnEljN1mcgmL2TPsMVN5DN9zXHW5eNQ6wfXR8rCfHwVIVcUuaB
+-----END RSA PRIVATE KEY-----`
+			keyCompareUpdate := "HrMHUvE9Esvn7GnZ+vAynaIg/8wlB3r0zm0htmnwofY0a95jf9O5bkBT8pEwjhLvcZOysVlRXE9fYFZ7heHoaihZmZIcnNPPi/SnNr1qVExgIWFYCf6QzpMdv7bMKag8AnYlalvbEIAyJA2tjZ0Gt9aQ9YlzmbGtyFX344481bSfLR/3fpNABO2j/6C6IQxxaGOPRiUeBEJ4VwPxmCUecRPWOHgQfyROReELWwkTIXZ17j0YeABDHWpsHASTjMdupvdwma20TlA3ruNV9WqDn1VE8hDTB4waAImqbZI0bBMdqDFVE0q50DSl2uzzO8X825CLjIa/E0U6JPid41hGOdadZph5Gbpnlou8xwOgRfzG1yyptPCKrAJcgIvsSz/CsYCqaoPCpil4TFjUq4PH0cWo6GlXN95TPX0LrAOh8WMCb7lZYXq5Q2TZ/sn5jF1GIiZZFWVUZujXK2og0I04 [...]
+			// key update compare
+			err = s.NewSecret(secretName, certUpdate, keyUpdate)
+			assert.Nil(ginkgo.GinkgoT(), err, "create secret error")
+			// check ssl in APISIX
+			time.Sleep(10 * time.Second)
+			tlsUpdate, err := s.ListApisixSsl()
+			assert.Nil(ginkgo.GinkgoT(), err, "list tlsUpdate error")
+			assert.Len(ginkgo.GinkgoT(), tlsUpdate, 1, "tls number not expect")
+			assert.Equal(ginkgo.GinkgoT(), certUpdate, tlsUpdate[0].Cert, "tls cert not expect")
+			assert.Equal(ginkgo.GinkgoT(), keyCompareUpdate, tlsUpdate[0].Key, "tls key not expect")
+			// check DP
+			s.NewAPISIXHttpsClient(host).GET("/ip").WithHeader("Host", host).Expect().Status(http.StatusOK).Body().Raw()
 		})
 	}