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 2022/03/28 02:12:26 UTC

[apisix-ingress-controller] branch master updated: feat: introduce v2 apiversion (#939)

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 3b99353  feat: introduce v2 apiversion (#939)
3b99353 is described below

commit 3b993533d66b25c186f4096727d373e5ed4131c6
Author: Jintao Zhang <zh...@gmail.com>
AuthorDate: Mon Mar 28 10:12:20 2022 +0800

    feat: introduce v2 apiversion (#939)
    
    Signed-off-by: Jintao Zhang <zh...@gmail.com>
---
 pkg/kube/apisix/apis/config/v2/doc.go              |   18 +
 pkg/kube/apisix/apis/config/v2/types.go            |  646 ++++++++++
 .../apisix/apis/config/v2/zz_generated.deepcopy.go | 1331 ++++++++++++++++++++
 .../apisix/apis/config/v2/zz_generated.register.go |   76 ++
 .../apisix/client/clientset/versioned/clientset.go |   14 +
 .../versioned/fake/clientset_generated.go          |    7 +
 .../client/clientset/versioned/fake/register.go    |    2 +
 .../client/clientset/versioned/scheme/register.go  |    2 +
 .../typed/config/v2/apisixclusterconfig.go         |  183 +++
 .../versioned/typed/config/v2/apisixconsumer.go    |  194 +++
 .../typed/config/v2/apisixpluginconfig.go          |  194 +++
 .../versioned/typed/config/v2/apisixroute.go       |  194 +++
 .../versioned/typed/config/v2/apisixtls.go         |  194 +++
 .../versioned/typed/config/v2/apisixupstream.go    |  194 +++
 .../versioned/typed/config/v2/config_client.go     |  113 ++
 .../clientset/versioned/typed/config/v2/doc.go     |   19 +
 .../versioned/typed/config/v2/fake/doc.go          |   19 +
 .../config/v2/fake/fake_apisixclusterconfig.go     |  132 ++
 .../typed/config/v2/fake/fake_apisixconsumer.go    |  141 +++
 .../config/v2/fake/fake_apisixpluginconfig.go      |  141 +++
 .../typed/config/v2/fake/fake_apisixroute.go       |  141 +++
 .../typed/config/v2/fake/fake_apisixtls.go         |  141 +++
 .../typed/config/v2/fake/fake_apisixupstream.go    |  141 +++
 .../typed/config/v2/fake/fake_config_client.go     |   59 +
 .../typed/config/v2/generated_expansion.go         |   30 +
 .../informers/externalversions/config/interface.go |    8 +
 .../config/v2/apisixclusterconfig.go               |   88 ++
 .../externalversions/config/v2/apisixconsumer.go   |   89 ++
 .../config/v2/apisixpluginconfig.go                |   89 ++
 .../externalversions/config/v2/apisixroute.go      |   89 ++
 .../externalversions/config/v2/apisixtls.go        |   89 ++
 .../externalversions/config/v2/apisixupstream.go   |   89 ++
 .../externalversions/config/v2/interface.go        |   79 ++
 .../client/informers/externalversions/generic.go   |   17 +-
 .../listers/config/v2/apisixclusterconfig.go       |   67 +
 .../client/listers/config/v2/apisixconsumer.go     |   98 ++
 .../client/listers/config/v2/apisixpluginconfig.go |   98 ++
 .../apisix/client/listers/config/v2/apisixroute.go |   98 ++
 .../apisix/client/listers/config/v2/apisixtls.go   |   98 ++
 .../client/listers/config/v2/apisixupstream.go     |   98 ++
 .../listers/config/v2/expansion_generated.go       |   62 +
 utils/update-codegen.sh                            |    4 +-
 utils/verify-codegen.sh                            |    4 +-
 43 files changed, 5585 insertions(+), 5 deletions(-)

diff --git a/pkg/kube/apisix/apis/config/v2/doc.go b/pkg/kube/apisix/apis/config/v2/doc.go
new file mode 100644
index 0000000..a2fe745
--- /dev/null
+++ b/pkg/kube/apisix/apis/config/v2/doc.go
@@ -0,0 +1,18 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +k8s:deepcopy-gen=package
+// +groupName=apisix.apache.org
+package v2
diff --git a/pkg/kube/apisix/apis/config/v2/types.go b/pkg/kube/apisix/apis/config/v2/types.go
new file mode 100644
index 0000000..95fa439
--- /dev/null
+++ b/pkg/kube/apisix/apis/config/v2/types.go
@@ -0,0 +1,646 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package v2
+
+import (
+	"encoding/json"
+	"time"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/util/intstr"
+
+	"github.com/apache/apisix-ingress-controller/pkg/types"
+)
+
+// +genclient
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// +kubebuilder:subresource:status
+// ApisixRoute is used to define the route rules and upstreams for Apache APISIX.
+type ApisixRoute struct {
+	metav1.TypeMeta   `json:",inline" yaml:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
+	Spec              ApisixRouteSpec `json:"spec,omitempty" yaml:"spec,omitempty"`
+	Status            ApisixStatus    `json:"status,omitempty" yaml:"status,omitempty"`
+}
+
+// ApisixStatus is the status report for Apisix ingress Resources
+type ApisixStatus struct {
+	Conditions []metav1.Condition `json:"conditions,omitempty" yaml:"conditions,omitempty"`
+}
+
+// ApisixRouteSpec is the spec definition for ApisixRouteSpec.
+type ApisixRouteSpec struct {
+	HTTP   []ApisixRouteHTTP   `json:"http,omitempty" yaml:"http,omitempty"`
+	Stream []ApisixRouteStream `json:"stream,omitempty" yaml:"stream,omitempty"`
+}
+
+// UpstreamTimeout is settings for the read, send and connect to the upstream.
+type UpstreamTimeout struct {
+	Connect metav1.Duration `json:"connect,omitempty" yaml:"connect,omitempty"`
+	Send    metav1.Duration `json:"send,omitempty" yaml:"send,omitempty"`
+	Read    metav1.Duration `json:"read,omitempty" yaml:"read,omitempty"`
+}
+
+// ApisixRouteHTTP represents a single route in for HTTP traffic.
+type ApisixRouteHTTP struct {
+	// The rule name, cannot be empty.
+	Name string `json:"name" yaml:"name"`
+	// Route priority, when multiple routes contains
+	// same URI path (for path matching), route with
+	// higher priority will take effect.
+	Priority int                  `json:"priority,omitempty" yaml:"priority,omitempty"`
+	Timeout  *UpstreamTimeout     `json:"timeout,omitempty" yaml:"timeout,omitempty"`
+	Match    ApisixRouteHTTPMatch `json:"match,omitempty" yaml:"match,omitempty"`
+	// Backends represents potential backends to proxy after the route
+	// rule matched. When number of backends are more than one, traffic-split
+	// plugin in APISIX will be used to split traffic based on the backend weight.
+	Backends         []ApisixRouteHTTPBackend  `json:"backends,omitempty" yaml:"backends,omitempty"`
+	Websocket        bool                      `json:"websocket" yaml:"websocket"`
+	PluginConfigName string                    `json:"plugin_config_name,omitempty" yaml:"plugin_config_name,omitempty"`
+	Plugins          []ApisixRouteHTTPPlugin   `json:"plugins,omitempty" yaml:"plugins,omitempty"`
+	Authentication   ApisixRouteAuthentication `json:"authentication,omitempty" yaml:"authentication,omitempty"`
+}
+
+// ApisixRouteHTTPBackend represents a HTTP backend (a Kuberentes Service).
+type ApisixRouteHTTPBackend struct {
+	// The name (short) of the service, note cross namespace is forbidden,
+	// so be sure the ApisixRoute and Service are in the same namespace.
+	ServiceName string `json:"serviceName" yaml:"serviceName"`
+	// The service port, could be the name or the port number.
+	ServicePort intstr.IntOrString `json:"servicePort" yaml:"servicePort"`
+	// The resolve granularity, can be "endpoints" or "service",
+	// when set to "endpoints", the pod ips will be used; other
+	// wise, the service ClusterIP or ExternalIP will be used,
+	// default is endpoints.
+	ResolveGranularity string `json:"resolveGranularity,omitempty" yaml:"resolveGranularity,omitempty"`
+	// Weight of this backend.
+	Weight *int `json:"weight" yaml:"weight"`
+	// Subset specifies a subset for the target Service. The subset should be pre-defined
+	// in ApisixUpstream about this service.
+	Subset string `json:"subset,omitempty" yaml:"subset,omitempty"`
+}
+
+// ApisixRouteHTTPMatch represents the match condition for hitting this route.
+type ApisixRouteHTTPMatch struct {
+	// URI path predicates, at least one path should be
+	// configured, path could be exact or prefix, for prefix path,
+	// append "*" after it, for instance, "/foo*".
+	Paths []string `json:"paths" yaml:"paths"`
+	// HTTP request method predicates.
+	Methods []string `json:"methods,omitempty" yaml:"methods,omitempty"`
+	// HTTP Host predicates, host can be a wildcard domain or
+	// an exact domain. For wildcard domain, only one generic
+	// level is allowed, for instance, "*.foo.com" is valid but
+	// "*.*.foo.com" is not.
+	Hosts []string `json:"hosts,omitempty" yaml:"hosts,omitempty"`
+	// Remote address predicates, items can be valid IPv4 address
+	// or IPv6 address or CIDR.
+	RemoteAddrs []string `json:"remoteAddrs,omitempty" yaml:"remoteAddrs,omitempty"`
+	// NginxVars represents generic match predicates,
+	// it uses Nginx variable systems, so any predicate
+	// like headers, querystring and etc can be leveraged
+	// here to match the route.
+	// For instance, it can be:
+	// nginxVars:
+	//   - subject: "$remote_addr"
+	//     op: in
+	//     value:
+	//       - "127.0.0.1"
+	//       - "10.0.5.11"
+	NginxVars []ApisixRouteHTTPMatchExpr `json:"exprs,omitempty" yaml:"exprs,omitempty"`
+}
+
+// ApisixRouteHTTPMatchExpr represents a binary route match expression .
+type ApisixRouteHTTPMatchExpr struct {
+	// Subject is the expression subject, it can
+	// be any string composed by literals and nginx
+	// vars.
+	Subject ApisixRouteHTTPMatchExprSubject `json:"subject" yaml:"subject"`
+	// Op is the operator.
+	Op string `json:"op" yaml:"op"`
+	// Set is an array type object of the expression.
+	// It should be used when the Op is "in" or "not_in";
+	Set []string `json:"set" yaml:"set"`
+	// Value is the normal type object for the expression,
+	// it should be used when the Op is not "in" and "not_in".
+	// Set and Value are exclusive so only of them can be set
+	// in the same time.
+	Value *string `json:"value" yaml:"value"`
+}
+
+// ApisixRouteHTTPMatchExprSubject describes the route match expression subject.
+type ApisixRouteHTTPMatchExprSubject struct {
+	// The subject scope, can be:
+	// ScopeQuery, ScopeHeader, ScopePath
+	// when subject is ScopePath, Name field
+	// will be ignored.
+	Scope string `json:"scope" yaml:"scope"`
+	// The name of subject.
+	Name string `json:"name" yaml:"name"`
+}
+
+// ApisixRouteHTTPPlugin represents an APISIX plugin.
+type ApisixRouteHTTPPlugin struct {
+	// The plugin name.
+	Name string `json:"name" yaml:"name"`
+	// Whether this plugin is in use, default is true.
+	Enable bool `json:"enable" yaml:"enable"`
+	// Plugin configuration.
+	Config ApisixRouteHTTPPluginConfig `json:"config" yaml:"config"`
+}
+
+// ApisixRouteHTTPPluginConfig is the configuration for
+// any plugins.
+type ApisixRouteHTTPPluginConfig map[string]interface{}
+
+// ApisixRouteAuthentication is the authentication-related
+// configuration in ApisixRoute.
+type ApisixRouteAuthentication struct {
+	Enable  bool                             `json:"enable" yaml:"enable"`
+	Type    string                           `json:"type" yaml:"type"`
+	KeyAuth ApisixRouteAuthenticationKeyAuth `json:"keyauth,omitempty" yaml:"keyauth,omitempty"`
+}
+
+// ApisixRouteAuthenticationKeyAuth is the keyAuth-related
+// configuration in ApisixRouteAuthentication.
+type ApisixRouteAuthenticationKeyAuth struct {
+	Header string `json:"header,omitempty" yaml:"header,omitempty"`
+}
+
+func (p ApisixRouteHTTPPluginConfig) DeepCopyInto(out *ApisixRouteHTTPPluginConfig) {
+	b, _ := json.Marshal(&p)
+	_ = json.Unmarshal(b, out)
+}
+
+func (p *ApisixRouteHTTPPluginConfig) DeepCopy() *ApisixRouteHTTPPluginConfig {
+	if p == nil {
+		return nil
+	}
+	out := new(ApisixRouteHTTPPluginConfig)
+	p.DeepCopyInto(out)
+	return out
+}
+
+// ApisixRouteStream is the configuration for level 4 route
+type ApisixRouteStream struct {
+	// The rule name, cannot be empty.
+	Name     string                   `json:"name" yaml:"name"`
+	Protocol string                   `json:"protocol" yaml:"protocol"`
+	Match    ApisixRouteStreamMatch   `json:"match" yaml:"match"`
+	Backend  ApisixRouteStreamBackend `json:"backend" yaml:"backend"`
+}
+
+// ApisixRouteStreamMatch represents the match conditions of stream route.
+type ApisixRouteStreamMatch struct {
+	// IngressPort represents the port listening on the Ingress proxy server.
+	// It should be pre-defined as APISIX doesn't support dynamic listening.
+	IngressPort int32 `json:"ingressPort" yaml:"ingressPort"`
+}
+
+// ApisixRouteStreamBackend represents a TCP backend (a Kubernetes Service).
+type ApisixRouteStreamBackend struct {
+	// The name (short) of the service, note cross namespace is forbidden,
+	// so be sure the ApisixRoute and Service are in the same namespace.
+	ServiceName string `json:"serviceName" yaml:"serviceName"`
+	// The service port, could be the name or the port number.
+	ServicePort intstr.IntOrString `json:"servicePort" yaml:"servicePort"`
+	// The resolve granularity, can be "endpoints" or "service",
+	// when set to "endpoints", the pod ips will be used; other
+	// wise, the service ClusterIP or ExternalIP will be used,
+	// default is endpoints.
+	ResolveGranularity string `json:"resolveGranularity,omitempty" yaml:"resolveGranularity,omitempty"`
+	// Subset specifies a subset for the target Service. The subset should be pre-defined
+	// in ApisixUpstream about this service.
+	Subset string `json:"subset,omitempty" yaml:"subset,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ApisixRouteList contains a list of ApisixRoute.
+type ApisixRouteList struct {
+	metav1.TypeMeta `json:",inline" yaml:",inline"`
+	metav1.ListMeta `json:"metadata" yaml:"metadata"`
+	Items           []ApisixRoute `json:"items,omitempty" yaml:"items,omitempty"`
+}
+
+// +genclient
+// +genclient:nonNamespaced
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// +kubebuilder:subresource:status
+
+// ApisixClusterConfig is the Schema for the ApisixClusterConfig resource.
+// An ApisixClusterConfig is used to identify an APISIX cluster, it's a
+// ClusterScoped resource so the name is unique.
+// It also contains some cluster-level configurations like monitoring.
+type ApisixClusterConfig struct {
+	metav1.TypeMeta   `json:",inline" yaml:",inline"`
+	metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
+
+	// Spec defines the desired state of ApisixClusterConfigSpec.
+	Spec   ApisixClusterConfigSpec `json:"spec" yaml:"spec"`
+	Status ApisixStatus            `json:"status,omitempty" yaml:"status,omitempty"`
+}
+
+// ApisixClusterConfigSpec defines the desired state of ApisixClusterConfigSpec.
+type ApisixClusterConfigSpec struct {
+	// Monitoring categories all monitoring related features.
+	// +optional
+	Monitoring *ApisixClusterMonitoringConfig `json:"monitoring" yaml:"monitoring"`
+	// Admin contains the Admin API information about APISIX cluster.
+	// +optional
+	Admin *ApisixClusterAdminConfig `json:"admin" yaml:"admin"`
+}
+
+// ApisixClusterMonitoringConfig categories all monitoring related features.
+type ApisixClusterMonitoringConfig struct {
+	// Prometheus is the config for using Prometheus in APISIX Cluster.
+	// +optional
+	Prometheus ApisixClusterPrometheusConfig `json:"prometheus" yaml:"prometheus"`
+	// Skywalking is the config for using Skywalking in APISIX Cluster.
+	// +optional
+	Skywalking ApisixClusterSkywalkingConfig `json:"skywalking" yaml:"skywalking"`
+}
+
+// ApisixClusterPrometheusConfig is the config for using Prometheus in APISIX Cluster.
+type ApisixClusterPrometheusConfig struct {
+	// Enable means whether enable Prometheus or not.
+	Enable bool `json:"enable" yaml:"enable"`
+}
+
+// ApisixClusterSkywalkingConfig is the config for using Skywalking in APISIX Cluster.
+type ApisixClusterSkywalkingConfig struct {
+	// Enable means whether enable Skywalking or not.
+	Enable bool `json:"enable" yaml:"enable"`
+	// SampleRatio means the ratio to collect
+	SampleRatio float64 `json:"sampleRatio" yaml:"sampleRatio"`
+}
+
+// ApisixClusterAdminConfig is the admin config for the corresponding APISIX Cluster.
+type ApisixClusterAdminConfig struct {
+	// BaseURL is the base URL for the APISIX Admin API.
+	// It looks like "http://apisix-admin.default.svc.cluster.local:9080/apisix/admin"
+	BaseURL string `json:"baseURL" yaml:"baseURL"`
+	// AdminKey is used to verify the admin API user.
+	AdminKey string `json:"adminKey" yaml:"adminKey"`
+	// ClientTimeout is request timeout for the APISIX Admin API client
+	ClientTimeout types.TimeDuration `json:"clientTimeout" yaml:"clientTimeout"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ApisixClusterConfigList contains a list of ApisixClusterConfig.
+type ApisixClusterConfigList struct {
+	metav1.TypeMeta `json:",inline" yaml:",inline"`
+	metav1.ListMeta `json:"metadata" yaml:"metadata"`
+
+	Items []ApisixClusterConfig `json:"items" yaml:"items"`
+}
+
+// +genclient
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// +kubebuilder:subresource:status
+
+// ApisixConsumer is the Schema for the ApisixConsumer resource.
+// An ApisixConsumer is used to identify a consumer.
+type ApisixConsumer struct {
+	metav1.TypeMeta   `json:",inline" yaml:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
+	Spec              ApisixConsumerSpec `json:"spec,omitempty" yaml:"spec,omitempty"`
+	Status            ApisixStatus       `json:"status,omitempty" yaml:"status,omitempty"`
+}
+
+// ApisixConsumerSpec defines the desired state of ApisixConsumer.
+type ApisixConsumerSpec struct {
+	AuthParameter ApisixConsumerAuthParameter `json:"authParameter" yaml:"authParameter"`
+}
+
+type ApisixConsumerAuthParameter struct {
+	BasicAuth *ApisixConsumerBasicAuth `json:"basicAuth,omitempty" yaml:"basicAuth"`
+	KeyAuth   *ApisixConsumerKeyAuth   `json:"keyAuth,omitempty" yaml:"keyAuth"`
+}
+
+// ApisixConsumerBasicAuth defines the configuration for basic auth.
+type ApisixConsumerBasicAuth struct {
+	SecretRef *corev1.LocalObjectReference  `json:"secretRef,omitempty" yaml:"secretRef,omitempty"`
+	Value     *ApisixConsumerBasicAuthValue `json:"value,omitempty" yaml:"value,omitempty"`
+}
+
+// ApisixConsumerBasicAuthValue defines the in-place username and password configuration for basic auth.
+type ApisixConsumerBasicAuthValue struct {
+	Username string `json:"username" yaml:"username"`
+	Password string `json:"password" yaml:"username"`
+}
+
+// ApisixConsumerKeyAuth defines the configuration for the key auth.
+type ApisixConsumerKeyAuth struct {
+	SecretRef *corev1.LocalObjectReference `json:"secretRef,omitempty" yaml:"secretRef,omitempty"`
+	Value     *ApisixConsumerKeyAuthValue  `json:"value,omitempty" yaml:"value,omitempty"`
+}
+
+// ApisixConsumerKeyAuthValue defines the in-place configuration for basic auth.
+type ApisixConsumerKeyAuthValue struct {
+	Key string `json:"key" yaml:"key"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ApisixConsumerList contains a list of ApisixConsumer.
+type ApisixConsumerList struct {
+	metav1.TypeMeta `json:",inline" yaml:",inline"`
+	metav1.ListMeta `json:"metadata" yaml:"metadata"`
+	Items           []ApisixConsumer `json:"items,omitempty" yaml:"items,omitempty"`
+}
+
+// +genclient
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// +kubebuilder:subresource:status
+// ApisixUpstream is a decorator for Kubernetes Service, it arms the Service
+// with rich features like health check, retry policies, load balancer and others.
+// It's designed to have same name with the Kubernetes Service and can be customized
+// for individual port.
+type ApisixUpstream struct {
+	metav1.TypeMeta   `json:",inline" yaml:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
+
+	Spec   *ApisixUpstreamSpec `json:"spec,omitempty" yaml:"spec,omitempty"`
+	Status ApisixStatus        `json:"status,omitempty" yaml:"status,omitempty"`
+}
+
+// ApisixUpstreamSpec describes the specification of ApisixUpstream.
+type ApisixUpstreamSpec struct {
+	ApisixUpstreamConfig `json:",inline" yaml:",inline"`
+
+	PortLevelSettings []PortLevelSettings `json:"portLevelSettings,omitempty" yaml:"portLevelSettings,omitempty"`
+}
+
+// ApisixUpstreamConfig contains rich features on APISIX Upstream, for instance
+// load balancer, health check and etc.
+type ApisixUpstreamConfig struct {
+	// LoadBalancer represents the load balancer configuration for Kubernetes Service.
+	// The default strategy is round robin.
+	// +optional
+	LoadBalancer *LoadBalancer `json:"loadbalancer,omitempty" yaml:"loadbalancer,omitempty"`
+	// The scheme used to talk with the upstream.
+	// Now value can be http, grpc.
+	// +optional
+	Scheme string `json:"scheme,omitempty" yaml:"scheme,omitempty"`
+
+	// How many times that the proxy (Apache APISIX) should do when
+	// errors occur (error, timeout or bad http status codes like 500, 502).
+	// +optional
+	Retries *int `json:"retries,omitempty" yaml:"retries,omitempty"`
+
+	// Timeout settings for the read, send and connect to the upstream.
+	// +optional
+	Timeout *UpstreamTimeout `json:"timeout,omitempty" yaml:"timeout,omitempty"`
+
+	// The health check configurations for the upstream.
+	// +optional
+	HealthCheck *HealthCheck `json:"healthCheck,omitempty" yaml:"healthCheck,omitempty"`
+
+	// Set the client certificate when connecting to TLS upstream.
+	// +optional
+	TLSSecret *ApisixSecret `json:"tlsSecret,omitempty" yaml:"tlsSecret,omitempty"`
+
+	// Subsets groups the service endpoints by their labels. Usually used to differentiate
+	// service versions.
+	// +optional
+	Subsets []ApisixUpstreamSubset `json:"subsets,omitempty" yaml:"subsets,omitempty"`
+}
+
+// ApisixUpstreamSubset defines a single endpoints group of one Service.
+type ApisixUpstreamSubset struct {
+	// Name is the name of subset.
+	Name string `json:"name" yaml:"name"`
+	// Labels is the label set of this subset.
+	Labels map[string]string `json:"labels" yaml:"labels"`
+}
+
+// PortLevelSettings configures the ApisixUpstreamConfig for each individual port. It inherits
+// configurations from the outer level (the whole Kubernetes Service) and overrides some of
+// them if they are set on the port level.
+type PortLevelSettings struct {
+	ApisixUpstreamConfig `json:",inline" yaml:",inline"`
+
+	// Port is a Kubernetes Service port, it should be already defined.
+	Port int32 `json:"port" yaml:"port"`
+}
+
+// LoadBalancer describes the load balancing parameters.
+type LoadBalancer struct {
+	Type string `json:"type" yaml:"type"`
+	// The HashOn and Key fields are required when Type is "chash".
+	// HashOn represents the key fetching scope.
+	HashOn string `json:"hashOn,omitempty" yaml:"hashOn,omitempty"`
+	// Key represents the hash key.
+	Key string `json:"key,omitempty" yaml:"key,omitempty"`
+}
+
+// HealthCheck describes the upstream health check parameters.
+type HealthCheck struct {
+	Active  *ActiveHealthCheck  `json:"active" yaml:"active"`
+	Passive *PassiveHealthCheck `json:"passive,omitempty" yaml:"passive,omitempty"`
+}
+
+// ActiveHealthCheck defines the active kind of upstream health check.
+type ActiveHealthCheck struct {
+	Type           string                      `json:"type,omitempty" yaml:"type,omitempty"`
+	Timeout        time.Duration               `json:"timeout,omitempty" yaml:"timeout,omitempty"`
+	Concurrency    int                         `json:"concurrency,omitempty" yaml:"concurrency,omitempty"`
+	Host           string                      `json:"host,omitempty" yaml:"host,omitempty"`
+	Port           int32                       `json:"port,omitempty" yaml:"port,omitempty"`
+	HTTPPath       string                      `json:"httpPath,omitempty" yaml:"httpPath,omitempty"`
+	StrictTLS      *bool                       `json:"strictTLS,omitempty" yaml:"strictTLS,omitempty"`
+	RequestHeaders []string                    `json:"requestHeaders,omitempty" yaml:"requestHeaders,omitempty"`
+	Healthy        *ActiveHealthCheckHealthy   `json:"healthy,omitempty" yaml:"healthy,omitempty"`
+	Unhealthy      *ActiveHealthCheckUnhealthy `json:"unhealthy,omitempty" yaml:"unhealthy,omitempty"`
+}
+
+// PassiveHealthCheck defines the conditions to judge whether
+// an upstream node is healthy with the passive manager.
+type PassiveHealthCheck struct {
+	Type      string                       `json:"type,omitempty" yaml:"type,omitempty"`
+	Healthy   *PassiveHealthCheckHealthy   `json:"healthy,omitempty" yaml:"healthy,omitempty"`
+	Unhealthy *PassiveHealthCheckUnhealthy `json:"unhealthy,omitempty" yaml:"unhealthy,omitempty"`
+}
+
+// ActiveHealthCheckHealthy defines the conditions to judge whether
+// an upstream node is healthy with the active manner.
+type ActiveHealthCheckHealthy struct {
+	PassiveHealthCheckHealthy `json:",inline" yaml:",inline"`
+
+	Interval metav1.Duration `json:"interval,omitempty" yaml:"interval,omitempty"`
+}
+
+// ActiveHealthCheckUnhealthy defines the conditions to judge whether
+// an upstream node is unhealthy with the active manager.
+type ActiveHealthCheckUnhealthy struct {
+	PassiveHealthCheckUnhealthy `json:",inline" yaml:",inline"`
+
+	Interval metav1.Duration `json:"interval,omitempty" yaml:"interval,omitempty"`
+}
+
+// PassiveHealthCheckHealthy defines the conditions to judge whether
+// an upstream node is healthy with the passive manner.
+type PassiveHealthCheckHealthy struct {
+	HTTPCodes []int `json:"httpCodes,omitempty" yaml:"httpCodes,omitempty"`
+	Successes int   `json:"successes,omitempty" yaml:"successes,omitempty"`
+}
+
+// PassiveHealthCheckUnhealthy defines the conditions to judge whether
+// an upstream node is unhealthy with the passive manager.
+type PassiveHealthCheckUnhealthy struct {
+	HTTPCodes    []int `json:"httpCodes,omitempty" yaml:"httpCodes,omitempty"`
+	HTTPFailures int   `json:"httpFailures,omitempty" yaml:"http_failures,omitempty"`
+	TCPFailures  int   `json:"tcpFailures,omitempty" yaml:"tcpFailures,omitempty"`
+	Timeouts     int   `json:"timeout,omitempty" yaml:"timeout,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+type ApisixUpstreamList struct {
+	metav1.TypeMeta `json:",inline" yaml:",inline"`
+	metav1.ListMeta `json:"metadata" yaml:"metadata"`
+	Items           []ApisixUpstream `json:"items,omitempty" yaml:"items,omitempty"`
+}
+
+type Plugin struct {
+	Name      string    `json:"name,omitempty" yaml:"name,omitempty"`
+	Enable    bool      `json:"enable,omitempty" yaml:"enable,omitempty"`
+	Config    Config    `json:"config,omitempty" yaml:"config,omitempty"`
+	ConfigSet ConfigSet `json:"config_set,omitempty" yaml:"config_set,omitempty"`
+}
+
+type ConfigSet []interface{}
+
+func (p ConfigSet) DeepCopyInto(out *ConfigSet) {
+	b, _ := json.Marshal(&p)
+	_ = json.Unmarshal(b, out)
+}
+
+func (p *ConfigSet) DeepCopy() *ConfigSet {
+	if p == nil {
+		return nil
+	}
+	out := new(ConfigSet)
+	p.DeepCopyInto(out)
+	return out
+}
+
+type Config map[string]interface{}
+
+func (p Config) DeepCopyInto(out *Config) {
+	b, _ := json.Marshal(&p)
+	_ = json.Unmarshal(b, out)
+}
+
+func (p *Config) DeepCopy() *Config {
+	if p == nil {
+		return nil
+	}
+	out := new(Config)
+	p.DeepCopyInto(out)
+	return out
+}
+
+// +genclient
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// +kubebuilder:resource:shortName=atls
+// +kubebuilder:subresource:status
+// ApisixTls defines SSL resource in APISIX.
+type ApisixTls struct {
+	metav1.TypeMeta   `json:",inline" yaml:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
+	Spec              *ApisixTlsSpec `json:"spec,omitempty" yaml:"spec,omitempty"`
+	// +optional
+	Status ApisixStatus `json:"status,omitempty" yaml:"status,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// +kubebuilder:printcolumn:name="SNIs",type=string,JSONPath=`.spec.hosts`
+// +kubebuilder:printcolumn:name="Secret Name",type=string,JSONPath=`.spec.secret.name`
+// +kubebuilder:printcolumn:name="Secret Namespace",type=string,JSONPath=`.spec.secret.namespace`
+// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
+// +kubebuilder:printcolumn:name="Client CA Secret Name",type=string,JSONPath=`.spec.client.ca.name`
+// +kubebuilder:printcolumn:name="Client CA Secret Namespace",type=string,JSONPath=`.spec.client.ca.namespace`
+type ApisixTlsList struct {
+	metav1.TypeMeta `json:",inline" yaml:",inline"`
+	metav1.ListMeta `json:"metadata" yaml:"metadata"`
+	Items           []ApisixTls `json:"items,omitempty" yaml:"items,omitempty"`
+}
+
+// +kubebuilder:validation:Pattern="^\\*?[0-9a-zA-Z-.]+$"
+type HostType string
+
+// ApisixTlsSpec is the specification of ApisixSSL.
+type ApisixTlsSpec struct {
+	// +required
+	// +kubebuilder:validation:Required
+	// +kubebuilder:validation:MinItems=1
+	Hosts []HostType `json:"hosts" yaml:"hosts,omitempty"`
+	// +required
+	// +kubebuilder:validation:Required
+	Secret ApisixSecret `json:"secret" yaml:"secret"`
+	// +optional
+	Client *ApisixMutualTlsClientConfig `json:"client,omitempty" yaml:"client,omitempty"`
+}
+
+// ApisixSecret describes the Kubernetes Secret name and namespace.
+type ApisixSecret struct {
+	// +kubebuilder:validation:MinLength=1
+	// +kubebuilder:validation:Required
+	Name string `json:"name" yaml:"name"`
+	// +kubebuilder:validation:MinLength=1
+	// +kubebuilder:validation:Required
+	Namespace string `json:"namespace" yaml:"namespace"`
+}
+
+// ApisixMutualTlsClientConfig describes the mutual TLS CA and verify depth
+type ApisixMutualTlsClientConfig struct {
+	CASecret ApisixSecret `json:"caSecret,omitempty" yaml:"caSecret,omitempty"`
+	Depth    int          `json:"depth,omitempty" yaml:"depth,omitempty"`
+}
+
+// +genclient
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// +kubebuilder:subresource:status
+
+// ApisixPluginConfig is the Schema for the ApisixPluginConfig resource.
+// An ApisixPluginConfig is used to support a group of plugin configs
+type ApisixPluginConfig struct {
+	metav1.TypeMeta   `json:",inline" yaml:",inline"`
+	metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
+
+	// Spec defines the desired state of ApisixPluginConfigSpec.
+	Spec   ApisixPluginConfigSpec `json:"spec" yaml:"spec"`
+	Status ApisixStatus           `json:"status,omitempty" yaml:"status,omitempty"`
+}
+
+// ApisixPluginConfigSpec defines the desired state of ApisixPluginConfigSpec.
+type ApisixPluginConfigSpec struct {
+	// Plugins contains a list of ApisixRouteHTTPPlugin
+	// +required
+	Plugins []ApisixRouteHTTPPlugin `json:"plugins" yaml:"plugins"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// +kubebuilder:object:generate=true
+
+// ApisixPluginConfigList contains a list of ApisixPluginConfig.
+type ApisixPluginConfigList struct {
+	metav1.TypeMeta `json:",inline" yaml:",inline"`
+	metav1.ListMeta `json:"metadata" yaml:"metadata"`
+	Items           []ApisixPluginConfig `json:"items,omitempty" yaml:"items,omitempty"`
+}
diff --git a/pkg/kube/apisix/apis/config/v2/zz_generated.deepcopy.go b/pkg/kube/apisix/apis/config/v2/zz_generated.deepcopy.go
new file mode 100644
index 0000000..e6525ee
--- /dev/null
+++ b/pkg/kube/apisix/apis/config/v2/zz_generated.deepcopy.go
@@ -0,0 +1,1331 @@
+// +build !ignore_autogenerated
+
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by deepcopy-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	v1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ActiveHealthCheck) DeepCopyInto(out *ActiveHealthCheck) {
+	*out = *in
+	if in.StrictTLS != nil {
+		in, out := &in.StrictTLS, &out.StrictTLS
+		*out = new(bool)
+		**out = **in
+	}
+	if in.RequestHeaders != nil {
+		in, out := &in.RequestHeaders, &out.RequestHeaders
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	if in.Healthy != nil {
+		in, out := &in.Healthy, &out.Healthy
+		*out = new(ActiveHealthCheckHealthy)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Unhealthy != nil {
+		in, out := &in.Unhealthy, &out.Unhealthy
+		*out = new(ActiveHealthCheckUnhealthy)
+		(*in).DeepCopyInto(*out)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveHealthCheck.
+func (in *ActiveHealthCheck) DeepCopy() *ActiveHealthCheck {
+	if in == nil {
+		return nil
+	}
+	out := new(ActiveHealthCheck)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ActiveHealthCheckHealthy) DeepCopyInto(out *ActiveHealthCheckHealthy) {
+	*out = *in
+	in.PassiveHealthCheckHealthy.DeepCopyInto(&out.PassiveHealthCheckHealthy)
+	out.Interval = in.Interval
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveHealthCheckHealthy.
+func (in *ActiveHealthCheckHealthy) DeepCopy() *ActiveHealthCheckHealthy {
+	if in == nil {
+		return nil
+	}
+	out := new(ActiveHealthCheckHealthy)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ActiveHealthCheckUnhealthy) DeepCopyInto(out *ActiveHealthCheckUnhealthy) {
+	*out = *in
+	in.PassiveHealthCheckUnhealthy.DeepCopyInto(&out.PassiveHealthCheckUnhealthy)
+	out.Interval = in.Interval
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ActiveHealthCheckUnhealthy.
+func (in *ActiveHealthCheckUnhealthy) DeepCopy() *ActiveHealthCheckUnhealthy {
+	if in == nil {
+		return nil
+	}
+	out := new(ActiveHealthCheckUnhealthy)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixClusterAdminConfig) DeepCopyInto(out *ApisixClusterAdminConfig) {
+	*out = *in
+	out.ClientTimeout = in.ClientTimeout
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixClusterAdminConfig.
+func (in *ApisixClusterAdminConfig) DeepCopy() *ApisixClusterAdminConfig {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixClusterAdminConfig)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixClusterConfig) DeepCopyInto(out *ApisixClusterConfig) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	in.Status.DeepCopyInto(&out.Status)
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixClusterConfig.
+func (in *ApisixClusterConfig) DeepCopy() *ApisixClusterConfig {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixClusterConfig)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ApisixClusterConfig) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixClusterConfigList) DeepCopyInto(out *ApisixClusterConfigList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]ApisixClusterConfig, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixClusterConfigList.
+func (in *ApisixClusterConfigList) DeepCopy() *ApisixClusterConfigList {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixClusterConfigList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ApisixClusterConfigList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixClusterConfigSpec) DeepCopyInto(out *ApisixClusterConfigSpec) {
+	*out = *in
+	if in.Monitoring != nil {
+		in, out := &in.Monitoring, &out.Monitoring
+		*out = new(ApisixClusterMonitoringConfig)
+		**out = **in
+	}
+	if in.Admin != nil {
+		in, out := &in.Admin, &out.Admin
+		*out = new(ApisixClusterAdminConfig)
+		**out = **in
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixClusterConfigSpec.
+func (in *ApisixClusterConfigSpec) DeepCopy() *ApisixClusterConfigSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixClusterConfigSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixClusterMonitoringConfig) DeepCopyInto(out *ApisixClusterMonitoringConfig) {
+	*out = *in
+	out.Prometheus = in.Prometheus
+	out.Skywalking = in.Skywalking
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixClusterMonitoringConfig.
+func (in *ApisixClusterMonitoringConfig) DeepCopy() *ApisixClusterMonitoringConfig {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixClusterMonitoringConfig)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixClusterPrometheusConfig) DeepCopyInto(out *ApisixClusterPrometheusConfig) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixClusterPrometheusConfig.
+func (in *ApisixClusterPrometheusConfig) DeepCopy() *ApisixClusterPrometheusConfig {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixClusterPrometheusConfig)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixClusterSkywalkingConfig) DeepCopyInto(out *ApisixClusterSkywalkingConfig) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixClusterSkywalkingConfig.
+func (in *ApisixClusterSkywalkingConfig) DeepCopy() *ApisixClusterSkywalkingConfig {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixClusterSkywalkingConfig)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixConsumer) DeepCopyInto(out *ApisixConsumer) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	in.Status.DeepCopyInto(&out.Status)
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixConsumer.
+func (in *ApisixConsumer) DeepCopy() *ApisixConsumer {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixConsumer)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ApisixConsumer) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixConsumerAuthParameter) DeepCopyInto(out *ApisixConsumerAuthParameter) {
+	*out = *in
+	if in.BasicAuth != nil {
+		in, out := &in.BasicAuth, &out.BasicAuth
+		*out = new(ApisixConsumerBasicAuth)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.KeyAuth != nil {
+		in, out := &in.KeyAuth, &out.KeyAuth
+		*out = new(ApisixConsumerKeyAuth)
+		(*in).DeepCopyInto(*out)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixConsumerAuthParameter.
+func (in *ApisixConsumerAuthParameter) DeepCopy() *ApisixConsumerAuthParameter {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixConsumerAuthParameter)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixConsumerBasicAuth) DeepCopyInto(out *ApisixConsumerBasicAuth) {
+	*out = *in
+	if in.SecretRef != nil {
+		in, out := &in.SecretRef, &out.SecretRef
+		*out = new(v1.LocalObjectReference)
+		**out = **in
+	}
+	if in.Value != nil {
+		in, out := &in.Value, &out.Value
+		*out = new(ApisixConsumerBasicAuthValue)
+		**out = **in
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixConsumerBasicAuth.
+func (in *ApisixConsumerBasicAuth) DeepCopy() *ApisixConsumerBasicAuth {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixConsumerBasicAuth)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixConsumerBasicAuthValue) DeepCopyInto(out *ApisixConsumerBasicAuthValue) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixConsumerBasicAuthValue.
+func (in *ApisixConsumerBasicAuthValue) DeepCopy() *ApisixConsumerBasicAuthValue {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixConsumerBasicAuthValue)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixConsumerKeyAuth) DeepCopyInto(out *ApisixConsumerKeyAuth) {
+	*out = *in
+	if in.SecretRef != nil {
+		in, out := &in.SecretRef, &out.SecretRef
+		*out = new(v1.LocalObjectReference)
+		**out = **in
+	}
+	if in.Value != nil {
+		in, out := &in.Value, &out.Value
+		*out = new(ApisixConsumerKeyAuthValue)
+		**out = **in
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixConsumerKeyAuth.
+func (in *ApisixConsumerKeyAuth) DeepCopy() *ApisixConsumerKeyAuth {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixConsumerKeyAuth)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixConsumerKeyAuthValue) DeepCopyInto(out *ApisixConsumerKeyAuthValue) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixConsumerKeyAuthValue.
+func (in *ApisixConsumerKeyAuthValue) DeepCopy() *ApisixConsumerKeyAuthValue {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixConsumerKeyAuthValue)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixConsumerList) DeepCopyInto(out *ApisixConsumerList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]ApisixConsumer, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixConsumerList.
+func (in *ApisixConsumerList) DeepCopy() *ApisixConsumerList {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixConsumerList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ApisixConsumerList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixConsumerSpec) DeepCopyInto(out *ApisixConsumerSpec) {
+	*out = *in
+	in.AuthParameter.DeepCopyInto(&out.AuthParameter)
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixConsumerSpec.
+func (in *ApisixConsumerSpec) DeepCopy() *ApisixConsumerSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixConsumerSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixMutualTlsClientConfig) DeepCopyInto(out *ApisixMutualTlsClientConfig) {
+	*out = *in
+	out.CASecret = in.CASecret
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixMutualTlsClientConfig.
+func (in *ApisixMutualTlsClientConfig) DeepCopy() *ApisixMutualTlsClientConfig {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixMutualTlsClientConfig)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixPluginConfig) DeepCopyInto(out *ApisixPluginConfig) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	in.Status.DeepCopyInto(&out.Status)
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixPluginConfig.
+func (in *ApisixPluginConfig) DeepCopy() *ApisixPluginConfig {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixPluginConfig)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ApisixPluginConfig) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixPluginConfigList) DeepCopyInto(out *ApisixPluginConfigList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]ApisixPluginConfig, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixPluginConfigList.
+func (in *ApisixPluginConfigList) DeepCopy() *ApisixPluginConfigList {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixPluginConfigList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ApisixPluginConfigList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixPluginConfigSpec) DeepCopyInto(out *ApisixPluginConfigSpec) {
+	*out = *in
+	if in.Plugins != nil {
+		in, out := &in.Plugins, &out.Plugins
+		*out = make([]ApisixRouteHTTPPlugin, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixPluginConfigSpec.
+func (in *ApisixPluginConfigSpec) DeepCopy() *ApisixPluginConfigSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixPluginConfigSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixRoute) DeepCopyInto(out *ApisixRoute) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	in.Status.DeepCopyInto(&out.Status)
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixRoute.
+func (in *ApisixRoute) DeepCopy() *ApisixRoute {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixRoute)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ApisixRoute) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixRouteAuthentication) DeepCopyInto(out *ApisixRouteAuthentication) {
+	*out = *in
+	out.KeyAuth = in.KeyAuth
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixRouteAuthentication.
+func (in *ApisixRouteAuthentication) DeepCopy() *ApisixRouteAuthentication {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixRouteAuthentication)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixRouteAuthenticationKeyAuth) DeepCopyInto(out *ApisixRouteAuthenticationKeyAuth) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixRouteAuthenticationKeyAuth.
+func (in *ApisixRouteAuthenticationKeyAuth) DeepCopy() *ApisixRouteAuthenticationKeyAuth {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixRouteAuthenticationKeyAuth)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixRouteHTTP) DeepCopyInto(out *ApisixRouteHTTP) {
+	*out = *in
+	if in.Timeout != nil {
+		in, out := &in.Timeout, &out.Timeout
+		*out = new(UpstreamTimeout)
+		**out = **in
+	}
+	in.Match.DeepCopyInto(&out.Match)
+	if in.Backends != nil {
+		in, out := &in.Backends, &out.Backends
+		*out = make([]ApisixRouteHTTPBackend, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.Plugins != nil {
+		in, out := &in.Plugins, &out.Plugins
+		*out = make([]ApisixRouteHTTPPlugin, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	out.Authentication = in.Authentication
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixRouteHTTP.
+func (in *ApisixRouteHTTP) DeepCopy() *ApisixRouteHTTP {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixRouteHTTP)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixRouteHTTPBackend) DeepCopyInto(out *ApisixRouteHTTPBackend) {
+	*out = *in
+	out.ServicePort = in.ServicePort
+	if in.Weight != nil {
+		in, out := &in.Weight, &out.Weight
+		*out = new(int)
+		**out = **in
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixRouteHTTPBackend.
+func (in *ApisixRouteHTTPBackend) DeepCopy() *ApisixRouteHTTPBackend {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixRouteHTTPBackend)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixRouteHTTPMatch) DeepCopyInto(out *ApisixRouteHTTPMatch) {
+	*out = *in
+	if in.Paths != nil {
+		in, out := &in.Paths, &out.Paths
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	if in.Methods != nil {
+		in, out := &in.Methods, &out.Methods
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	if in.Hosts != nil {
+		in, out := &in.Hosts, &out.Hosts
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	if in.RemoteAddrs != nil {
+		in, out := &in.RemoteAddrs, &out.RemoteAddrs
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	if in.NginxVars != nil {
+		in, out := &in.NginxVars, &out.NginxVars
+		*out = make([]ApisixRouteHTTPMatchExpr, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixRouteHTTPMatch.
+func (in *ApisixRouteHTTPMatch) DeepCopy() *ApisixRouteHTTPMatch {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixRouteHTTPMatch)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixRouteHTTPMatchExpr) DeepCopyInto(out *ApisixRouteHTTPMatchExpr) {
+	*out = *in
+	out.Subject = in.Subject
+	if in.Set != nil {
+		in, out := &in.Set, &out.Set
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	if in.Value != nil {
+		in, out := &in.Value, &out.Value
+		*out = new(string)
+		**out = **in
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixRouteHTTPMatchExpr.
+func (in *ApisixRouteHTTPMatchExpr) DeepCopy() *ApisixRouteHTTPMatchExpr {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixRouteHTTPMatchExpr)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixRouteHTTPMatchExprSubject) DeepCopyInto(out *ApisixRouteHTTPMatchExprSubject) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixRouteHTTPMatchExprSubject.
+func (in *ApisixRouteHTTPMatchExprSubject) DeepCopy() *ApisixRouteHTTPMatchExprSubject {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixRouteHTTPMatchExprSubject)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixRouteHTTPPlugin) DeepCopyInto(out *ApisixRouteHTTPPlugin) {
+	*out = *in
+	in.Config.DeepCopyInto(&out.Config)
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixRouteHTTPPlugin.
+func (in *ApisixRouteHTTPPlugin) DeepCopy() *ApisixRouteHTTPPlugin {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixRouteHTTPPlugin)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixRouteList) DeepCopyInto(out *ApisixRouteList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]ApisixRoute, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixRouteList.
+func (in *ApisixRouteList) DeepCopy() *ApisixRouteList {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixRouteList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ApisixRouteList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixRouteSpec) DeepCopyInto(out *ApisixRouteSpec) {
+	*out = *in
+	if in.HTTP != nil {
+		in, out := &in.HTTP, &out.HTTP
+		*out = make([]ApisixRouteHTTP, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.Stream != nil {
+		in, out := &in.Stream, &out.Stream
+		*out = make([]ApisixRouteStream, len(*in))
+		copy(*out, *in)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixRouteSpec.
+func (in *ApisixRouteSpec) DeepCopy() *ApisixRouteSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixRouteSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixRouteStream) DeepCopyInto(out *ApisixRouteStream) {
+	*out = *in
+	out.Match = in.Match
+	out.Backend = in.Backend
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixRouteStream.
+func (in *ApisixRouteStream) DeepCopy() *ApisixRouteStream {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixRouteStream)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixRouteStreamBackend) DeepCopyInto(out *ApisixRouteStreamBackend) {
+	*out = *in
+	out.ServicePort = in.ServicePort
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixRouteStreamBackend.
+func (in *ApisixRouteStreamBackend) DeepCopy() *ApisixRouteStreamBackend {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixRouteStreamBackend)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixRouteStreamMatch) DeepCopyInto(out *ApisixRouteStreamMatch) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixRouteStreamMatch.
+func (in *ApisixRouteStreamMatch) DeepCopy() *ApisixRouteStreamMatch {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixRouteStreamMatch)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixSecret) DeepCopyInto(out *ApisixSecret) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixSecret.
+func (in *ApisixSecret) DeepCopy() *ApisixSecret {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixSecret)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixStatus) DeepCopyInto(out *ApisixStatus) {
+	*out = *in
+	if in.Conditions != nil {
+		in, out := &in.Conditions, &out.Conditions
+		*out = make([]metav1.Condition, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixStatus.
+func (in *ApisixStatus) DeepCopy() *ApisixStatus {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixStatus)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixTls) DeepCopyInto(out *ApisixTls) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	if in.Spec != nil {
+		in, out := &in.Spec, &out.Spec
+		*out = new(ApisixTlsSpec)
+		(*in).DeepCopyInto(*out)
+	}
+	in.Status.DeepCopyInto(&out.Status)
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixTls.
+func (in *ApisixTls) DeepCopy() *ApisixTls {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixTls)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ApisixTls) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixTlsList) DeepCopyInto(out *ApisixTlsList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]ApisixTls, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixTlsList.
+func (in *ApisixTlsList) DeepCopy() *ApisixTlsList {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixTlsList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ApisixTlsList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixTlsSpec) DeepCopyInto(out *ApisixTlsSpec) {
+	*out = *in
+	if in.Hosts != nil {
+		in, out := &in.Hosts, &out.Hosts
+		*out = make([]HostType, len(*in))
+		copy(*out, *in)
+	}
+	out.Secret = in.Secret
+	if in.Client != nil {
+		in, out := &in.Client, &out.Client
+		*out = new(ApisixMutualTlsClientConfig)
+		**out = **in
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixTlsSpec.
+func (in *ApisixTlsSpec) DeepCopy() *ApisixTlsSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixTlsSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixUpstream) DeepCopyInto(out *ApisixUpstream) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	if in.Spec != nil {
+		in, out := &in.Spec, &out.Spec
+		*out = new(ApisixUpstreamSpec)
+		(*in).DeepCopyInto(*out)
+	}
+	in.Status.DeepCopyInto(&out.Status)
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixUpstream.
+func (in *ApisixUpstream) DeepCopy() *ApisixUpstream {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixUpstream)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ApisixUpstream) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixUpstreamConfig) DeepCopyInto(out *ApisixUpstreamConfig) {
+	*out = *in
+	if in.LoadBalancer != nil {
+		in, out := &in.LoadBalancer, &out.LoadBalancer
+		*out = new(LoadBalancer)
+		**out = **in
+	}
+	if in.Retries != nil {
+		in, out := &in.Retries, &out.Retries
+		*out = new(int)
+		**out = **in
+	}
+	if in.Timeout != nil {
+		in, out := &in.Timeout, &out.Timeout
+		*out = new(UpstreamTimeout)
+		**out = **in
+	}
+	if in.HealthCheck != nil {
+		in, out := &in.HealthCheck, &out.HealthCheck
+		*out = new(HealthCheck)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.TLSSecret != nil {
+		in, out := &in.TLSSecret, &out.TLSSecret
+		*out = new(ApisixSecret)
+		**out = **in
+	}
+	if in.Subsets != nil {
+		in, out := &in.Subsets, &out.Subsets
+		*out = make([]ApisixUpstreamSubset, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixUpstreamConfig.
+func (in *ApisixUpstreamConfig) DeepCopy() *ApisixUpstreamConfig {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixUpstreamConfig)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixUpstreamList) DeepCopyInto(out *ApisixUpstreamList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]ApisixUpstream, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixUpstreamList.
+func (in *ApisixUpstreamList) DeepCopy() *ApisixUpstreamList {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixUpstreamList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ApisixUpstreamList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixUpstreamSpec) DeepCopyInto(out *ApisixUpstreamSpec) {
+	*out = *in
+	in.ApisixUpstreamConfig.DeepCopyInto(&out.ApisixUpstreamConfig)
+	if in.PortLevelSettings != nil {
+		in, out := &in.PortLevelSettings, &out.PortLevelSettings
+		*out = make([]PortLevelSettings, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixUpstreamSpec.
+func (in *ApisixUpstreamSpec) DeepCopy() *ApisixUpstreamSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixUpstreamSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApisixUpstreamSubset) DeepCopyInto(out *ApisixUpstreamSubset) {
+	*out = *in
+	if in.Labels != nil {
+		in, out := &in.Labels, &out.Labels
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApisixUpstreamSubset.
+func (in *ApisixUpstreamSubset) DeepCopy() *ApisixUpstreamSubset {
+	if in == nil {
+		return nil
+	}
+	out := new(ApisixUpstreamSubset)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *HealthCheck) DeepCopyInto(out *HealthCheck) {
+	*out = *in
+	if in.Active != nil {
+		in, out := &in.Active, &out.Active
+		*out = new(ActiveHealthCheck)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Passive != nil {
+		in, out := &in.Passive, &out.Passive
+		*out = new(PassiveHealthCheck)
+		(*in).DeepCopyInto(*out)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HealthCheck.
+func (in *HealthCheck) DeepCopy() *HealthCheck {
+	if in == nil {
+		return nil
+	}
+	out := new(HealthCheck)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *LoadBalancer) DeepCopyInto(out *LoadBalancer) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoadBalancer.
+func (in *LoadBalancer) DeepCopy() *LoadBalancer {
+	if in == nil {
+		return nil
+	}
+	out := new(LoadBalancer)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PassiveHealthCheck) DeepCopyInto(out *PassiveHealthCheck) {
+	*out = *in
+	if in.Healthy != nil {
+		in, out := &in.Healthy, &out.Healthy
+		*out = new(PassiveHealthCheckHealthy)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Unhealthy != nil {
+		in, out := &in.Unhealthy, &out.Unhealthy
+		*out = new(PassiveHealthCheckUnhealthy)
+		(*in).DeepCopyInto(*out)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PassiveHealthCheck.
+func (in *PassiveHealthCheck) DeepCopy() *PassiveHealthCheck {
+	if in == nil {
+		return nil
+	}
+	out := new(PassiveHealthCheck)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PassiveHealthCheckHealthy) DeepCopyInto(out *PassiveHealthCheckHealthy) {
+	*out = *in
+	if in.HTTPCodes != nil {
+		in, out := &in.HTTPCodes, &out.HTTPCodes
+		*out = make([]int, len(*in))
+		copy(*out, *in)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PassiveHealthCheckHealthy.
+func (in *PassiveHealthCheckHealthy) DeepCopy() *PassiveHealthCheckHealthy {
+	if in == nil {
+		return nil
+	}
+	out := new(PassiveHealthCheckHealthy)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PassiveHealthCheckUnhealthy) DeepCopyInto(out *PassiveHealthCheckUnhealthy) {
+	*out = *in
+	if in.HTTPCodes != nil {
+		in, out := &in.HTTPCodes, &out.HTTPCodes
+		*out = make([]int, len(*in))
+		copy(*out, *in)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PassiveHealthCheckUnhealthy.
+func (in *PassiveHealthCheckUnhealthy) DeepCopy() *PassiveHealthCheckUnhealthy {
+	if in == nil {
+		return nil
+	}
+	out := new(PassiveHealthCheckUnhealthy)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Plugin) DeepCopyInto(out *Plugin) {
+	*out = *in
+	in.Config.DeepCopyInto(&out.Config)
+	in.ConfigSet.DeepCopyInto(&out.ConfigSet)
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Plugin.
+func (in *Plugin) DeepCopy() *Plugin {
+	if in == nil {
+		return nil
+	}
+	out := new(Plugin)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PortLevelSettings) DeepCopyInto(out *PortLevelSettings) {
+	*out = *in
+	in.ApisixUpstreamConfig.DeepCopyInto(&out.ApisixUpstreamConfig)
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PortLevelSettings.
+func (in *PortLevelSettings) DeepCopy() *PortLevelSettings {
+	if in == nil {
+		return nil
+	}
+	out := new(PortLevelSettings)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *UpstreamTimeout) DeepCopyInto(out *UpstreamTimeout) {
+	*out = *in
+	out.Connect = in.Connect
+	out.Send = in.Send
+	out.Read = in.Read
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpstreamTimeout.
+func (in *UpstreamTimeout) DeepCopy() *UpstreamTimeout {
+	if in == nil {
+		return nil
+	}
+	out := new(UpstreamTimeout)
+	in.DeepCopyInto(out)
+	return out
+}
diff --git a/pkg/kube/apisix/apis/config/v2/zz_generated.register.go b/pkg/kube/apisix/apis/config/v2/zz_generated.register.go
new file mode 100644
index 0000000..ea4fd31
--- /dev/null
+++ b/pkg/kube/apisix/apis/config/v2/zz_generated.register.go
@@ -0,0 +1,76 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by register-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+)
+
+// GroupName specifies the group name used to register the objects.
+const GroupName = "apisix.apache.org"
+
+// GroupVersion specifies the group and the version used to register the objects.
+var GroupVersion = v1.GroupVersion{Group: GroupName, Version: "v2"}
+
+// SchemeGroupVersion is group version used to register these objects
+// Deprecated: use GroupVersion instead.
+var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v2"}
+
+// Resource takes an unqualified resource and returns a Group qualified GroupResource
+func Resource(resource string) schema.GroupResource {
+	return SchemeGroupVersion.WithResource(resource).GroupResource()
+}
+
+var (
+	// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
+	SchemeBuilder      runtime.SchemeBuilder
+	localSchemeBuilder = &SchemeBuilder
+	// Depreciated: use Install instead
+	AddToScheme = localSchemeBuilder.AddToScheme
+	Install     = localSchemeBuilder.AddToScheme
+)
+
+func init() {
+	// We only register manually written functions here. The registration of the
+	// generated functions takes place in the generated files. The separation
+	// makes the code compile even when the generated files are missing.
+	localSchemeBuilder.Register(addKnownTypes)
+}
+
+// Adds the list of known types to Scheme.
+func addKnownTypes(scheme *runtime.Scheme) error {
+	scheme.AddKnownTypes(SchemeGroupVersion,
+		&ApisixClusterConfig{},
+		&ApisixClusterConfigList{},
+		&ApisixConsumer{},
+		&ApisixConsumerList{},
+		&ApisixPluginConfig{},
+		&ApisixPluginConfigList{},
+		&ApisixRoute{},
+		&ApisixRouteList{},
+		&ApisixTls{},
+		&ApisixTlsList{},
+		&ApisixUpstream{},
+		&ApisixUpstreamList{},
+	)
+	// AddToGroupVersion allows the serialization of client types like ListOptions.
+	v1.AddToGroupVersion(scheme, SchemeGroupVersion)
+	return nil
+}
diff --git a/pkg/kube/apisix/client/clientset/versioned/clientset.go b/pkg/kube/apisix/client/clientset/versioned/clientset.go
index fbe2985..0397709 100644
--- a/pkg/kube/apisix/client/clientset/versioned/clientset.go
+++ b/pkg/kube/apisix/client/clientset/versioned/clientset.go
@@ -20,6 +20,7 @@ package versioned
 import (
 	"fmt"
 
+	apisixv2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned/typed/config/v2"
 	apisixv2beta2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned/typed/config/v2beta2"
 	apisixv2beta3 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned/typed/config/v2beta3"
 	discovery "k8s.io/client-go/discovery"
@@ -29,6 +30,7 @@ import (
 
 type Interface interface {
 	Discovery() discovery.DiscoveryInterface
+	ApisixV2() apisixv2.ApisixV2Interface
 	ApisixV2beta3() apisixv2beta3.ApisixV2beta3Interface
 	ApisixV2beta2() apisixv2beta2.ApisixV2beta2Interface
 }
@@ -37,10 +39,16 @@ type Interface interface {
 // version included in a Clientset.
 type Clientset struct {
 	*discovery.DiscoveryClient
+	apisixV2      *apisixv2.ApisixV2Client
 	apisixV2beta3 *apisixv2beta3.ApisixV2beta3Client
 	apisixV2beta2 *apisixv2beta2.ApisixV2beta2Client
 }
 
+// ApisixV2 retrieves the ApisixV2Client
+func (c *Clientset) ApisixV2() apisixv2.ApisixV2Interface {
+	return c.apisixV2
+}
+
 // ApisixV2beta3 retrieves the ApisixV2beta3Client
 func (c *Clientset) ApisixV2beta3() apisixv2beta3.ApisixV2beta3Interface {
 	return c.apisixV2beta3
@@ -72,6 +80,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
 	}
 	var cs Clientset
 	var err error
+	cs.apisixV2, err = apisixv2.NewForConfig(&configShallowCopy)
+	if err != nil {
+		return nil, err
+	}
 	cs.apisixV2beta3, err = apisixv2beta3.NewForConfig(&configShallowCopy)
 	if err != nil {
 		return nil, err
@@ -92,6 +104,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
 // panics if there is an error in the config.
 func NewForConfigOrDie(c *rest.Config) *Clientset {
 	var cs Clientset
+	cs.apisixV2 = apisixv2.NewForConfigOrDie(c)
 	cs.apisixV2beta3 = apisixv2beta3.NewForConfigOrDie(c)
 	cs.apisixV2beta2 = apisixv2beta2.NewForConfigOrDie(c)
 
@@ -102,6 +115,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
 // New creates a new Clientset for the given RESTClient.
 func New(c rest.Interface) *Clientset {
 	var cs Clientset
+	cs.apisixV2 = apisixv2.New(c)
 	cs.apisixV2beta3 = apisixv2beta3.New(c)
 	cs.apisixV2beta2 = apisixv2beta2.New(c)
 
diff --git a/pkg/kube/apisix/client/clientset/versioned/fake/clientset_generated.go b/pkg/kube/apisix/client/clientset/versioned/fake/clientset_generated.go
index cfc91ed..5d9d1fc 100644
--- a/pkg/kube/apisix/client/clientset/versioned/fake/clientset_generated.go
+++ b/pkg/kube/apisix/client/clientset/versioned/fake/clientset_generated.go
@@ -19,6 +19,8 @@ package fake
 
 import (
 	clientset "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned"
+	apisixv2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned/typed/config/v2"
+	fakeapisixv2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake"
 	apisixv2beta2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned/typed/config/v2beta2"
 	fakeapisixv2beta2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned/typed/config/v2beta2/fake"
 	apisixv2beta3 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned/typed/config/v2beta3"
@@ -80,6 +82,11 @@ var (
 	_ testing.FakeClient  = &Clientset{}
 )
 
+// ApisixV2 retrieves the ApisixV2Client
+func (c *Clientset) ApisixV2() apisixv2.ApisixV2Interface {
+	return &fakeapisixv2.FakeApisixV2{Fake: &c.Fake}
+}
+
 // ApisixV2beta3 retrieves the ApisixV2beta3Client
 func (c *Clientset) ApisixV2beta3() apisixv2beta3.ApisixV2beta3Interface {
 	return &fakeapisixv2beta3.FakeApisixV2beta3{Fake: &c.Fake}
diff --git a/pkg/kube/apisix/client/clientset/versioned/fake/register.go b/pkg/kube/apisix/client/clientset/versioned/fake/register.go
index fa982e0..3554021 100644
--- a/pkg/kube/apisix/client/clientset/versioned/fake/register.go
+++ b/pkg/kube/apisix/client/clientset/versioned/fake/register.go
@@ -18,6 +18,7 @@
 package fake
 
 import (
+	apisixv2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
 	apisixv2beta2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2beta2"
 	apisixv2beta3 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2beta3"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -31,6 +32,7 @@ var scheme = runtime.NewScheme()
 var codecs = serializer.NewCodecFactory(scheme)
 
 var localSchemeBuilder = runtime.SchemeBuilder{
+	apisixv2.AddToScheme,
 	apisixv2beta3.AddToScheme,
 	apisixv2beta2.AddToScheme,
 }
diff --git a/pkg/kube/apisix/client/clientset/versioned/scheme/register.go b/pkg/kube/apisix/client/clientset/versioned/scheme/register.go
index 55d1ea7..0d25dcc 100644
--- a/pkg/kube/apisix/client/clientset/versioned/scheme/register.go
+++ b/pkg/kube/apisix/client/clientset/versioned/scheme/register.go
@@ -18,6 +18,7 @@
 package scheme
 
 import (
+	apisixv2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
 	apisixv2beta2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2beta2"
 	apisixv2beta3 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2beta3"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -31,6 +32,7 @@ var Scheme = runtime.NewScheme()
 var Codecs = serializer.NewCodecFactory(Scheme)
 var ParameterCodec = runtime.NewParameterCodec(Scheme)
 var localSchemeBuilder = runtime.SchemeBuilder{
+	apisixv2.AddToScheme,
 	apisixv2beta3.AddToScheme,
 	apisixv2beta2.AddToScheme,
 }
diff --git a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/apisixclusterconfig.go b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/apisixclusterconfig.go
new file mode 100644
index 0000000..6f0da57
--- /dev/null
+++ b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/apisixclusterconfig.go
@@ -0,0 +1,183 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	"context"
+	"time"
+
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	scheme "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned/scheme"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	rest "k8s.io/client-go/rest"
+)
+
+// ApisixClusterConfigsGetter has a method to return a ApisixClusterConfigInterface.
+// A group's client should implement this interface.
+type ApisixClusterConfigsGetter interface {
+	ApisixClusterConfigs() ApisixClusterConfigInterface
+}
+
+// ApisixClusterConfigInterface has methods to work with ApisixClusterConfig resources.
+type ApisixClusterConfigInterface interface {
+	Create(ctx context.Context, apisixClusterConfig *v2.ApisixClusterConfig, opts v1.CreateOptions) (*v2.ApisixClusterConfig, error)
+	Update(ctx context.Context, apisixClusterConfig *v2.ApisixClusterConfig, opts v1.UpdateOptions) (*v2.ApisixClusterConfig, error)
+	UpdateStatus(ctx context.Context, apisixClusterConfig *v2.ApisixClusterConfig, opts v1.UpdateOptions) (*v2.ApisixClusterConfig, error)
+	Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
+	DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
+	Get(ctx context.Context, name string, opts v1.GetOptions) (*v2.ApisixClusterConfig, error)
+	List(ctx context.Context, opts v1.ListOptions) (*v2.ApisixClusterConfigList, error)
+	Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
+	Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ApisixClusterConfig, err error)
+	ApisixClusterConfigExpansion
+}
+
+// apisixClusterConfigs implements ApisixClusterConfigInterface
+type apisixClusterConfigs struct {
+	client rest.Interface
+}
+
+// newApisixClusterConfigs returns a ApisixClusterConfigs
+func newApisixClusterConfigs(c *ApisixV2Client) *apisixClusterConfigs {
+	return &apisixClusterConfigs{
+		client: c.RESTClient(),
+	}
+}
+
+// Get takes name of the apisixClusterConfig, and returns the corresponding apisixClusterConfig object, and an error if there is any.
+func (c *apisixClusterConfigs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2.ApisixClusterConfig, err error) {
+	result = &v2.ApisixClusterConfig{}
+	err = c.client.Get().
+		Resource("apisixclusterconfigs").
+		Name(name).
+		VersionedParams(&options, scheme.ParameterCodec).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// List takes label and field selectors, and returns the list of ApisixClusterConfigs that match those selectors.
+func (c *apisixClusterConfigs) List(ctx context.Context, opts v1.ListOptions) (result *v2.ApisixClusterConfigList, err error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	result = &v2.ApisixClusterConfigList{}
+	err = c.client.Get().
+		Resource("apisixclusterconfigs").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Watch returns a watch.Interface that watches the requested apisixClusterConfigs.
+func (c *apisixClusterConfigs) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	opts.Watch = true
+	return c.client.Get().
+		Resource("apisixclusterconfigs").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Watch(ctx)
+}
+
+// Create takes the representation of a apisixClusterConfig and creates it.  Returns the server's representation of the apisixClusterConfig, and an error, if there is any.
+func (c *apisixClusterConfigs) Create(ctx context.Context, apisixClusterConfig *v2.ApisixClusterConfig, opts v1.CreateOptions) (result *v2.ApisixClusterConfig, err error) {
+	result = &v2.ApisixClusterConfig{}
+	err = c.client.Post().
+		Resource("apisixclusterconfigs").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(apisixClusterConfig).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Update takes the representation of a apisixClusterConfig and updates it. Returns the server's representation of the apisixClusterConfig, and an error, if there is any.
+func (c *apisixClusterConfigs) Update(ctx context.Context, apisixClusterConfig *v2.ApisixClusterConfig, opts v1.UpdateOptions) (result *v2.ApisixClusterConfig, err error) {
+	result = &v2.ApisixClusterConfig{}
+	err = c.client.Put().
+		Resource("apisixclusterconfigs").
+		Name(apisixClusterConfig.Name).
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(apisixClusterConfig).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *apisixClusterConfigs) UpdateStatus(ctx context.Context, apisixClusterConfig *v2.ApisixClusterConfig, opts v1.UpdateOptions) (result *v2.ApisixClusterConfig, err error) {
+	result = &v2.ApisixClusterConfig{}
+	err = c.client.Put().
+		Resource("apisixclusterconfigs").
+		Name(apisixClusterConfig.Name).
+		SubResource("status").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(apisixClusterConfig).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Delete takes name of the apisixClusterConfig and deletes it. Returns an error if one occurs.
+func (c *apisixClusterConfigs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	return c.client.Delete().
+		Resource("apisixclusterconfigs").
+		Name(name).
+		Body(&opts).
+		Do(ctx).
+		Error()
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *apisixClusterConfigs) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	var timeout time.Duration
+	if listOpts.TimeoutSeconds != nil {
+		timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
+	}
+	return c.client.Delete().
+		Resource("apisixclusterconfigs").
+		VersionedParams(&listOpts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Body(&opts).
+		Do(ctx).
+		Error()
+}
+
+// Patch applies the patch and returns the patched apisixClusterConfig.
+func (c *apisixClusterConfigs) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ApisixClusterConfig, err error) {
+	result = &v2.ApisixClusterConfig{}
+	err = c.client.Patch(pt).
+		Resource("apisixclusterconfigs").
+		Name(name).
+		SubResource(subresources...).
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(data).
+		Do(ctx).
+		Into(result)
+	return
+}
diff --git a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/apisixconsumer.go b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/apisixconsumer.go
new file mode 100644
index 0000000..4ed2708
--- /dev/null
+++ b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/apisixconsumer.go
@@ -0,0 +1,194 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	"context"
+	"time"
+
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	scheme "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned/scheme"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	rest "k8s.io/client-go/rest"
+)
+
+// ApisixConsumersGetter has a method to return a ApisixConsumerInterface.
+// A group's client should implement this interface.
+type ApisixConsumersGetter interface {
+	ApisixConsumers(namespace string) ApisixConsumerInterface
+}
+
+// ApisixConsumerInterface has methods to work with ApisixConsumer resources.
+type ApisixConsumerInterface interface {
+	Create(ctx context.Context, apisixConsumer *v2.ApisixConsumer, opts v1.CreateOptions) (*v2.ApisixConsumer, error)
+	Update(ctx context.Context, apisixConsumer *v2.ApisixConsumer, opts v1.UpdateOptions) (*v2.ApisixConsumer, error)
+	UpdateStatus(ctx context.Context, apisixConsumer *v2.ApisixConsumer, opts v1.UpdateOptions) (*v2.ApisixConsumer, error)
+	Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
+	DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
+	Get(ctx context.Context, name string, opts v1.GetOptions) (*v2.ApisixConsumer, error)
+	List(ctx context.Context, opts v1.ListOptions) (*v2.ApisixConsumerList, error)
+	Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
+	Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ApisixConsumer, err error)
+	ApisixConsumerExpansion
+}
+
+// apisixConsumers implements ApisixConsumerInterface
+type apisixConsumers struct {
+	client rest.Interface
+	ns     string
+}
+
+// newApisixConsumers returns a ApisixConsumers
+func newApisixConsumers(c *ApisixV2Client, namespace string) *apisixConsumers {
+	return &apisixConsumers{
+		client: c.RESTClient(),
+		ns:     namespace,
+	}
+}
+
+// Get takes name of the apisixConsumer, and returns the corresponding apisixConsumer object, and an error if there is any.
+func (c *apisixConsumers) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2.ApisixConsumer, err error) {
+	result = &v2.ApisixConsumer{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("apisixconsumers").
+		Name(name).
+		VersionedParams(&options, scheme.ParameterCodec).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// List takes label and field selectors, and returns the list of ApisixConsumers that match those selectors.
+func (c *apisixConsumers) List(ctx context.Context, opts v1.ListOptions) (result *v2.ApisixConsumerList, err error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	result = &v2.ApisixConsumerList{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("apisixconsumers").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Watch returns a watch.Interface that watches the requested apisixConsumers.
+func (c *apisixConsumers) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	opts.Watch = true
+	return c.client.Get().
+		Namespace(c.ns).
+		Resource("apisixconsumers").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Watch(ctx)
+}
+
+// Create takes the representation of a apisixConsumer and creates it.  Returns the server's representation of the apisixConsumer, and an error, if there is any.
+func (c *apisixConsumers) Create(ctx context.Context, apisixConsumer *v2.ApisixConsumer, opts v1.CreateOptions) (result *v2.ApisixConsumer, err error) {
+	result = &v2.ApisixConsumer{}
+	err = c.client.Post().
+		Namespace(c.ns).
+		Resource("apisixconsumers").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(apisixConsumer).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Update takes the representation of a apisixConsumer and updates it. Returns the server's representation of the apisixConsumer, and an error, if there is any.
+func (c *apisixConsumers) Update(ctx context.Context, apisixConsumer *v2.ApisixConsumer, opts v1.UpdateOptions) (result *v2.ApisixConsumer, err error) {
+	result = &v2.ApisixConsumer{}
+	err = c.client.Put().
+		Namespace(c.ns).
+		Resource("apisixconsumers").
+		Name(apisixConsumer.Name).
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(apisixConsumer).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *apisixConsumers) UpdateStatus(ctx context.Context, apisixConsumer *v2.ApisixConsumer, opts v1.UpdateOptions) (result *v2.ApisixConsumer, err error) {
+	result = &v2.ApisixConsumer{}
+	err = c.client.Put().
+		Namespace(c.ns).
+		Resource("apisixconsumers").
+		Name(apisixConsumer.Name).
+		SubResource("status").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(apisixConsumer).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Delete takes name of the apisixConsumer and deletes it. Returns an error if one occurs.
+func (c *apisixConsumers) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	return c.client.Delete().
+		Namespace(c.ns).
+		Resource("apisixconsumers").
+		Name(name).
+		Body(&opts).
+		Do(ctx).
+		Error()
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *apisixConsumers) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	var timeout time.Duration
+	if listOpts.TimeoutSeconds != nil {
+		timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
+	}
+	return c.client.Delete().
+		Namespace(c.ns).
+		Resource("apisixconsumers").
+		VersionedParams(&listOpts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Body(&opts).
+		Do(ctx).
+		Error()
+}
+
+// Patch applies the patch and returns the patched apisixConsumer.
+func (c *apisixConsumers) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ApisixConsumer, err error) {
+	result = &v2.ApisixConsumer{}
+	err = c.client.Patch(pt).
+		Namespace(c.ns).
+		Resource("apisixconsumers").
+		Name(name).
+		SubResource(subresources...).
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(data).
+		Do(ctx).
+		Into(result)
+	return
+}
diff --git a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/apisixpluginconfig.go b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/apisixpluginconfig.go
new file mode 100644
index 0000000..dbb7a51
--- /dev/null
+++ b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/apisixpluginconfig.go
@@ -0,0 +1,194 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	"context"
+	"time"
+
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	scheme "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned/scheme"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	rest "k8s.io/client-go/rest"
+)
+
+// ApisixPluginConfigsGetter has a method to return a ApisixPluginConfigInterface.
+// A group's client should implement this interface.
+type ApisixPluginConfigsGetter interface {
+	ApisixPluginConfigs(namespace string) ApisixPluginConfigInterface
+}
+
+// ApisixPluginConfigInterface has methods to work with ApisixPluginConfig resources.
+type ApisixPluginConfigInterface interface {
+	Create(ctx context.Context, apisixPluginConfig *v2.ApisixPluginConfig, opts v1.CreateOptions) (*v2.ApisixPluginConfig, error)
+	Update(ctx context.Context, apisixPluginConfig *v2.ApisixPluginConfig, opts v1.UpdateOptions) (*v2.ApisixPluginConfig, error)
+	UpdateStatus(ctx context.Context, apisixPluginConfig *v2.ApisixPluginConfig, opts v1.UpdateOptions) (*v2.ApisixPluginConfig, error)
+	Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
+	DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
+	Get(ctx context.Context, name string, opts v1.GetOptions) (*v2.ApisixPluginConfig, error)
+	List(ctx context.Context, opts v1.ListOptions) (*v2.ApisixPluginConfigList, error)
+	Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
+	Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ApisixPluginConfig, err error)
+	ApisixPluginConfigExpansion
+}
+
+// apisixPluginConfigs implements ApisixPluginConfigInterface
+type apisixPluginConfigs struct {
+	client rest.Interface
+	ns     string
+}
+
+// newApisixPluginConfigs returns a ApisixPluginConfigs
+func newApisixPluginConfigs(c *ApisixV2Client, namespace string) *apisixPluginConfigs {
+	return &apisixPluginConfigs{
+		client: c.RESTClient(),
+		ns:     namespace,
+	}
+}
+
+// Get takes name of the apisixPluginConfig, and returns the corresponding apisixPluginConfig object, and an error if there is any.
+func (c *apisixPluginConfigs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2.ApisixPluginConfig, err error) {
+	result = &v2.ApisixPluginConfig{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("apisixpluginconfigs").
+		Name(name).
+		VersionedParams(&options, scheme.ParameterCodec).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// List takes label and field selectors, and returns the list of ApisixPluginConfigs that match those selectors.
+func (c *apisixPluginConfigs) List(ctx context.Context, opts v1.ListOptions) (result *v2.ApisixPluginConfigList, err error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	result = &v2.ApisixPluginConfigList{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("apisixpluginconfigs").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Watch returns a watch.Interface that watches the requested apisixPluginConfigs.
+func (c *apisixPluginConfigs) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	opts.Watch = true
+	return c.client.Get().
+		Namespace(c.ns).
+		Resource("apisixpluginconfigs").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Watch(ctx)
+}
+
+// Create takes the representation of a apisixPluginConfig and creates it.  Returns the server's representation of the apisixPluginConfig, and an error, if there is any.
+func (c *apisixPluginConfigs) Create(ctx context.Context, apisixPluginConfig *v2.ApisixPluginConfig, opts v1.CreateOptions) (result *v2.ApisixPluginConfig, err error) {
+	result = &v2.ApisixPluginConfig{}
+	err = c.client.Post().
+		Namespace(c.ns).
+		Resource("apisixpluginconfigs").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(apisixPluginConfig).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Update takes the representation of a apisixPluginConfig and updates it. Returns the server's representation of the apisixPluginConfig, and an error, if there is any.
+func (c *apisixPluginConfigs) Update(ctx context.Context, apisixPluginConfig *v2.ApisixPluginConfig, opts v1.UpdateOptions) (result *v2.ApisixPluginConfig, err error) {
+	result = &v2.ApisixPluginConfig{}
+	err = c.client.Put().
+		Namespace(c.ns).
+		Resource("apisixpluginconfigs").
+		Name(apisixPluginConfig.Name).
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(apisixPluginConfig).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *apisixPluginConfigs) UpdateStatus(ctx context.Context, apisixPluginConfig *v2.ApisixPluginConfig, opts v1.UpdateOptions) (result *v2.ApisixPluginConfig, err error) {
+	result = &v2.ApisixPluginConfig{}
+	err = c.client.Put().
+		Namespace(c.ns).
+		Resource("apisixpluginconfigs").
+		Name(apisixPluginConfig.Name).
+		SubResource("status").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(apisixPluginConfig).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Delete takes name of the apisixPluginConfig and deletes it. Returns an error if one occurs.
+func (c *apisixPluginConfigs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	return c.client.Delete().
+		Namespace(c.ns).
+		Resource("apisixpluginconfigs").
+		Name(name).
+		Body(&opts).
+		Do(ctx).
+		Error()
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *apisixPluginConfigs) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	var timeout time.Duration
+	if listOpts.TimeoutSeconds != nil {
+		timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
+	}
+	return c.client.Delete().
+		Namespace(c.ns).
+		Resource("apisixpluginconfigs").
+		VersionedParams(&listOpts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Body(&opts).
+		Do(ctx).
+		Error()
+}
+
+// Patch applies the patch and returns the patched apisixPluginConfig.
+func (c *apisixPluginConfigs) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ApisixPluginConfig, err error) {
+	result = &v2.ApisixPluginConfig{}
+	err = c.client.Patch(pt).
+		Namespace(c.ns).
+		Resource("apisixpluginconfigs").
+		Name(name).
+		SubResource(subresources...).
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(data).
+		Do(ctx).
+		Into(result)
+	return
+}
diff --git a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/apisixroute.go b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/apisixroute.go
new file mode 100644
index 0000000..941c4cc
--- /dev/null
+++ b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/apisixroute.go
@@ -0,0 +1,194 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	"context"
+	"time"
+
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	scheme "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned/scheme"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	rest "k8s.io/client-go/rest"
+)
+
+// ApisixRoutesGetter has a method to return a ApisixRouteInterface.
+// A group's client should implement this interface.
+type ApisixRoutesGetter interface {
+	ApisixRoutes(namespace string) ApisixRouteInterface
+}
+
+// ApisixRouteInterface has methods to work with ApisixRoute resources.
+type ApisixRouteInterface interface {
+	Create(ctx context.Context, apisixRoute *v2.ApisixRoute, opts v1.CreateOptions) (*v2.ApisixRoute, error)
+	Update(ctx context.Context, apisixRoute *v2.ApisixRoute, opts v1.UpdateOptions) (*v2.ApisixRoute, error)
+	UpdateStatus(ctx context.Context, apisixRoute *v2.ApisixRoute, opts v1.UpdateOptions) (*v2.ApisixRoute, error)
+	Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
+	DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
+	Get(ctx context.Context, name string, opts v1.GetOptions) (*v2.ApisixRoute, error)
+	List(ctx context.Context, opts v1.ListOptions) (*v2.ApisixRouteList, error)
+	Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
+	Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ApisixRoute, err error)
+	ApisixRouteExpansion
+}
+
+// apisixRoutes implements ApisixRouteInterface
+type apisixRoutes struct {
+	client rest.Interface
+	ns     string
+}
+
+// newApisixRoutes returns a ApisixRoutes
+func newApisixRoutes(c *ApisixV2Client, namespace string) *apisixRoutes {
+	return &apisixRoutes{
+		client: c.RESTClient(),
+		ns:     namespace,
+	}
+}
+
+// Get takes name of the apisixRoute, and returns the corresponding apisixRoute object, and an error if there is any.
+func (c *apisixRoutes) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2.ApisixRoute, err error) {
+	result = &v2.ApisixRoute{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("apisixroutes").
+		Name(name).
+		VersionedParams(&options, scheme.ParameterCodec).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// List takes label and field selectors, and returns the list of ApisixRoutes that match those selectors.
+func (c *apisixRoutes) List(ctx context.Context, opts v1.ListOptions) (result *v2.ApisixRouteList, err error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	result = &v2.ApisixRouteList{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("apisixroutes").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Watch returns a watch.Interface that watches the requested apisixRoutes.
+func (c *apisixRoutes) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	opts.Watch = true
+	return c.client.Get().
+		Namespace(c.ns).
+		Resource("apisixroutes").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Watch(ctx)
+}
+
+// Create takes the representation of a apisixRoute and creates it.  Returns the server's representation of the apisixRoute, and an error, if there is any.
+func (c *apisixRoutes) Create(ctx context.Context, apisixRoute *v2.ApisixRoute, opts v1.CreateOptions) (result *v2.ApisixRoute, err error) {
+	result = &v2.ApisixRoute{}
+	err = c.client.Post().
+		Namespace(c.ns).
+		Resource("apisixroutes").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(apisixRoute).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Update takes the representation of a apisixRoute and updates it. Returns the server's representation of the apisixRoute, and an error, if there is any.
+func (c *apisixRoutes) Update(ctx context.Context, apisixRoute *v2.ApisixRoute, opts v1.UpdateOptions) (result *v2.ApisixRoute, err error) {
+	result = &v2.ApisixRoute{}
+	err = c.client.Put().
+		Namespace(c.ns).
+		Resource("apisixroutes").
+		Name(apisixRoute.Name).
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(apisixRoute).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *apisixRoutes) UpdateStatus(ctx context.Context, apisixRoute *v2.ApisixRoute, opts v1.UpdateOptions) (result *v2.ApisixRoute, err error) {
+	result = &v2.ApisixRoute{}
+	err = c.client.Put().
+		Namespace(c.ns).
+		Resource("apisixroutes").
+		Name(apisixRoute.Name).
+		SubResource("status").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(apisixRoute).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Delete takes name of the apisixRoute and deletes it. Returns an error if one occurs.
+func (c *apisixRoutes) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	return c.client.Delete().
+		Namespace(c.ns).
+		Resource("apisixroutes").
+		Name(name).
+		Body(&opts).
+		Do(ctx).
+		Error()
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *apisixRoutes) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	var timeout time.Duration
+	if listOpts.TimeoutSeconds != nil {
+		timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
+	}
+	return c.client.Delete().
+		Namespace(c.ns).
+		Resource("apisixroutes").
+		VersionedParams(&listOpts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Body(&opts).
+		Do(ctx).
+		Error()
+}
+
+// Patch applies the patch and returns the patched apisixRoute.
+func (c *apisixRoutes) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ApisixRoute, err error) {
+	result = &v2.ApisixRoute{}
+	err = c.client.Patch(pt).
+		Namespace(c.ns).
+		Resource("apisixroutes").
+		Name(name).
+		SubResource(subresources...).
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(data).
+		Do(ctx).
+		Into(result)
+	return
+}
diff --git a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/apisixtls.go b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/apisixtls.go
new file mode 100644
index 0000000..922918d
--- /dev/null
+++ b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/apisixtls.go
@@ -0,0 +1,194 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	"context"
+	"time"
+
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	scheme "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned/scheme"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	rest "k8s.io/client-go/rest"
+)
+
+// ApisixTlsesGetter has a method to return a ApisixTlsInterface.
+// A group's client should implement this interface.
+type ApisixTlsesGetter interface {
+	ApisixTlses(namespace string) ApisixTlsInterface
+}
+
+// ApisixTlsInterface has methods to work with ApisixTls resources.
+type ApisixTlsInterface interface {
+	Create(ctx context.Context, apisixTls *v2.ApisixTls, opts v1.CreateOptions) (*v2.ApisixTls, error)
+	Update(ctx context.Context, apisixTls *v2.ApisixTls, opts v1.UpdateOptions) (*v2.ApisixTls, error)
+	UpdateStatus(ctx context.Context, apisixTls *v2.ApisixTls, opts v1.UpdateOptions) (*v2.ApisixTls, error)
+	Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
+	DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
+	Get(ctx context.Context, name string, opts v1.GetOptions) (*v2.ApisixTls, error)
+	List(ctx context.Context, opts v1.ListOptions) (*v2.ApisixTlsList, error)
+	Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
+	Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ApisixTls, err error)
+	ApisixTlsExpansion
+}
+
+// apisixTlses implements ApisixTlsInterface
+type apisixTlses struct {
+	client rest.Interface
+	ns     string
+}
+
+// newApisixTlses returns a ApisixTlses
+func newApisixTlses(c *ApisixV2Client, namespace string) *apisixTlses {
+	return &apisixTlses{
+		client: c.RESTClient(),
+		ns:     namespace,
+	}
+}
+
+// Get takes name of the apisixTls, and returns the corresponding apisixTls object, and an error if there is any.
+func (c *apisixTlses) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2.ApisixTls, err error) {
+	result = &v2.ApisixTls{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("apisixtlses").
+		Name(name).
+		VersionedParams(&options, scheme.ParameterCodec).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// List takes label and field selectors, and returns the list of ApisixTlses that match those selectors.
+func (c *apisixTlses) List(ctx context.Context, opts v1.ListOptions) (result *v2.ApisixTlsList, err error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	result = &v2.ApisixTlsList{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("apisixtlses").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Watch returns a watch.Interface that watches the requested apisixTlses.
+func (c *apisixTlses) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	opts.Watch = true
+	return c.client.Get().
+		Namespace(c.ns).
+		Resource("apisixtlses").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Watch(ctx)
+}
+
+// Create takes the representation of a apisixTls and creates it.  Returns the server's representation of the apisixTls, and an error, if there is any.
+func (c *apisixTlses) Create(ctx context.Context, apisixTls *v2.ApisixTls, opts v1.CreateOptions) (result *v2.ApisixTls, err error) {
+	result = &v2.ApisixTls{}
+	err = c.client.Post().
+		Namespace(c.ns).
+		Resource("apisixtlses").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(apisixTls).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Update takes the representation of a apisixTls and updates it. Returns the server's representation of the apisixTls, and an error, if there is any.
+func (c *apisixTlses) Update(ctx context.Context, apisixTls *v2.ApisixTls, opts v1.UpdateOptions) (result *v2.ApisixTls, err error) {
+	result = &v2.ApisixTls{}
+	err = c.client.Put().
+		Namespace(c.ns).
+		Resource("apisixtlses").
+		Name(apisixTls.Name).
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(apisixTls).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *apisixTlses) UpdateStatus(ctx context.Context, apisixTls *v2.ApisixTls, opts v1.UpdateOptions) (result *v2.ApisixTls, err error) {
+	result = &v2.ApisixTls{}
+	err = c.client.Put().
+		Namespace(c.ns).
+		Resource("apisixtlses").
+		Name(apisixTls.Name).
+		SubResource("status").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(apisixTls).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Delete takes name of the apisixTls and deletes it. Returns an error if one occurs.
+func (c *apisixTlses) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	return c.client.Delete().
+		Namespace(c.ns).
+		Resource("apisixtlses").
+		Name(name).
+		Body(&opts).
+		Do(ctx).
+		Error()
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *apisixTlses) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	var timeout time.Duration
+	if listOpts.TimeoutSeconds != nil {
+		timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
+	}
+	return c.client.Delete().
+		Namespace(c.ns).
+		Resource("apisixtlses").
+		VersionedParams(&listOpts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Body(&opts).
+		Do(ctx).
+		Error()
+}
+
+// Patch applies the patch and returns the patched apisixTls.
+func (c *apisixTlses) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ApisixTls, err error) {
+	result = &v2.ApisixTls{}
+	err = c.client.Patch(pt).
+		Namespace(c.ns).
+		Resource("apisixtlses").
+		Name(name).
+		SubResource(subresources...).
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(data).
+		Do(ctx).
+		Into(result)
+	return
+}
diff --git a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/apisixupstream.go b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/apisixupstream.go
new file mode 100644
index 0000000..b996353
--- /dev/null
+++ b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/apisixupstream.go
@@ -0,0 +1,194 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	"context"
+	"time"
+
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	scheme "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned/scheme"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	rest "k8s.io/client-go/rest"
+)
+
+// ApisixUpstreamsGetter has a method to return a ApisixUpstreamInterface.
+// A group's client should implement this interface.
+type ApisixUpstreamsGetter interface {
+	ApisixUpstreams(namespace string) ApisixUpstreamInterface
+}
+
+// ApisixUpstreamInterface has methods to work with ApisixUpstream resources.
+type ApisixUpstreamInterface interface {
+	Create(ctx context.Context, apisixUpstream *v2.ApisixUpstream, opts v1.CreateOptions) (*v2.ApisixUpstream, error)
+	Update(ctx context.Context, apisixUpstream *v2.ApisixUpstream, opts v1.UpdateOptions) (*v2.ApisixUpstream, error)
+	UpdateStatus(ctx context.Context, apisixUpstream *v2.ApisixUpstream, opts v1.UpdateOptions) (*v2.ApisixUpstream, error)
+	Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
+	DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
+	Get(ctx context.Context, name string, opts v1.GetOptions) (*v2.ApisixUpstream, error)
+	List(ctx context.Context, opts v1.ListOptions) (*v2.ApisixUpstreamList, error)
+	Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
+	Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ApisixUpstream, err error)
+	ApisixUpstreamExpansion
+}
+
+// apisixUpstreams implements ApisixUpstreamInterface
+type apisixUpstreams struct {
+	client rest.Interface
+	ns     string
+}
+
+// newApisixUpstreams returns a ApisixUpstreams
+func newApisixUpstreams(c *ApisixV2Client, namespace string) *apisixUpstreams {
+	return &apisixUpstreams{
+		client: c.RESTClient(),
+		ns:     namespace,
+	}
+}
+
+// Get takes name of the apisixUpstream, and returns the corresponding apisixUpstream object, and an error if there is any.
+func (c *apisixUpstreams) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2.ApisixUpstream, err error) {
+	result = &v2.ApisixUpstream{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("apisixupstreams").
+		Name(name).
+		VersionedParams(&options, scheme.ParameterCodec).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// List takes label and field selectors, and returns the list of ApisixUpstreams that match those selectors.
+func (c *apisixUpstreams) List(ctx context.Context, opts v1.ListOptions) (result *v2.ApisixUpstreamList, err error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	result = &v2.ApisixUpstreamList{}
+	err = c.client.Get().
+		Namespace(c.ns).
+		Resource("apisixupstreams").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Watch returns a watch.Interface that watches the requested apisixUpstreams.
+func (c *apisixUpstreams) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	var timeout time.Duration
+	if opts.TimeoutSeconds != nil {
+		timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+	}
+	opts.Watch = true
+	return c.client.Get().
+		Namespace(c.ns).
+		Resource("apisixupstreams").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Watch(ctx)
+}
+
+// Create takes the representation of a apisixUpstream and creates it.  Returns the server's representation of the apisixUpstream, and an error, if there is any.
+func (c *apisixUpstreams) Create(ctx context.Context, apisixUpstream *v2.ApisixUpstream, opts v1.CreateOptions) (result *v2.ApisixUpstream, err error) {
+	result = &v2.ApisixUpstream{}
+	err = c.client.Post().
+		Namespace(c.ns).
+		Resource("apisixupstreams").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(apisixUpstream).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Update takes the representation of a apisixUpstream and updates it. Returns the server's representation of the apisixUpstream, and an error, if there is any.
+func (c *apisixUpstreams) Update(ctx context.Context, apisixUpstream *v2.ApisixUpstream, opts v1.UpdateOptions) (result *v2.ApisixUpstream, err error) {
+	result = &v2.ApisixUpstream{}
+	err = c.client.Put().
+		Namespace(c.ns).
+		Resource("apisixupstreams").
+		Name(apisixUpstream.Name).
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(apisixUpstream).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *apisixUpstreams) UpdateStatus(ctx context.Context, apisixUpstream *v2.ApisixUpstream, opts v1.UpdateOptions) (result *v2.ApisixUpstream, err error) {
+	result = &v2.ApisixUpstream{}
+	err = c.client.Put().
+		Namespace(c.ns).
+		Resource("apisixupstreams").
+		Name(apisixUpstream.Name).
+		SubResource("status").
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(apisixUpstream).
+		Do(ctx).
+		Into(result)
+	return
+}
+
+// Delete takes name of the apisixUpstream and deletes it. Returns an error if one occurs.
+func (c *apisixUpstreams) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	return c.client.Delete().
+		Namespace(c.ns).
+		Resource("apisixupstreams").
+		Name(name).
+		Body(&opts).
+		Do(ctx).
+		Error()
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *apisixUpstreams) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	var timeout time.Duration
+	if listOpts.TimeoutSeconds != nil {
+		timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
+	}
+	return c.client.Delete().
+		Namespace(c.ns).
+		Resource("apisixupstreams").
+		VersionedParams(&listOpts, scheme.ParameterCodec).
+		Timeout(timeout).
+		Body(&opts).
+		Do(ctx).
+		Error()
+}
+
+// Patch applies the patch and returns the patched apisixUpstream.
+func (c *apisixUpstreams) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ApisixUpstream, err error) {
+	result = &v2.ApisixUpstream{}
+	err = c.client.Patch(pt).
+		Namespace(c.ns).
+		Resource("apisixupstreams").
+		Name(name).
+		SubResource(subresources...).
+		VersionedParams(&opts, scheme.ParameterCodec).
+		Body(data).
+		Do(ctx).
+		Into(result)
+	return
+}
diff --git a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/config_client.go b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/config_client.go
new file mode 100644
index 0000000..885531c
--- /dev/null
+++ b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/config_client.go
@@ -0,0 +1,113 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	"github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned/scheme"
+	rest "k8s.io/client-go/rest"
+)
+
+type ApisixV2Interface interface {
+	RESTClient() rest.Interface
+	ApisixClusterConfigsGetter
+	ApisixConsumersGetter
+	ApisixPluginConfigsGetter
+	ApisixRoutesGetter
+	ApisixTlsesGetter
+	ApisixUpstreamsGetter
+}
+
+// ApisixV2Client is used to interact with features provided by the apisix.apache.org group.
+type ApisixV2Client struct {
+	restClient rest.Interface
+}
+
+func (c *ApisixV2Client) ApisixClusterConfigs() ApisixClusterConfigInterface {
+	return newApisixClusterConfigs(c)
+}
+
+func (c *ApisixV2Client) ApisixConsumers(namespace string) ApisixConsumerInterface {
+	return newApisixConsumers(c, namespace)
+}
+
+func (c *ApisixV2Client) ApisixPluginConfigs(namespace string) ApisixPluginConfigInterface {
+	return newApisixPluginConfigs(c, namespace)
+}
+
+func (c *ApisixV2Client) ApisixRoutes(namespace string) ApisixRouteInterface {
+	return newApisixRoutes(c, namespace)
+}
+
+func (c *ApisixV2Client) ApisixTlses(namespace string) ApisixTlsInterface {
+	return newApisixTlses(c, namespace)
+}
+
+func (c *ApisixV2Client) ApisixUpstreams(namespace string) ApisixUpstreamInterface {
+	return newApisixUpstreams(c, namespace)
+}
+
+// NewForConfig creates a new ApisixV2Client for the given config.
+func NewForConfig(c *rest.Config) (*ApisixV2Client, error) {
+	config := *c
+	if err := setConfigDefaults(&config); err != nil {
+		return nil, err
+	}
+	client, err := rest.RESTClientFor(&config)
+	if err != nil {
+		return nil, err
+	}
+	return &ApisixV2Client{client}, nil
+}
+
+// NewForConfigOrDie creates a new ApisixV2Client for the given config and
+// panics if there is an error in the config.
+func NewForConfigOrDie(c *rest.Config) *ApisixV2Client {
+	client, err := NewForConfig(c)
+	if err != nil {
+		panic(err)
+	}
+	return client
+}
+
+// New creates a new ApisixV2Client for the given RESTClient.
+func New(c rest.Interface) *ApisixV2Client {
+	return &ApisixV2Client{c}
+}
+
+func setConfigDefaults(config *rest.Config) error {
+	gv := v2.SchemeGroupVersion
+	config.GroupVersion = &gv
+	config.APIPath = "/apis"
+	config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
+
+	if config.UserAgent == "" {
+		config.UserAgent = rest.DefaultKubernetesUserAgent()
+	}
+
+	return nil
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *ApisixV2Client) RESTClient() rest.Interface {
+	if c == nil {
+		return nil
+	}
+	return c.restClient
+}
diff --git a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/doc.go b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/doc.go
new file mode 100644
index 0000000..34f963c
--- /dev/null
+++ b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/doc.go
@@ -0,0 +1,19 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// This package has the automatically generated typed clients.
+package v2
diff --git a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/doc.go b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/doc.go
new file mode 100644
index 0000000..cfa1988
--- /dev/null
+++ b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/doc.go
@@ -0,0 +1,19 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_apisixclusterconfig.go b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_apisixclusterconfig.go
new file mode 100644
index 0000000..476093f
--- /dev/null
+++ b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_apisixclusterconfig.go
@@ -0,0 +1,132 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	"context"
+
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	labels "k8s.io/apimachinery/pkg/labels"
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	testing "k8s.io/client-go/testing"
+)
+
+// FakeApisixClusterConfigs implements ApisixClusterConfigInterface
+type FakeApisixClusterConfigs struct {
+	Fake *FakeApisixV2
+}
+
+var apisixclusterconfigsResource = schema.GroupVersionResource{Group: "apisix.apache.org", Version: "v2", Resource: "apisixclusterconfigs"}
+
+var apisixclusterconfigsKind = schema.GroupVersionKind{Group: "apisix.apache.org", Version: "v2", Kind: "ApisixClusterConfig"}
+
+// Get takes name of the apisixClusterConfig, and returns the corresponding apisixClusterConfig object, and an error if there is any.
+func (c *FakeApisixClusterConfigs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2.ApisixClusterConfig, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootGetAction(apisixclusterconfigsResource, name), &v2.ApisixClusterConfig{})
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixClusterConfig), err
+}
+
+// List takes label and field selectors, and returns the list of ApisixClusterConfigs that match those selectors.
+func (c *FakeApisixClusterConfigs) List(ctx context.Context, opts v1.ListOptions) (result *v2.ApisixClusterConfigList, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootListAction(apisixclusterconfigsResource, apisixclusterconfigsKind, opts), &v2.ApisixClusterConfigList{})
+	if obj == nil {
+		return nil, err
+	}
+
+	label, _, _ := testing.ExtractFromListOptions(opts)
+	if label == nil {
+		label = labels.Everything()
+	}
+	list := &v2.ApisixClusterConfigList{ListMeta: obj.(*v2.ApisixClusterConfigList).ListMeta}
+	for _, item := range obj.(*v2.ApisixClusterConfigList).Items {
+		if label.Matches(labels.Set(item.Labels)) {
+			list.Items = append(list.Items, item)
+		}
+	}
+	return list, err
+}
+
+// Watch returns a watch.Interface that watches the requested apisixClusterConfigs.
+func (c *FakeApisixClusterConfigs) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	return c.Fake.
+		InvokesWatch(testing.NewRootWatchAction(apisixclusterconfigsResource, opts))
+}
+
+// Create takes the representation of a apisixClusterConfig and creates it.  Returns the server's representation of the apisixClusterConfig, and an error, if there is any.
+func (c *FakeApisixClusterConfigs) Create(ctx context.Context, apisixClusterConfig *v2.ApisixClusterConfig, opts v1.CreateOptions) (result *v2.ApisixClusterConfig, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootCreateAction(apisixclusterconfigsResource, apisixClusterConfig), &v2.ApisixClusterConfig{})
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixClusterConfig), err
+}
+
+// Update takes the representation of a apisixClusterConfig and updates it. Returns the server's representation of the apisixClusterConfig, and an error, if there is any.
+func (c *FakeApisixClusterConfigs) Update(ctx context.Context, apisixClusterConfig *v2.ApisixClusterConfig, opts v1.UpdateOptions) (result *v2.ApisixClusterConfig, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootUpdateAction(apisixclusterconfigsResource, apisixClusterConfig), &v2.ApisixClusterConfig{})
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixClusterConfig), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeApisixClusterConfigs) UpdateStatus(ctx context.Context, apisixClusterConfig *v2.ApisixClusterConfig, opts v1.UpdateOptions) (*v2.ApisixClusterConfig, error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootUpdateSubresourceAction(apisixclusterconfigsResource, "status", apisixClusterConfig), &v2.ApisixClusterConfig{})
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixClusterConfig), err
+}
+
+// Delete takes name of the apisixClusterConfig and deletes it. Returns an error if one occurs.
+func (c *FakeApisixClusterConfigs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	_, err := c.Fake.
+		Invokes(testing.NewRootDeleteAction(apisixclusterconfigsResource, name), &v2.ApisixClusterConfig{})
+	return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeApisixClusterConfigs) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	action := testing.NewRootDeleteCollectionAction(apisixclusterconfigsResource, listOpts)
+
+	_, err := c.Fake.Invokes(action, &v2.ApisixClusterConfigList{})
+	return err
+}
+
+// Patch applies the patch and returns the patched apisixClusterConfig.
+func (c *FakeApisixClusterConfigs) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ApisixClusterConfig, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootPatchSubresourceAction(apisixclusterconfigsResource, name, pt, data, subresources...), &v2.ApisixClusterConfig{})
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixClusterConfig), err
+}
diff --git a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_apisixconsumer.go b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_apisixconsumer.go
new file mode 100644
index 0000000..97d88e8
--- /dev/null
+++ b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_apisixconsumer.go
@@ -0,0 +1,141 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	"context"
+
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	labels "k8s.io/apimachinery/pkg/labels"
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	testing "k8s.io/client-go/testing"
+)
+
+// FakeApisixConsumers implements ApisixConsumerInterface
+type FakeApisixConsumers struct {
+	Fake *FakeApisixV2
+	ns   string
+}
+
+var apisixconsumersResource = schema.GroupVersionResource{Group: "apisix.apache.org", Version: "v2", Resource: "apisixconsumers"}
+
+var apisixconsumersKind = schema.GroupVersionKind{Group: "apisix.apache.org", Version: "v2", Kind: "ApisixConsumer"}
+
+// Get takes name of the apisixConsumer, and returns the corresponding apisixConsumer object, and an error if there is any.
+func (c *FakeApisixConsumers) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2.ApisixConsumer, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewGetAction(apisixconsumersResource, c.ns, name), &v2.ApisixConsumer{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixConsumer), err
+}
+
+// List takes label and field selectors, and returns the list of ApisixConsumers that match those selectors.
+func (c *FakeApisixConsumers) List(ctx context.Context, opts v1.ListOptions) (result *v2.ApisixConsumerList, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewListAction(apisixconsumersResource, apisixconsumersKind, c.ns, opts), &v2.ApisixConsumerList{})
+
+	if obj == nil {
+		return nil, err
+	}
+
+	label, _, _ := testing.ExtractFromListOptions(opts)
+	if label == nil {
+		label = labels.Everything()
+	}
+	list := &v2.ApisixConsumerList{ListMeta: obj.(*v2.ApisixConsumerList).ListMeta}
+	for _, item := range obj.(*v2.ApisixConsumerList).Items {
+		if label.Matches(labels.Set(item.Labels)) {
+			list.Items = append(list.Items, item)
+		}
+	}
+	return list, err
+}
+
+// Watch returns a watch.Interface that watches the requested apisixConsumers.
+func (c *FakeApisixConsumers) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	return c.Fake.
+		InvokesWatch(testing.NewWatchAction(apisixconsumersResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a apisixConsumer and creates it.  Returns the server's representation of the apisixConsumer, and an error, if there is any.
+func (c *FakeApisixConsumers) Create(ctx context.Context, apisixConsumer *v2.ApisixConsumer, opts v1.CreateOptions) (result *v2.ApisixConsumer, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewCreateAction(apisixconsumersResource, c.ns, apisixConsumer), &v2.ApisixConsumer{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixConsumer), err
+}
+
+// Update takes the representation of a apisixConsumer and updates it. Returns the server's representation of the apisixConsumer, and an error, if there is any.
+func (c *FakeApisixConsumers) Update(ctx context.Context, apisixConsumer *v2.ApisixConsumer, opts v1.UpdateOptions) (result *v2.ApisixConsumer, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewUpdateAction(apisixconsumersResource, c.ns, apisixConsumer), &v2.ApisixConsumer{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixConsumer), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeApisixConsumers) UpdateStatus(ctx context.Context, apisixConsumer *v2.ApisixConsumer, opts v1.UpdateOptions) (*v2.ApisixConsumer, error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewUpdateSubresourceAction(apisixconsumersResource, "status", c.ns, apisixConsumer), &v2.ApisixConsumer{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixConsumer), err
+}
+
+// Delete takes name of the apisixConsumer and deletes it. Returns an error if one occurs.
+func (c *FakeApisixConsumers) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	_, err := c.Fake.
+		Invokes(testing.NewDeleteAction(apisixconsumersResource, c.ns, name), &v2.ApisixConsumer{})
+
+	return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeApisixConsumers) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	action := testing.NewDeleteCollectionAction(apisixconsumersResource, c.ns, listOpts)
+
+	_, err := c.Fake.Invokes(action, &v2.ApisixConsumerList{})
+	return err
+}
+
+// Patch applies the patch and returns the patched apisixConsumer.
+func (c *FakeApisixConsumers) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ApisixConsumer, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewPatchSubresourceAction(apisixconsumersResource, c.ns, name, pt, data, subresources...), &v2.ApisixConsumer{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixConsumer), err
+}
diff --git a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_apisixpluginconfig.go b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_apisixpluginconfig.go
new file mode 100644
index 0000000..8c87b0f
--- /dev/null
+++ b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_apisixpluginconfig.go
@@ -0,0 +1,141 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	"context"
+
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	labels "k8s.io/apimachinery/pkg/labels"
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	testing "k8s.io/client-go/testing"
+)
+
+// FakeApisixPluginConfigs implements ApisixPluginConfigInterface
+type FakeApisixPluginConfigs struct {
+	Fake *FakeApisixV2
+	ns   string
+}
+
+var apisixpluginconfigsResource = schema.GroupVersionResource{Group: "apisix.apache.org", Version: "v2", Resource: "apisixpluginconfigs"}
+
+var apisixpluginconfigsKind = schema.GroupVersionKind{Group: "apisix.apache.org", Version: "v2", Kind: "ApisixPluginConfig"}
+
+// Get takes name of the apisixPluginConfig, and returns the corresponding apisixPluginConfig object, and an error if there is any.
+func (c *FakeApisixPluginConfigs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2.ApisixPluginConfig, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewGetAction(apisixpluginconfigsResource, c.ns, name), &v2.ApisixPluginConfig{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixPluginConfig), err
+}
+
+// List takes label and field selectors, and returns the list of ApisixPluginConfigs that match those selectors.
+func (c *FakeApisixPluginConfigs) List(ctx context.Context, opts v1.ListOptions) (result *v2.ApisixPluginConfigList, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewListAction(apisixpluginconfigsResource, apisixpluginconfigsKind, c.ns, opts), &v2.ApisixPluginConfigList{})
+
+	if obj == nil {
+		return nil, err
+	}
+
+	label, _, _ := testing.ExtractFromListOptions(opts)
+	if label == nil {
+		label = labels.Everything()
+	}
+	list := &v2.ApisixPluginConfigList{ListMeta: obj.(*v2.ApisixPluginConfigList).ListMeta}
+	for _, item := range obj.(*v2.ApisixPluginConfigList).Items {
+		if label.Matches(labels.Set(item.Labels)) {
+			list.Items = append(list.Items, item)
+		}
+	}
+	return list, err
+}
+
+// Watch returns a watch.Interface that watches the requested apisixPluginConfigs.
+func (c *FakeApisixPluginConfigs) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	return c.Fake.
+		InvokesWatch(testing.NewWatchAction(apisixpluginconfigsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a apisixPluginConfig and creates it.  Returns the server's representation of the apisixPluginConfig, and an error, if there is any.
+func (c *FakeApisixPluginConfigs) Create(ctx context.Context, apisixPluginConfig *v2.ApisixPluginConfig, opts v1.CreateOptions) (result *v2.ApisixPluginConfig, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewCreateAction(apisixpluginconfigsResource, c.ns, apisixPluginConfig), &v2.ApisixPluginConfig{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixPluginConfig), err
+}
+
+// Update takes the representation of a apisixPluginConfig and updates it. Returns the server's representation of the apisixPluginConfig, and an error, if there is any.
+func (c *FakeApisixPluginConfigs) Update(ctx context.Context, apisixPluginConfig *v2.ApisixPluginConfig, opts v1.UpdateOptions) (result *v2.ApisixPluginConfig, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewUpdateAction(apisixpluginconfigsResource, c.ns, apisixPluginConfig), &v2.ApisixPluginConfig{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixPluginConfig), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeApisixPluginConfigs) UpdateStatus(ctx context.Context, apisixPluginConfig *v2.ApisixPluginConfig, opts v1.UpdateOptions) (*v2.ApisixPluginConfig, error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewUpdateSubresourceAction(apisixpluginconfigsResource, "status", c.ns, apisixPluginConfig), &v2.ApisixPluginConfig{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixPluginConfig), err
+}
+
+// Delete takes name of the apisixPluginConfig and deletes it. Returns an error if one occurs.
+func (c *FakeApisixPluginConfigs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	_, err := c.Fake.
+		Invokes(testing.NewDeleteAction(apisixpluginconfigsResource, c.ns, name), &v2.ApisixPluginConfig{})
+
+	return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeApisixPluginConfigs) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	action := testing.NewDeleteCollectionAction(apisixpluginconfigsResource, c.ns, listOpts)
+
+	_, err := c.Fake.Invokes(action, &v2.ApisixPluginConfigList{})
+	return err
+}
+
+// Patch applies the patch and returns the patched apisixPluginConfig.
+func (c *FakeApisixPluginConfigs) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ApisixPluginConfig, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewPatchSubresourceAction(apisixpluginconfigsResource, c.ns, name, pt, data, subresources...), &v2.ApisixPluginConfig{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixPluginConfig), err
+}
diff --git a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_apisixroute.go b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_apisixroute.go
new file mode 100644
index 0000000..19efe5d
--- /dev/null
+++ b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_apisixroute.go
@@ -0,0 +1,141 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	"context"
+
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	labels "k8s.io/apimachinery/pkg/labels"
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	testing "k8s.io/client-go/testing"
+)
+
+// FakeApisixRoutes implements ApisixRouteInterface
+type FakeApisixRoutes struct {
+	Fake *FakeApisixV2
+	ns   string
+}
+
+var apisixroutesResource = schema.GroupVersionResource{Group: "apisix.apache.org", Version: "v2", Resource: "apisixroutes"}
+
+var apisixroutesKind = schema.GroupVersionKind{Group: "apisix.apache.org", Version: "v2", Kind: "ApisixRoute"}
+
+// Get takes name of the apisixRoute, and returns the corresponding apisixRoute object, and an error if there is any.
+func (c *FakeApisixRoutes) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2.ApisixRoute, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewGetAction(apisixroutesResource, c.ns, name), &v2.ApisixRoute{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixRoute), err
+}
+
+// List takes label and field selectors, and returns the list of ApisixRoutes that match those selectors.
+func (c *FakeApisixRoutes) List(ctx context.Context, opts v1.ListOptions) (result *v2.ApisixRouteList, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewListAction(apisixroutesResource, apisixroutesKind, c.ns, opts), &v2.ApisixRouteList{})
+
+	if obj == nil {
+		return nil, err
+	}
+
+	label, _, _ := testing.ExtractFromListOptions(opts)
+	if label == nil {
+		label = labels.Everything()
+	}
+	list := &v2.ApisixRouteList{ListMeta: obj.(*v2.ApisixRouteList).ListMeta}
+	for _, item := range obj.(*v2.ApisixRouteList).Items {
+		if label.Matches(labels.Set(item.Labels)) {
+			list.Items = append(list.Items, item)
+		}
+	}
+	return list, err
+}
+
+// Watch returns a watch.Interface that watches the requested apisixRoutes.
+func (c *FakeApisixRoutes) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	return c.Fake.
+		InvokesWatch(testing.NewWatchAction(apisixroutesResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a apisixRoute and creates it.  Returns the server's representation of the apisixRoute, and an error, if there is any.
+func (c *FakeApisixRoutes) Create(ctx context.Context, apisixRoute *v2.ApisixRoute, opts v1.CreateOptions) (result *v2.ApisixRoute, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewCreateAction(apisixroutesResource, c.ns, apisixRoute), &v2.ApisixRoute{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixRoute), err
+}
+
+// Update takes the representation of a apisixRoute and updates it. Returns the server's representation of the apisixRoute, and an error, if there is any.
+func (c *FakeApisixRoutes) Update(ctx context.Context, apisixRoute *v2.ApisixRoute, opts v1.UpdateOptions) (result *v2.ApisixRoute, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewUpdateAction(apisixroutesResource, c.ns, apisixRoute), &v2.ApisixRoute{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixRoute), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeApisixRoutes) UpdateStatus(ctx context.Context, apisixRoute *v2.ApisixRoute, opts v1.UpdateOptions) (*v2.ApisixRoute, error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewUpdateSubresourceAction(apisixroutesResource, "status", c.ns, apisixRoute), &v2.ApisixRoute{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixRoute), err
+}
+
+// Delete takes name of the apisixRoute and deletes it. Returns an error if one occurs.
+func (c *FakeApisixRoutes) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	_, err := c.Fake.
+		Invokes(testing.NewDeleteAction(apisixroutesResource, c.ns, name), &v2.ApisixRoute{})
+
+	return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeApisixRoutes) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	action := testing.NewDeleteCollectionAction(apisixroutesResource, c.ns, listOpts)
+
+	_, err := c.Fake.Invokes(action, &v2.ApisixRouteList{})
+	return err
+}
+
+// Patch applies the patch and returns the patched apisixRoute.
+func (c *FakeApisixRoutes) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ApisixRoute, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewPatchSubresourceAction(apisixroutesResource, c.ns, name, pt, data, subresources...), &v2.ApisixRoute{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixRoute), err
+}
diff --git a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_apisixtls.go b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_apisixtls.go
new file mode 100644
index 0000000..76a8545
--- /dev/null
+++ b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_apisixtls.go
@@ -0,0 +1,141 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	"context"
+
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	labels "k8s.io/apimachinery/pkg/labels"
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	testing "k8s.io/client-go/testing"
+)
+
+// FakeApisixTlses implements ApisixTlsInterface
+type FakeApisixTlses struct {
+	Fake *FakeApisixV2
+	ns   string
+}
+
+var apisixtlsesResource = schema.GroupVersionResource{Group: "apisix.apache.org", Version: "v2", Resource: "apisixtlses"}
+
+var apisixtlsesKind = schema.GroupVersionKind{Group: "apisix.apache.org", Version: "v2", Kind: "ApisixTls"}
+
+// Get takes name of the apisixTls, and returns the corresponding apisixTls object, and an error if there is any.
+func (c *FakeApisixTlses) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2.ApisixTls, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewGetAction(apisixtlsesResource, c.ns, name), &v2.ApisixTls{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixTls), err
+}
+
+// List takes label and field selectors, and returns the list of ApisixTlses that match those selectors.
+func (c *FakeApisixTlses) List(ctx context.Context, opts v1.ListOptions) (result *v2.ApisixTlsList, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewListAction(apisixtlsesResource, apisixtlsesKind, c.ns, opts), &v2.ApisixTlsList{})
+
+	if obj == nil {
+		return nil, err
+	}
+
+	label, _, _ := testing.ExtractFromListOptions(opts)
+	if label == nil {
+		label = labels.Everything()
+	}
+	list := &v2.ApisixTlsList{ListMeta: obj.(*v2.ApisixTlsList).ListMeta}
+	for _, item := range obj.(*v2.ApisixTlsList).Items {
+		if label.Matches(labels.Set(item.Labels)) {
+			list.Items = append(list.Items, item)
+		}
+	}
+	return list, err
+}
+
+// Watch returns a watch.Interface that watches the requested apisixTlses.
+func (c *FakeApisixTlses) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	return c.Fake.
+		InvokesWatch(testing.NewWatchAction(apisixtlsesResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a apisixTls and creates it.  Returns the server's representation of the apisixTls, and an error, if there is any.
+func (c *FakeApisixTlses) Create(ctx context.Context, apisixTls *v2.ApisixTls, opts v1.CreateOptions) (result *v2.ApisixTls, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewCreateAction(apisixtlsesResource, c.ns, apisixTls), &v2.ApisixTls{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixTls), err
+}
+
+// Update takes the representation of a apisixTls and updates it. Returns the server's representation of the apisixTls, and an error, if there is any.
+func (c *FakeApisixTlses) Update(ctx context.Context, apisixTls *v2.ApisixTls, opts v1.UpdateOptions) (result *v2.ApisixTls, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewUpdateAction(apisixtlsesResource, c.ns, apisixTls), &v2.ApisixTls{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixTls), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeApisixTlses) UpdateStatus(ctx context.Context, apisixTls *v2.ApisixTls, opts v1.UpdateOptions) (*v2.ApisixTls, error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewUpdateSubresourceAction(apisixtlsesResource, "status", c.ns, apisixTls), &v2.ApisixTls{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixTls), err
+}
+
+// Delete takes name of the apisixTls and deletes it. Returns an error if one occurs.
+func (c *FakeApisixTlses) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	_, err := c.Fake.
+		Invokes(testing.NewDeleteAction(apisixtlsesResource, c.ns, name), &v2.ApisixTls{})
+
+	return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeApisixTlses) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	action := testing.NewDeleteCollectionAction(apisixtlsesResource, c.ns, listOpts)
+
+	_, err := c.Fake.Invokes(action, &v2.ApisixTlsList{})
+	return err
+}
+
+// Patch applies the patch and returns the patched apisixTls.
+func (c *FakeApisixTlses) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ApisixTls, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewPatchSubresourceAction(apisixtlsesResource, c.ns, name, pt, data, subresources...), &v2.ApisixTls{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixTls), err
+}
diff --git a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_apisixupstream.go b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_apisixupstream.go
new file mode 100644
index 0000000..7196f0f
--- /dev/null
+++ b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_apisixupstream.go
@@ -0,0 +1,141 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	"context"
+
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	labels "k8s.io/apimachinery/pkg/labels"
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	testing "k8s.io/client-go/testing"
+)
+
+// FakeApisixUpstreams implements ApisixUpstreamInterface
+type FakeApisixUpstreams struct {
+	Fake *FakeApisixV2
+	ns   string
+}
+
+var apisixupstreamsResource = schema.GroupVersionResource{Group: "apisix.apache.org", Version: "v2", Resource: "apisixupstreams"}
+
+var apisixupstreamsKind = schema.GroupVersionKind{Group: "apisix.apache.org", Version: "v2", Kind: "ApisixUpstream"}
+
+// Get takes name of the apisixUpstream, and returns the corresponding apisixUpstream object, and an error if there is any.
+func (c *FakeApisixUpstreams) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2.ApisixUpstream, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewGetAction(apisixupstreamsResource, c.ns, name), &v2.ApisixUpstream{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixUpstream), err
+}
+
+// List takes label and field selectors, and returns the list of ApisixUpstreams that match those selectors.
+func (c *FakeApisixUpstreams) List(ctx context.Context, opts v1.ListOptions) (result *v2.ApisixUpstreamList, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewListAction(apisixupstreamsResource, apisixupstreamsKind, c.ns, opts), &v2.ApisixUpstreamList{})
+
+	if obj == nil {
+		return nil, err
+	}
+
+	label, _, _ := testing.ExtractFromListOptions(opts)
+	if label == nil {
+		label = labels.Everything()
+	}
+	list := &v2.ApisixUpstreamList{ListMeta: obj.(*v2.ApisixUpstreamList).ListMeta}
+	for _, item := range obj.(*v2.ApisixUpstreamList).Items {
+		if label.Matches(labels.Set(item.Labels)) {
+			list.Items = append(list.Items, item)
+		}
+	}
+	return list, err
+}
+
+// Watch returns a watch.Interface that watches the requested apisixUpstreams.
+func (c *FakeApisixUpstreams) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+	return c.Fake.
+		InvokesWatch(testing.NewWatchAction(apisixupstreamsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a apisixUpstream and creates it.  Returns the server's representation of the apisixUpstream, and an error, if there is any.
+func (c *FakeApisixUpstreams) Create(ctx context.Context, apisixUpstream *v2.ApisixUpstream, opts v1.CreateOptions) (result *v2.ApisixUpstream, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewCreateAction(apisixupstreamsResource, c.ns, apisixUpstream), &v2.ApisixUpstream{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixUpstream), err
+}
+
+// Update takes the representation of a apisixUpstream and updates it. Returns the server's representation of the apisixUpstream, and an error, if there is any.
+func (c *FakeApisixUpstreams) Update(ctx context.Context, apisixUpstream *v2.ApisixUpstream, opts v1.UpdateOptions) (result *v2.ApisixUpstream, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewUpdateAction(apisixupstreamsResource, c.ns, apisixUpstream), &v2.ApisixUpstream{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixUpstream), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeApisixUpstreams) UpdateStatus(ctx context.Context, apisixUpstream *v2.ApisixUpstream, opts v1.UpdateOptions) (*v2.ApisixUpstream, error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewUpdateSubresourceAction(apisixupstreamsResource, "status", c.ns, apisixUpstream), &v2.ApisixUpstream{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixUpstream), err
+}
+
+// Delete takes name of the apisixUpstream and deletes it. Returns an error if one occurs.
+func (c *FakeApisixUpstreams) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+	_, err := c.Fake.
+		Invokes(testing.NewDeleteAction(apisixupstreamsResource, c.ns, name), &v2.ApisixUpstream{})
+
+	return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeApisixUpstreams) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+	action := testing.NewDeleteCollectionAction(apisixupstreamsResource, c.ns, listOpts)
+
+	_, err := c.Fake.Invokes(action, &v2.ApisixUpstreamList{})
+	return err
+}
+
+// Patch applies the patch and returns the patched apisixUpstream.
+func (c *FakeApisixUpstreams) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ApisixUpstream, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewPatchSubresourceAction(apisixupstreamsResource, c.ns, name, pt, data, subresources...), &v2.ApisixUpstream{})
+
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v2.ApisixUpstream), err
+}
diff --git a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_config_client.go b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_config_client.go
new file mode 100644
index 0000000..025feb4
--- /dev/null
+++ b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/fake/fake_config_client.go
@@ -0,0 +1,59 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned/typed/config/v2"
+	rest "k8s.io/client-go/rest"
+	testing "k8s.io/client-go/testing"
+)
+
+type FakeApisixV2 struct {
+	*testing.Fake
+}
+
+func (c *FakeApisixV2) ApisixClusterConfigs() v2.ApisixClusterConfigInterface {
+	return &FakeApisixClusterConfigs{c}
+}
+
+func (c *FakeApisixV2) ApisixConsumers(namespace string) v2.ApisixConsumerInterface {
+	return &FakeApisixConsumers{c, namespace}
+}
+
+func (c *FakeApisixV2) ApisixPluginConfigs(namespace string) v2.ApisixPluginConfigInterface {
+	return &FakeApisixPluginConfigs{c, namespace}
+}
+
+func (c *FakeApisixV2) ApisixRoutes(namespace string) v2.ApisixRouteInterface {
+	return &FakeApisixRoutes{c, namespace}
+}
+
+func (c *FakeApisixV2) ApisixTlses(namespace string) v2.ApisixTlsInterface {
+	return &FakeApisixTlses{c, namespace}
+}
+
+func (c *FakeApisixV2) ApisixUpstreams(namespace string) v2.ApisixUpstreamInterface {
+	return &FakeApisixUpstreams{c, namespace}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeApisixV2) RESTClient() rest.Interface {
+	var ret *rest.RESTClient
+	return ret
+}
diff --git a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/generated_expansion.go b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/generated_expansion.go
new file mode 100644
index 0000000..0955558
--- /dev/null
+++ b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2/generated_expansion.go
@@ -0,0 +1,30 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v2
+
+type ApisixClusterConfigExpansion interface{}
+
+type ApisixConsumerExpansion interface{}
+
+type ApisixPluginConfigExpansion interface{}
+
+type ApisixRouteExpansion interface{}
+
+type ApisixTlsExpansion interface{}
+
+type ApisixUpstreamExpansion interface{}
diff --git a/pkg/kube/apisix/client/informers/externalversions/config/interface.go b/pkg/kube/apisix/client/informers/externalversions/config/interface.go
index d0dde71..01ba0e2 100644
--- a/pkg/kube/apisix/client/informers/externalversions/config/interface.go
+++ b/pkg/kube/apisix/client/informers/externalversions/config/interface.go
@@ -18,6 +18,7 @@
 package config
 
 import (
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/informers/externalversions/config/v2"
 	v2beta2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/informers/externalversions/config/v2beta2"
 	v2beta3 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/informers/externalversions/config/v2beta3"
 	internalinterfaces "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/informers/externalversions/internalinterfaces"
@@ -25,6 +26,8 @@ import (
 
 // Interface provides access to each of this group's versions.
 type Interface interface {
+	// V2 provides access to shared informers for resources in V2.
+	V2() v2.Interface
 	// V2beta3 provides access to shared informers for resources in V2beta3.
 	V2beta3() v2beta3.Interface
 	// V2beta2 provides access to shared informers for resources in V2beta2.
@@ -42,6 +45,11 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
 	return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
 }
 
+// V2 returns a new v2.Interface.
+func (g *group) V2() v2.Interface {
+	return v2.New(g.factory, g.namespace, g.tweakListOptions)
+}
+
 // V2beta3 returns a new v2beta3.Interface.
 func (g *group) V2beta3() v2beta3.Interface {
 	return v2beta3.New(g.factory, g.namespace, g.tweakListOptions)
diff --git a/pkg/kube/apisix/client/informers/externalversions/config/v2/apisixclusterconfig.go b/pkg/kube/apisix/client/informers/externalversions/config/v2/apisixclusterconfig.go
new file mode 100644
index 0000000..2b7056d
--- /dev/null
+++ b/pkg/kube/apisix/client/informers/externalversions/config/v2/apisixclusterconfig.go
@@ -0,0 +1,88 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	"context"
+	time "time"
+
+	configv2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	versioned "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned"
+	internalinterfaces "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/informers/externalversions/internalinterfaces"
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/listers/config/v2"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	watch "k8s.io/apimachinery/pkg/watch"
+	cache "k8s.io/client-go/tools/cache"
+)
+
+// ApisixClusterConfigInformer provides access to a shared informer and lister for
+// ApisixClusterConfigs.
+type ApisixClusterConfigInformer interface {
+	Informer() cache.SharedIndexInformer
+	Lister() v2.ApisixClusterConfigLister
+}
+
+type apisixClusterConfigInformer struct {
+	factory          internalinterfaces.SharedInformerFactory
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+}
+
+// NewApisixClusterConfigInformer constructs a new informer for ApisixClusterConfig type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewApisixClusterConfigInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
+	return NewFilteredApisixClusterConfigInformer(client, resyncPeriod, indexers, nil)
+}
+
+// NewFilteredApisixClusterConfigInformer constructs a new informer for ApisixClusterConfig type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewFilteredApisixClusterConfigInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
+	return cache.NewSharedIndexInformer(
+		&cache.ListWatch{
+			ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.ApisixV2().ApisixClusterConfigs().List(context.TODO(), options)
+			},
+			WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.ApisixV2().ApisixClusterConfigs().Watch(context.TODO(), options)
+			},
+		},
+		&configv2.ApisixClusterConfig{},
+		resyncPeriod,
+		indexers,
+	)
+}
+
+func (f *apisixClusterConfigInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
+	return NewFilteredApisixClusterConfigInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
+}
+
+func (f *apisixClusterConfigInformer) Informer() cache.SharedIndexInformer {
+	return f.factory.InformerFor(&configv2.ApisixClusterConfig{}, f.defaultInformer)
+}
+
+func (f *apisixClusterConfigInformer) Lister() v2.ApisixClusterConfigLister {
+	return v2.NewApisixClusterConfigLister(f.Informer().GetIndexer())
+}
diff --git a/pkg/kube/apisix/client/informers/externalversions/config/v2/apisixconsumer.go b/pkg/kube/apisix/client/informers/externalversions/config/v2/apisixconsumer.go
new file mode 100644
index 0000000..4c5c969
--- /dev/null
+++ b/pkg/kube/apisix/client/informers/externalversions/config/v2/apisixconsumer.go
@@ -0,0 +1,89 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	"context"
+	time "time"
+
+	configv2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	versioned "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned"
+	internalinterfaces "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/informers/externalversions/internalinterfaces"
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/listers/config/v2"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	watch "k8s.io/apimachinery/pkg/watch"
+	cache "k8s.io/client-go/tools/cache"
+)
+
+// ApisixConsumerInformer provides access to a shared informer and lister for
+// ApisixConsumers.
+type ApisixConsumerInformer interface {
+	Informer() cache.SharedIndexInformer
+	Lister() v2.ApisixConsumerLister
+}
+
+type apisixConsumerInformer struct {
+	factory          internalinterfaces.SharedInformerFactory
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+	namespace        string
+}
+
+// NewApisixConsumerInformer constructs a new informer for ApisixConsumer type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewApisixConsumerInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
+	return NewFilteredApisixConsumerInformer(client, namespace, resyncPeriod, indexers, nil)
+}
+
+// NewFilteredApisixConsumerInformer constructs a new informer for ApisixConsumer type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewFilteredApisixConsumerInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
+	return cache.NewSharedIndexInformer(
+		&cache.ListWatch{
+			ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.ApisixV2().ApisixConsumers(namespace).List(context.TODO(), options)
+			},
+			WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.ApisixV2().ApisixConsumers(namespace).Watch(context.TODO(), options)
+			},
+		},
+		&configv2.ApisixConsumer{},
+		resyncPeriod,
+		indexers,
+	)
+}
+
+func (f *apisixConsumerInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
+	return NewFilteredApisixConsumerInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
+}
+
+func (f *apisixConsumerInformer) Informer() cache.SharedIndexInformer {
+	return f.factory.InformerFor(&configv2.ApisixConsumer{}, f.defaultInformer)
+}
+
+func (f *apisixConsumerInformer) Lister() v2.ApisixConsumerLister {
+	return v2.NewApisixConsumerLister(f.Informer().GetIndexer())
+}
diff --git a/pkg/kube/apisix/client/informers/externalversions/config/v2/apisixpluginconfig.go b/pkg/kube/apisix/client/informers/externalversions/config/v2/apisixpluginconfig.go
new file mode 100644
index 0000000..1bd1ce1
--- /dev/null
+++ b/pkg/kube/apisix/client/informers/externalversions/config/v2/apisixpluginconfig.go
@@ -0,0 +1,89 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	"context"
+	time "time"
+
+	configv2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	versioned "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned"
+	internalinterfaces "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/informers/externalversions/internalinterfaces"
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/listers/config/v2"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	watch "k8s.io/apimachinery/pkg/watch"
+	cache "k8s.io/client-go/tools/cache"
+)
+
+// ApisixPluginConfigInformer provides access to a shared informer and lister for
+// ApisixPluginConfigs.
+type ApisixPluginConfigInformer interface {
+	Informer() cache.SharedIndexInformer
+	Lister() v2.ApisixPluginConfigLister
+}
+
+type apisixPluginConfigInformer struct {
+	factory          internalinterfaces.SharedInformerFactory
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+	namespace        string
+}
+
+// NewApisixPluginConfigInformer constructs a new informer for ApisixPluginConfig type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewApisixPluginConfigInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
+	return NewFilteredApisixPluginConfigInformer(client, namespace, resyncPeriod, indexers, nil)
+}
+
+// NewFilteredApisixPluginConfigInformer constructs a new informer for ApisixPluginConfig type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewFilteredApisixPluginConfigInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
+	return cache.NewSharedIndexInformer(
+		&cache.ListWatch{
+			ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.ApisixV2().ApisixPluginConfigs(namespace).List(context.TODO(), options)
+			},
+			WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.ApisixV2().ApisixPluginConfigs(namespace).Watch(context.TODO(), options)
+			},
+		},
+		&configv2.ApisixPluginConfig{},
+		resyncPeriod,
+		indexers,
+	)
+}
+
+func (f *apisixPluginConfigInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
+	return NewFilteredApisixPluginConfigInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
+}
+
+func (f *apisixPluginConfigInformer) Informer() cache.SharedIndexInformer {
+	return f.factory.InformerFor(&configv2.ApisixPluginConfig{}, f.defaultInformer)
+}
+
+func (f *apisixPluginConfigInformer) Lister() v2.ApisixPluginConfigLister {
+	return v2.NewApisixPluginConfigLister(f.Informer().GetIndexer())
+}
diff --git a/pkg/kube/apisix/client/informers/externalversions/config/v2/apisixroute.go b/pkg/kube/apisix/client/informers/externalversions/config/v2/apisixroute.go
new file mode 100644
index 0000000..fedda8e
--- /dev/null
+++ b/pkg/kube/apisix/client/informers/externalversions/config/v2/apisixroute.go
@@ -0,0 +1,89 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	"context"
+	time "time"
+
+	configv2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	versioned "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned"
+	internalinterfaces "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/informers/externalversions/internalinterfaces"
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/listers/config/v2"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	watch "k8s.io/apimachinery/pkg/watch"
+	cache "k8s.io/client-go/tools/cache"
+)
+
+// ApisixRouteInformer provides access to a shared informer and lister for
+// ApisixRoutes.
+type ApisixRouteInformer interface {
+	Informer() cache.SharedIndexInformer
+	Lister() v2.ApisixRouteLister
+}
+
+type apisixRouteInformer struct {
+	factory          internalinterfaces.SharedInformerFactory
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+	namespace        string
+}
+
+// NewApisixRouteInformer constructs a new informer for ApisixRoute type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewApisixRouteInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
+	return NewFilteredApisixRouteInformer(client, namespace, resyncPeriod, indexers, nil)
+}
+
+// NewFilteredApisixRouteInformer constructs a new informer for ApisixRoute type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewFilteredApisixRouteInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
+	return cache.NewSharedIndexInformer(
+		&cache.ListWatch{
+			ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.ApisixV2().ApisixRoutes(namespace).List(context.TODO(), options)
+			},
+			WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.ApisixV2().ApisixRoutes(namespace).Watch(context.TODO(), options)
+			},
+		},
+		&configv2.ApisixRoute{},
+		resyncPeriod,
+		indexers,
+	)
+}
+
+func (f *apisixRouteInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
+	return NewFilteredApisixRouteInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
+}
+
+func (f *apisixRouteInformer) Informer() cache.SharedIndexInformer {
+	return f.factory.InformerFor(&configv2.ApisixRoute{}, f.defaultInformer)
+}
+
+func (f *apisixRouteInformer) Lister() v2.ApisixRouteLister {
+	return v2.NewApisixRouteLister(f.Informer().GetIndexer())
+}
diff --git a/pkg/kube/apisix/client/informers/externalversions/config/v2/apisixtls.go b/pkg/kube/apisix/client/informers/externalversions/config/v2/apisixtls.go
new file mode 100644
index 0000000..ac621ad
--- /dev/null
+++ b/pkg/kube/apisix/client/informers/externalversions/config/v2/apisixtls.go
@@ -0,0 +1,89 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	"context"
+	time "time"
+
+	configv2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	versioned "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned"
+	internalinterfaces "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/informers/externalversions/internalinterfaces"
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/listers/config/v2"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	watch "k8s.io/apimachinery/pkg/watch"
+	cache "k8s.io/client-go/tools/cache"
+)
+
+// ApisixTlsInformer provides access to a shared informer and lister for
+// ApisixTlses.
+type ApisixTlsInformer interface {
+	Informer() cache.SharedIndexInformer
+	Lister() v2.ApisixTlsLister
+}
+
+type apisixTlsInformer struct {
+	factory          internalinterfaces.SharedInformerFactory
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+	namespace        string
+}
+
+// NewApisixTlsInformer constructs a new informer for ApisixTls type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewApisixTlsInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
+	return NewFilteredApisixTlsInformer(client, namespace, resyncPeriod, indexers, nil)
+}
+
+// NewFilteredApisixTlsInformer constructs a new informer for ApisixTls type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewFilteredApisixTlsInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
+	return cache.NewSharedIndexInformer(
+		&cache.ListWatch{
+			ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.ApisixV2().ApisixTlses(namespace).List(context.TODO(), options)
+			},
+			WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.ApisixV2().ApisixTlses(namespace).Watch(context.TODO(), options)
+			},
+		},
+		&configv2.ApisixTls{},
+		resyncPeriod,
+		indexers,
+	)
+}
+
+func (f *apisixTlsInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
+	return NewFilteredApisixTlsInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
+}
+
+func (f *apisixTlsInformer) Informer() cache.SharedIndexInformer {
+	return f.factory.InformerFor(&configv2.ApisixTls{}, f.defaultInformer)
+}
+
+func (f *apisixTlsInformer) Lister() v2.ApisixTlsLister {
+	return v2.NewApisixTlsLister(f.Informer().GetIndexer())
+}
diff --git a/pkg/kube/apisix/client/informers/externalversions/config/v2/apisixupstream.go b/pkg/kube/apisix/client/informers/externalversions/config/v2/apisixupstream.go
new file mode 100644
index 0000000..fd605b2
--- /dev/null
+++ b/pkg/kube/apisix/client/informers/externalversions/config/v2/apisixupstream.go
@@ -0,0 +1,89 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	"context"
+	time "time"
+
+	configv2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	versioned "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned"
+	internalinterfaces "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/informers/externalversions/internalinterfaces"
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/listers/config/v2"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	watch "k8s.io/apimachinery/pkg/watch"
+	cache "k8s.io/client-go/tools/cache"
+)
+
+// ApisixUpstreamInformer provides access to a shared informer and lister for
+// ApisixUpstreams.
+type ApisixUpstreamInformer interface {
+	Informer() cache.SharedIndexInformer
+	Lister() v2.ApisixUpstreamLister
+}
+
+type apisixUpstreamInformer struct {
+	factory          internalinterfaces.SharedInformerFactory
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+	namespace        string
+}
+
+// NewApisixUpstreamInformer constructs a new informer for ApisixUpstream type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewApisixUpstreamInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
+	return NewFilteredApisixUpstreamInformer(client, namespace, resyncPeriod, indexers, nil)
+}
+
+// NewFilteredApisixUpstreamInformer constructs a new informer for ApisixUpstream type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewFilteredApisixUpstreamInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
+	return cache.NewSharedIndexInformer(
+		&cache.ListWatch{
+			ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.ApisixV2().ApisixUpstreams(namespace).List(context.TODO(), options)
+			},
+			WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
+				if tweakListOptions != nil {
+					tweakListOptions(&options)
+				}
+				return client.ApisixV2().ApisixUpstreams(namespace).Watch(context.TODO(), options)
+			},
+		},
+		&configv2.ApisixUpstream{},
+		resyncPeriod,
+		indexers,
+	)
+}
+
+func (f *apisixUpstreamInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
+	return NewFilteredApisixUpstreamInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
+}
+
+func (f *apisixUpstreamInformer) Informer() cache.SharedIndexInformer {
+	return f.factory.InformerFor(&configv2.ApisixUpstream{}, f.defaultInformer)
+}
+
+func (f *apisixUpstreamInformer) Lister() v2.ApisixUpstreamLister {
+	return v2.NewApisixUpstreamLister(f.Informer().GetIndexer())
+}
diff --git a/pkg/kube/apisix/client/informers/externalversions/config/v2/interface.go b/pkg/kube/apisix/client/informers/externalversions/config/v2/interface.go
new file mode 100644
index 0000000..3d6cd93
--- /dev/null
+++ b/pkg/kube/apisix/client/informers/externalversions/config/v2/interface.go
@@ -0,0 +1,79 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	internalinterfaces "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/informers/externalversions/internalinterfaces"
+)
+
+// Interface provides access to all the informers in this group version.
+type Interface interface {
+	// ApisixClusterConfigs returns a ApisixClusterConfigInformer.
+	ApisixClusterConfigs() ApisixClusterConfigInformer
+	// ApisixConsumers returns a ApisixConsumerInformer.
+	ApisixConsumers() ApisixConsumerInformer
+	// ApisixPluginConfigs returns a ApisixPluginConfigInformer.
+	ApisixPluginConfigs() ApisixPluginConfigInformer
+	// ApisixRoutes returns a ApisixRouteInformer.
+	ApisixRoutes() ApisixRouteInformer
+	// ApisixTlses returns a ApisixTlsInformer.
+	ApisixTlses() ApisixTlsInformer
+	// ApisixUpstreams returns a ApisixUpstreamInformer.
+	ApisixUpstreams() ApisixUpstreamInformer
+}
+
+type version struct {
+	factory          internalinterfaces.SharedInformerFactory
+	namespace        string
+	tweakListOptions internalinterfaces.TweakListOptionsFunc
+}
+
+// New returns a new Interface.
+func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
+	return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
+}
+
+// ApisixClusterConfigs returns a ApisixClusterConfigInformer.
+func (v *version) ApisixClusterConfigs() ApisixClusterConfigInformer {
+	return &apisixClusterConfigInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
+}
+
+// ApisixConsumers returns a ApisixConsumerInformer.
+func (v *version) ApisixConsumers() ApisixConsumerInformer {
+	return &apisixConsumerInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
+}
+
+// ApisixPluginConfigs returns a ApisixPluginConfigInformer.
+func (v *version) ApisixPluginConfigs() ApisixPluginConfigInformer {
+	return &apisixPluginConfigInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
+}
+
+// ApisixRoutes returns a ApisixRouteInformer.
+func (v *version) ApisixRoutes() ApisixRouteInformer {
+	return &apisixRouteInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
+}
+
+// ApisixTlses returns a ApisixTlsInformer.
+func (v *version) ApisixTlses() ApisixTlsInformer {
+	return &apisixTlsInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
+}
+
+// ApisixUpstreams returns a ApisixUpstreamInformer.
+func (v *version) ApisixUpstreams() ApisixUpstreamInformer {
+	return &apisixUpstreamInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
+}
diff --git a/pkg/kube/apisix/client/informers/externalversions/generic.go b/pkg/kube/apisix/client/informers/externalversions/generic.go
index 3aeb04c..a86ba23 100644
--- a/pkg/kube/apisix/client/informers/externalversions/generic.go
+++ b/pkg/kube/apisix/client/informers/externalversions/generic.go
@@ -20,6 +20,7 @@ package externalversions
 import (
 	"fmt"
 
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
 	v2beta2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2beta2"
 	v2beta3 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2beta3"
 	schema "k8s.io/apimachinery/pkg/runtime/schema"
@@ -52,7 +53,21 @@ func (f *genericInformer) Lister() cache.GenericLister {
 // TODO extend this to unknown resources with a client pool
 func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
 	switch resource {
-	// Group=apisix.apache.org, Version=v2beta2
+	// Group=apisix.apache.org, Version=v2
+	case v2.SchemeGroupVersion.WithResource("apisixclusterconfigs"):
+		return &genericInformer{resource: resource.GroupResource(), informer: f.Apisix().V2().ApisixClusterConfigs().Informer()}, nil
+	case v2.SchemeGroupVersion.WithResource("apisixconsumers"):
+		return &genericInformer{resource: resource.GroupResource(), informer: f.Apisix().V2().ApisixConsumers().Informer()}, nil
+	case v2.SchemeGroupVersion.WithResource("apisixpluginconfigs"):
+		return &genericInformer{resource: resource.GroupResource(), informer: f.Apisix().V2().ApisixPluginConfigs().Informer()}, nil
+	case v2.SchemeGroupVersion.WithResource("apisixroutes"):
+		return &genericInformer{resource: resource.GroupResource(), informer: f.Apisix().V2().ApisixRoutes().Informer()}, nil
+	case v2.SchemeGroupVersion.WithResource("apisixtlses"):
+		return &genericInformer{resource: resource.GroupResource(), informer: f.Apisix().V2().ApisixTlses().Informer()}, nil
+	case v2.SchemeGroupVersion.WithResource("apisixupstreams"):
+		return &genericInformer{resource: resource.GroupResource(), informer: f.Apisix().V2().ApisixUpstreams().Informer()}, nil
+
+		// Group=apisix.apache.org, Version=v2beta2
 	case v2beta2.SchemeGroupVersion.WithResource("apisixroutes"):
 		return &genericInformer{resource: resource.GroupResource(), informer: f.Apisix().V2beta2().ApisixRoutes().Informer()}, nil
 
diff --git a/pkg/kube/apisix/client/listers/config/v2/apisixclusterconfig.go b/pkg/kube/apisix/client/listers/config/v2/apisixclusterconfig.go
new file mode 100644
index 0000000..ef3720f
--- /dev/null
+++ b/pkg/kube/apisix/client/listers/config/v2/apisixclusterconfig.go
@@ -0,0 +1,67 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	"k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/client-go/tools/cache"
+)
+
+// ApisixClusterConfigLister helps list ApisixClusterConfigs.
+// All objects returned here must be treated as read-only.
+type ApisixClusterConfigLister interface {
+	// List lists all ApisixClusterConfigs in the indexer.
+	// Objects returned here must be treated as read-only.
+	List(selector labels.Selector) (ret []*v2.ApisixClusterConfig, err error)
+	// Get retrieves the ApisixClusterConfig from the index for a given name.
+	// Objects returned here must be treated as read-only.
+	Get(name string) (*v2.ApisixClusterConfig, error)
+	ApisixClusterConfigListerExpansion
+}
+
+// apisixClusterConfigLister implements the ApisixClusterConfigLister interface.
+type apisixClusterConfigLister struct {
+	indexer cache.Indexer
+}
+
+// NewApisixClusterConfigLister returns a new ApisixClusterConfigLister.
+func NewApisixClusterConfigLister(indexer cache.Indexer) ApisixClusterConfigLister {
+	return &apisixClusterConfigLister{indexer: indexer}
+}
+
+// List lists all ApisixClusterConfigs in the indexer.
+func (s *apisixClusterConfigLister) List(selector labels.Selector) (ret []*v2.ApisixClusterConfig, err error) {
+	err = cache.ListAll(s.indexer, selector, func(m interface{}) {
+		ret = append(ret, m.(*v2.ApisixClusterConfig))
+	})
+	return ret, err
+}
+
+// Get retrieves the ApisixClusterConfig from the index for a given name.
+func (s *apisixClusterConfigLister) Get(name string) (*v2.ApisixClusterConfig, error) {
+	obj, exists, err := s.indexer.GetByKey(name)
+	if err != nil {
+		return nil, err
+	}
+	if !exists {
+		return nil, errors.NewNotFound(v2.Resource("apisixclusterconfig"), name)
+	}
+	return obj.(*v2.ApisixClusterConfig), nil
+}
diff --git a/pkg/kube/apisix/client/listers/config/v2/apisixconsumer.go b/pkg/kube/apisix/client/listers/config/v2/apisixconsumer.go
new file mode 100644
index 0000000..264a737
--- /dev/null
+++ b/pkg/kube/apisix/client/listers/config/v2/apisixconsumer.go
@@ -0,0 +1,98 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	"k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/client-go/tools/cache"
+)
+
+// ApisixConsumerLister helps list ApisixConsumers.
+// All objects returned here must be treated as read-only.
+type ApisixConsumerLister interface {
+	// List lists all ApisixConsumers in the indexer.
+	// Objects returned here must be treated as read-only.
+	List(selector labels.Selector) (ret []*v2.ApisixConsumer, err error)
+	// ApisixConsumers returns an object that can list and get ApisixConsumers.
+	ApisixConsumers(namespace string) ApisixConsumerNamespaceLister
+	ApisixConsumerListerExpansion
+}
+
+// apisixConsumerLister implements the ApisixConsumerLister interface.
+type apisixConsumerLister struct {
+	indexer cache.Indexer
+}
+
+// NewApisixConsumerLister returns a new ApisixConsumerLister.
+func NewApisixConsumerLister(indexer cache.Indexer) ApisixConsumerLister {
+	return &apisixConsumerLister{indexer: indexer}
+}
+
+// List lists all ApisixConsumers in the indexer.
+func (s *apisixConsumerLister) List(selector labels.Selector) (ret []*v2.ApisixConsumer, err error) {
+	err = cache.ListAll(s.indexer, selector, func(m interface{}) {
+		ret = append(ret, m.(*v2.ApisixConsumer))
+	})
+	return ret, err
+}
+
+// ApisixConsumers returns an object that can list and get ApisixConsumers.
+func (s *apisixConsumerLister) ApisixConsumers(namespace string) ApisixConsumerNamespaceLister {
+	return apisixConsumerNamespaceLister{indexer: s.indexer, namespace: namespace}
+}
+
+// ApisixConsumerNamespaceLister helps list and get ApisixConsumers.
+// All objects returned here must be treated as read-only.
+type ApisixConsumerNamespaceLister interface {
+	// List lists all ApisixConsumers in the indexer for a given namespace.
+	// Objects returned here must be treated as read-only.
+	List(selector labels.Selector) (ret []*v2.ApisixConsumer, err error)
+	// Get retrieves the ApisixConsumer from the indexer for a given namespace and name.
+	// Objects returned here must be treated as read-only.
+	Get(name string) (*v2.ApisixConsumer, error)
+	ApisixConsumerNamespaceListerExpansion
+}
+
+// apisixConsumerNamespaceLister implements the ApisixConsumerNamespaceLister
+// interface.
+type apisixConsumerNamespaceLister struct {
+	indexer   cache.Indexer
+	namespace string
+}
+
+// List lists all ApisixConsumers in the indexer for a given namespace.
+func (s apisixConsumerNamespaceLister) List(selector labels.Selector) (ret []*v2.ApisixConsumer, err error) {
+	err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
+		ret = append(ret, m.(*v2.ApisixConsumer))
+	})
+	return ret, err
+}
+
+// Get retrieves the ApisixConsumer from the indexer for a given namespace and name.
+func (s apisixConsumerNamespaceLister) Get(name string) (*v2.ApisixConsumer, error) {
+	obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
+	if err != nil {
+		return nil, err
+	}
+	if !exists {
+		return nil, errors.NewNotFound(v2.Resource("apisixconsumer"), name)
+	}
+	return obj.(*v2.ApisixConsumer), nil
+}
diff --git a/pkg/kube/apisix/client/listers/config/v2/apisixpluginconfig.go b/pkg/kube/apisix/client/listers/config/v2/apisixpluginconfig.go
new file mode 100644
index 0000000..1d51151
--- /dev/null
+++ b/pkg/kube/apisix/client/listers/config/v2/apisixpluginconfig.go
@@ -0,0 +1,98 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	"k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/client-go/tools/cache"
+)
+
+// ApisixPluginConfigLister helps list ApisixPluginConfigs.
+// All objects returned here must be treated as read-only.
+type ApisixPluginConfigLister interface {
+	// List lists all ApisixPluginConfigs in the indexer.
+	// Objects returned here must be treated as read-only.
+	List(selector labels.Selector) (ret []*v2.ApisixPluginConfig, err error)
+	// ApisixPluginConfigs returns an object that can list and get ApisixPluginConfigs.
+	ApisixPluginConfigs(namespace string) ApisixPluginConfigNamespaceLister
+	ApisixPluginConfigListerExpansion
+}
+
+// apisixPluginConfigLister implements the ApisixPluginConfigLister interface.
+type apisixPluginConfigLister struct {
+	indexer cache.Indexer
+}
+
+// NewApisixPluginConfigLister returns a new ApisixPluginConfigLister.
+func NewApisixPluginConfigLister(indexer cache.Indexer) ApisixPluginConfigLister {
+	return &apisixPluginConfigLister{indexer: indexer}
+}
+
+// List lists all ApisixPluginConfigs in the indexer.
+func (s *apisixPluginConfigLister) List(selector labels.Selector) (ret []*v2.ApisixPluginConfig, err error) {
+	err = cache.ListAll(s.indexer, selector, func(m interface{}) {
+		ret = append(ret, m.(*v2.ApisixPluginConfig))
+	})
+	return ret, err
+}
+
+// ApisixPluginConfigs returns an object that can list and get ApisixPluginConfigs.
+func (s *apisixPluginConfigLister) ApisixPluginConfigs(namespace string) ApisixPluginConfigNamespaceLister {
+	return apisixPluginConfigNamespaceLister{indexer: s.indexer, namespace: namespace}
+}
+
+// ApisixPluginConfigNamespaceLister helps list and get ApisixPluginConfigs.
+// All objects returned here must be treated as read-only.
+type ApisixPluginConfigNamespaceLister interface {
+	// List lists all ApisixPluginConfigs in the indexer for a given namespace.
+	// Objects returned here must be treated as read-only.
+	List(selector labels.Selector) (ret []*v2.ApisixPluginConfig, err error)
+	// Get retrieves the ApisixPluginConfig from the indexer for a given namespace and name.
+	// Objects returned here must be treated as read-only.
+	Get(name string) (*v2.ApisixPluginConfig, error)
+	ApisixPluginConfigNamespaceListerExpansion
+}
+
+// apisixPluginConfigNamespaceLister implements the ApisixPluginConfigNamespaceLister
+// interface.
+type apisixPluginConfigNamespaceLister struct {
+	indexer   cache.Indexer
+	namespace string
+}
+
+// List lists all ApisixPluginConfigs in the indexer for a given namespace.
+func (s apisixPluginConfigNamespaceLister) List(selector labels.Selector) (ret []*v2.ApisixPluginConfig, err error) {
+	err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
+		ret = append(ret, m.(*v2.ApisixPluginConfig))
+	})
+	return ret, err
+}
+
+// Get retrieves the ApisixPluginConfig from the indexer for a given namespace and name.
+func (s apisixPluginConfigNamespaceLister) Get(name string) (*v2.ApisixPluginConfig, error) {
+	obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
+	if err != nil {
+		return nil, err
+	}
+	if !exists {
+		return nil, errors.NewNotFound(v2.Resource("apisixpluginconfig"), name)
+	}
+	return obj.(*v2.ApisixPluginConfig), nil
+}
diff --git a/pkg/kube/apisix/client/listers/config/v2/apisixroute.go b/pkg/kube/apisix/client/listers/config/v2/apisixroute.go
new file mode 100644
index 0000000..7443102
--- /dev/null
+++ b/pkg/kube/apisix/client/listers/config/v2/apisixroute.go
@@ -0,0 +1,98 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	"k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/client-go/tools/cache"
+)
+
+// ApisixRouteLister helps list ApisixRoutes.
+// All objects returned here must be treated as read-only.
+type ApisixRouteLister interface {
+	// List lists all ApisixRoutes in the indexer.
+	// Objects returned here must be treated as read-only.
+	List(selector labels.Selector) (ret []*v2.ApisixRoute, err error)
+	// ApisixRoutes returns an object that can list and get ApisixRoutes.
+	ApisixRoutes(namespace string) ApisixRouteNamespaceLister
+	ApisixRouteListerExpansion
+}
+
+// apisixRouteLister implements the ApisixRouteLister interface.
+type apisixRouteLister struct {
+	indexer cache.Indexer
+}
+
+// NewApisixRouteLister returns a new ApisixRouteLister.
+func NewApisixRouteLister(indexer cache.Indexer) ApisixRouteLister {
+	return &apisixRouteLister{indexer: indexer}
+}
+
+// List lists all ApisixRoutes in the indexer.
+func (s *apisixRouteLister) List(selector labels.Selector) (ret []*v2.ApisixRoute, err error) {
+	err = cache.ListAll(s.indexer, selector, func(m interface{}) {
+		ret = append(ret, m.(*v2.ApisixRoute))
+	})
+	return ret, err
+}
+
+// ApisixRoutes returns an object that can list and get ApisixRoutes.
+func (s *apisixRouteLister) ApisixRoutes(namespace string) ApisixRouteNamespaceLister {
+	return apisixRouteNamespaceLister{indexer: s.indexer, namespace: namespace}
+}
+
+// ApisixRouteNamespaceLister helps list and get ApisixRoutes.
+// All objects returned here must be treated as read-only.
+type ApisixRouteNamespaceLister interface {
+	// List lists all ApisixRoutes in the indexer for a given namespace.
+	// Objects returned here must be treated as read-only.
+	List(selector labels.Selector) (ret []*v2.ApisixRoute, err error)
+	// Get retrieves the ApisixRoute from the indexer for a given namespace and name.
+	// Objects returned here must be treated as read-only.
+	Get(name string) (*v2.ApisixRoute, error)
+	ApisixRouteNamespaceListerExpansion
+}
+
+// apisixRouteNamespaceLister implements the ApisixRouteNamespaceLister
+// interface.
+type apisixRouteNamespaceLister struct {
+	indexer   cache.Indexer
+	namespace string
+}
+
+// List lists all ApisixRoutes in the indexer for a given namespace.
+func (s apisixRouteNamespaceLister) List(selector labels.Selector) (ret []*v2.ApisixRoute, err error) {
+	err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
+		ret = append(ret, m.(*v2.ApisixRoute))
+	})
+	return ret, err
+}
+
+// Get retrieves the ApisixRoute from the indexer for a given namespace and name.
+func (s apisixRouteNamespaceLister) Get(name string) (*v2.ApisixRoute, error) {
+	obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
+	if err != nil {
+		return nil, err
+	}
+	if !exists {
+		return nil, errors.NewNotFound(v2.Resource("apisixroute"), name)
+	}
+	return obj.(*v2.ApisixRoute), nil
+}
diff --git a/pkg/kube/apisix/client/listers/config/v2/apisixtls.go b/pkg/kube/apisix/client/listers/config/v2/apisixtls.go
new file mode 100644
index 0000000..ad4f4a5
--- /dev/null
+++ b/pkg/kube/apisix/client/listers/config/v2/apisixtls.go
@@ -0,0 +1,98 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	"k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/client-go/tools/cache"
+)
+
+// ApisixTlsLister helps list ApisixTlses.
+// All objects returned here must be treated as read-only.
+type ApisixTlsLister interface {
+	// List lists all ApisixTlses in the indexer.
+	// Objects returned here must be treated as read-only.
+	List(selector labels.Selector) (ret []*v2.ApisixTls, err error)
+	// ApisixTlses returns an object that can list and get ApisixTlses.
+	ApisixTlses(namespace string) ApisixTlsNamespaceLister
+	ApisixTlsListerExpansion
+}
+
+// apisixTlsLister implements the ApisixTlsLister interface.
+type apisixTlsLister struct {
+	indexer cache.Indexer
+}
+
+// NewApisixTlsLister returns a new ApisixTlsLister.
+func NewApisixTlsLister(indexer cache.Indexer) ApisixTlsLister {
+	return &apisixTlsLister{indexer: indexer}
+}
+
+// List lists all ApisixTlses in the indexer.
+func (s *apisixTlsLister) List(selector labels.Selector) (ret []*v2.ApisixTls, err error) {
+	err = cache.ListAll(s.indexer, selector, func(m interface{}) {
+		ret = append(ret, m.(*v2.ApisixTls))
+	})
+	return ret, err
+}
+
+// ApisixTlses returns an object that can list and get ApisixTlses.
+func (s *apisixTlsLister) ApisixTlses(namespace string) ApisixTlsNamespaceLister {
+	return apisixTlsNamespaceLister{indexer: s.indexer, namespace: namespace}
+}
+
+// ApisixTlsNamespaceLister helps list and get ApisixTlses.
+// All objects returned here must be treated as read-only.
+type ApisixTlsNamespaceLister interface {
+	// List lists all ApisixTlses in the indexer for a given namespace.
+	// Objects returned here must be treated as read-only.
+	List(selector labels.Selector) (ret []*v2.ApisixTls, err error)
+	// Get retrieves the ApisixTls from the indexer for a given namespace and name.
+	// Objects returned here must be treated as read-only.
+	Get(name string) (*v2.ApisixTls, error)
+	ApisixTlsNamespaceListerExpansion
+}
+
+// apisixTlsNamespaceLister implements the ApisixTlsNamespaceLister
+// interface.
+type apisixTlsNamespaceLister struct {
+	indexer   cache.Indexer
+	namespace string
+}
+
+// List lists all ApisixTlses in the indexer for a given namespace.
+func (s apisixTlsNamespaceLister) List(selector labels.Selector) (ret []*v2.ApisixTls, err error) {
+	err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
+		ret = append(ret, m.(*v2.ApisixTls))
+	})
+	return ret, err
+}
+
+// Get retrieves the ApisixTls from the indexer for a given namespace and name.
+func (s apisixTlsNamespaceLister) Get(name string) (*v2.ApisixTls, error) {
+	obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
+	if err != nil {
+		return nil, err
+	}
+	if !exists {
+		return nil, errors.NewNotFound(v2.Resource("apisixtls"), name)
+	}
+	return obj.(*v2.ApisixTls), nil
+}
diff --git a/pkg/kube/apisix/client/listers/config/v2/apisixupstream.go b/pkg/kube/apisix/client/listers/config/v2/apisixupstream.go
new file mode 100644
index 0000000..63faa5a
--- /dev/null
+++ b/pkg/kube/apisix/client/listers/config/v2/apisixupstream.go
@@ -0,0 +1,98 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v2
+
+import (
+	v2 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2"
+	"k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/client-go/tools/cache"
+)
+
+// ApisixUpstreamLister helps list ApisixUpstreams.
+// All objects returned here must be treated as read-only.
+type ApisixUpstreamLister interface {
+	// List lists all ApisixUpstreams in the indexer.
+	// Objects returned here must be treated as read-only.
+	List(selector labels.Selector) (ret []*v2.ApisixUpstream, err error)
+	// ApisixUpstreams returns an object that can list and get ApisixUpstreams.
+	ApisixUpstreams(namespace string) ApisixUpstreamNamespaceLister
+	ApisixUpstreamListerExpansion
+}
+
+// apisixUpstreamLister implements the ApisixUpstreamLister interface.
+type apisixUpstreamLister struct {
+	indexer cache.Indexer
+}
+
+// NewApisixUpstreamLister returns a new ApisixUpstreamLister.
+func NewApisixUpstreamLister(indexer cache.Indexer) ApisixUpstreamLister {
+	return &apisixUpstreamLister{indexer: indexer}
+}
+
+// List lists all ApisixUpstreams in the indexer.
+func (s *apisixUpstreamLister) List(selector labels.Selector) (ret []*v2.ApisixUpstream, err error) {
+	err = cache.ListAll(s.indexer, selector, func(m interface{}) {
+		ret = append(ret, m.(*v2.ApisixUpstream))
+	})
+	return ret, err
+}
+
+// ApisixUpstreams returns an object that can list and get ApisixUpstreams.
+func (s *apisixUpstreamLister) ApisixUpstreams(namespace string) ApisixUpstreamNamespaceLister {
+	return apisixUpstreamNamespaceLister{indexer: s.indexer, namespace: namespace}
+}
+
+// ApisixUpstreamNamespaceLister helps list and get ApisixUpstreams.
+// All objects returned here must be treated as read-only.
+type ApisixUpstreamNamespaceLister interface {
+	// List lists all ApisixUpstreams in the indexer for a given namespace.
+	// Objects returned here must be treated as read-only.
+	List(selector labels.Selector) (ret []*v2.ApisixUpstream, err error)
+	// Get retrieves the ApisixUpstream from the indexer for a given namespace and name.
+	// Objects returned here must be treated as read-only.
+	Get(name string) (*v2.ApisixUpstream, error)
+	ApisixUpstreamNamespaceListerExpansion
+}
+
+// apisixUpstreamNamespaceLister implements the ApisixUpstreamNamespaceLister
+// interface.
+type apisixUpstreamNamespaceLister struct {
+	indexer   cache.Indexer
+	namespace string
+}
+
+// List lists all ApisixUpstreams in the indexer for a given namespace.
+func (s apisixUpstreamNamespaceLister) List(selector labels.Selector) (ret []*v2.ApisixUpstream, err error) {
+	err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
+		ret = append(ret, m.(*v2.ApisixUpstream))
+	})
+	return ret, err
+}
+
+// Get retrieves the ApisixUpstream from the indexer for a given namespace and name.
+func (s apisixUpstreamNamespaceLister) Get(name string) (*v2.ApisixUpstream, error) {
+	obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
+	if err != nil {
+		return nil, err
+	}
+	if !exists {
+		return nil, errors.NewNotFound(v2.Resource("apisixupstream"), name)
+	}
+	return obj.(*v2.ApisixUpstream), nil
+}
diff --git a/pkg/kube/apisix/client/listers/config/v2/expansion_generated.go b/pkg/kube/apisix/client/listers/config/v2/expansion_generated.go
new file mode 100644
index 0000000..2bbd0fd
--- /dev/null
+++ b/pkg/kube/apisix/client/listers/config/v2/expansion_generated.go
@@ -0,0 +1,62 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v2
+
+// ApisixClusterConfigListerExpansion allows custom methods to be added to
+// ApisixClusterConfigLister.
+type ApisixClusterConfigListerExpansion interface{}
+
+// ApisixConsumerListerExpansion allows custom methods to be added to
+// ApisixConsumerLister.
+type ApisixConsumerListerExpansion interface{}
+
+// ApisixConsumerNamespaceListerExpansion allows custom methods to be added to
+// ApisixConsumerNamespaceLister.
+type ApisixConsumerNamespaceListerExpansion interface{}
+
+// ApisixPluginConfigListerExpansion allows custom methods to be added to
+// ApisixPluginConfigLister.
+type ApisixPluginConfigListerExpansion interface{}
+
+// ApisixPluginConfigNamespaceListerExpansion allows custom methods to be added to
+// ApisixPluginConfigNamespaceLister.
+type ApisixPluginConfigNamespaceListerExpansion interface{}
+
+// ApisixRouteListerExpansion allows custom methods to be added to
+// ApisixRouteLister.
+type ApisixRouteListerExpansion interface{}
+
+// ApisixRouteNamespaceListerExpansion allows custom methods to be added to
+// ApisixRouteNamespaceLister.
+type ApisixRouteNamespaceListerExpansion interface{}
+
+// ApisixTlsListerExpansion allows custom methods to be added to
+// ApisixTlsLister.
+type ApisixTlsListerExpansion interface{}
+
+// ApisixTlsNamespaceListerExpansion allows custom methods to be added to
+// ApisixTlsNamespaceLister.
+type ApisixTlsNamespaceListerExpansion interface{}
+
+// ApisixUpstreamListerExpansion allows custom methods to be added to
+// ApisixUpstreamLister.
+type ApisixUpstreamListerExpansion interface{}
+
+// ApisixUpstreamNamespaceListerExpansion allows custom methods to be added to
+// ApisixUpstreamNamespaceLister.
+type ApisixUpstreamNamespaceListerExpansion interface{}
diff --git a/utils/update-codegen.sh b/utils/update-codegen.sh
index 606acb2..df94dc8 100755
--- a/utils/update-codegen.sh
+++ b/utils/update-codegen.sh
@@ -31,7 +31,7 @@ rm -rf "$GENERATED_ROOT"
 
 bash "${SCRIPT_ROOT}"/generate-groups.sh "deepcopy,client,informer,lister" \
   ${PKG_NAME}/pkg/kube/apisix/client ${PKG_NAME}/pkg/kube/apisix/apis \
