feat:add labels for resources (#378)

diff --git a/pkg/kube/translation/apisix_route.go b/pkg/kube/translation/apisix_route.go
index dd8917c..0e03a82 100644
--- a/pkg/kube/translation/apisix_route.go
+++ b/pkg/kube/translation/apisix_route.go
@@ -38,9 +38,6 @@
 
 	for _, r := range ar.Spec.Rules {
 		for _, p := range r.Http.Paths {
-			routeName := r.Host + p.Path
-			upstreamName := apisixv1.ComposeUpstreamName(ar.Namespace, p.Backend.ServiceName, int32(p.Backend.ServicePort))
-
 			pluginMap := make(apisixv1.Plugins)
 			// 1.add annotation plugins
 			for k, v := range plugins {
@@ -59,28 +56,26 @@
 					pluginMap[plugin.Name] = make(map[string]interface{})
 				}
 			}
-			upsId := id.GenID(upstreamName)
-			route := &apisixv1.Route{
-				Metadata: apisixv1.Metadata{
-					ID:   id.GenID(routeName),
-					Name: routeName,
-				},
-				Host:       r.Host,
-				Uri:        p.Path,
-				UpstreamId: upsId,
-				Plugins:    pluginMap,
-			}
-			routes = append(routes, route)
+
+			upstreamName := apisixv1.ComposeUpstreamName(ar.Namespace, p.Backend.ServiceName, int32(p.Backend.ServicePort))
+			route := apisixv1.NewDefaultRoute()
+			route.Name = r.Host + p.Path
+			route.ID = id.GenID(route.Name)
+			route.Host = r.Host
+			route.Uri = p.Path
+			route.Plugins = pluginMap
+			route.UpstreamId = id.GenID(upstreamName)
 
 			if _, ok := upstreamMap[upstreamName]; !ok {
 				ups, err := t.TranslateUpstream(ar.Namespace, p.Backend.ServiceName, int32(p.Backend.ServicePort))
 				if err != nil {
 					return nil, nil, err
 				}
-				ups.ID = upsId
+				ups.ID = route.UpstreamId
 				ups.Name = upstreamName
 				upstreamMap[ups.Name] = ups
 			}
+			routes = append(routes, route)
 		}
 	}
 	for _, ups := range upstreamMap {
@@ -169,23 +164,18 @@
 			return nil, nil, err
 		}
 
-		routeName := apisixv1.ComposeRouteName(ar.Namespace, ar.Name, part.Name)
 		upstreamName := apisixv1.ComposeUpstreamName(ar.Namespace, backend.ServiceName, svcPort)
-		upsId := id.GenID(upstreamName)
-		route := &apisixv1.Route{
-			Metadata: apisixv1.Metadata{
-				Name: routeName,
-				ID:   id.GenID(routeName),
-			},
-			Priority:    part.Priority,
-			RemoteAddrs: part.Match.RemoteAddrs,
-			Vars:        exprs,
-			Hosts:       part.Match.Hosts,
-			Uris:        part.Match.Paths,
-			Methods:     part.Match.Methods,
-			UpstreamId:  upsId,
-			Plugins:     pluginMap,
-		}
+		route := apisixv1.NewDefaultRoute()
+		route.Name = apisixv1.ComposeRouteName(ar.Namespace, ar.Name, part.Name)
+		route.ID = id.GenID(route.Name)
+		route.Priority = part.Priority
+		route.RemoteAddrs = part.Match.RemoteAddrs
+		route.Vars = exprs
+		route.Hosts = part.Match.Hosts
+		route.Uris = part.Match.Paths
+		route.Methods = part.Match.Methods
+		route.UpstreamId = id.GenID(upstreamName)
+		route.Plugins = pluginMap
 
 		if len(backends) > 0 {
 			weight := _defaultWeight
diff --git a/pkg/kube/translation/apisix_ssl.go b/pkg/kube/translation/apisix_ssl.go
index 51f4de8..3dd4f30 100644
--- a/pkg/kube/translation/apisix_ssl.go
+++ b/pkg/kube/translation/apisix_ssl.go
@@ -51,6 +51,9 @@
 		Cert:   string(cert),
 		Key:    string(key),
 		Status: 1,
+		Labels: map[string]string{
+			"managed-by": "apisix-ingress-controller",
+		},
 	}
 	return ssl, nil
 }
