add feature: java agent injector (#30)

* add feature-injector

* add license

* fix naming errors

* add configmap
* add a default configmap to save the default agent config
* when create operator, the configmap will be created

* add default annotation and validate func
* add some annotation override template
* add sidecar fields' default value
* add some func to validate the agent config annotation

* sidecar inject
* users can choose different injection strategies through annotations
* sidecar coverage is enabled by default, and agent coverage is the user's choice
* agent.config will be overwritten by configmap
* failure to inject will return an error annotation

* add func test

* update label

* fix lint error

* fix bug, refactor code and add feature
* fix naming and version.
* fix the bug about inject container.
* use annotations.yaml to generate configmap and overlay the value of sidecar and agent
* create a controller to watch the default configmap
* add function to validate configmap's key and value

* fix bug

* remove validate function and add optional plugins
* remove most of the validate function and retain the functions that validate service_name and backend_service.
* add overridable annotations to use optioncal plugins.

* add optional-reporter

Co-authored-by: 吴晟 Wu Sheng <wu.sheng@foxmail.com>
diff --git a/Makefile b/Makefile
index 27f6156..c0f0ecb 100644
--- a/Makefile
+++ b/Makefile
@@ -98,7 +98,7 @@
 
 # Generate code
 generate: controller-gen
-	$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./apis/..."
+	#$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./apis/..."
 	$(MAKE) format
 
 GO_LICENSER := $(GOBIN)/go-licenser
diff --git a/apis/operator/v1alpha1/javaagent_webhook.go b/apis/operator/v1alpha1/javaagent_webhook.go
new file mode 100644
index 0000000..35ef715
--- /dev/null
+++ b/apis/operator/v1alpha1/javaagent_webhook.go
@@ -0,0 +1,80 @@
+// Licensed to 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. Apache Software Foundation (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 v1alpha1
+
+import (
+	"context"
+	"net/http"
+
+	corev1 "k8s.io/api/core/v1"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+	logf "sigs.k8s.io/controller-runtime/pkg/log"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
+
+	"github.com/apache/skywalking-swck/pkg/operator/injector"
+)
+
+// log is for logging in this package.
+var javaagentlog = logf.Log.WithName("javaagent")
+
+// nolint: lll
+// +kubebuilder:webhook:path=/mutate-v1-pod,mutating=true,failurePolicy=fail,groups="",resources=pods,verbs=create;update,versions=v1,name=mpod.kb.io
+
+// Javaagent injects java agent into Pods
+type Javaagent struct {
+	Client  client.Client
+	decoder *admission.Decoder
+}
+
+// Handle will process every coming pod under the
+// specified namespace which labeled "swck-injection=enabled"
+func (r *Javaagent) Handle(ctx context.Context, req admission.Request) admission.Response {
+	pod := &corev1.Pod{}
+
+	err := r.decoder.Decode(req, pod)
+	if err != nil {
+		return admission.Errored(http.StatusBadRequest, err)
+	}
+
+	// set Annotations to avoid repeated judgments
+	if pod.Annotations == nil {
+		pod.Annotations = map[string]string{}
+	}
+	// initialize all annotation types that can be overridden
+	anno, err := injector.NewAnnotations()
+	if err != nil {
+		javaagentlog.Error(err, "get NewAnnotations error")
+	}
+	// initialize Annotations to store the overlaied value
+	ao := injector.NewAnnotationOverlay()
+	// initialize SidecarInjectField and get injected strategy from annotations
+	s := injector.NewSidecarInjectField()
+	// initialize InjectProcess as a call chain
+	ip := injector.NewInjectProcess(ctx, s, anno, ao, pod, req, javaagentlog, r.Client)
+	// do real injection
+	return ip.Run()
+}
+
+// Javaagent implements admission.DecoderInjector.
+// A decoder will be automatically injected.
+
+// InjectDecoder injects the decoder.
+func (r *Javaagent) InjectDecoder(d *admission.Decoder) error {
+	r.decoder = d
+	return nil
+}
diff --git a/apis/operator/v1alpha1/zz_generated.deepcopy.go b/apis/operator/v1alpha1/zz_generated.deepcopy.go
index 32409ca..27953b1 100644
--- a/apis/operator/v1alpha1/zz_generated.deepcopy.go
+++ b/apis/operator/v1alpha1/zz_generated.deepcopy.go
@@ -181,6 +181,21 @@
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Javaagent) DeepCopyInto(out *Javaagent) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Javaagent.
+func (in *Javaagent) DeepCopy() *Javaagent {
+	if in == nil {
+		return nil
+	}
+	out := new(Javaagent)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *OAPServer) DeepCopyInto(out *OAPServer) {
 	*out = *in
 	out.TypeMeta = in.TypeMeta
diff --git a/cmd/manager/manager.go b/cmd/manager/manager.go
index f85fd82..5446df3 100644
--- a/cmd/manager/manager.go
+++ b/cmd/manager/manager.go
@@ -23,9 +23,9 @@
 
 	"k8s.io/apimachinery/pkg/runtime"
 	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
-	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/log/zap"
+	"sigs.k8s.io/controller-runtime/pkg/webhook"
 
 	operatorv1alpha1 "github.com/apache/skywalking-swck/apis/operator/v1alpha1"
 	operatorcontroller "github.com/apache/skywalking-swck/controllers/operator"
@@ -103,6 +103,16 @@
 		setupLog.Error(err, "unable to create controller", "controller", "Fetcher")
 		os.Exit(1)
 	}
+
+	if err = (&operatorcontroller.ConfigMapReconciler{
+		Client:   mgr.GetClient(),
+		Log:      ctrl.Log.WithName("controllers").WithName("ConfigMap"),
+		Scheme:   mgr.GetScheme(),
+		FileRepo: repo.NewRepo("injector"),
+	}).SetupWithManager(mgr); err != nil {
+		setupLog.Error(err, "unable to create controller", "controller", "ConfigMap")
+		os.Exit(1)
+	}
 	if os.Getenv("ENABLE_WEBHOOKS") != "false" {
 		if err = (&operatorv1alpha1.OAPServer{}).SetupWebhookWithManager(mgr); err != nil {
 			setupLog.Error(err, "unable to create webhook", "webhook", "OAPServer")
@@ -116,6 +126,12 @@
 			setupLog.Error(err, "unable to create webhook", "webhook", "Fetcher")
 			os.Exit(1)
 		}
+		// register a webhook to enable the agent injector,
+		setupLog.Info("registering /mutate-v1-pod webhook")
+		mgr.GetWebhookServer().Register("/mutate-v1-pod",
+			&webhook.Admission{
+				Handler: &operatorv1alpha1.Javaagent{Client: mgr.GetClient()}})
+		setupLog.Info("/mutate-v1-pod webhook is registered")
 	}
 	// +kubebuilder:scaffold:builder
 