-  config:v2beta3,v2beta2 ${PKG_NAME} \
+  config:v2,v2beta3,v2beta2 ${PKG_NAME} \
   --output-base "$GENERATED_ROOT" \
   --go-header-file "${SCRIPT_ROOT}"/boilerplate.go.txt \
   "$@"
@@ -45,7 +45,7 @@ bash "${SCRIPT_ROOT}"/generate-groups.sh "deepcopy" \
 
 bash "${SCRIPT_ROOT}"/generate-groups.sh "register" \
   ${PKG_NAME}/pkg/kube/apisix/apis ${PKG_NAME}/pkg/kube/apisix/apis \
-  config:v2beta3,v2beta2,v1 ${PKG_NAME} \
+  config:v2,v2beta3,v2beta2,v1 ${PKG_NAME} \
   --output-base "$GENERATED_ROOT" \
   --go-header-file "${SCRIPT_ROOT}"/boilerplate.go.txt \
   "$@"
diff --git a/utils/verify-codegen.sh b/utils/verify-codegen.sh
index 9d5cdab..dcc67ec 100755
--- a/utils/verify-codegen.sh
+++ b/utils/verify-codegen.sh
@@ -50,7 +50,7 @@ ret=0
 
 bash "${SCRIPT_ROOT}"/generate-groups.sh "deepcopy,client,informer,lister" \
   ${PKG_NAME}/pkg/kube/apisix/client ${PKG_NAME}/pkg/kube/apisix/apis \
-  config:v2beta3,v2beta2 ${PKG_NAME} \
+  config:v2,v2beta3,v2beta2 ${PKG_NAME} \
   --output-base "$GENERATED_ROOT" \
   --go-header-file "${SCRIPT_ROOT}"/boilerplate.go.txt \
   --verify-only || ret=$?
@@ -68,7 +68,7 @@ fi
 if [[ $ret -eq 0 ]]; then
 bash "${SCRIPT_ROOT}"/generate-groups.sh "register" \
   ${PKG_NAME}/pkg/kube/apisix/apis ${PKG_NAME}/pkg/kube/apisix/apis \
-  config:v2beta3,v2beta2,v1 ${PKG_NAME} \
+  config:v2,v2beta3,v2beta2,v1 ${PKG_NAME} \
   --output-base "$GENERATED_ROOT" \
   --go-header-file "${SCRIPT_ROOT}"/boilerplate.go.txt \
   --verify-only|| ret=$?