diff --git a/pkg/kube/translation/ingress.go b/pkg/kube/translation/ingress.go
index d1e3f8e..0ea9903 100644
--- a/pkg/kube/translation/ingress.go
+++ b/pkg/kube/translation/ingress.go
@@ -71,14 +71,11 @@
 				}
 				uris = append(uris, prefix)
 			}
-			route := &apisixv1.Route{
-				Metadata: apisixv1.Metadata{
-					Name: composeIngressRouteName(rule.Host, pathRule.Path),
-				},
-				Host: rule.Host,
-				Uris: uris,
-			}
+			route := apisixv1.NewDefaultRoute()
+			route.Name = composeIngressRouteName(rule.Host, pathRule.Path)
 			route.ID = id.GenID(route.Name)
+			route.Host = rule.Host
+			route.Uris = uris
 			if ups != nil {
 				route.UpstreamId = ups.ID
 			}
@@ -130,14 +127,11 @@
 				}
 				uris = append(uris, prefix)
 			}
-			route := &apisixv1.Route{
-				Metadata: apisixv1.Metadata{
-					Name: composeIngressRouteName(rule.Host, pathRule.Path),
-				},
-				Host: rule.Host,
-				Uris: uris,
-			}
+			route := apisixv1.NewDefaultRoute()
+			route.Name = composeIngressRouteName(rule.Host, pathRule.Path)
 			route.ID = id.GenID(route.Name)
+			route.Host = rule.Host
+			route.Uris = uris
 			if ups != nil {
 				route.UpstreamId = ups.ID
 			}
diff --git a/pkg/types/apisix/v1/types.go b/pkg/types/apisix/v1/types.go
index 4eec171..ec4cf2e 100644
--- a/pkg/types/apisix/v1/types.go
+++ b/pkg/types/apisix/v1/types.go
@@ -64,14 +64,17 @@
 	// the active health check.
 	ActiveHealthCheckMinInterval = time.Second
 
-	// Default connect, read and send timeout (in seconds) with upstreams.
+	// DefaultUpstreamTimeout represents the default connect,
+	// read and send timeout (in seconds) with upstreams.
 	DefaultUpstreamTimeout = 60
 )
 
 // Metadata contains all meta information about resources.
 type Metadata struct {
-	ID   string `json:"id,omitempty" yaml:"id,omitempty"`
-	Name string `json:"name,omitempty" yaml:"name,omitempty"`
+	ID     string            `json:"id,omitempty" yaml:"id,omitempty"`
+	Name   string            `json:"name,omitempty" yaml:"name,omitempty"`
+	Desc   string            `json:"desc,omitempty" yaml:"desc,omitempty"`
+	Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
 }
 
 // Route apisix route object
@@ -268,11 +271,12 @@
 // Ssl apisix ssl object
 // +k8s:deepcopy-gen=true
 type Ssl struct {
-	ID     string   `json:"id,omitempty" yaml:"id,omitempty"`
-	Snis   []string `json:"snis,omitempty" yaml:"snis,omitempty"`
-	Cert   string   `json:"cert,omitempty" yaml:"cert,omitempty"`
-	Key    string   `json:"key,omitempty" yaml:"key,omitempty"`
-	Status int      `json:"status,omitempty" yaml:"status,omitempty"`
+	ID     string            `json:"id,omitempty" yaml:"id,omitempty"`
+	Snis   []string          `json:"snis,omitempty" yaml:"snis,omitempty"`
+	Cert   string            `json:"cert,omitempty" yaml:"cert,omitempty"`
+	Key    string            `json:"key,omitempty" yaml:"key,omitempty"`
+	Status int               `json:"status,omitempty" yaml:"status,omitempty"`
+	Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
 }
 
 // TrafficSplitConfig is the config of traffic-split plugin.