diff --git a/config/operator/configmap/configmap.yaml b/config/operator/configmap/configmap.yaml
new file mode 100644
index 0000000..58c9d81
--- /dev/null
+++ b/config/operator/configmap/configmap.yaml
@@ -0,0 +1,282 @@
+# Licensed to 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. Apache Software Foundation (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.
+
+
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: java-agent-configmap  #the name will add a namePrefix "skywalking-swck-" finally
+  namespace: skywalking-swck-system
+data:
+  agent.config: |
+    # 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.
+
+    # The agent namespace
+    agent.namespace=${SW_AGENT_NAMESPACE:}
+
+    # The service name in UI
+    agent.service_name=${SW_AGENT_NAME:Your_ApplicationName}
+
+    # Instance name is the identity of an instance, should be unique in the service. If empty, SkyWalking agent will
+    # generate an 32-bit uuid. BY Default, SkyWalking uses UUID@hostname as the instance name. Max length is 50(UTF-8 char)
+    agent.instance_name=${SW_AGENT_INSTANCE_NAME:}
+
+    # The number of sampled traces per 3 seconds
+    # Negative or zero means off, by default
+    agent.sample_n_per_3_secs=${SW_AGENT_SAMPLE:-1}
+
+    # Authentication active is based on backend setting, see application.yml for more details.
+    agent.authentication=${SW_AGENT_AUTHENTICATION:}
+
+    # The max amount of spans in a single segment.
+    # Through this config item, SkyWalking keep your application memory cost estimated.
+    agent.span_limit_per_segment=${SW_AGENT_SPAN_LIMIT:300}
+
+    # If the operation name of the first span is included in this set, this segment should be ignored. Multiple values should be separated by `,`.
+    agent.ignore_suffix=${SW_AGENT_IGNORE_SUFFIX:.jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg}
+
+    # If true, SkyWalking agent will save all instrumented classes files in `/debugging` folder.
+    # SkyWalking team may ask for these files in order to resolve compatible problem.
+    agent.is_open_debugging_class=${SW_AGENT_OPEN_DEBUG:false}
+
+    # If true, SkyWalking agent will cache all instrumented classes files to memory or disk files (decided by class cache mode),
+    # allow other javaagent to enhance those classes that enhanced by SkyWalking agent.
+    agent.is_cache_enhanced_class=${SW_AGENT_CACHE_CLASS:false}
+
+    # The instrumented classes cache mode: MEMORY or FILE
+    # MEMORY: cache class bytes to memory, if instrumented classes is too many or too large, it may take up more memory
+    # FILE: cache class bytes in `/class-cache` folder, automatically clean up cached class files when the application exits
+    agent.class_cache_mode=${SW_AGENT_CLASS_CACHE_MODE:MEMORY}
+
+    # How depth the agent goes, when log all cause exceptions.
+    agent.cause_exception_depth=${SW_AGENT_CAUSE_EXCEPTION_DEPTH:5}
+
+    # Force reconnection period of grpc, based on grpc_channel_check_interval.
+    agent.force_reconnection_period=${SW_AGENT_FORCE_RECONNECTION_PERIOD:1}
+
+    # The operationName max length
+    # Notice, in the current practice, we don't recommend the length over 190.
+    agent.operation_name_threshold=${SW_AGENT_OPERATION_NAME_THRESHOLD:150}
+
+    # Keep tracing even the backend is not available if this value is true.
+    agent.keep_tracing=${SW_AGENT_KEEP_TRACING:false}
+
+    # The agent use gRPC plain text in default.
+    # If true, SkyWalking agent uses TLS even no CA file detected.
+    agent.force_tls=${SW_AGENT_FORCE_TLS:false}
+
+    # Limit the length of the ipv4 list size.
+    osinfo.ipv4_list_size=${SW_AGENT_OSINFO_IPV4_LIST_SIZE:10}
+
+    # grpc channel status check interval.
+    collector.grpc_channel_check_interval=${SW_AGENT_COLLECTOR_GRPC_CHANNEL_CHECK_INTERVAL:30}
+    # Agent heartbeat report period. Unit, second.
+    collector.heartbeat_period=${SW_AGENT_COLLECTOR_HEARTBEAT_PERIOD:30}
+    # The agent sends the instance properties to the backend every
+    # collector.heartbeat_period * collector.properties_report_period_factor seconds
+    collector.properties_report_period_factor=${SW_AGENT_COLLECTOR_PROPERTIES_REPORT_PERIOD_FACTOR:10}
+    # Backend service addresses.
+    collector.backend_service=${SW_AGENT_COLLECTOR_BACKEND_SERVICES:127.0.0.1:11800}
+    # How long grpc client will timeout in sending data to upstream. Unit is second.
+    collector.grpc_upstream_timeout=${SW_AGENT_COLLECTOR_GRPC_UPSTREAM_TIMEOUT:30}
+    # Sniffer get profile task list interval.
+    collector.get_profile_task_interval=${SW_AGENT_COLLECTOR_GET_PROFILE_TASK_INTERVAL:20}
+    # Sniffer get agent dynamic config interval.
+    collector.get_agent_dynamic_config_interval=${SW_AGENT_COLLECTOR_GET_AGENT_DYNAMIC_CONFIG_INTERVAL:20}
+    # If true, skywalking agent will enable periodically resolving DNS to update receiver service addresses.
+    collector.is_resolve_dns_periodically=${SW_AGENT_COLLECTOR_IS_RESOLVE_DNS_PERIODICALLY:false}
+
+    # Logging level
+    logging.level=${SW_LOGGING_LEVEL:INFO}
+    # Logging file_name
+    logging.file_name=${SW_LOGGING_FILE_NAME:skywalking-api.log}
+    # Log output. Default is FILE. Use CONSOLE means output to stdout.
+    logging.output=${SW_LOGGING_OUTPUT:FILE}
+    # Log files directory. Default is blank string, meaning use "{theSkywalkingAgentJarDir}/logs " to output logs.
+    # {theSkywalkingAgentJarDir} is the directory where the skywalking agent jar file is located
+    logging.dir=${SW_LOGGING_DIR:}
+    # Logger resolver: PATTERN or JSON. The default is PATTERN, which uses logging.pattern to print traditional text logs.
+    # JSON resolver prints logs in JSON format.
+    logging.resolver=${SW_LOGGING_RESOLVER:PATTERN}
+    # Logging format. There are all conversion specifiers:
+    #  * %level means log level.
+    #  * %timestamp means now of time with format yyyy-MM-dd HH:mm:ss:SSS.
+    #  * %thread means name of current thread.
+    #  * %msg means some message which user logged.
+    #  * %class means SimpleName of TargetClass.
+    #  * %throwable means a throwable which user called.
+    #  * %agent_name means agent.service_name. Only apply to the PatternLogger.
+    logging.pattern=${SW_LOGGING_PATTERN:%level %timestamp %thread %class : %msg %throwable}
+    # Logging max_file_size, default: 300 * 1024 * 1024 = 314572800
+    logging.max_file_size=${SW_LOGGING_MAX_FILE_SIZE:314572800}
+    # The max history log files. When rollover happened, if log files exceed this number,
+    # then the oldest file will be delete. Negative or zero means off, by default.
+    logging.max_history_files=${SW_LOGGING_MAX_HISTORY_FILES:-1}
+
+    # Listed exceptions would not be treated as an error. Because in some codes, the exception is being used as a way of controlling business flow.
+    # Besides, the annotation named IgnoredException in the trace toolkit is another way to configure ignored exceptions.
+    statuscheck.ignored_exceptions=${SW_STATUSCHECK_IGNORED_EXCEPTIONS:}
+    # The max recursive depth when checking the exception traced by the agent. Typically, we don't recommend setting this more than 10, which could cause a performance issue. Negative value and 0 would be ignored, which means all exceptions would make the span tagged in error status.
+    statuscheck.max_recursive_depth=${SW_STATUSCHECK_MAX_RECURSIVE_DEPTH:1}
+
+    # Max element count in the correlation context
+    correlation.element_max_number=${SW_CORRELATION_ELEMENT_MAX_NUMBER:3}
+
+    # Max value length of each element.
+    correlation.value_max_length=${SW_CORRELATION_VALUE_MAX_LENGTH:128}
+    # Tag the span by the key/value in the correlation context, when the keys listed here exist.
+    correlation.auto_tag_keys=${SW_CORRELATION_AUTO_TAG_KEYS:}
+    # The buffer size of collected JVM info.
+    jvm.buffer_size=${SW_JVM_BUFFER_SIZE:600}
+    # The buffer channel size.
+    buffer.channel_size=${SW_BUFFER_CHANNEL_SIZE:5}
+    # The buffer size.
+    buffer.buffer_size=${SW_BUFFER_BUFFER_SIZE:300}
+    # If true, skywalking agent will enable profile when user create a new profile task. Otherwise disable profile.
+    profile.active=${SW_AGENT_PROFILE_ACTIVE:true}
+    # Parallel monitor segment count
+    profile.max_parallel=${SW_AGENT_PROFILE_MAX_PARALLEL:5}
+    # Max monitor segment time(minutes), if current segment monitor time out of limit, then stop it.
+    profile.duration=${SW_AGENT_PROFILE_DURATION:10}
+    # Max dump thread stack depth
+    profile.dump_max_stack_depth=${SW_AGENT_PROFILE_DUMP_MAX_STACK_DEPTH:500}
+    # Snapshot transport to backend buffer size
+    profile.snapshot_transport_buffer_size=${SW_AGENT_PROFILE_SNAPSHOT_TRANSPORT_BUFFER_SIZE:50}
+    # If true, the agent collects and reports metrics to the backend.
+    meter.active=${SW_METER_ACTIVE:true}
+    # Report meters interval. The unit is second
+    meter.report_interval=${SW_METER_REPORT_INTERVAL:20}
+    #  Max size of the meter pool 
+    meter.max_meter_size=${SW_METER_MAX_METER_SIZE:500}
+    #  Mount the specific folders of the plugins. Plugins in mounted folders would work.
+
+    plugin.mount=${SW_MOUNT_FOLDERS:plugins,activations}
+    # Peer maximum description limit.
+    plugin.peer_max_length=${SW_PLUGIN_PEER_MAX_LENGTH:200}
+    # Exclude some plugins define in plugins dir.Plugin names is defined in [Agent plugin list](Plugin-list.md)
+    plugin.exclude_plugins=${SW_EXCLUDE_PLUGINS:}
+    # If true, trace all the parameters in MongoDB access, default is false. Only trace the operation, not include parameters.
+    plugin.mongodb.trace_param=${SW_PLUGIN_MONGODB_TRACE_PARAM:false}
+    # If set to positive number, the `WriteRequest.params` would be truncated to this length, otherwise it would be completely saved, which may cause performance problem.
+    plugin.mongodb.filter_length_limit=${SW_PLUGIN_MONGODB_FILTER_LENGTH_LIMIT:256}
+    # If true, trace all the DSL(Domain Specific Language) in ElasticSearch access, default is false.
+    plugin.elasticsearch.trace_dsl=${SW_PLUGIN_ELASTICSEARCH_TRACE_DSL:false}
+    # If true, the fully qualified method name will be used as the endpoint name instead of the request URL, default is false.
+    plugin.springmvc.use_qualified_name_as_endpoint_name=${SW_PLUGIN_SPRINGMVC_USE_QUALIFIED_NAME_AS_ENDPOINT_NAME:false}
+    # If true, the fully qualified method name will be used as the operation name instead of the given operation name, default is false.
+    plugin.toolit.use_qualified_name_as_operation_name=${SW_PLUGIN_TOOLIT_USE_QUALIFIED_NAME_AS_OPERATION_NAME:false}
+    # If set to true, the parameters of the sql (typically `java.sql.PreparedStatement`) would be collected.
+    plugin.jdbc.trace_sql_parameters=${SW_JDBC_TRACE_SQL_PARAMETERS:false}
+    # If set to positive number, the `db.sql.parameters` would be truncated to this length, otherwise it would be completely saved, which may cause performance problem.
+    plugin.jdbc.sql_parameters_max_length=${SW_PLUGIN_JDBC_SQL_PARAMETERS_MAX_LENGTH:512}
+    # If set to positive number, the `db.statement` would be truncated to this length, otherwise it would be completely saved, which may cause performance problem.
+    plugin.jdbc.sql_body_max_length=${SW_PLUGIN_JDBC_SQL_BODY_MAX_LENGTH:2048}
+    # If true, trace all the query parameters(include deleteByIds and deleteByQuery) in Solr query request, default is false.
+    plugin.solrj.trace_statement=${SW_PLUGIN_SOLRJ_TRACE_STATEMENT:false}
+    # If true, trace all the operation parameters in Solr request, default is false.
+    plugin.solrj.trace_ops_params=${SW_PLUGIN_SOLRJ_TRACE_OPS_PARAMS:false}
+    # If true, trace all middleware/business handlers that are part of the Light4J handler chain for a request.
+    plugin.light4j.trace_handler_chain=${SW_PLUGIN_LIGHT4J_TRACE_HANDLER_CHAIN:false}
+    # If true, the transaction definition name will be simplified.
+    plugin.springtransaction.simplify_transaction_definition_name=${SW_PLUGIN_SPRINGTRANSACTION_SIMPLIFY_TRANSACTION_DEFINITION_NAME:false}
+    #  Threading classes (`java.lang.Runnable` and `java.util.concurrent.Callable`) and their subclasses, including anonymous inner classes whose name match any one of the `THREADING_CLASS_PREFIXES` (splitted by `,`) will be instrumented, make sure to only specify as narrow prefixes as what you're expecting to instrument, (`java.` and `javax.` will be ignored due to safety issues)
+    plugin.jdkthreading.threading_class_prefixes=${SW_PLUGIN_JDKTHREADING_THREADING_CLASS_PREFIXES:}
+    #  This config item controls that whether the Tomcat plugin should collect the parameters of the request. Also, activate implicitly in the profiled trace. 
+    plugin.tomcat.collect_http_params=${SW_PLUGIN_TOMCAT_COLLECT_HTTP_PARAMS:false}
+    #  This config item controls that whether the SpringMVC plugin should collect the parameters of the request, when your Spring application is based on Tomcat, consider only setting either `plugin.tomcat.collect_http_params` or `plugin.springmvc.collect_http_params`. Also, activate implicitly in the profiled trace. 
+    plugin.springmvc.collect_http_params=${SW_PLUGIN_SPRINGMVC_COLLECT_HTTP_PARAMS:false}
+    #  This config item controls that whether the HttpClient plugin should collect the parameters of the request 
+    plugin.httpclient.collect_http_params=${SW_PLUGIN_HTTPCLIENT_COLLECT_HTTP_PARAMS:false}
+    #  When `COLLECT_HTTP_PARAMS` is enabled, how many characters to keep and send to the OAP backend, use negative values to keep and send the complete parameters, NB. this config item is added for the sake of performance.  
+    plugin.http.http_params_length_threshold=${SW_PLUGIN_HTTP_HTTP_PARAMS_LENGTH_THRESHOLD:1024}
+    #  When `include_http_headers` declares header names, this threshold controls the length limitation of all header values. use negative values to keep and send the complete headers. Note. this config item is added for the sake of performance. 
+    plugin.http.http_headers_length_threshold=${SW_PLUGIN_HTTP_HTTP_HEADERS_LENGTH_THRESHOLD:2048}
+    #  Set the header names, which should be collected by the plugin. Header name must follow `javax.servlet.http` definition. Multiple names should be split by comma.
+    plugin.http.include_http_headers=${SW_PLUGIN_HTTP_INCLUDE_HTTP_HEADERS:}
+    #  This config item controls that whether the Feign plugin should collect the http body of the request. 
+    plugin.feign.collect_request_body=${SW_PLUGIN_FEIGN_COLLECT_REQUEST_BODY:false}
+    #  When `COLLECT_REQUEST_BODY` is enabled, how many characters to keep and send to the OAP backend, use negative values to keep and send the complete body.  
+    plugin.feign.filter_length_limit=${SW_PLUGIN_FEIGN_FILTER_LENGTH_LIMIT:1024}
+    #  When `COLLECT_REQUEST_BODY` is enabled and content-type start with SUPPORTED_CONTENT_TYPES_PREFIX, collect the body of the request , multiple paths should be separated by `,`  
+    plugin.feign.supported_content_types_prefix=${SW_PLUGIN_FEIGN_SUPPORTED_CONTENT_TYPES_PREFIX:application/json,text/}
+    # If true, trace all the influxql(query and write) in InfluxDB access, default is true.
+    plugin.influxdb.trace_influxql=${SW_PLUGIN_INFLUXDB_TRACE_INFLUXQL:true}
+    #  Apache Dubbo consumer collect `arguments` in RPC call, use `Object#toString` to collect `arguments`. 
+    plugin.dubbo.collect_consumer_arguments=${SW_PLUGIN_DUBBO_COLLECT_CONSUMER_ARGUMENTS:false}
+    #  When `plugin.dubbo.collect_consumer_arguments` is `true`, Arguments of length from the front will to the OAP backend 
+    plugin.dubbo.consumer_arguments_length_threshold=${SW_PLUGIN_DUBBO_CONSUMER_ARGUMENTS_LENGTH_THRESHOLD:256}
+    #  Apache Dubbo provider collect `arguments` in RPC call, use `Object#toString` to collect `arguments`. 
+    plugin.dubbo.collect_provider_arguments=${SW_PLUGIN_DUBBO_COLLECT_PROVIDER_ARGUMENTS:false}
+    #  When `plugin.dubbo.provider_consumer_arguments` is `true`, Arguments of length from the front will to the OAP backend 
+    plugin.dubbo.consumer_provider_length_threshold=${SW_PLUGIN_DUBBO_CONSUMER_PROVIDER_LENGTH_THRESHOLD:256}
+    #  A list of host/port pairs to use for establishing the initial connection to the Kafka cluster. 
+    plugin.kafka.bootstrap_servers=${SW_KAFKA_BOOTSTRAP_SERVERS:localhost:9092}
+    #  Timeout period of reading topics from the Kafka server, the unit is second. 
+    plugin.kafka.get_topic_timeout=${SW_GET_TOPIC_TIMEOUT:10}
+    #  Kafka producer configuration.
+    plugin.kafka.consumer_config=${SW_PLUGIN_KAFKA_CONSUMER_CONFIG:}
+    # Kafka producer configuration. Read [producer configure](http://kafka.apache.org/24/documentation.html#producerconfigs)
+    # to get more details. Check [Kafka report doc](How-to-enable-kafka-reporter.md) for more details and examples.
+    plugin.kafka.producer_config=${SW_PLUGIN_KAFKA_PRODUCER_CONFIG:}
+    #  Specify which Kafka topic name for Meter System data to report to. 
+    plugin.kafka.topic_meter=${SW_PLUGIN_KAFKA_TOPIC_METER:skywalking-meters}
+    #  Specify which Kafka topic name for JVM metrics data to report to. 
+    plugin.kafka.topic_metrics=${SW_PLUGIN_KAFKA_TOPIC_METRICS:skywalking-metrics}
+    #  Specify which Kafka topic name for traces data to report to. 
+    plugin.kafka.topic_segment=${SW_PLUGIN_KAFKA_TOPIC_SEGMENT:skywalking-segments}
+    #  Specify which Kafka topic name for Thread Profiling snapshot to report to. 
+    plugin.kafka.topic_profiling=${SW_PLUGIN_KAFKA_TOPIC_PROFILINGS:skywalking-profilings}
+    #  Specify which Kafka topic name for the register or heartbeat data of Service Instance to report to. 
+    plugin.kafka.topic_management=${SW_PLUGIN_KAFKA_TOPIC_MANAGEMENT:skywalking-managements}
+    #  isolate multi OAP server when using same Kafka cluster (final topic name will append namespace before Kafka topics with `-` ).  
+    plugin.kafka.namespace=${SW_KAFKA_NAMESPACE:}
+    #   Match spring beans with regular expression for the class name. Multiple expressions could be separated by a comma. This only works when `Spring annotation plugin` has been activated. 
+    plugin.springannotation.classname_match_regex=${SW_SPRINGANNOTATION_CLASSNAME_MATCH_REGEX:}
+    #  Whether or not to transmit logged data as formatted or un-formatted. 
+    plugin.toolkit.log.transmit_formatted=${SW_PLUGIN_TOOLKIT_LOG_TRANSMIT_FORMATTED:true}
+    #  Specify which grpc server's host for log data to report to. 
+    plugin.toolkit.log.grpc.reporter.server_host=${SW_GRPC_LOG_SERVER_HOST:127.0.0.1}
+    #  Specify which grpc server's port for log data to report to. 
+    plugin.toolkit.log.grpc.reporter.server_port=${SW_GRPC_LOG_SERVER_PORT:11800}
+    #  Specify the maximum size of log data for grpc client to report to. 
+    plugin.toolkit.log.grpc.reporter.max_message_size=${SW_PLUGIN_TOOLKIT_LOG_GRPC_REPORTER_MAX_MESSAGE_SIZE:10485760}
+    #  How long grpc client will timeout in sending data to upstream. Unit is second.
+    plugin.toolkit.log.grpc.reporter.upstream_timeout=${SW_PLUGIN_TOOLKIT_LOG_GRPC_REPORTER_UPSTREAM_TIMEOUT:30}
+    #  If set to true, the parameters of Redis commands would be collected by Lettuce agent.
+    plugin.lettuce.trace_redis_parameters=${SW_PLUGIN_LETTUCE_TRACE_REDIS_PARAMETERS:false}
+    #  If set to positive number and `plugin.lettuce.trace_redis_parameters` is set to `true`, Redis command parameters would be collected and truncated to this length.
+    plugin.lettuce.redis_parameter_max_length=${SW_PLUGIN_LETTUCE_REDIS_PARAMETER_MAX_LENGTH:128}
+    # If set to true, the parameters of the cypher would be collected.
+    plugin.neo4j.trace_cypher_parameters=${SW_PLUGIN_NEO4J_TRACE_CYPHER_PARAMETERS:false}
+    # If set to positive number, the `db.cypher.parameters` would be truncated to this length, otherwise it would be completely saved, which may cause performance problem.
+    plugin.neo4j.cypher_parameters_max_length=${SW_PLUGIN_NEO4J_CYPHER_PARAMETERS_MAX_LENGTH:512}
+    # If set to positive number, the `db.statement` would be truncated to this length, otherwise it would be completely saved, which may cause performance problem.
+    plugin.neo4j.cypher_body_max_length=${SW_PLUGIN_NEO4J_CYPHER_BODY_MAX_LENGTH:2048}
\ No newline at end of file
diff --git a/config/operator/configmap/kustomization.yaml b/config/operator/configmap/kustomization.yaml
new file mode 100644
index 0000000..294f574
--- /dev/null
+++ b/config/operator/configmap/kustomization.yaml
@@ -0,0 +1,20 @@
+# Licensed to 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. Apache Software Foundation (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.
+
+resources:
+- configmap.yaml
+
diff --git a/config/operator/default/kustomization.yaml b/config/operator/default/kustomization.yaml
index f374c38..9aa1007 100644
--- a/config/operator/default/kustomization.yaml
+++ b/config/operator/default/kustomization.yaml
@@ -35,6 +35,7 @@
 - ../manager
 - ../webhook
 - ../certmanager