@@ -300,8 +304,26 @@
 	return &Upstream{
 		Type:   LbRoundRobin,
 		Key:    "",
-		Nodes:  nil,
+		Nodes:  make(UpstreamNodes, 0),
 		Scheme: SchemeHTTP,
+		Metadata: Metadata{
+			Desc: "Created by apisix-ingress-controller, DO NOT modify it manually",
+			Labels: map[string]string{
+				"managed-by": "apisix-ingress-controller",
+			},
+		},
+	}
+}
+
+// NewDefaultRoute returns an empty Route with default values.
+func NewDefaultRoute() *Route {
+	return &Route{
+		Metadata: Metadata{
+			Desc: "Created by apisix-ingress-controller, DO NOT modify it manually",
+			Labels: map[string]string{
+				"managed-by": "apisix-ingress-controller",
+			},
+		},
 	}
 }
 
diff --git a/test/e2e/ingress/resourcepushing.go b/test/e2e/ingress/resourcepushing.go
index fd93d99..99e201c 100644
--- a/test/e2e/ingress/resourcepushing.go
+++ b/test/e2e/ingress/resourcepushing.go
@@ -334,7 +334,7 @@
 		resp.Header("X-Request-Id").NotEmpty()
 	})
 
-	ginkgo.It("verify route items", func() {
+	ginkgo.It("verify route/upstream items", func() {
 		backendSvc, backendSvcPort := s.DefaultHTTPBackend()
 		apisixRoute := fmt.Sprintf(`
 apiVersion: apisix.apache.org/v2alpha1
@@ -366,6 +366,20 @@
 		assert.Equal(ginkgo.GinkgoT(), routes[0].Name, name)
 		assert.Equal(ginkgo.GinkgoT(), routes[0].Uris, []string{"/ip"})
 		assert.Equal(ginkgo.GinkgoT(), routes[0].Hosts, []string{"httpbin.com"})
+		assert.Equal(ginkgo.GinkgoT(), routes[0].Desc,
+			"Created by apisix-ingress-controller, DO NOT modify it manually")
+		assert.Equal(ginkgo.GinkgoT(), routes[0].Labels, map[string]string{
+			"managed-by": "apisix-ingress-controller",
+		})
+
+		ups, err := s.ListApisixUpstreams()
+		assert.Nil(ginkgo.GinkgoT(), err, "listing upstreams")
+		assert.Len(ginkgo.GinkgoT(), ups, 1)
+		assert.Equal(ginkgo.GinkgoT(), ups[0].Desc,
+			"Created by apisix-ingress-controller, DO NOT modify it manually")
+		assert.Equal(ginkgo.GinkgoT(), ups[0].Labels, map[string]string{
+			"managed-by": "apisix-ingress-controller",
+		})
 
 		resp := s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.com").Expect()
 		resp.Status(http.StatusOK)
diff --git a/test/e2e/ingress/ssl.go b/test/e2e/ingress/ssl.go
index 72d1d32..5511a86 100644
--- a/test/e2e/ingress/ssl.go
+++ b/test/e2e/ingress/ssl.go
@@ -157,6 +157,9 @@
 		assert.Nil(ginkgo.GinkgoT(), err, "list tls error")
 		assert.Len(ginkgo.GinkgoT(), tls, 1, "tls number not expect")
 		assert.Equal(ginkgo.GinkgoT(), tls[0].Snis[0], host, "tls host is error")
+		assert.Equal(ginkgo.GinkgoT(), tls[0].Labels, map[string]string{
+			"managed-by": "apisix-ingress-controller",
+		})
 	})
 	ginkgo.It("delete a SSL from ApisixTls ", func() {
 		secretName := "test-apisix-tls"