+- ../configmap
 
 patchesStrategicMerge:
   # Protect the /metrics endpoint by putting it behind auth.
diff --git a/config/operator/rbac/role.yaml b/config/operator/rbac/role.yaml
index ae23be3..94f4c1b 100644
--- a/config/operator/rbac/role.yaml
+++ b/config/operator/rbac/role.yaml
@@ -38,6 +38,14 @@
 - apiGroups:
   - ""
   resources:
+  - configmaps/status
+  verbs:
+  - get
+  - patch
+  - update
+- apiGroups:
+  - ""
+  resources:
   - serviceaccounts
   - services
   verbs:
diff --git a/config/operator/webhook/kustomization.yaml b/config/operator/webhook/kustomization.yaml
index 83db5a8..ee44e46 100644
--- a/config/operator/webhook/kustomization.yaml
+++ b/config/operator/webhook/kustomization.yaml
@@ -19,6 +19,9 @@
 - service.yaml
 - manifests.yaml
 
+patchesStrategicMerge:
+- ns_selector_patch.yaml
+
 configurations:
 - kustomizeconfig.yaml
 
diff --git a/config/operator/webhook/manifests.yaml b/config/operator/webhook/manifests.yaml
index 649d2be..ff62b0d 100644
--- a/config/operator/webhook/manifests.yaml
+++ b/config/operator/webhook/manifests.yaml
@@ -46,6 +46,24 @@
     service:
       name: webhook-service
       namespace: system
+      path: /mutate-v1-pod
+  failurePolicy: Fail
+  name: mpod.kb.io
+  rules:
+  - apiGroups:
+    - ""
+    apiVersions:
+    - v1
+    operations:
+    - CREATE
+    - UPDATE
+    resources:
+    - pods
+- clientConfig:
+    caBundle: Cg==
+    service:
+      name: webhook-service
+      namespace: system
       path: /mutate-operator-skywalking-apache-org-v1alpha1-oapserver
   failurePolicy: Fail
   name: moapserver.kb.io
diff --git a/config/operator/webhook/ns_selector_patch.yaml b/config/operator/webhook/ns_selector_patch.yaml
new file mode 100644
index 0000000..175acc2
--- /dev/null
+++ b/config/operator/webhook/ns_selector_patch.yaml
@@ -0,0 +1,31 @@
+# Licensed to 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. Apache Software Foundation (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.
+
+apiVersion: admissionregistration.k8s.io/v1beta1
+kind: MutatingWebhookConfiguration
+metadata:
+  name: mutating-webhook-configuration
+webhooks:
+- clientConfig:
+    service:
+      name: webhook-service
+      namespace: system
+      path: /mutate-v1-pod
+  name: mpod.kb.io
+  namespaceSelector:
+    matchLabels:
+      swck-injection: enabled
diff --git a/controllers/operator/configmap_controller.go b/controllers/operator/configmap_controller.go
new file mode 100644
index 0000000..6bd7bb2
--- /dev/null
+++ b/controllers/operator/configmap_controller.go
@@ -0,0 +1,122 @@
+// Licensed to 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. Apache Software Foundation (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 controllers
+
+import (
+	"context"
+	"fmt"
+
+	"github.com/go-logr/logr"
+	core "k8s.io/api/core/v1"
+	apierrors "k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/runtime"
+	ctrl "sigs.k8s.io/controller-runtime"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/event"
+	"sigs.k8s.io/controller-runtime/pkg/predicate"
+
+	"github.com/apache/skywalking-swck/pkg/kubernetes"
+	"github.com/apache/skywalking-swck/pkg/operator/injector"
+)
+
+// ConfigMapReconciler reconciles a ConfigMap object
+type ConfigMapReconciler struct {
+	client.Client
+	Log      logr.Logger
+	Scheme   *runtime.Scheme
+	FileRepo kubernetes.Repo
+}
+
+// +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups="",resources=configmaps/status,verbs=get;update;patch
+
+func (r *ConfigMapReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
+	log := r.Log.WithValues("configmap", req.NamespacedName)
+	log.Info("=====================reconcile started================================")
+	errCol := new(kubernetes.ErrorCollector)
+
+	configmap := &core.ConfigMap{}
+	err := r.Client.Get(ctx, client.ObjectKey{Namespace: injector.DefaultConfigmapNamespace, Name: injector.DefaultConfigmapName}, configmap)
+	if err != nil && !apierrors.IsNotFound(err) {
+		errCol.Collect(fmt.Errorf("failed to get configmap: %w", err))
+	}
+	// if change the default configmap, we need to validate the value
+	// if validate false , we will delete the configmap and recreate a default configmap
+	if !apierrors.IsNotFound(err) {
+		ok, errinfo := injector.ValidateConfigmap(configmap)
+		if !ok {
+			log.Error(errinfo, "the default configmap validate false")
+			if deleteErr := r.Client.Delete(ctx, configmap); deleteErr != nil {
+				log.Error(deleteErr, "failed to delete the configmap that validate false")
+			}
+		}
+		log.Info("delete the configmap that validate false")
+	}
+	app := kubernetes.Application{
+		Client:   r.Client,
+		FileRepo: r.FileRepo,
+		CR:       configmap,
+		GVK:      core.SchemeGroupVersion.WithKind("ConfigMap"),
+		TmplFunc: injector.GetTmplFunc(),
+	}
+
+	// adding false means the configmap don't need to compose , such as ownerReferences
+	ap, err := app.Apply(ctx, "injector/templates/configmap.yaml", log, false)
+	if err != nil {
+		log.Error(err, "failed to apply default configmap")
+		return ctrl.Result{}, err
+	}
+	if ap {
+		log.Info("create default configmap")
+	}
+
+	return ctrl.Result{}, nil
+}
+
+func (r *ConfigMapReconciler) SetupWithManager(mgr ctrl.Manager) error {
+	// Only monitor the default configmap template
+	return ctrl.NewControllerManagedBy(mgr).
+		For(&core.ConfigMap{}).
+		WithEventFilter(
+			predicate.Funcs{
+				CreateFunc: func(e event.CreateEvent) bool {
+					if e.Object.GetNamespace() == injector.DefaultConfigmapNamespace &&
+						e.Object.GetName() == injector.DefaultConfigmapName {
+						return true
+					}
+					return false
+				},
+				UpdateFunc: func(e event.UpdateEvent) bool {
+					if (e.ObjectNew.GetName() == injector.DefaultConfigmapName &&
+						e.ObjectNew.GetNamespace() == injector.DefaultConfigmapNamespace) ||
+						(e.ObjectOld.GetName() == injector.DefaultConfigmapName &&
+							e.ObjectOld.GetNamespace() == injector.DefaultConfigmapNamespace) {
+						return true
+					}
+					return false
+				},
+				DeleteFunc: func(e event.DeleteEvent) bool {
+					if e.Object.GetNamespace() == injector.DefaultConfigmapNamespace &&
+						e.Object.GetName() == injector.DefaultConfigmapName {
+						return true
+					}
+					return false
+				},
+			}).
+		Complete(r)
+}
diff --git a/go.sum b/go.sum
index 27f1b01..8403523 100644
--- a/go.sum
+++ b/go.sum
@@ -965,4 +965,4 @@
 sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
 sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
 sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
-sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
+sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
\ No newline at end of file
diff --git a/main.go b/main.go
index 495d846..2efbf53 100644
--- a/main.go
+++ b/main.go
@@ -23,9 +23,9 @@
 
 	"k8s.io/apimachinery/pkg/runtime"
 	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
-	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/log/zap"
+	"sigs.k8s.io/controller-runtime/pkg/webhook"
 
 	operatorv1alpha1 "github.com/apache/skywalking-swck/apis/operator/v1alpha1"
 	controllers "github.com/apache/skywalking-swck/controllers/operator"
@@ -116,6 +116,13 @@
 	}
 	// +kubebuilder:scaffold:builder
 
+	// register a webhook to enable the agent injector,
+	setupLog.Info("registering /mutate-v1-pod webhook")
+	mgr.GetWebhookServer().Register("/mutate-v1-pod",
+		&webhook.Admission{
+			Handler: &operatorv1alpha1.Javaagent{Client: mgr.GetClient()}})
+	setupLog.Info("/mutate-v1-pod webhook is registered")
+
 	setupLog.Info("starting manager")
 	if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
 		setupLog.Error(err, "problem running manager")
diff --git a/pkg/kubernetes/apply.go b/pkg/kubernetes/apply.go
index 0bc70f1..a877dce 100644
--- a/pkg/kubernetes/apply.go
+++ b/pkg/kubernetes/apply.go
@@ -55,7 +55,7 @@
 	var changedFf []string
 	for _, f := range manifestFiles {
 		sl := log.WithName(f)
-		changed, err := a.Apply(ctx, f, sl)
+		changed, err := a.Apply(ctx, f, sl, true)
 		if err != nil {
 			l.Error(err, "failed to apply resource")
 			a.Recorder.Eventf(a.CR, v1.EventTypeWarning, "failed to apply resource", "encountered err: %v", err)
@@ -72,7 +72,7 @@
 }
 
 // Apply a template represents a component to api server
-func (a *Application) Apply(ctx context.Context, manifest string, log logr.Logger) (bool, error) {
+func (a *Application) Apply(ctx context.Context, manifest string, log logr.Logger, needCompose bool) (bool, error) {
 	manifests, err := a.FileRepo.ReadFile(manifest)
 	if err != nil {
 		return false, err
@@ -86,31 +86,35 @@
 	if err != nil {
 		return false, fmt.Errorf("failed to load %s template: %w", manifest, err)
 	}
-	return a.apply(ctx, proto, log)
+	return a.apply(ctx, proto, log, needCompose)
 }
 
 // ApplyFromObject apply an object to api server
-func (a *Application) ApplyFromObject(ctx context.Context, obj runtime.Object, log logr.Logger) (bool, error) {
+func (a *Application) ApplyFromObject(ctx context.Context, obj runtime.Object, log logr.Logger, needCompose bool) (bool, error) {
 	proto, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
 	if err != nil {
 		return false, fmt.Errorf("failed to convert object to unstructed: %v", err)
 	}
-	return a.apply(ctx, &unstructured.Unstructured{Object: proto}, log)
+	return a.apply(ctx, &unstructured.Unstructured{Object: proto}, log, needCompose)
 }
 
-func (a *Application) apply(ctx context.Context, obj *unstructured.Unstructured, log logr.Logger) (bool, error) {
+func (a *Application) apply(ctx context.Context, obj *unstructured.Unstructured, log logr.Logger, needCompose bool) (bool, error) {
 	key := client.ObjectKeyFromObject(obj)
 	current := &unstructured.Unstructured{}
 	current.SetGroupVersionKind(obj.GetObjectKind().GroupVersionKind())
 	err := a.Get(ctx, key, current)
+
 	if apierrors.IsNotFound(err) {
 		log.Info("could not find existing resource, creating one...")
-		curr, errComp := a.compose(obj)
-		if errComp != nil {
-			return false, fmt.Errorf("failed to compose: %w", errComp)
+		if needCompose {
+			curr, errComp := a.compose(obj)
+			if errComp != nil {
+				return false, fmt.Errorf("failed to compose: %w", errComp)
+			}
+			obj = curr
 		}
 
-		if err = a.Create(ctx, curr); err != nil {
+		if err = a.Create(ctx, obj); err != nil {
 			return false, fmt.Errorf("failed to create: %w", err)
 		}
 
@@ -121,16 +125,19 @@
 		return false, fmt.Errorf("failed to get %v : %w", key, err)
 	}
 
-	object, err := a.compose(obj)
-	if err != nil {
-		return false, fmt.Errorf("failed to compose: %w", err)
+	if needCompose {
+		object, err := a.compose(obj)
+		if err != nil {
+			return false, fmt.Errorf("failed to compose: %w", err)
+		}
+		obj = object
 	}
 
-	if getVersion(current, a.versionKey()) == getVersion(object, a.versionKey()) {
+	if getVersion(current, a.versionKey()) == getVersion(obj, a.versionKey()) {
 		log.Info("resource keeps the same as before")
 		return false, nil
 	}
-	if err := a.Update(ctx, object); err != nil {
+	if err := a.Update(ctx, obj); err != nil {
 		return false, fmt.Errorf("failed to update: %w", err)
 	}
 	log.Info("updated")
diff --git a/pkg/operator/injector/annotation.go b/pkg/operator/injector/annotation.go
new file mode 100644
index 0000000..e2835c3
--- /dev/null
+++ b/pkg/operator/injector/annotation.go
@@ -0,0 +1,123 @@
+// Licensed to 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. Apache Software Foundation (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 injector
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/ghodss/yaml"
+
+	"github.com/apache/skywalking-swck/pkg/operator/repo"
+)
+
+// Annotation defines configuration that user can overlay, including
+// sidecar configuration and java agent configuration.
+type Annotation struct {
+	// Name defines the reference to configuration used in Pod's AnnotationOverlay.
+	Name string `yaml:"name"`
+	// DefaultValue defines the default value of configuration, if there
+	// isn't a default value, it will be "nil".
+	DefaultValue string `yaml:"defaultValue"`
+	// ValidateFunc defines a Validate func to judge whether the value
+	// is valid, if there isn't a validate func, it will be "nil".
+	ValidateFunc string `yaml:"validateFunc"`
+	// UseQuotes defines whether the key or value of the annotation needs
+	// to be wrapped in quotes, if don't need quotes, it will be "nil" .
+	// if UseQuotes is set to "key", it means the key of annotation need quotes.
+	// if UseQuotes is set to "value", it means the value of annotation need quotes.
+	UseQuotes string `yaml:"useQuotes"`
+	// EnvName represent the environment variable , just like following
+	// in agent.namespace=${SW_AGENT_NAMESPACE:} , the EnvName is SW_AGENT_NAMESPACE
+	EnvName string `yaml:"envName"`
+}
+
+// Annotations are
+type Annotations struct {
+	Annotations []Annotation
+}
+
+//AnnotationOverlay is used to set overlaied value
+type AnnotationOverlay map[Annotation]string
+
+// NewAnnotations will create a new AnnotationOverlay
+func NewAnnotations() (*Annotations, error) {
+	fileRepo := repo.NewRepo("injector")
+	data, err := fileRepo.ReadFile("injector/templates/annotations.yaml")
+	if err != nil {
+		return nil, err
+	}
+	a := new(Annotations)
+	if err := yaml.Unmarshal(data, a); err != nil {
+		return nil,
+			fmt.Errorf("unmarshal annotations.yaml to struct Annotations :%s", err.Error())
+	}
+	return a, nil
+}
+
+// GetAnnotationsByPrefix is
+func GetAnnotationsByPrefix(a Annotations, prefixName string) *Annotations {
+	anno := new(Annotations)
+	for _, v := range a.Annotations {
+		if strings.HasPrefix(v.Name, prefixName) {
+			anno.Annotations = append(anno.Annotations, v)
+		}
+	}
+	return anno
+}
+
+//NewAnnotationOverlay will create a new AnnotationOverlay
+func NewAnnotationOverlay() *AnnotationOverlay {
+	a := make(AnnotationOverlay)
+	return &a
+}
+
+//GetFinalValue will get overlaied value first , then default
+func (as *AnnotationOverlay) GetFinalValue(a Annotation) string {
+	ov := a.DefaultValue
+	if v, ok := (*as)[a]; ok {
+		ov = v
+	}
+	return ov
+}
+
+//SetOverlay will set overlaied value
+func (as *AnnotationOverlay) SetOverlay(AnnotationOverlay *map[string]string, a Annotation) error {
+	if v, ok := (*AnnotationOverlay)[a.Name]; ok {
+		//if annotation has validate func then validate
+		f := FindValidateFunc(a.ValidateFunc)
+		if f != nil {
+			err := f(a.Name, v)
+			//validate error
+			if err != nil {
+				return err
+			}
+		}
+		//if no validate func then set Overlay directly
+		(*as)[a] = v
+	}
+	return nil
+}
+
+//GetOverlayValue will get overlaied value, if not then return ""
+func (as *AnnotationOverlay) GetOverlayValue(a Annotation) string {
+	if v, ok := (*as)[a]; ok {
+		return v
+	}
+	return ""
+}
diff --git a/pkg/operator/injector/configmap.go b/pkg/operator/injector/configmap.go
new file mode 100644
index 0000000..cdca73c
--- /dev/null
+++ b/pkg/operator/injector/configmap.go
@@ -0,0 +1,113 @@
+// Licensed to 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. Apache Software Foundation (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 injector
+
+import (
+	"fmt"
+	"strings"
+
+	corev1 "k8s.io/api/core/v1"
+)
+
+const (
+	// DefaultConfigmapNamespace is the system namespace
+	DefaultConfigmapNamespace = "skywalking-swck-system"
+	// DefaultConfigmapName is the default configmap's name
+	DefaultConfigmapName = "skywalking-swck-java-agent-configmap"
+	// DefaultConfigmapKey is the key of default configmap
+	DefaultConfigmapKey = "agent.config"
+)
+
+// Get agent annotation from annotations.yaml
+func getAgentAnnotations() []Annotation {
+	anno, err := NewAnnotations()
+	if err != nil {
+		return nil
+	}
+	agent := GetAnnotationsByPrefix(*anno, agentAnnotationPrefix)
+	return agent.Annotations
+}
+
+// Remove the prefix of annotation in annotations.yaml
+func parse(s string) string {
+	i := strings.Index(s, "/")
+	return s[i+1:]
+}
+
+// GetTmplFunc will create template func used in configmap.yaml
+func GetTmplFunc() map[string]interface{} {
+	return map[string]interface{}{"getAgentAnnotations": getAgentAnnotations, "parse": parse}
+}
+
+// ValidateConfigmap will verify the value of configmap
+func ValidateConfigmap(configmap *corev1.ConfigMap) (bool, error) {
+	data := configmap.Data
+	if data == nil {
+		return false, fmt.Errorf("configmap don't have data")
+	}
+	v, ok := data[DefaultConfigmapKey]
+	if !ok {
+		return false, fmt.Errorf("DefaultConfigmapKey %s not exist", DefaultConfigmapKey)
+	}
+
+	anno, err := NewAnnotations()
+	if err != nil {
+		return false, fmt.Errorf("get NewAnnotations error:%s", err)
+	}
+
+	// the following code is to extract the {option}={value} from data of configmap
+	// such as agent.service_name=${SW_AGENT_NAME:Your_ApplicationName}  or
+	//         agent.service_name = Your_ApplicationName
+	// we will get "agent.service_name" and "Your_ApplicationName"
+	// so that we can validate every option's value if it has validate function
+
+	str := strings.Split(v, "\n")
+	for i := range str {
+		if index := strings.Index(str[i], "="); index != -1 {
+
+			// set option and value
+			option := strings.Trim(str[i][:index], " ")
+			value := strings.Trim(str[i][index+1:], " ")
+
+			// if option has environment variable like SW_AGENT_NAME
+			if strings.Contains(str[i], ":") {
+				valueStart := strings.Index(str[i], ":")
+				valueEnd := strings.Index(str[i], "}")
+				if valueStart == -1 || valueEnd == -1 || valueStart >= valueEnd {
+					continue
+				}
+				value = strings.Trim(str[i][valueStart+1:valueEnd], " ")
+			}
+			if len(value) == 0 {
+				continue
+			}
+			for _, a := range anno.Annotations {
+				if strings.Contains(a.Name, option) {
+					f := FindValidateFunc(a.ValidateFunc)
+					if f != nil {
+						err := f(a.Name, value)
+						//validate error
+						if err != nil {
+							return false, fmt.Errorf("validate error:%v", err)
+						}
+					}
+				}
+			}
+		}
+	}
+	return true, nil
+}
diff --git a/pkg/operator/injector/injection.go b/pkg/operator/injector/injection.go
new file mode 100644
index 0000000..d2430f7
--- /dev/null
+++ b/pkg/operator/injector/injection.go
@@ -0,0 +1,228 @@
+// Licensed to 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. Apache Software Foundation (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 injector
+
+import (
+	"context"
+	"encoding/json"
+	"net/http"
+	"strings"
+
+	"github.com/go-logr/logr"
+	corev1 "k8s.io/api/core/v1"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
+)
+
+// Injection is each step of the injection process
+type Injection interface {
+	execute(*InjectProcessData) admission.Response
+	// set next step
+	setNext(Injection)
+}
+
+// InjectProcessData defines data that needs to be processed in the injection process
+// Divide the entire injection process into 6 steps
+// 1.Get injection strategy
+// 2.Overlay the sidecar info
+// 3.Overlay the agent by setting jvm string
+// 4.Overlay the plugins by setting jvm string and set the optional plugins
+// 5.Get the ConfigMap
+// 6.Inject fields into Pod
+// After all steps are completed, return fully injected Pod, Or there is an error
+// in a certain step, inject error info into annotations and return incompletely injected Pod
+type InjectProcessData struct {
+	injectFileds      *SidecarInjectField
+	annotation        *Annotations
+	annotationOverlay *AnnotationOverlay
+	pod               *corev1.Pod
+	req               admission.Request
+	log               logr.Logger
+	kubeclient        client.Client
+	ctx               context.Context
+}
+
+// PatchReq is to fill the injected pod into the request and return the Response
+func PatchReq(pod *corev1.Pod, req admission.Request) admission.Response {
+	marshaledPod, err := json.Marshal(pod)
+	if err != nil {
+		return admission.Errored(http.StatusInternalServerError, err)
+	}
+
+	return admission.PatchResponseFromRaw(req.Object.Raw, marshaledPod)
+}
+
+// GetStrategy is the first step of injection process
+type GetStrategy struct {
+	next Injection
+}
+
+// get injection strategy from pod's labels and annotations
+// if don't need to inject, then return the original pod, otherwise go to the next step
+func (gs *GetStrategy) execute(ipd *InjectProcessData) admission.Response {
+	ipd.injectFileds.GetInjectStrategy(*ipd.annotation, &ipd.pod.ObjectMeta.Labels, &ipd.pod.ObjectMeta.Annotations)
+	if !ipd.injectFileds.NeedInject {
+		log.Info("don't inject agent")
+		return admission.Allowed("ok")
+	}
+	return gs.next.execute(ipd)
+}
+
+func (gs *GetStrategy) setNext(next Injection) {
+	gs.next = next
+}
+
+// OverlaySidecar is the second step of injection process
+type OverlaySidecar struct {
+	next Injection
+}
+
+// OverlaySidecar will inject sidecar information such as image, command, args etc.
+// Since we did not set the validation function for these fields, it usually goes to the next step
+func (os *OverlaySidecar) execute(ipd *InjectProcessData) admission.Response {
+	if !ipd.injectFileds.OverlaySidecar(*ipd.annotation, ipd.annotationOverlay, &ipd.pod.ObjectMeta.Annotations) {
+		return PatchReq(ipd.pod, ipd.req)
+	}
+	return os.next.execute(ipd)
+}
+
+func (os *OverlaySidecar) setNext(next Injection) {
+	os.next = next
+}
+
+// OverlayAgent is the third step of injection process
+type OverlayAgent struct {
+	next Injection
+}
+
+// OverlayAgent overlays the agent by getting the pod's annotations
+// If the agent overlay option is not set, go directly to the next step
+// If set the wrong value in the annotation , inject the error info and return
+func (oa *OverlayAgent) execute(ipd *InjectProcessData) admission.Response {
+	if !ipd.injectFileds.AgentOverlay {
+		return oa.next.execute(ipd)
+	}
+	if !ipd.injectFileds.OverlayAgent(*ipd.annotation, ipd.annotationOverlay, &ipd.pod.ObjectMeta.Annotations) {
+		ipd.log.Info("overlay agent config error!please look the error annotation!")
+		return PatchReq(ipd.pod, ipd.req)
+	}
+	return oa.next.execute(ipd)
+}
+
+func (oa *OverlayAgent) setNext(next Injection) {
+	oa.next = next
+}
+
+// OverlayPlugins is the fourth step of injection process
+type OverlayPlugins struct {
+	next Injection
+}
+
+// OverlayPlugins contains two step , the first is to set jvm string , the second is to set optional plugins
+// during the step , we need to add jvm string to the Env of injected container
+func (op *OverlayPlugins) execute(ipd *InjectProcessData) admission.Response {
+	if !ipd.injectFileds.AgentOverlay {
+		return op.next.execute(ipd)
+	}
+	ipd.injectFileds.OverlayPlugins(&ipd.pod.ObjectMeta.Annotations)
+	if ipd.injectFileds.JvmAgentConfigStr != "" {
+		ipd.injectFileds.Env.Value = strings.Join([]string{ipd.injectFileds.Env.Value, ipd.injectFileds.JvmAgentConfigStr}, "=")
+	}
+	ipd.injectFileds.OverlayOptional(&ipd.pod.ObjectMeta.Annotations)
+	return op.next.execute(ipd)
+}
+func (op *OverlayPlugins) setNext(next Injection) {
+	op.next = next
+}
+
+// GetConfigmap is the fifth step of injection process
+type GetConfigmap struct {
+	next Injection
+}
+
+// GetConfigmap will get the configmap specified in the annotation. if not exist ,
+// we will get data from default configmap and create configmap in the req's namespace
+func (gc *GetConfigmap) execute(ipd *InjectProcessData) admission.Response {
+	if !ipd.injectFileds.CreateConfigmap(ipd.ctx, ipd.kubeclient, ipd.req.Namespace, &ipd.pod.ObjectMeta.Annotations) {
+		return PatchReq(ipd.pod, ipd.req)
+	}
+	return gc.next.execute(ipd)
+}
+func (gc *GetConfigmap) setNext(next Injection) {
+	gc.next = next
+}
+
+// PodInject is the sixth step of injection process
+type PodInject struct {
+	next Injection
+}
+
+// PodInject will inject all fields to the pod
+func (pi *PodInject) execute(ipd *InjectProcessData) admission.Response {
+	ipd.injectFileds.Inject(ipd.pod)
+	log.Info("inject successfully!")
+	return PatchReq(ipd.pod, ipd.req)
+}
+func (pi *PodInject) setNext(next Injection) {
+	pi.next = next
+}
+
+// NewInjectProcess create a new InjectProcess
+func NewInjectProcess(ctx context.Context, injectFileds *SidecarInjectField, annotation *Annotations,
+	annotationOverlay *AnnotationOverlay, pod *corev1.Pod, req admission.Request, log logr.Logger,
+	kubeclient client.Client) *InjectProcessData {
+	return &InjectProcessData{
+		ctx:               ctx,
+		injectFileds:      injectFileds,
+		annotation:        annotation,
+		annotationOverlay: annotationOverlay,
+		pod:               pod,
+		req:               req,
+		log:               log,
+		kubeclient:        kubeclient,
+	}
+}
+
+// Run will connect the above six steps into a chain and start to execute the first step
+func (ipd *InjectProcessData) Run() admission.Response {
+	// set final step
+	podInject := &PodInject{}
+
+	// set next step is PodInject
+	getConfigmap := &GetConfigmap{}
+	getConfigmap.setNext(podInject)
+
+	// set next step is GetConfigmap
+	overlayPlugins := &OverlayPlugins{}
+	overlayPlugins.setNext(getConfigmap)
+
+	// set next step is OverlayPlugins
+	overlayAgent := &OverlayAgent{}
+	overlayAgent.setNext(overlayPlugins)
+
+	// set next step is OverlayAgent
+	overlaysidecar := &OverlaySidecar{}
+	overlaysidecar.setNext(overlayAgent)
+
+	// set next step is OverlaySidecar
+	getStrategy := &GetStrategy{}
+	getStrategy.setNext(overlaysidecar)
+
+	// this is first step and do real injection
+	return getStrategy.execute(ipd)
+}
diff --git a/pkg/operator/injector/injector.go b/pkg/operator/injector/injector.go
new file mode 100644
index 0000000..b048d1f
--- /dev/null
+++ b/pkg/operator/injector/injector.go
@@ -0,0 +1,396 @@
+// Licensed to 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. Apache Software Foundation (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 injector
+
+import (
+	"context"
+	"fmt"
+	"strings"
+
+	corev1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+	logf "sigs.k8s.io/controller-runtime/pkg/log"
+)
+
+const (
+	// the label means whether to enbale injection , "true" of "false"
+	labelKeyagentInjector = "swck-java-agent-injected"
+	// the annotation means which container to inject
+	sidecarInjectContainerAnno = "strategy.skywalking.apache.org/inject.Container"
+	// the annotation means whether to enable overlay agent, "true" of "false"
+	sidecarAgentOverlayAnno = "strategy.skywalking.apache.org/agent.Overlay"
+	// the annotation that specify the reason for injection failure
+	sidecarInjectErrorAnno = "sidecar.skywalking.apache.org/error"
+	// those annotations with the following prefixes represent sidecar information
+	sidecarAnnotationPrefix = "sidecar.skywalking.apache.org/"
+	// those annotations with the following prefixes represent agent information
+	agentAnnotationPrefix = "agent.skywalking.apache.org/"
+	// If user want to use other Plugins' config ,the annotation must have the following form
+	// plugins.skywalking.apache.org/${config.name} = ${config.value}
+	// for example , if user want to enable plugin.mongodb.trace_param
+	// the annotation is plugins.skywalking.apache.org/plugin.mongodb.trace_param: "true"
+	pluginsAnnotationPrefix = "plugins.skywalking.apache.org/"
+	// If user want to use optional-plugins , the annotation must match a optinal plugin
+	// such as optional.skywalking.apache.org: "*ehcache*"
+	// Notice , If the injected container's image don't has the optional plugin ,
+	// the container will panic
+	optionsAnnotation = "optional.skywalking.apache.org"
+	// If user want to use optional-reporter-plugins , the annotation must match a optinal-reporter plugin
+	// such as optional-exporter.skywalking.apache.org: "kafka*"
+	optionsReporterAnnotation = "optional-reporter.skywalking.apache.org"
+)
+
+// log is for logging in this package.
+var log = logf.Log.WithName("injector")
+
+// SidecarInjectField contains all info that will be injected
+type SidecarInjectField struct {
+	// determine whether to inject , default is not to inject
+	NeedInject bool
+	// determine whether to use annotation to overlay agent config ,
+	// default is not to overlay,which means only use configmap to set agent config
+	// Otherwise, the way to overlay is set jvm agent ,just like following
+	// -javaagent: /sky/agent/skywalking-agent,jar={config1}={value1},{config2}={value2}
+	AgentOverlay bool
+	// Initcontainer is a container that has the agent folder
+	Initcontainer corev1.Container
+	// sidecarVolume is a shared directory between App's container and initcontainer
+	SidecarVolume corev1.Volume
+	// sidecarVolumeMount is a path that specifies a shared directory
+	SidecarVolumeMount corev1.VolumeMount
+	// configmapVolume is volume that provide user with configmap
+	ConfigmapVolume corev1.Volume
+	// configmapVolumeMount is the configmap's mountpath for user
+	// Notice : the mount path will overwrite the original agent/config/agent.config
+	// So the mount path must match the path of agent.config in the image
+	ConfigmapVolumeMount corev1.VolumeMount
+	// env is used to set java agent’s parameters
+	Env corev1.EnvVar
+	// the string is used to set jvm agent ,just like following
+	// -javaagent: /sky/agent/skywalking-agent,jar=jvmAgentConfigStr
+	JvmAgentConfigStr string
+	// determine which container to inject , default is to inject all containers
+	InjectContainer string
+}
+
+// NewSidecarInjectField will create a new SidecarInjectField
+func NewSidecarInjectField() *SidecarInjectField {
+	return new(SidecarInjectField)
+}
+
+// Inject will do real injection
+func (s *SidecarInjectField) Inject(pod *corev1.Pod) {
+	// add initcontrainers to spec
+	if pod.Spec.InitContainers != nil {
+		pod.Spec.InitContainers = append(pod.Spec.InitContainers, s.Initcontainer)
+	} else {
+		pod.Spec.InitContainers = []corev1.Container{s.Initcontainer}
+	}
+
+	// add volume to spec
+	if pod.Spec.Volumes != nil {
+		pod.Spec.Volumes = append(pod.Spec.Volumes, s.SidecarVolume, s.ConfigmapVolume)
+	} else {
+		pod.Spec.Volumes = []corev1.Volume{s.SidecarVolume, s.ConfigmapVolume}
+	}
+
+	// choose a specific container to inject
+	containers := []*corev1.Container{}
+
+	c := s.findInjectContainer(pod.Spec.Containers)
+	if c != nil {
+		containers = append(containers, c)
+	} else {
+		for i := range pod.Spec.Containers {
+			containers = append(containers, &pod.Spec.Containers[i])
+		}
+	}
+
+	// add volumemount and env to container
+	for i := range containers {
+		if (*containers[i]).VolumeMounts != nil {
+			(*containers[i]).VolumeMounts = append((*containers[i]).VolumeMounts,
+				s.SidecarVolumeMount, s.ConfigmapVolumeMount)
+		} else {
+			(*containers[i]).VolumeMounts = []corev1.VolumeMount{s.SidecarVolumeMount,
+				s.ConfigmapVolumeMount}
+		}
+		if (*containers[i]).Env != nil {
+			(*containers[i]).Env = append((*containers[i]).Env, s.Env)
+		} else {
+			(*containers[i]).Env = []corev1.EnvVar{s.Env}
+		}
+	}
+}
+
+// GetInjectStrategy gets user's injection strategy
+func (s *SidecarInjectField) GetInjectStrategy(a Annotations, labels,
+	annotation *map[string]string) {
+	// set default value
+	s.NeedInject = false
+	s.InjectContainer = ""
+	s.AgentOverlay = false
+
+	// set NeedInject's value , if the pod has the label "swck-java-agent-injected=true",means need inject
+	if *labels == nil {
+		return
+	}
+
+	if strings.ToLower((*labels)[labelKeyagentInjector]) == "true" {
+		s.NeedInject = true
+	}
+
+	if *annotation == nil {
+		return
+	}
+
+	// set injectContainer's value
+	if v, ok := (*annotation)[sidecarInjectContainerAnno]; ok {
+		s.InjectContainer = v
+	}
+
+	// set AgentOverlay's value
+	if v, ok := (*annotation)[sidecarAgentOverlayAnno]; ok {
+		if strings.ToLower(v) == "true" {
+			s.AgentOverlay = true
+		}
+	}
+}
+
+func (s *SidecarInjectField) findInjectContainer(containers []corev1.Container) *corev1.Container {
+	// validate the container is or not exist
+	if s.InjectContainer == "" {
+		return nil
+	}
+
+	for i := range containers {
+		if containers[i].Name == s.InjectContainer {
+			return &containers[i]
+		}
+	}
+	return nil
+}
+func (s *SidecarInjectField) injectErrorAnnotation(annotation *map[string]string, errorInfo string) {
+	(*annotation)[sidecarInjectErrorAnno] = errorInfo
+}
+
+// SidecarOverlayandGetValue get final value of sidecar
+func (s *SidecarInjectField) SidecarOverlayandGetValue(ao *AnnotationOverlay, annotation *map[string]string,
+	a Annotation) (string, bool) {
+	if _, ok := (*annotation)[a.Name]; ok {
+		err := ao.SetOverlay(annotation, a)
+		if err != nil {
+			s.injectErrorAnnotation(annotation, err.Error())
+			return "", false
+		}
+	}
+	return ao.GetFinalValue(a), true
+}
+
+func (s *SidecarInjectField) setValue(config *string, ao *AnnotationOverlay, annotation *map[string]string,
+	a Annotation) bool {
+	if v, ok := s.SidecarOverlayandGetValue(ao, annotation, a); ok {
+		*config = v
+		return true
+	}
+	return false
+}
+
+// OverlaySidecar overlays default config
+func (s *SidecarInjectField) OverlaySidecar(a Annotations, ao *AnnotationOverlay, annotation *map[string]string) bool {
+	s.ConfigmapVolume.ConfigMap = new(corev1.ConfigMapVolumeSource)
+	s.Initcontainer.Command = make([]string, 1)
+	s.Initcontainer.Args = make([]string, 2)
+	// every annotation map a pointer to the field of SidecarInjectField
+	annoField := map[string]*string{
+		"initcontainer.Name":             &s.Initcontainer.Name,
+		"initcontainer.Image":            &s.Initcontainer.Image,
+		"initcontainer.Command":          &s.Initcontainer.Command[0],
+		"initcontainer.args.Option":      &s.Initcontainer.Args[0],
+		"initcontainer.args.Command":     &s.Initcontainer.Args[1],
+		"sidecarVolume.Name":             &s.SidecarVolume.Name,
+		"sidecarVolumeMount.MountPath":   &s.SidecarVolumeMount.MountPath,
+		"configmapVolume.ConfigMap.Name": &s.ConfigmapVolume.ConfigMap.Name,
+		"configmapVolume.Name":           &s.ConfigmapVolume.Name,
+		"configmapVolumeMount.MountPath": &s.ConfigmapVolumeMount.MountPath,
+		"env.Name":                       &s.Env.Name,
+		"env.Value":                      &s.Env.Value,
+	}
+	anno := GetAnnotationsByPrefix(a, sidecarAnnotationPrefix)
+	for _, v := range anno.Annotations {
+		fieldName := strings.TrimPrefix(v.Name, sidecarAnnotationPrefix)
+		if pointer, ok := annoField[fieldName]; ok {
+			if !s.setValue(pointer, ao, annotation, v) {
+				return false
+			}
+		}
+	}
+	s.SidecarVolumeMount.Name = s.SidecarVolume.Name
+	s.ConfigmapVolumeMount.Name = s.ConfigmapVolume.Name
+	s.Initcontainer.VolumeMounts = []corev1.VolumeMount{s.SidecarVolumeMount}
+
+	// the sidecar volume's type is determined
+	s.SidecarVolume.VolumeSource.EmptyDir = nil
+
+	return true
+}
+
+// AgentOverlayandGetValue will do real annotation overlay
+func (s *SidecarInjectField) AgentOverlayandGetValue(ao *AnnotationOverlay, annotation *map[string]string,
+	a Annotation) (string, bool) {
+	if _, ok := (*annotation)[a.Name]; ok {
+		err := ao.SetOverlay(annotation, a)
+		if err != nil {
+			s.injectErrorAnnotation(annotation, err.Error())
+			return "", false
+		}
+	}
+	return ao.GetOverlayValue(a), true
+}
+
+func (s *SidecarInjectField) setJvmAgentStr(ao *AnnotationOverlay, annotation *map[string]string, a Annotation) bool {
+	v, ok := s.AgentOverlayandGetValue(ao, annotation, a)
+	if v != "" && ok {
+		// get {config1}={value1}
+		configName := strings.TrimPrefix(a.Name, agentAnnotationPrefix)
+		switch a.UseQuotes {
+		case "option":
+			configName = strings.Join([]string{"'", "'"}, configName)
+		case "value":
+			v = strings.Join([]string{"'", "'"}, v)
+		}
+		config := strings.Join([]string{configName, v}, "=")
+
+		// add to jvmAgentConfigStr
+		if s.JvmAgentConfigStr != "" {
+			s.JvmAgentConfigStr = strings.Join([]string{s.JvmAgentConfigStr, config}, ",")
+		} else {
+			s.JvmAgentConfigStr = config
+		}
+	}
+	return ok
+}
+
+// OverlayAgent overlays agent
+func (s *SidecarInjectField) OverlayAgent(a Annotations, ao *AnnotationOverlay, annotation *map[string]string) bool {
+	// jvmAgentConfigStr init
+	s.JvmAgentConfigStr = ""
+	anno := GetAnnotationsByPrefix(a, agentAnnotationPrefix)
+	for _, v := range anno.Annotations {
+		if !s.setJvmAgentStr(ao, annotation, v) {
+			return false
+		}
+	}
+	return true
+}
+
+// OverlayOptional overlays optional plugins and move optional plugins to the directory(/plugins)
+// user must ensure that the optional plugins are in the injected container's image
+// Notice , user must specify the correctness of the regular value
+// such as optional.skywalking.apache.org: "*ehcache*" or optional-reporter.skywalking.apache.org: "kafka*"
+// the final command will be "cp /optional-plugins/*ehcache*  /plugins/" or
+// "cp /optional-exporter-plugins/kafka*  /plugins/"
+func (s *SidecarInjectField) OverlayOptional(annotation *map[string]string) {
+	sourceOptionalPath := strings.Join([]string{s.SidecarVolumeMount.MountPath, "optional-plugins/"}, "/")
+	sourceOptionalReporterPath := strings.Join([]string{s.SidecarVolumeMount.MountPath, "optional-reporter-plugins/"}, "/")
+	targetPath := strings.Join([]string{s.SidecarVolumeMount.MountPath, "plugins/"}, "/")
+
+	for k, v := range *annotation {
+		command := ""
+		if strings.EqualFold(k, optionsAnnotation) {
+			command = strings.Join([]string{"cp", sourceOptionalPath}, " ")
+		} else if strings.EqualFold(k, optionsReporterAnnotation) {
+			command = strings.Join([]string{"cp", sourceOptionalReporterPath}, " ")
+		}
+		if command != "" {
+			command = command + v + " " + targetPath
+			s.Initcontainer.Args[1] = strings.Join([]string{s.Initcontainer.Args[1], command}, " && ")
+		}
+	}
+
+}
+
+// OverlayPlugins will add Plugins' config to JvmAgentStr without verification
+// Notice, if a config is not in agent.config, it will be seen as a plugin config
+// user must ensure the accuracy of configuration.
+// Otherwides,If a separator(, or =) in the option or value, it should be wrapped in quotes.
+func (s *SidecarInjectField) OverlayPlugins(annotation *map[string]string) {
+	for k, v := range *annotation {
+		if strings.HasPrefix(k, pluginsAnnotationPrefix) {
+			configName := strings.TrimPrefix(k, pluginsAnnotationPrefix)
+			config := strings.Join([]string{configName, v}, "=")
+			// add to jvmAgentConfigStr
+			if s.JvmAgentConfigStr != "" {
+				s.JvmAgentConfigStr = strings.Join([]string{s.JvmAgentConfigStr, config}, ",")
+			} else {
+				s.JvmAgentConfigStr = config
+			}
+		}
+	}
+}
+
+// CreateConfigmap will create a configmap to set java agent config.
+func (s *SidecarInjectField) CreateConfigmap(ctx context.Context, kubeclient client.Client, namespace string,
+	annotation *map[string]string) bool {
+	configmap := &corev1.ConfigMap{}
+	configmapName := s.ConfigmapVolume.VolumeSource.ConfigMap.LocalObjectReference.Name
+	// check whether the configmap is existed
+	err := kubeclient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: configmapName}, configmap)
+	if err != nil && !errors.IsNotFound(err) {
+		log.Error(err, "Get Configmap failed", "configmapName", configmapName, "namespace", namespace)
+		return false
+	}
+	// if configmap exist , validate it
+	if !errors.IsNotFound(err) {
+		ok, errinfo := ValidateConfigmap(configmap)
+		if ok {
+			log.Info("the configmap validate true", "configmapName", configmapName)
+			return true
+		}
+		log.Error(errinfo, "the configmap validate false", "configmapName", configmapName)
+	}
+	// if configmap not exist or validate false , get default configmap
+	defaultConfigmap := &corev1.ConfigMap{}
+	if err := kubeclient.Get(ctx, client.ObjectKey{Namespace: DefaultConfigmapNamespace,
+		Name: DefaultConfigmapName}, defaultConfigmap); err != nil {
+		log.Error(err, "can't get default configmap")
+		s.injectErrorAnnotation(annotation, fmt.Sprintf("get configmap %s from namespace %s error[%s]",
+			DefaultConfigmapName, DefaultConfigmapNamespace, err.Error()))
+		return false
+	}
+
+	// use default configmap's data to create new configmap and update namespace
+	injectConfigmap := corev1.ConfigMap{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      configmapName,
+			Namespace: namespace,
+		},
+		Data: defaultConfigmap.Data,
+	}
+
+	// create the configmap in user's namespace
+	if err := kubeclient.Create(ctx, &injectConfigmap); err != nil {
+		log.Error(err, "create configmap failed")
+		s.injectErrorAnnotation(annotation, fmt.Sprintf("create configmap %s in namespace %s error[%s]",
+			configmapName, namespace, err.Error()))
+		return false
+	}
+	return true
+}
diff --git a/pkg/operator/injector/validate.go b/pkg/operator/injector/validate.go
new file mode 100644
index 0000000..c6f9e48
--- /dev/null
+++ b/pkg/operator/injector/validate.go
@@ -0,0 +1,80 @@
+// Licensed to 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. Apache Software Foundation (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 injector
+
+import (
+	"fmt"
+	"reflect"
+	"regexp"
+	"runtime"
+	"strings"
+)
+
+// AnnotationValidateFunc is the type of validate function
+type AnnotationValidateFunc func(annotation, value string) error
+
+var (
+	//AnnotationValidateFuncs define all validate functions
+	AnnotationValidateFuncs = []AnnotationValidateFunc{
+		ValidateServiceName,
+		ValidateIpandPort,
+	}
+)
+
+// FindValidateFunc is find the validate function for an annotation
+func FindValidateFunc(funcName string) AnnotationValidateFunc {
+	for _, f := range AnnotationValidateFuncs {
+		// extract the function name into a string , it will be like following
+		// github.com/apache/skywalking-swck/pkg/operator/injector.ValidateBool
+		fname := runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
+		// get real validate function name in injector
+		index := strings.LastIndex(fname, ".")
+		funcname := fname[index+1:]
+
+		if funcname == funcName {
+			return f
+		}
+	}
+	return nil
+}
+
+//ValidateServiceName validates the ServiceName is nil or not
+func ValidateServiceName(annotation, value string) error {
+	if value == "" {
+		return fmt.Errorf("%s error:the service name is nil", annotation)
+	}
+	return nil
+}
+
+//ValidateIpandPort validates an annotation's value is valid ip and port
+func ValidateIpandPort(annotation, value string) error {
+	match, err := regexp.MatchString(`(^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.`+
+		`(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.`+
+		`(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.`+
+		`(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])|`+
+		`localhost)\:`+
+		`([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])$`, value)
+
+	if err != nil {
+		return fmt.Errorf("%s error:%s", annotation, err.Error())
+	}
+	if !match {
+		return fmt.Errorf("%s error:not a valid ip and port", annotation)
+	}
+	return nil
+}
diff --git a/pkg/operator/manifests/injector/templates/annotations.yaml b/pkg/operator/manifests/injector/templates/annotations.yaml
new file mode 100644
index 0000000..506db07
--- /dev/null
+++ b/pkg/operator/manifests/injector/templates/annotations.yaml
@@ -0,0 +1,390 @@
+# Licensed to 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. Apache Software Foundation (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.
+
+# name means the reference to configuration used in pod's annotations.
+# defaultValue is the default value in agent.config
+# vaildateFunc means use which function to validate the value
+# Notice , the vaildateFunc must exist in validate.go , 
+# if don't have the vaildateFunc , please set nil
+# useQuotes means a separator(, or =) in the option or value, it should be wrapped in quotes.
+# if there is a separator in the option, then set useQuotes: option
+# if there is a separator in the value, then set useQuotes: value
+# if there isn't a separator,then set useQuotes: nil
+# envName is the environment variable in agent.config
+
+annotations:
+  # Next is the annotation of the sidecar configuration
+  - name: sidecar.skywalking.apache.org/initcontainer.Name
+    defaultValue: inject-skywalking-agent
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/initcontainer.Image
+    defaultValue: apache/skywalking-java-agent:8.7.0-jdk8
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/initcontainer.Command
+    defaultValue: sh
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/initcontainer.args.Option
+    defaultValue: -c
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/initcontainer.args.Command
+    defaultValue: "mkdir -p /sky/agent && cp -r /skywalking/agent/* /sky/agent"
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/sidecarVolume.Name
+    defaultValue: sky-agent
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/sidecarVolumeMount.MountPath
+    defaultValue: /sky/agent
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/configmapVolume.ConfigMap.Name
+    defaultValue: skywalking-swck-java-agent-configmap
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/configmapVolume.Name
+    defaultValue: java-agent-configmap-volume
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/configmapVolumeMount.MountPath
+    defaultValue: /sky/agent/config
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/env.Name
+    defaultValue: AGENT_OPTS
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/env.Value
+    defaultValue: -javaagent:/sky/agent/skywalking-agent.jar
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  # Next is the annotation of the java agent configuration
+  - name: agent.skywalking.apache.org/agent.namespace
+    defaultValue: default-namespace
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_NAMESPACE
+
+  - name: agent.skywalking.apache.org/agent.service_name
+    defaultValue: Your_ApplicationName
+    validateFunc: ValidateServiceName
+    useQuotes: nil
+    envName: SW_AGENT_NAME
+
+  - name: agent.skywalking.apache.org/agent.instance_name
+    defaultValue: nil
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_INSTANCE_NAME
+
+  - name: agent.skywalking.apache.org/agent.sample_n_per_3_secs
+    defaultValue: -1
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_SAMPLE
+
+  - name: agent.skywalking.apache.org/agent.authentication
+    defaultValue: nil
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_AUTHENTICATION
+
+  - name: agent.skywalking.apache.org/agent.span_limit_per_segment
+    defaultValue: 300
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_SPAN_LIMIT
+
+  - name: agent.skywalking.apache.org/agent.ignore_suffix
+    defaultValue: .jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg
+    validateFunc: nil
+    useQuotes: value
+    envName: SW_AGENT_IGNORE_SUFFIX
+
+  - name: agent.skywalking.apache.org/agent.is_open_debugging_class
+    defaultValue: true
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_OPEN_DEBUG
+
+  - name: agent.skywalking.apache.org/agent.is_cache_enhanced_class
+    defaultValue: false
+    validateFunc: nil
+    useQuotes: nil  
+    envName: SW_AGENT_CACHE_CLASS
+
+  - name: agent.skywalking.apache.org/agent.class_cache_mode
+    defaultValue: MEMORY
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_CLASS_CACHE_MODE
+
+  - name: agent.skywalking.apache.org/agent.cause_exception_depth
+    defaultValue: 5
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_CAUSE_EXCEPTION_DEPTH
+
+  - name: agent.skywalking.apache.org/agent.force_reconnection_period
+    defaultValue: 1
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_FORCE_RECONNECTION_PERIOD
+
+  - name: agent.skywalking.apache.org/agent.operation_name_threshold
+    defaultValue: 150
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_OPERATION_NAME_THRESHOLD
+
+  - name: agent.skywalking.apache.org/agent.keep_tracing
+    defaultValue: false
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_KEEP_TRACING
+
+  - name: agent.skywalking.apache.org/agent.force_tls
+    defaultValue: false
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_FORCE_TLS
+
+  - name: agent.skywalking.apache.org/osinfo.ipv4_list_size
+    defaultValue: 10
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_OSINFO_IPV4_LIST_SIZE
+
+  - name: agent.skywalking.apache.org/collector.grpc_channel_check_interval
+    defaultValue: 30
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_COLLECTOR_GRPC_CHANNEL_CHECK_INTERVAL
+
+  - name: agent.skywalking.apache.org/collector.heartbeat_period
+    defaultValue: 30
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_COLLECTOR_HEARTBEAT_PERIOD
+
+  - name: agent.skywalking.apache.org/collector.properties_report_period_factor
+    defaultValue: 10
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_COLLECTOR_PROPERTIES_REPORT_PERIOD_FACTOR
+
+  - name: agent.skywalking.apache.org/collector.backend_service
+    defaultValue: 127.0.0.1:11800
+    validateFunc: ValidateIpandPort
+    useQuotes: nil
+    envName: SW_AGENT_COLLECTOR_BACKEND_SERVICES
+
+  - name: agent.skywalking.apache.org/collector.grpc_upstream_timeout
+    defaultValue: 30
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_COLLECTOR_GRPC_UPSTREAM_TIMEOUT
+
+  - name: agent.skywalking.apache.org/collector.get_profile_task_interval
+    defaultValue: 20
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_COLLECTOR_GET_PROFILE_TASK_INTERVAL 
+
+  - name: agent.skywalking.apache.org/collector.get_agent_dynamic_config_interval
+    defaultValue: 20
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_COLLECTOR_GET_AGENT_DYNAMIC_CONFIG_INTERVAL 
+
+  - name: agent.skywalking.apache.org/collector.is_resolve_dns_periodically
+    defaultValue: false
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_COLLECTOR_IS_RESOLVE_DNS_PERIODICALLY 
+
+  - name: agent.skywalking.apache.org/logging.level
+    defaultValue: INFO
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_LOGGING_LEVEL
+
+  - name: agent.skywalking.apache.org/logging.file_name
+    defaultValue: skywalking-api.log
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_LOGGING_FILE_NAME
+
+  - name: agent.skywalking.apache.org/logging.output
+    defaultValue: FILE
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_LOGGING_OUTPUT
+
+  - name: agent.skywalking.apache.org/logging.dir
+    defaultValue: nil
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_LOGGING_DIR 
+
+  - name: agent.skywalking.apache.org/logging.resolver
+    defaultValue: PATTERN
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_LOGGING_RESOLVER
+
+  - name: agent.skywalking.apache.org/logging.pattern
+    defaultValue: "%level %timestamp %thread %class : %msg %throwable"
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_LOGGING_PATTERN
+
+  - name: agent.skywalking.apache.org/logging.max_file_size
+    defaultValue: 314572800
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_LOGGING_MAX_FILE_SIZE
+
+  - name: agent.skywalking.apache.org/logging.max_history_files
+    defaultValue: -1
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_LOGGING_MAX_HISTORY_FILES  
+
+  - name: agent.skywalking.apache.org/statuscheck.ignored_exceptions
+    defaultValue: nil
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_STATUSCHECK_IGNORED_EXCEPTIONS
+
+  - name: agent.skywalking.apache.org/statuscheck.max_recursive_depth
+    defaultValue: 1
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_STATUSCHECK_MAX_RECURSIVE_DEPTH
+
+  - name: agent.skywalking.apache.org/correlation.element_max_number
+    defaultValue: 3
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_CORRELATION_ELEMENT_MAX_NUMBER
+
+  - name: agent.skywalking.apache.org/correlation.value_max_length
+    defaultValue: 128
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_CORRELATION_VALUE_MAX_LENGTH
+
+  - name: agent.skywalking.apache.org/correlation.auto_tag_keys
+    defaultValue: nil
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_CORRELATION_AUTO_TAG_KEYS
+
+  - name: agent.skywalking.apache.org/jvm.buffer_size
+    defaultValue: 600
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_JVM_BUFFER_SIZE
+
+  - name: agent.skywalking.apache.org/buffer.channel_size
+    defaultValue: 5
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_BUFFER_CHANNEL_SIZE
+
+  - name: agent.skywalking.apache.org/buffer.buffer_size
+    defaultValue: 300
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_BUFFER_BUFFER_SIZE
+
+  - name: agent.skywalking.apache.org/profile.active
+    defaultValue: true
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_PROFILE_ACTIVE
+
+  - name: agent.skywalking.apache.org/profile.max_parallel
+    defaultValue: 5
+    validateFunc: nil
+    useQuotes: nil    
+    envName: SW_AGENT_PROFILE_MAX_PARALLEL
+
+  - name: agent.skywalking.apache.org/profile.duration
+    defaultValue: 10
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_PROFILE_DURATION
+
+  - name: agent.skywalking.apache.org/profile.dump_max_stack_depth
+    defaultValue: 500
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_PROFILE_DUMP_MAX_STACK_DEPTH
+
+  - name: agent.skywalking.apache.org/profile.snapshot_transport_buffer_size
+    defaultValue: 50
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_PROFILE_SNAPSHOT_TRANSPORT_BUFFER_SIZE
+
+  - name: agent.skywalking.apache.org/meter.active
+    defaultValue: true
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_METER_ACTIVE
+
+  - name: agent.skywalking.apache.org/meter.report_interval
+    defaultValue: 20
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_METER_REPORT_INTERVAL
+
+  - name: agent.skywalking.apache.org/meter.max_meter_size
+    defaultValue: 500
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_METER_MAX_METER_SIZE
diff --git a/pkg/operator/manifests/injector/templates/configmap.yaml b/pkg/operator/manifests/injector/templates/configmap.yaml
new file mode 100644
index 0000000..e3b6017
--- /dev/null
+++ b/pkg/operator/manifests/injector/templates/configmap.yaml
@@ -0,0 +1,47 @@
+# Licensed to 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. Apache Software Foundation (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.
+
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: skywalking-swck-java-agent-configmap 
+  namespace: skywalking-swck-system
+data:
+  agent.config: |
+    # 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.
+    {{- $anno := getAgentAnnotations }}
+    {{- range $anno -}}
+    {{- if ne .DefaultValue "nil" }}
+    {{parse .Name}}=${ {{- .EnvName}}:{{.DefaultValue -}} }
+    {{- else}}
+    {{parse .Name}}=${ {{- .EnvName}}:}
+    {{- end -}}
+    {{- end -}}
\ No newline at end of file
diff --git a/pkg/operator/repo/assets.gen.go b/pkg/operator/repo/assets.gen.go
index ec575a6..910ee98 100644
--- a/pkg/operator/repo/assets.gen.go
+++ b/pkg/operator/repo/assets.gen.go
@@ -21,6 +21,8 @@
 // fetcher/templates/configmap.yaml (3.082kB)
 // fetcher/templates/deployment.yaml (2.084kB)
 // fetcher/templates/service_account.yaml (1.088kB)
+// injector/templates/annotations.yaml (11.792kB)
+// injector/templates/configmap.yaml (2.044kB)
 // oapserver/templates/cluster_role.yaml (1.241kB)
 // oapserver/templates/cluster_role_binding.yaml (1.207kB)
 // oapserver/templates/deployment.yaml (3.429kB)
@@ -396,6 +398,476 @@
 	return a, nil
 }
 
+var _injectorTemplatesAnnotationsYaml = []byte(`# Licensed to 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. Apache Software Foundation (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.
+
+# name means the reference to configuration used in pod's annotations.
+# defaultValue is the default value in agent.config
+# vaildateFunc means use which function to validate the value
+# Notice , the vaildateFunc must exist in validate.go , 
+# if don't have the vaildateFunc , please set nil
+# useQuotes means a separator(, or =) in the option or value, it should be wrapped in quotes.
+# if there is a separator in the option, then set useQuotes: option
+# if there is a separator in the value, then set useQuotes: value
+# if there isn't a separator,then set useQuotes: nil
+# envName is the environment variable in agent.config
+
+annotations:
+  # Next is the annotation of the sidecar configuration
+  - name: sidecar.skywalking.apache.org/initcontainer.Name
+    defaultValue: inject-skywalking-agent
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/initcontainer.Image
+    defaultValue: apache/skywalking-java-agent:8.7.0-jdk8
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/initcontainer.Command
+    defaultValue: sh
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/initcontainer.args.Option
+    defaultValue: -c
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/initcontainer.args.Command
+    defaultValue: "mkdir -p /sky/agent && cp -r /skywalking/agent/* /sky/agent"
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/sidecarVolume.Name
+    defaultValue: sky-agent
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/sidecarVolumeMount.MountPath
+    defaultValue: /sky/agent
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/configmapVolume.ConfigMap.Name
+    defaultValue: skywalking-swck-java-agent-configmap
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/configmapVolume.Name
+    defaultValue: java-agent-configmap-volume
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/configmapVolumeMount.MountPath
+    defaultValue: /sky/agent/config
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/env.Name
+    defaultValue: AGENT_OPTS
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  - name: sidecar.skywalking.apache.org/env.Value
+    defaultValue: -javaagent:/sky/agent/skywalking-agent.jar
+    validateFunc: nil
+    useQuotes: nil
+    envName: nil
+
+  # Next is the annotation of the java agent configuration
+  - name: agent.skywalking.apache.org/agent.namespace
+    defaultValue: default-namespace
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_NAMESPACE
+
+  - name: agent.skywalking.apache.org/agent.service_name
+    defaultValue: Your_ApplicationName
+    validateFunc: ValidateServiceName
+    useQuotes: nil
+    envName: SW_AGENT_NAME
+
+  - name: agent.skywalking.apache.org/agent.instance_name
+    defaultValue: nil
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_INSTANCE_NAME
+
+  - name: agent.skywalking.apache.org/agent.sample_n_per_3_secs
+    defaultValue: -1
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_SAMPLE
+
+  - name: agent.skywalking.apache.org/agent.authentication
+    defaultValue: nil
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_AUTHENTICATION
+
+  - name: agent.skywalking.apache.org/agent.span_limit_per_segment
+    defaultValue: 300
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_SPAN_LIMIT
+
+  - name: agent.skywalking.apache.org/agent.ignore_suffix
+    defaultValue: .jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg
+    validateFunc: nil
+    useQuotes: value
+    envName: SW_AGENT_IGNORE_SUFFIX
+
+  - name: agent.skywalking.apache.org/agent.is_open_debugging_class
+    defaultValue: true
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_OPEN_DEBUG
+
+  - name: agent.skywalking.apache.org/agent.is_cache_enhanced_class
+    defaultValue: false
+    validateFunc: nil
+    useQuotes: nil  
+    envName: SW_AGENT_CACHE_CLASS
+
+  - name: agent.skywalking.apache.org/agent.class_cache_mode
+    defaultValue: MEMORY
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_CLASS_CACHE_MODE
+
+  - name: agent.skywalking.apache.org/agent.cause_exception_depth
+    defaultValue: 5
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_CAUSE_EXCEPTION_DEPTH
+
+  - name: agent.skywalking.apache.org/agent.force_reconnection_period
+    defaultValue: 1
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_FORCE_RECONNECTION_PERIOD
+
+  - name: agent.skywalking.apache.org/agent.operation_name_threshold
+    defaultValue: 150
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_OPERATION_NAME_THRESHOLD
+
+  - name: agent.skywalking.apache.org/agent.keep_tracing
+    defaultValue: false
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_KEEP_TRACING
+
+  - name: agent.skywalking.apache.org/agent.force_tls
+    defaultValue: false
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_FORCE_TLS
+
+  - name: agent.skywalking.apache.org/osinfo.ipv4_list_size
+    defaultValue: 10
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_OSINFO_IPV4_LIST_SIZE
+
+  - name: agent.skywalking.apache.org/collector.grpc_channel_check_interval
+    defaultValue: 30
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_COLLECTOR_GRPC_CHANNEL_CHECK_INTERVAL
+
+  - name: agent.skywalking.apache.org/collector.heartbeat_period
+    defaultValue: 30
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_COLLECTOR_HEARTBEAT_PERIOD
+
+  - name: agent.skywalking.apache.org/collector.properties_report_period_factor
+    defaultValue: 10
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_COLLECTOR_PROPERTIES_REPORT_PERIOD_FACTOR
+
+  - name: agent.skywalking.apache.org/collector.backend_service
+    defaultValue: 127.0.0.1:11800
+    validateFunc: ValidateIpandPort
+    useQuotes: nil
+    envName: SW_AGENT_COLLECTOR_BACKEND_SERVICES
+
+  - name: agent.skywalking.apache.org/collector.grpc_upstream_timeout
+    defaultValue: 30
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_COLLECTOR_GRPC_UPSTREAM_TIMEOUT
+
+  - name: agent.skywalking.apache.org/collector.get_profile_task_interval
+    defaultValue: 20
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_COLLECTOR_GET_PROFILE_TASK_INTERVAL 
+
+  - name: agent.skywalking.apache.org/collector.get_agent_dynamic_config_interval
+    defaultValue: 20
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_COLLECTOR_GET_AGENT_DYNAMIC_CONFIG_INTERVAL 
+
+  - name: agent.skywalking.apache.org/collector.is_resolve_dns_periodically
+    defaultValue: false
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_COLLECTOR_IS_RESOLVE_DNS_PERIODICALLY 
+
+  - name: agent.skywalking.apache.org/logging.level
+    defaultValue: INFO
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_LOGGING_LEVEL
+
+  - name: agent.skywalking.apache.org/logging.file_name
+    defaultValue: skywalking-api.log
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_LOGGING_FILE_NAME
+
+  - name: agent.skywalking.apache.org/logging.output
+    defaultValue: FILE
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_LOGGING_OUTPUT
+
+  - name: agent.skywalking.apache.org/logging.dir
+    defaultValue: nil
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_LOGGING_DIR 
+
+  - name: agent.skywalking.apache.org/logging.resolver
+    defaultValue: PATTERN
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_LOGGING_RESOLVER
+
+  - name: agent.skywalking.apache.org/logging.pattern
+    defaultValue: "%level %timestamp %thread %class : %msg %throwable"
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_LOGGING_PATTERN
+
+  - name: agent.skywalking.apache.org/logging.max_file_size
+    defaultValue: 314572800
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_LOGGING_MAX_FILE_SIZE
+
+  - name: agent.skywalking.apache.org/logging.max_history_files
+    defaultValue: -1
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_LOGGING_MAX_HISTORY_FILES  
+
+  - name: agent.skywalking.apache.org/statuscheck.ignored_exceptions
+    defaultValue: nil
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_STATUSCHECK_IGNORED_EXCEPTIONS
+
+  - name: agent.skywalking.apache.org/statuscheck.max_recursive_depth
+    defaultValue: 1
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_STATUSCHECK_MAX_RECURSIVE_DEPTH
+
+  - name: agent.skywalking.apache.org/correlation.element_max_number
+    defaultValue: 3
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_CORRELATION_ELEMENT_MAX_NUMBER
+
+  - name: agent.skywalking.apache.org/correlation.value_max_length
+    defaultValue: 128
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_CORRELATION_VALUE_MAX_LENGTH
+
+  - name: agent.skywalking.apache.org/correlation.auto_tag_keys
+    defaultValue: nil
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_CORRELATION_AUTO_TAG_KEYS
+
+  - name: agent.skywalking.apache.org/jvm.buffer_size
+    defaultValue: 600
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_JVM_BUFFER_SIZE
+
+  - name: agent.skywalking.apache.org/buffer.channel_size
+    defaultValue: 5
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_BUFFER_CHANNEL_SIZE
+
+  - name: agent.skywalking.apache.org/buffer.buffer_size
+    defaultValue: 300
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_BUFFER_BUFFER_SIZE
+
+  - name: agent.skywalking.apache.org/profile.active
+    defaultValue: true
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_PROFILE_ACTIVE
+
+  - name: agent.skywalking.apache.org/profile.max_parallel
+    defaultValue: 5
+    validateFunc: nil
+    useQuotes: nil    
+    envName: SW_AGENT_PROFILE_MAX_PARALLEL
+
+  - name: agent.skywalking.apache.org/profile.duration
+    defaultValue: 10
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_PROFILE_DURATION
+
+  - name: agent.skywalking.apache.org/profile.dump_max_stack_depth
+    defaultValue: 500
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_PROFILE_DUMP_MAX_STACK_DEPTH
+
+  - name: agent.skywalking.apache.org/profile.snapshot_transport_buffer_size
+    defaultValue: 50
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_AGENT_PROFILE_SNAPSHOT_TRANSPORT_BUFFER_SIZE
+
+  - name: agent.skywalking.apache.org/meter.active
+    defaultValue: true
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_METER_ACTIVE
+
+  - name: agent.skywalking.apache.org/meter.report_interval
+    defaultValue: 20
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_METER_REPORT_INTERVAL
+
+  - name: agent.skywalking.apache.org/meter.max_meter_size
+    defaultValue: 500
+    validateFunc: nil
+    useQuotes: nil
+    envName: SW_METER_MAX_METER_SIZE
+`)
+
+func injectorTemplatesAnnotationsYamlBytes() ([]byte, error) {
+	return _injectorTemplatesAnnotationsYaml, nil
+}
+
+func injectorTemplatesAnnotationsYaml() (*asset, error) {
+	bytes, err := injectorTemplatesAnnotationsYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "injector/templates/annotations.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x80, 0x70, 0xea, 0x8c, 0x8a, 0xa2, 0xc3, 0x6a, 0xec, 0x88, 0x88, 0x90, 0x41, 0x13, 0xe7, 0x8f, 0x23, 0xba, 0x13, 0x44, 0x89, 0x20, 0xed, 0xbe, 0xa2, 0xdd, 0x40, 0x71, 0xa6, 0x67, 0xf0, 0xdd}}
+	return a, nil
+}
+
+var _injectorTemplatesConfigmapYaml = []byte(`# Licensed to 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. Apache Software Foundation (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.
+
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: skywalking-swck-java-agent-configmap 
+  namespace: skywalking-swck-system
+data:
+  agent.config: |
+    # 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.
+    {{- $anno := getAgentAnnotations }}
+    {{- range $anno -}}
+    {{- if ne .DefaultValue "nil" }}
+    {{parse .Name}}=${ {{- .EnvName}}:{{.DefaultValue -}} }
+    {{- else}}
+    {{parse .Name}}=${ {{- .EnvName}}:}
+    {{- end -}}
+    {{- end -}}`)
+
+func injectorTemplatesConfigmapYamlBytes() ([]byte, error) {
+	return _injectorTemplatesConfigmapYaml, nil
+}
+
+func injectorTemplatesConfigmapYaml() (*asset, error) {
+	bytes, err := injectorTemplatesConfigmapYamlBytes()
+	if err != nil {
+		return nil, err
+	}
+
+	info := bindataFileInfo{name: "injector/templates/configmap.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
+	a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa4, 0xf9, 0x1c, 0x4f, 0x27, 0xe7, 0x88, 0xed, 0xfb, 0xf0, 0x9c, 0xa1, 0x33, 0x40, 0xba, 0x8c, 0xf3, 0x0, 0x71, 0xfc, 0xa9, 0x2b, 0x46, 0x1d, 0x53, 0xb3, 0x48, 0xd3, 0x1b, 0x5d, 0xe7, 0x9f}}
+	return a, nil
+}
+
 var _oapserverTemplatesCluster_roleYaml = []byte(`# Licensed to Apache Software Foundation (ASF) under one or more contributor
 # license agreements. See the NOTICE file distributed with
 # this work for additional information regarding copyright
@@ -1126,6 +1598,8 @@
 	"fetcher/templates/configmap.yaml":              fetcherTemplatesConfigmapYaml,
 	"fetcher/templates/deployment.yaml":             fetcherTemplatesDeploymentYaml,
 	"fetcher/templates/service_account.yaml":        fetcherTemplatesService_accountYaml,
+	"injector/templates/annotations.yaml":           injectorTemplatesAnnotationsYaml,
+	"injector/templates/configmap.yaml":             injectorTemplatesConfigmapYaml,
 	"oapserver/templates/cluster_role.yaml":         oapserverTemplatesCluster_roleYaml,
 	"oapserver/templates/cluster_role_binding.yaml": oapserverTemplatesCluster_role_bindingYaml,
 	"oapserver/templates/deployment.yaml":           oapserverTemplatesDeploymentYaml,
@@ -1190,6 +1664,12 @@
 			"service_account.yaml":      &bintree{fetcherTemplatesService_accountYaml, map[string]*bintree{}},
 		}},
 	}},
+	"injector": &bintree{nil, map[string]*bintree{
+		"templates": &bintree{nil, map[string]*bintree{
+			"annotations.yaml": &bintree{injectorTemplatesAnnotationsYaml, map[string]*bintree{}},
+			"configmap.yaml":   &bintree{injectorTemplatesConfigmapYaml, map[string]*bintree{}},
+		}},
+	}},
 	"oapserver": &bintree{nil, map[string]*bintree{
 		"templates": &bintree{nil, map[string]*bintree{
 			"cluster_role.yaml":         &bintree{oapserverTemplatesCluster_roleYaml, map[string]*bintree{}},