From 8e04fce8f43e05042318eea83cb89f1b158a0e63 Mon Sep 17 00:00:00 2001 From: dashanji <952129620@qq.com> Date: Wed, 16 Jun 2021 21:49:20 +0800 Subject: [PATCH 01/13] add feature-injector --- apis/operator/v1alpha1/oapserver_webhook.go | 5 + cmd/manager/manager.go | 8 ++ config/operator/webhook/add_nsSelector.yaml | 31 ++++ config/operator/webhook/kustomization.yaml | 3 + config/operator/webhook/manifests.yaml | 18 +++ main.go | 9 ++ pkg/operator/injector/injector.go | 134 +++++++++++++++++ pkg/operator/injector/injector_test.go | 151 ++++++++++++++++++++ 8 files changed, 359 insertions(+) create mode 100644 config/operator/webhook/add_nsSelector.yaml create mode 100644 pkg/operator/injector/injector.go create mode 100644 pkg/operator/injector/injector_test.go diff --git a/apis/operator/v1alpha1/oapserver_webhook.go b/apis/operator/v1alpha1/oapserver_webhook.go index c0e09a82..a38a6b5e 100644 --- a/apis/operator/v1alpha1/oapserver_webhook.go +++ b/apis/operator/v1alpha1/oapserver_webhook.go @@ -37,6 +37,11 @@ func (r *OAPServer) SetupWebhookWithManager(mgr ctrl.Manager) error { Complete() } +// nolint: lll +// this line is to have controller-gen generate the webhook configuration, +// the real path /mutate-v1-pod is handled in injector_webhook.go +// +kubebuilder:webhook:path=/mutate-v1-pod,mutating=true,failurePolicy=fail,groups="",resources=pods,verbs=create;update,versions=v1,name=mpod.kb.io + // nolint: lll // +kubebuilder:webhook:path=/mutate-operator-skywalking-apache-org-v1alpha1-oapserver,mutating=true,failurePolicy=fail,groups=operator.skywalking.apache.org,resources=oapservers,verbs=create;update,versions=v1alpha1,name=moapserver.kb.io diff --git a/cmd/manager/manager.go b/cmd/manager/manager.go index f85fd824..10cba446 100644 --- a/cmd/manager/manager.go +++ b/cmd/manager/manager.go @@ -26,9 +26,11 @@ import ( _ "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" + "github.com/apache/skywalking-swck/pkg/operator/injector" "github.com/apache/skywalking-swck/pkg/operator/repo" // +kubebuilder:scaffold:imports ) @@ -116,6 +118,12 @@ func main() { 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: &injector.PodInjector{Client: mgr.GetClient()}}) + setupLog.Info("/mutate-v1-pod webhook is registered") } // +kubebuilder:scaffold:builder diff --git a/config/operator/webhook/add_nsSelector.yaml b/config/operator/webhook/add_nsSelector.yaml new file mode 100644 index 00000000..175acc2b --- /dev/null +++ b/config/operator/webhook/add_nsSelector.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/config/operator/webhook/kustomization.yaml b/config/operator/webhook/kustomization.yaml index 83db5a8d..e8fb8387 100644 --- a/config/operator/webhook/kustomization.yaml +++ b/config/operator/webhook/kustomization.yaml @@ -19,6 +19,9 @@ resources: - service.yaml - manifests.yaml +patchesStrategicMerge: +- add_nsSelector.yaml + configurations: - kustomizeconfig.yaml diff --git a/config/operator/webhook/manifests.yaml b/config/operator/webhook/manifests.yaml index 649d2beb..ff62b0d0 100644 --- a/config/operator/webhook/manifests.yaml +++ b/config/operator/webhook/manifests.yaml @@ -41,6 +41,24 @@ webhooks: - UPDATE resources: - fetchers +- clientConfig: + caBundle: Cg== + 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: diff --git a/main.go b/main.go index 495d8463..98c00243 100644 --- a/main.go +++ b/main.go @@ -26,10 +26,12 @@ import ( _ "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" operatorcontroller "github.com/apache/skywalking-swck/controllers/operator" + "github.com/apache/skywalking-swck/pkg/operator/injector" "github.com/apache/skywalking-swck/pkg/operator/repo" // +kubebuilder:scaffold:imports ) @@ -116,6 +118,13 @@ func main() { } // +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: &injector.PodInjector{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/operator/injector/injector.go b/pkg/operator/injector/injector.go new file mode 100644 index 00000000..268b509a --- /dev/null +++ b/pkg/operator/injector/injector.go @@ -0,0 +1,134 @@ +package injector + +import ( + "context" + "encoding/json" + "net/http" + "strings" + + 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" +) + +const ( + annotationKeyagentInjector = "swck-agent-injected" +) + +// PodInjector injects agent into Pods +type PodInjector struct { + Client client.Client + decoder *admission.Decoder +} + +// PodInjector will process every comming pod under the +// specified namespace which labeled "swck-injection=enabled" +func (r *PodInjector) Handle(ctx context.Context, req admission.Request) admission.Response { + pod := &corev1.Pod{} + PodInjectorLog := logf.Log.WithName("PodInjector") + err := r.decoder.Decode(req, pod) + if err != nil { + return admission.Errored(http.StatusBadRequest, err) + } + + //if the pod don't have the label "swck-agent-injected=true",return ok + if !needInject(pod) { + PodInjectorLog.Info("don't inject agent") + return admission.Allowed("ok") + } + + //if the pod has the label "swck-agent-injected=true",add agent + addAgent(pod) + PodInjectorLog.Info("will inject agent,please wait for a moment!") + + marshaledPod, err := json.Marshal(pod) + if err != nil { + return admission.Errored(http.StatusInternalServerError, err) + } + + return admission.PatchResponseFromRaw(req.Object.Raw, marshaledPod) +} + +// PodInjector implements admission.DecoderInjector. +// A decoder will be automatically injected. + +// InjectDecoder injects the decoder. +func (r *PodInjector) InjectDecoder(d *admission.Decoder) error { + r.decoder = d + return nil +} + +//if pod has label "swck-agent-injected=true" , it means the pod needs agent injected +func needInject(pod *corev1.Pod) bool { + injected := false + + labels := pod.ObjectMeta.Labels + if labels == nil { + return injected + } + + switch strings.ToLower(labels[annotationKeyagentInjector]) { + case "true": + injected = true + } + + return injected +} + +//when agent is injected,we need to push agent image and +// mount the volume to the specified directory +func addAgent(pod *corev1.Pod) { + // set InitContainer's VolumeMount + vm := corev1.VolumeMount{ + MountPath: "/sky/agent", + Name: "sky-agent", + } + + // set the agent image to be injected + needAddInitContainer := corev1.Container{ + Name: "inject-sky-agent", + Image: "apache/skywalking-java-agent:8.6.0-jdk8", + Command: []string{"sh"}, + Args: []string{"-c", "mkdir -p /sky/agent && cp -r /skywalking/agent/* /sky/agent"}, + VolumeMounts: []corev1.VolumeMount{vm}, + } + + // set emptyDir Volume + needAddVolumes := corev1.Volume{ + Name: "sky-agent", + VolumeSource: corev1.VolumeSource{EmptyDir: nil}, + } + + // set container's VolumeMount + needAddVolumeMount := corev1.VolumeMount{ + MountPath: "/sky/agent", + Name: "sky-agent", + } + + // set container's EnvVar + needAddEnv := corev1.EnvVar{ + Name: "AGENT_OPTS", + Value: " -javaagent:/sky/agent/skywalking-agent.jar", + } + + // add VolumeMount to spec + if pod.Spec.Volumes != nil { + pod.Spec.Volumes = append(pod.Spec.Volumes, needAddVolumes) + } else { + pod.Spec.Volumes = []corev1.Volume{needAddVolumes} + } + + // add InitContrainers to spec + if pod.Spec.InitContainers != nil { + pod.Spec.InitContainers = append(pod.Spec.InitContainers, needAddInitContainer) + } else { + pod.Spec.InitContainers = []corev1.Container{needAddInitContainer} + } + + // add VolumeMount and env to every container + for i := 0; i < len(pod.Spec.Containers); i++ { + pod.Spec.Containers[i].VolumeMounts = append(pod.Spec.Containers[i].VolumeMounts, needAddVolumeMount) + pod.Spec.Containers[i].Env = append(pod.Spec.Containers[i].Env, needAddEnv) + } +} diff --git a/pkg/operator/injector/injector_test.go b/pkg/operator/injector/injector_test.go new file mode 100644 index 00000000..ce0ef1e4 --- /dev/null +++ b/pkg/operator/injector/injector_test.go @@ -0,0 +1,151 @@ +package injector + +import ( + "reflect" + "testing" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func Test_needInject(t *testing.T) { + type args struct { + pod *corev1.Pod + } + + // set a pod with a wrong label + unlabeled_pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "swck-agent-injected": "false", + }, + }, + } + + // set a pod with a right label + labeled_pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "swck-agent-injected": "true", + }, + }, + } + + tests := []struct { + name string + args args + want bool + }{ + { + name: "don't need injected", + args: args{ + pod: unlabeled_pod, + }, + // false means we don't need injected + want: false, + }, + { + name: "need injected", + args: args{ + pod: labeled_pod, + }, + // true means we need injected + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := needInject(tt.args.pod); got != tt.want { + t.Errorf("needInject() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_addAgent(t *testing.T) { + type args struct { + pod *corev1.Pod + } + + Pod := &corev1.Pod{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + corev1.Container{ + Name: "app", + }, + }, + }, + } + + // injected InitContainer's VolumeMount + injectedICVM := corev1.VolumeMount{ + MountPath: "/sky/agent", + Name: "sky-agent", + } + + // injected InitContainer + injectedIC := corev1.Container{ + Name: "inject-sky-agent", + Image: "apache/skywalking-java-agent:8.6.0-jdk8", + Command: []string{"sh"}, + Args: []string{"-c", "mkdir -p /sky/agent && cp -r /skywalking/agent/* /sky/agent"}, + VolumeMounts: []corev1.VolumeMount{injectedICVM}, + } + + // injected Volumes + injectedV := corev1.Volume{ + Name: "sky-agent", + VolumeSource: corev1.VolumeSource{EmptyDir: nil}, + } + + // injected Container's VolumeMount + injectedVM := corev1.VolumeMount{ + MountPath: "/sky/agent", + Name: "sky-agent", + } + + // injected Container's EnvVar + injectedEV := corev1.EnvVar{ + Name: "AGENT_OPTS", + Value: " -javaagent:/sky/agent/skywalking-agent.jar", + } + + injectedPod := &corev1.Pod{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + corev1.Container{ + Name: "app", + VolumeMounts: []corev1.VolumeMount{ + injectedVM, + }, + Env: []corev1.EnvVar{ + injectedEV, + }, + }, + }, + InitContainers: []corev1.Container{ + injectedIC, + }, + Volumes: []corev1.Volume{ + injectedV, + }, + }, + } + tests := []struct { + name string + args args + }{ + { + name: "test injected", + args: args{Pod}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + addAgent(tt.args.pod) + if !reflect.DeepEqual(Pod, tt.args.pod) { + t.Errorf("needInject() = %v, want %v end", Pod, injectedPod) + } + }) + } +} From 4a1e02d0c05e0462ddd70be2e9a86cee8ccd7375 Mon Sep 17 00:00:00 2001 From: dashanji <952129620@qq.com> Date: Wed, 16 Jun 2021 22:10:54 +0800 Subject: [PATCH 02/13] add license --- pkg/operator/injector/injector.go | 17 +++++++++++++++++ pkg/operator/injector/injector_test.go | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/pkg/operator/injector/injector.go b/pkg/operator/injector/injector.go index 268b509a..f4059d21 100644 --- a/pkg/operator/injector/injector.go +++ b/pkg/operator/injector/injector.go @@ -1,3 +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. + package injector import ( diff --git a/pkg/operator/injector/injector_test.go b/pkg/operator/injector/injector_test.go index ce0ef1e4..d946a25c 100644 --- a/pkg/operator/injector/injector_test.go +++ b/pkg/operator/injector/injector_test.go @@ -1,3 +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. + package injector import ( From c75219873b245899d98ca59020bd50e3cbd43d0e Mon Sep 17 00:00:00 2001 From: dashanji <952129620@qq.com> Date: Wed, 16 Jun 2021 23:08:55 +0800 Subject: [PATCH 03/13] fix naming errors --- apis/operator/v1alpha1/oapserver_webhook.go | 2 +- pkg/operator/injector/injector.go | 2 +- pkg/operator/injector/injector_test.go | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apis/operator/v1alpha1/oapserver_webhook.go b/apis/operator/v1alpha1/oapserver_webhook.go index a38a6b5e..1de388d8 100644 --- a/apis/operator/v1alpha1/oapserver_webhook.go +++ b/apis/operator/v1alpha1/oapserver_webhook.go @@ -39,7 +39,7 @@ func (r *OAPServer) SetupWebhookWithManager(mgr ctrl.Manager) error { // nolint: lll // this line is to have controller-gen generate the webhook configuration, -// the real path /mutate-v1-pod is handled in injector_webhook.go +// the real path /mutate-v1-pod is handled in injector.go // +kubebuilder:webhook:path=/mutate-v1-pod,mutating=true,failurePolicy=fail,groups="",resources=pods,verbs=create;update,versions=v1,name=mpod.kb.io // nolint: lll diff --git a/pkg/operator/injector/injector.go b/pkg/operator/injector/injector.go index f4059d21..72a3daee 100644 --- a/pkg/operator/injector/injector.go +++ b/pkg/operator/injector/injector.go @@ -39,7 +39,7 @@ type PodInjector struct { decoder *admission.Decoder } -// PodInjector will process every comming pod under the +// PodInjector will process every coming pod under the // specified namespace which labeled "swck-injection=enabled" func (r *PodInjector) Handle(ctx context.Context, req admission.Request) admission.Response { pod := &corev1.Pod{} diff --git a/pkg/operator/injector/injector_test.go b/pkg/operator/injector/injector_test.go index d946a25c..767ec933 100644 --- a/pkg/operator/injector/injector_test.go +++ b/pkg/operator/injector/injector_test.go @@ -31,7 +31,7 @@ func Test_needInject(t *testing.T) { } // set a pod with a wrong label - unlabeled_pod := &corev1.Pod{ + unlabeledPod := &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{ "swck-agent-injected": "false", @@ -40,7 +40,7 @@ func Test_needInject(t *testing.T) { } // set a pod with a right label - labeled_pod := &corev1.Pod{ + labeledPod := &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{ "swck-agent-injected": "true", @@ -56,7 +56,7 @@ func Test_needInject(t *testing.T) { { name: "don't need injected", args: args{ - pod: unlabeled_pod, + pod: unlabeledPod, }, // false means we don't need injected want: false, @@ -64,7 +64,7 @@ func Test_needInject(t *testing.T) { { name: "need injected", args: args{ - pod: labeled_pod, + pod: labeledPod, }, // true means we need injected want: true, From b52d3dae8ed2235e447609da223abb7eb0ee612e Mon Sep 17 00:00:00 2001 From: dashanji <952129620@qq.com> Date: Sat, 14 Aug 2021 18:45:14 +0800 Subject: [PATCH 04/13] add configmap * add a default configmap to save the default agent config * when create operator, the configmap will be created --- config/operator/configmap/configmap.yaml | 138 +++++++++++++++++++ config/operator/configmap/kustomization.yaml | 20 +++ config/operator/default/kustomization.yaml | 1 + 3 files changed, 159 insertions(+) create mode 100644 config/operator/configmap/configmap.yaml create mode 100644 config/operator/configmap/kustomization.yaml diff --git a/config/operator/configmap/configmap.yaml b/config/operator/configmap/configmap.yaml new file mode 100644 index 00000000..7e53c523 --- /dev/null +++ b/config/operator/configmap/configmap.yaml @@ -0,0 +1,138 @@ +# 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:default-namespace} + + # The service name in UI + agent.service_name=${SW_AGENT_NAME:Your_ApplicationName} + + # 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:xxxx} + + # 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:150} + + # 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:true} + + # 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} + + # 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} + + # 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} + + # 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.max_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} + + # Backend service addresses. + collector.backend_service=${SW_AGENT_COLLECTOR_BACKEND_SERVICES:127.0.0.1:11800} + + # Logging file_name + logging.file_name=${SW_LOGGING_FILE_NAME:skywalking-api.log} + + # Logging level + logging.level=${SW_LOGGING_LEVEL:INFO} + + # Logging dir + # logging.dir=${SW_LOGGING_DIR:""} + + # 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} + + # Mount the specific folders of the plugins. Plugins in mounted folders would work. + plugin.mount=${SW_MOUNT_FOLDERS:plugins,activations} + + # Exclude activated plugins + # plugin.exclude_plugins=${SW_EXCLUDE_PLUGINS:} + + # 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} + + # Kafka producer configuration + # plugin.kafka.bootstrap_servers=${SW_KAFKA_BOOTSTRAP_SERVERS:localhost:9092} + # if you want to set namespace. please make sure the OAP server has set it in Kafka fetcher module + # plugin.kafka.namespace=${SW_KAFKA_NAMESPACE:""} + + # Match spring bean with regex expression for classname + # plugin.springannotation.classname_match_regex=${SW_SPRINGANNOTATION_CLASSNAME_MATCH_REGEX:} diff --git a/config/operator/configmap/kustomization.yaml b/config/operator/configmap/kustomization.yaml new file mode 100644 index 00000000..294f574e --- /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 f374c380..9aa10073 100644 --- a/config/operator/default/kustomization.yaml +++ b/config/operator/default/kustomization.yaml @@ -35,6 +35,7 @@ bases: - ../manager - ../webhook - ../certmanager +- ../configmap patchesStrategicMerge: # Protect the /metrics endpoint by putting it behind auth. From ee06d5d656501559aeae1c7f39b586a940730e0c Mon Sep 17 00:00:00 2001 From: dashanji <952129620@qq.com> Date: Sat, 14 Aug 2021 18:52:42 +0800 Subject: [PATCH 05/13] 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 --- pkg/operator/injector/annotation.go | 134 ++++++++++++++++++++++++++++ pkg/operator/injector/constants.go | 74 +++++++++++++++ pkg/operator/injector/validate.go | 107 ++++++++++++++++++++++ 3 files changed, 315 insertions(+) create mode 100644 pkg/operator/injector/annotation.go create mode 100644 pkg/operator/injector/constants.go create mode 100644 pkg/operator/injector/validate.go diff --git a/pkg/operator/injector/annotation.go b/pkg/operator/injector/annotation.go new file mode 100644 index 00000000..d5914fb3 --- /dev/null +++ b/pkg/operator/injector/annotation.go @@ -0,0 +1,134 @@ +// 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 + +//Annotation is used to set default value +type Annotation struct { + Name string + DefaultValue string +} + +//Annotations is used to set overlaied value +type Annotations map[Annotation]string + +func setDefaultAnnotation(name, value string) Annotation { + return Annotation{ + Name: name, + DefaultValue: value, + } +} + +const ( + namePrefix = "skywalking-swck-" +) + +// nolint +var ( + //set sidecar's basic information + AnnoInitcontainerName = setDefaultAnnotation(SidecarInitcontainerName, "inject-sky-agent") + AnnoInitcontainerImage = setDefaultAnnotation(SidecarInitcontainerImage, + "apache/skywalking-java-agent:8.6.0-jdk8") + AnnoInitcontainerCommand = setDefaultAnnotation(SidecarInitcontainerCommand, "sh") + AnnoInitcontainerArgsOption = setDefaultAnnotation(SidecarInitcontainerArgsOption, "-c") + AnnoInitcontainerArgsCommand = setDefaultAnnotation(SidecarInitcontainerArgsCommand, + "mkdir -p /sky/agent && cp -r /skywalking/agent/* /sky/agent") + AnnoSidecarVolumeName = setDefaultAnnotation(SidecarVolumeName, "sky-agent") + AnnoSidecarVolumemountMountpath = setDefaultAnnotation(SidecarVolumemountMountpath, "/sky/agent") + AnnoConfigmapName = setDefaultAnnotation(ConfigmapName, namePrefix+"java-agent-configmap") + AnnoConfigmapVolumeName = setDefaultAnnotation(ConfigmapVolumeName, "java-agent-configmap-volume") + AnnoConfigmapVolumemountMountpath = setDefaultAnnotation(ConfigmapVolumemountMountpath, "/sky/agent/config") + AnnoEnvVarName = setDefaultAnnotation(SidecarEnvVarName, "AGENT_OPTS") + AnnoEnvVarValue = setDefaultAnnotation(SidecarEnvValue, + "-javaagent:/sky/agent/skywalking-agent.jar") + AnnoInjectContainerName = setDefaultAnnotation(SidecarInjectContainerName, "") + //set nil + AnnoInjectErrorInfo = setDefaultAnnotation(SidecarInjectErrorInfo, "") + AnnoAgentConfigOverlay = setDefaultAnnotation(SidecarAgentConfigOverlay, "false") + //set agent config + AnnoAgentNamespace = setDefaultAnnotation(AgentNamespace, "default-namespace") + AnnoAgentServiceName = setDefaultAnnotation(AgentServiceName, "") + AnnoAgentSampleNumber = setDefaultAnnotation(AgentSampleNumber, "-1") + AnnoAgentAuthentication = setDefaultAnnotation(AgentAuthentication, "xxxx") + AnnoAgentSpanLimit = setDefaultAnnotation(AgentSpanLimit, "150") + AnnoAgentIgnoreSuffix = setDefaultAnnotation(AgentIgnoreSuffix, + ".jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg") + AnnoAgentIsOpenDebugging = setDefaultAnnotation(AgentIsOpenDebugging, "true") + AnnoAgentIsCacheEnhaned = setDefaultAnnotation(AgentIsCacheEnhaned, "false") + AnnoAgentClassCache = setDefaultAnnotation(AgentClassCache, "MEMORY") + AnnoAgentOperationName = setDefaultAnnotation(AgentOperationName, "150") + AnnoAgentForceTLS = setDefaultAnnotation(AgentForceTLS, "false") + AnnoAgentProfileActive = setDefaultAnnotation(AgentProfileActive, "true") + AnnoAgentProfileMaxParallel = setDefaultAnnotation(AgentProfileMaxParallel, "5") + AnnoAgentProfileMaxDuration = setDefaultAnnotation(AgentProfileMaxDuration, "10") + AnnoAgentProfileDump = setDefaultAnnotation(AgentProfileDump, "500") + AnnoAgentProfileSnapshot = setDefaultAnnotation(AgentProfileSnapshot, "50") + AnnoAgentCollectorService = setDefaultAnnotation(AgentCollectorService, "127.0.0.1:11800") + AnnoAgentLoggingName = setDefaultAnnotation(AgentLoggingName, "skywalking-api.log") + AnnoAgentLoggingLevel = setDefaultAnnotation(AgentLoggingLevel, "INFO") + AnnoAgentLoggingDir = setDefaultAnnotation(AgentLoggingDir, "") + AnnoAgentLoggingMaxSize = setDefaultAnnotation(AgentLoggingMaxSize, "314572800") + AnnoAgentLoggingMaxFiles = setDefaultAnnotation(AgentLoggingMaxFiles, "-1") + AnnoAgentStatuscheckExceptions = setDefaultAnnotation(AgentStatuscheckExceptions, "") + AnnoAgentStatuscheckDepth = setDefaultAnnotation(AgentStatuscheckDepth, "1") + AnnoAgentPluginMount = setDefaultAnnotation(AgentPluginMount, "plugins,activations") + AnnoAgentExcludePlugins = setDefaultAnnotation(AgentExcludePlugins, "") + AnnoAgentPluginJdbc = setDefaultAnnotation(AgentPluginJdbc, "false") + AnnoAgentPluginKafkaServers = setDefaultAnnotation(AgentPluginKafkaServers, "localhost:9092") + AnnoAgentPluginKafkaNamespace = setDefaultAnnotation(AgentPluginKafkaNamespace, "") + AnnoAgentPluginSpringannotation = setDefaultAnnotation(AgentPluginSpringannotation, "") +) + +//NewAnnotations will create a new Annotations +func NewAnnotations() *Annotations { + a := make(Annotations) + return &a +} + +//GetFinalValue will get overlaied value first , then default +func (as *Annotations) GetFinalValue(a Annotation) string { + ov := a.DefaultValue + if v, ok := (*as)[a]; ok { + ov = v + } + return ov +} + +//SetOverlay will set overlaied value +func (as *Annotations) SetOverlay(annotations *map[string]string, a Annotation) error { + if v, ok := (*annotations)[a.Name]; ok { + //if annotation has validate func then validate + if f, funok := AnnotationValidate[a.Name]; funok { + 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 *Annotations) GetOverlayValue(a Annotation) string { + if v, ok := (*as)[a]; ok { + return v + } + return "" +} diff --git a/pkg/operator/injector/constants.go b/pkg/operator/injector/constants.go new file mode 100644 index 00000000..1ee9937d --- /dev/null +++ b/pkg/operator/injector/constants.go @@ -0,0 +1,74 @@ +// 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 + +// nolint +const ( + //the annotation that contain the sidecar's basic information,such as agent container..etc + SidecarInitcontainerName = "sidecar.skywalking.apache.org/initcontainers.name" + SidecarInitcontainerImage = "sidecar.skywalking.apache.org/initcontainers.image" + SidecarInitcontainerCommand = "sidecar.skywalking.apache.org/initcontainers.command" + SidecarInitcontainerArgsOption = "sidecar.skywalking.apache.org/initcontainers.args.option" + SidecarInitcontainerArgsCommand = "sidecar.skywalking.apache.org/initcontainers.args.command" + SidecarVolumeName = "sidecar.skywalking.apache.org/volume.name" + SidecarVolumemountMountpath = "sidecar.skywalking.apache.org/containers.volumemounts.mountpath" + ConfigmapName = "sidecar.skywalking.apache.org/configmap.name" + ConfigmapVolumeName = "sidecar.skywalking.apache.org/configmap.volume.name" + ConfigmapVolumemountMountpath = "sidecar.skywalking.apache.org/configmap.volumemounts.mountpath" + SidecarEnvVarName = "sidecar.skywalking.apache.org/envvar.name" + SidecarEnvValue = "sidecar.skywalking.apache.org/envvar.value" + SidecarInjectContainerName = "sidecar.skywalking.apache.org/sidecar.containers.name" + + //the annotation that specify the reason for injection failure + SidecarInjectErrorInfo = "sidecar.skywalking.apache.org/error" + + //the annotation that open or close agent overlay + SidecarAgentConfigOverlay = "sidecar.skywalking.apache.org/agent.config.overlay" + + //the annotation that specify the agent config + AgentNamespace = "agent.skywalking.apache.org/agent.namespace" + AgentServiceName = "agent.skywalking.apache.org/agent.service_name" + AgentSampleNumber = "agent.skywalking.apache.org/agent.sample_n_per_3_secs" + AgentAuthentication = "agent.skywalking.apache.org/agent.authentication" + AgentSpanLimit = "agent.skywalking.apache.org/agent.span_limit_per_segment" + AgentIgnoreSuffix = "agent.skywalking.apache.org/agent.ignore_suffix" + AgentIsOpenDebugging = "agent.skywalking.apache.org/agent.is_open_debugging_class" + AgentIsCacheEnhaned = "agent.skywalking.apache.org/agent.is_cache_enhanced_class" + AgentClassCache = "agent.skywalking.apache.org/agent.class_cache_mode" + AgentOperationName = "agent.skywalking.apache.org/agent.operation_name_threshold" + AgentForceTLS = "agent.skywalking.apache.org/agent.force_tls" + AgentProfileActive = "agent.skywalking.apache.org/profile.active" + AgentProfileMaxParallel = "agent.skywalking.apache.org/profile.max_parallel" + AgentProfileMaxDuration = "agent.skywalking.apache.org/profile.max_duration" + AgentProfileDump = "agent.skywalking.apache.org/profile.dump_max_stack_depth" + AgentProfileSnapshot = "agent.skywalking.apache.org/profile.snapshot_transport_buffer_size" + AgentCollectorService = "agent.skywalking.apache.org/collector.backend_service" + AgentLoggingName = "agent.skywalking.apache.org/logging.file_name" + AgentLoggingLevel = "agent.skywalking.apache.org/logging.level" + AgentLoggingDir = "agent.skywalking.apache.org/logging.dir" + AgentLoggingMaxSize = "agent.skywalking.apache.org/logging.max_file_size" + AgentLoggingMaxFiles = "agent.skywalking.apache.org/logging.max_history_files" + AgentStatuscheckExceptions = "agent.skywalking.apache.org/statuscheck.ignored_exceptions" + AgentStatuscheckDepth = "agent.skywalking.apache.org/statuscheck.max_recursive_depth" + AgentPluginMount = "agent.skywalking.apache.org/plugin.mount" + AgentExcludePlugins = "agent.skywalking.apache.org/plugin.exclude_plugins" + AgentPluginJdbc = "agent.skywalking.apache.org/plugin.jdbc.trace_sql_parameters" + AgentPluginKafkaServers = "agent.skywalking.apache.org/plugin.kafka.bootstrap_servers" + AgentPluginKafkaNamespace = "agent.skywalking.apache.org/plugin.kafka.namespace" + AgentPluginSpringannotation = "agent.skywalking.apache.org/plugin.springannotation.classname_match_regex" +) diff --git a/pkg/operator/injector/validate.go b/pkg/operator/injector/validate.go new file mode 100644 index 00000000..557a7b6b --- /dev/null +++ b/pkg/operator/injector/validate.go @@ -0,0 +1,107 @@ +// 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" + "regexp" + "strconv" + "strings" +) + +type annotationValidateFunc func(annotation, value string) error + +var ( + //AnnotationValidate is a map between an Annotation and its validate function + AnnotationValidate = map[string]annotationValidateFunc{ + AgentSampleNumber: ValidateInt, + AgentSpanLimit: ValidateInt, + AgentIsOpenDebugging: ValidateBool, + AgentIsCacheEnhaned: ValidateBool, + AgentClassCache: ValidateClassCacheMode, + AgentOperationName: ValidateInt, + AgentForceTLS: ValidateBool, + AgentProfileActive: ValidateBool, + AgentProfileMaxParallel: ValidateInt, + AgentProfileMaxDuration: ValidateInt, + AgentProfileDump: ValidateInt, + AgentProfileSnapshot: ValidateInt, + AgentCollectorService: ValidateIpandPort, + AgentLoggingLevel: ValidateLoggingLevel, + AgentLoggingMaxSize: ValidateInt, + AgentLoggingMaxFiles: ValidateInt, + AgentStatuscheckDepth: ValidateInt, + AgentPluginJdbc: ValidateBool, + AgentPluginKafkaServers: ValidateIpandPort, + } +) + +//ValidateBool validates an annotation's value is bool +func ValidateBool(annotation, value string) error { + _, err := strconv.ParseBool(value) + if err != nil { + return fmt.Errorf("%s error:%s", annotation, err.Error()) + } + return nil +} + +//ValidateInt validates an annotation's value is int +func ValidateInt(annotation, value string) error { + _, err := strconv.ParseInt(value, 10, 32) + if err != nil { + return fmt.Errorf("%s error:%s", annotation, err.Error()) + } + return nil +} + +//ValidateClassCacheMode validates an annotation's value is right cache mode +func ValidateClassCacheMode(annotation, value string) error { + if !strings.EqualFold(value, "MEMORY") && !strings.EqualFold(value, "FILE") { + return fmt.Errorf("%s error:the mode is not MEMORY or FILE", 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 +} + +//ValidateLoggingLevel validates an annotation's value is right logging level +func ValidateLoggingLevel(annotation, value string) error { + if !strings.EqualFold(value, "TRACE") && !strings.EqualFold(value, "DEBUG") && + !strings.EqualFold(value, "INFO") && !strings.EqualFold(value, "WARN") && + !strings.EqualFold(value, "ERROR") && !strings.EqualFold(value, "OFF") { + return fmt.Errorf("%s error:the Level is not in [TRACE,DEBUG,INFO,WARN,ERROR,OFF]", annotation) + } + return nil +} From d93f76d8eea316f57625b4f653692353d1c9c4e8 Mon Sep 17 00:00:00 2001 From: dashanji <952129620@qq.com> Date: Sat, 14 Aug 2021 18:53:35 +0800 Subject: [PATCH 06/13] 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 --- pkg/operator/injector/injector.go | 496 +++++++++++++++++++++---- pkg/operator/injector/injector_test.go | 168 --------- 2 files changed, 417 insertions(+), 247 deletions(-) delete mode 100644 pkg/operator/injector/injector_test.go diff --git a/pkg/operator/injector/injector.go b/pkg/operator/injector/injector.go index 72a3daee..9a5e1e3a 100644 --- a/pkg/operator/injector/injector.go +++ b/pkg/operator/injector/injector.go @@ -20,132 +20,470 @@ package injector import ( "context" "encoding/json" + "fmt" "net/http" "strings" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) const ( - annotationKeyagentInjector = "swck-agent-injected" + labelKeyagentInjector = "swck-agent-injected" + defaultConfigmapNamespace = "skywalking-swck-system" + agentConfigAnnotationPrefix = "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" + otherPluginsAnnotationPrefix = "plugins.skywalking.apache.org/" ) -// PodInjector injects agent into Pods -type PodInjector struct { - Client client.Client - decoder *admission.Decoder +// log is for logging in this package. +var log = logf.Log.WithName("injector") + +// SidecarInjectField contains all info that will be injected +type SidecarInjectField struct { + // 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 whether to inject , default is not to inject + needInject bool + // determine which container to inject , default is to inject all containers + injectContainer string + // 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 } -// PodInjector will process every coming pod under the -// specified namespace which labeled "swck-injection=enabled" -func (r *PodInjector) Handle(ctx context.Context, req admission.Request) admission.Response { - pod := &corev1.Pod{} - PodInjectorLog := logf.Log.WithName("PodInjector") - err := r.decoder.Decode(req, pod) - if err != nil { - return admission.Errored(http.StatusBadRequest, err) +// 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} } - //if the pod don't have the label "swck-agent-injected=true",return ok - if !needInject(pod) { - PodInjectorLog.Info("don't inject agent") - return admission.Allowed("ok") + // 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} } - //if the pod has the label "swck-agent-injected=true",add agent - addAgent(pod) - PodInjectorLog.Info("will inject agent,please wait for a moment!") + // add volumemount and env to container + for i, c := range pod.Spec.Containers { + // choose a specific container to inject + if s.injectContainer != "" && c.Name == s.injectContainer { + if c.VolumeMounts != nil { + pod.Spec.Containers[i].VolumeMounts = append(pod.Spec.Containers[i].VolumeMounts, + s.sidecarVolumeMount, s.configmapVolumeMount) + } else { + pod.Spec.Containers[i].VolumeMounts = []corev1.VolumeMount{s.sidecarVolumeMount, + s.configmapVolumeMount} + } + if c.Env != nil { + pod.Spec.Containers[i].Env = append(pod.Spec.Containers[i].Env, s.env) + } else { + pod.Spec.Containers[i].Env = []corev1.EnvVar{s.env} + } + break + } else { + if c.VolumeMounts != nil { + pod.Spec.Containers[i].VolumeMounts = append(pod.Spec.Containers[i].VolumeMounts, + s.sidecarVolumeMount, s.configmapVolumeMount) + } else { + pod.Spec.Containers[i].VolumeMounts = []corev1.VolumeMount{s.sidecarVolumeMount, + s.configmapVolumeMount} + } + if c.Env != nil { + pod.Spec.Containers[i].Env = append(pod.Spec.Containers[i].Env, s.env) + } else { + pod.Spec.Containers[i].Env = []corev1.EnvVar{s.env} + } + } + } +} - marshaledPod, err := json.Marshal(pod) - if err != nil { - return admission.Errored(http.StatusInternalServerError, err) +// GetInjectStrategy gets user's injection strategy +func (s *SidecarInjectField) GetInjectStrategy(containers []corev1.Container, 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-agent-injected=true",means need inject + if *labels == nil { + labels = new(map[string]string) + s.needInject = false + } + + switch strings.ToLower((*labels)[labelKeyagentInjector]) { + case "true": + s.needInject = true + } + + // set injectContainer's value + if *annotation == nil { + annotation = new(map[string]string) + s.injectContainer = "" + s.agentOverlay = false + } + + // validate the container is or not exist + if v, ok := (*annotation)[AnnoInjectContainerName.Name]; ok { + for _, c := range containers { + if c.Name == v { + s.injectContainer = v + break + } + } + } + + // set agentOverlay's value + switch strings.ToLower((*annotation)[AnnoAgentConfigOverlay.Name]) { + case "true": + s.agentOverlay = true } - return admission.PatchResponseFromRaw(req.Object.Raw, marshaledPod) } -// PodInjector implements admission.DecoderInjector. -// A decoder will be automatically injected. +func (s *SidecarInjectField) injectErrorAnnotation(annotation *map[string]string, errorInfo string) { + (*annotation)[AnnoInjectErrorInfo.Name] = errorInfo +} -// InjectDecoder injects the decoder. -func (r *PodInjector) InjectDecoder(d *admission.Decoder) error { - r.decoder = d - return nil +// SidecarOverlayandGetValue get final value of sidecar +func (s *SidecarInjectField) SidecarOverlayandGetValue(as *Annotations, annotation *map[string]string, + a Annotation) (string, bool) { + if _, ok := (*annotation)[a.Name]; ok { + err := as.SetOverlay(annotation, a) + if err != nil { + s.injectErrorAnnotation(annotation, err.Error()) + return "", false + } + } + return as.GetFinalValue(a), true +} + +func (s *SidecarInjectField) setValue(config *string, as *Annotations, annotation *map[string]string, + a Annotation) bool { + if v, ok := s.SidecarOverlayandGetValue(as, annotation, a); ok { + *config = v + return true + } + return false } -//if pod has label "swck-agent-injected=true" , it means the pod needs agent injected -func needInject(pod *corev1.Pod) bool { - injected := false +// OverlaySidecar overlays default config +func (s *SidecarInjectField) OverlaySidecar(as *Annotations, annotation *map[string]string) bool { + var ( + command string + argOption string + argCommand string + configmapName string + ) - labels := pod.ObjectMeta.Labels - if labels == nil { - return injected + switch { + case !s.setValue(&s.initcontainer.Name, as, annotation, AnnoInitcontainerName): + return false + case !s.setValue(&s.initcontainer.Image, as, annotation, AnnoInitcontainerImage): + return false + case !s.setValue(&command, as, annotation, AnnoInitcontainerCommand): + return false + case !s.setValue(&argOption, as, annotation, AnnoInitcontainerArgsOption): + return false + case !s.setValue(&argCommand, as, annotation, AnnoInitcontainerArgsCommand): + return false + case !s.setValue(&s.sidecarVolume.Name, as, annotation, AnnoSidecarVolumeName): + return false + case !s.setValue(&s.sidecarVolumeMount.Name, as, annotation, AnnoSidecarVolumeName): + return false + case !s.setValue(&s.sidecarVolumeMount.MountPath, as, annotation, AnnoSidecarVolumemountMountpath): + return false + case !s.setValue(&configmapName, as, annotation, AnnoConfigmapName): + return false + case !s.setValue(&s.configmapVolume.Name, as, annotation, AnnoConfigmapVolumeName): + return false + case !s.setValue(&s.configmapVolumeMount.Name, as, annotation, AnnoConfigmapVolumeName): + return false + case !s.setValue(&s.configmapVolumeMount.MountPath, as, annotation, AnnoConfigmapVolumemountMountpath): + return false + case !s.setValue(&s.env.Name, as, annotation, AnnoEnvVarName): + return false + case !s.setValue(&s.env.Value, as, annotation, AnnoEnvVarValue): + return false } - switch strings.ToLower(labels[annotationKeyagentInjector]) { - case "true": - injected = true + s.initcontainer.Command = []string{command} + s.initcontainer.Args = []string{argOption, argCommand} + s.initcontainer.VolumeMounts = []corev1.VolumeMount{s.sidecarVolumeMount} + + // the sidecar volume's type is determined + s.sidecarVolume.VolumeSource.EmptyDir = nil + + s.configmapVolume.VolumeSource = corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: configmapName, + }, + }, } - return injected + return true } -//when agent is injected,we need to push agent image and -// mount the volume to the specified directory -func addAgent(pod *corev1.Pod) { - // set InitContainer's VolumeMount - vm := corev1.VolumeMount{ - MountPath: "/sky/agent", - Name: "sky-agent", +// AgentOverlayandGetValue will do real annotation overlay +func (s *SidecarInjectField) AgentOverlayandGetValue(as *Annotations, annotation *map[string]string, + a Annotation) (string, bool) { + if _, ok := (*annotation)[a.Name]; ok { + err := as.SetOverlay(annotation, a) + if err != nil { + s.injectErrorAnnotation(annotation, err.Error()) + return "", false + } } + return as.GetOverlayValue(a), true +} + +func (s *SidecarInjectField) setJvmAgentStr(as *Annotations, annotation *map[string]string, a Annotation, + specialStr bool) bool { + v, ok := s.AgentOverlayandGetValue(as, annotation, a) + if v != "" && ok { + // get {config1}={value1} + configName := strings.TrimPrefix(a.Name, agentConfigAnnotationPrefix) + if specialStr { + v = strings.Join([]string{"'", "'"}, v) + } + config := strings.Join([]string{configName, v}, "=") - // set the agent image to be injected - needAddInitContainer := corev1.Container{ - Name: "inject-sky-agent", - Image: "apache/skywalking-java-agent:8.6.0-jdk8", - Command: []string{"sh"}, - Args: []string{"-c", "mkdir -p /sky/agent && cp -r /skywalking/agent/* /sky/agent"}, - VolumeMounts: []corev1.VolumeMount{vm}, + // add to jvmAgentConfigStr + if s.jvmAgentConfigStr != "" { + s.jvmAgentConfigStr = strings.Join([]string{s.jvmAgentConfigStr, config}, ",") + } else { + s.jvmAgentConfigStr = config + } } + return ok +} - // set emptyDir Volume - needAddVolumes := corev1.Volume{ - Name: "sky-agent", - VolumeSource: corev1.VolumeSource{EmptyDir: nil}, +// OverlayAgentConfig overlays agent config +func (s *SidecarInjectField) OverlayAgentConfig(as *Annotations, annotation *map[string]string) bool { + // jvmAgentConfigStr init + s.jvmAgentConfigStr = "" + + switch { + case !s.setJvmAgentStr(as, annotation, AnnoAgentNamespace, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentServiceName, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentSampleNumber, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentAuthentication, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentSpanLimit, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentIgnoreSuffix, true): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentIsOpenDebugging, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentIsCacheEnhaned, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentClassCache, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentOperationName, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentForceTLS, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentProfileActive, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentProfileMaxParallel, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentProfileMaxDuration, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentProfileDump, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentProfileSnapshot, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentCollectorService, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentLoggingName, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentLoggingLevel, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentLoggingDir, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentLoggingMaxSize, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentLoggingMaxFiles, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentStatuscheckExceptions, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentStatuscheckDepth, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentPluginMount, true): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentExcludePlugins, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentPluginJdbc, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentPluginKafkaServers, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentPluginKafkaNamespace, false): + return false + case !s.setJvmAgentStr(as, annotation, AnnoAgentPluginSpringannotation, false): + return false } - // set container's VolumeMount - needAddVolumeMount := corev1.VolumeMount{ - MountPath: "/sky/agent", - Name: "sky-agent", + return true +} + +// OverlayPluginsConfig 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) OverlayPluginsConfig(annotation *map[string]string) bool { + for k, v := range *annotation { + if strings.HasPrefix(k, otherPluginsAnnotationPrefix) { + configName := strings.TrimPrefix(k, otherPluginsAnnotationPrefix) + 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 true +} + +// CreateConfigmap will find a configmap to set agent config +// if not exist , then create a configmap +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 configmap not exist , get configmap from defaultConfigmapNamespace + if err != nil { + defaultConfigmap := &corev1.ConfigMap{} + if err := kubeclient.Get(ctx, client.ObjectKey{Namespace: defaultConfigmapNamespace, + Name: AnnoConfigmapName.DefaultValue}, defaultConfigmap); err != nil { + log.Info(err.Error()) + s.injectErrorAnnotation(annotation, fmt.Sprintf("get configmap %s from namespace %s error[%s]", + AnnoConfigmapName.DefaultValue, defaultConfigmapNamespace, err.Error())) + return false + } + // create new configmap and update namespace + injectConfigmap := corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: configmapName, + Namespace: namespace, + }, + Data: defaultConfigmap.Data, + } - // set container's EnvVar - needAddEnv := corev1.EnvVar{ - Name: "AGENT_OPTS", - Value: " -javaagent:/sky/agent/skywalking-agent.jar", + if err := kubeclient.Create(ctx, &injectConfigmap); err != nil { + log.Info(err.Error()) + s.injectErrorAnnotation(annotation, fmt.Sprintf("create configmap %s in namespace %s error[%s]", + configmapName, namespace, err.Error())) + return false + } } + return true +} - // add VolumeMount to spec - if pod.Spec.Volumes != nil { - pod.Spec.Volumes = append(pod.Spec.Volumes, needAddVolumes) - } else { - pod.Spec.Volumes = []corev1.Volume{needAddVolumes} +// PodInjector injects agent into Pods +type PodInjector struct { + Client client.Client + decoder *admission.Decoder +} + +// Handle will process every coming pod under the +// specified namespace which labeled "swck-injection=enabled" +func (r *PodInjector) 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) } - // add InitContrainers to spec - if pod.Spec.InitContainers != nil { - pod.Spec.InitContainers = append(pod.Spec.InitContainers, needAddInitContainer) + // init Annotations to store the overlaied value + as := NewAnnotations() + + // init SidecarInjectField and get injected strategy from annotations + s := NewSidecarInjectField() + s.GetInjectStrategy(pod.Spec.Containers, &pod.ObjectMeta.Labels, &pod.ObjectMeta.Annotations) + + if s.needInject { + log.Info("will inject agent,please wait for a moment!") + // the overlation function is always on + s.OverlaySidecar(as, &pod.ObjectMeta.Annotations) + switch { + // only if user choose to overlay agent config in annotations, then start agent and plugins' overlay + case s.agentOverlay && (!s.OverlayAgentConfig(as, &pod.ObjectMeta.Annotations) || + !s.OverlayPluginsConfig(&pod.ObjectMeta.Annotations)): + log.Info("overlay agent config error!please look the error annotation!") + break + // configmap will always overwrite the original agent.config in image + case !s.CreateConfigmap(ctx, r.Client, req.Namespace, &pod.ObjectMeta.Annotations): + log.Info("create configmap error!please look the error annotation!") + break + // add jvmStr to EnvVar and do real injection + default: + if s.jvmAgentConfigStr != "" { + s.env.Value = strings.Join([]string{s.env.Value, s.jvmAgentConfigStr}, "=") + } + s.Inject(pod) + log.Info("inject successfully!") + } } else { - pod.Spec.InitContainers = []corev1.Container{needAddInitContainer} + // if the pod don't have the label "swck-agent-injected=true",return ok + log.Info("don't inject agent!") + return admission.Allowed("ok") } - // add VolumeMount and env to every container - for i := 0; i < len(pod.Spec.Containers); i++ { - pod.Spec.Containers[i].VolumeMounts = append(pod.Spec.Containers[i].VolumeMounts, needAddVolumeMount) - pod.Spec.Containers[i].Env = append(pod.Spec.Containers[i].Env, needAddEnv) + marshaledPod, err := json.Marshal(pod) + if err != nil { + return admission.Errored(http.StatusInternalServerError, err) } + + return admission.PatchResponseFromRaw(req.Object.Raw, marshaledPod) +} + +// PodInjector implements admission.DecoderInjector. +// A decoder will be automatically injected. + +// InjectDecoder injects the decoder. +func (r *PodInjector) InjectDecoder(d *admission.Decoder) error { + r.decoder = d + return nil } diff --git a/pkg/operator/injector/injector_test.go b/pkg/operator/injector/injector_test.go deleted file mode 100644 index 767ec933..00000000 --- a/pkg/operator/injector/injector_test.go +++ /dev/null @@ -1,168 +0,0 @@ -// 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 ( - "reflect" - "testing" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func Test_needInject(t *testing.T) { - type args struct { - pod *corev1.Pod - } - - // set a pod with a wrong label - unlabeledPod := &corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "swck-agent-injected": "false", - }, - }, - } - - // set a pod with a right label - labeledPod := &corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "swck-agent-injected": "true", - }, - }, - } - - tests := []struct { - name string - args args - want bool - }{ - { - name: "don't need injected", - args: args{ - pod: unlabeledPod, - }, - // false means we don't need injected - want: false, - }, - { - name: "need injected", - args: args{ - pod: labeledPod, - }, - // true means we need injected - want: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := needInject(tt.args.pod); got != tt.want { - t.Errorf("needInject() = %v, want %v", got, tt.want) - } - }) - } -} - -func Test_addAgent(t *testing.T) { - type args struct { - pod *corev1.Pod - } - - Pod := &corev1.Pod{ - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - corev1.Container{ - Name: "app", - }, - }, - }, - } - - // injected InitContainer's VolumeMount - injectedICVM := corev1.VolumeMount{ - MountPath: "/sky/agent", - Name: "sky-agent", - } - - // injected InitContainer - injectedIC := corev1.Container{ - Name: "inject-sky-agent", - Image: "apache/skywalking-java-agent:8.6.0-jdk8", - Command: []string{"sh"}, - Args: []string{"-c", "mkdir -p /sky/agent && cp -r /skywalking/agent/* /sky/agent"}, - VolumeMounts: []corev1.VolumeMount{injectedICVM}, - } - - // injected Volumes - injectedV := corev1.Volume{ - Name: "sky-agent", - VolumeSource: corev1.VolumeSource{EmptyDir: nil}, - } - - // injected Container's VolumeMount - injectedVM := corev1.VolumeMount{ - MountPath: "/sky/agent", - Name: "sky-agent", - } - - // injected Container's EnvVar - injectedEV := corev1.EnvVar{ - Name: "AGENT_OPTS", - Value: " -javaagent:/sky/agent/skywalking-agent.jar", - } - - injectedPod := &corev1.Pod{ - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - corev1.Container{ - Name: "app", - VolumeMounts: []corev1.VolumeMount{ - injectedVM, - }, - Env: []corev1.EnvVar{ - injectedEV, - }, - }, - }, - InitContainers: []corev1.Container{ - injectedIC, - }, - Volumes: []corev1.Volume{ - injectedV, - }, - }, - } - tests := []struct { - name string - args args - }{ - { - name: "test injected", - args: args{Pod}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - addAgent(tt.args.pod) - if !reflect.DeepEqual(Pod, tt.args.pod) { - t.Errorf("needInject() = %v, want %v end", Pod, injectedPod) - } - }) - } -} From 4cf223b9b6d218c9baaaf5f405c4dfd8478a3cd9 Mon Sep 17 00:00:00 2001 From: dashanji <952129620@qq.com> Date: Sat, 14 Aug 2021 18:54:36 +0800 Subject: [PATCH 07/13] add func test --- pkg/operator/injector/injector_test.go | 514 +++++++++++++++++++++++++ pkg/operator/injector/validate_test.go | 282 ++++++++++++++ 2 files changed, 796 insertions(+) create mode 100644 pkg/operator/injector/injector_test.go create mode 100644 pkg/operator/injector/validate_test.go diff --git a/pkg/operator/injector/injector_test.go b/pkg/operator/injector/injector_test.go new file mode 100644 index 00000000..2ea9e5dd --- /dev/null +++ b/pkg/operator/injector/injector_test.go @@ -0,0 +1,514 @@ +// 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" + "testing" + + corev1 "k8s.io/api/core/v1" +) + +func TestSidecarInjectField_Inject(t *testing.T) { + type fields struct { + initcontainer corev1.Container + sidecarVolume corev1.Volume + sidecarVolumeMount corev1.VolumeMount + configmapVolume corev1.Volume + configmapVolumeMount corev1.VolumeMount + env corev1.EnvVar + jvmAgentConfigStr string + needInject bool + injectContainer string + agentOverlay bool + } + type args struct { + pod *corev1.Pod + } + + Pod := &corev1.Pod{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "app", + }, + }, + }, + } + + // injected sidecar Volumes + injectedSV := corev1.Volume{ + Name: "sky-agent", + VolumeSource: corev1.VolumeSource{EmptyDir: nil}, + } + + // injected configmap Volumes + injectedCV := corev1.Volume{ + Name: "java-agent-configmap-volume", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "java-agent-configmap", + }, + }, + }, + } + + // injected Sidecar's VolumeMount + injectedSVM := corev1.VolumeMount{ + MountPath: "/sky/agent", + Name: "sky-agent", + } + + // injected Configmap's VolumeMount + injectedCVM := corev1.VolumeMount{ + Name: "java-agent-configmap-volume", + MountPath: "/sky/agent/config", + } + + // injected InitContainer + injectedIC := corev1.Container{ + Name: "inject-sky-agent", + Image: "apache/skywalking-java-agent:8.6.0-jdk8", + Command: []string{"sh"}, + Args: []string{"-c", "mkdir -p /sky/agent && cp -r /skywalking/agent/* /sky/agent"}, + VolumeMounts: []corev1.VolumeMount{injectedSVM}, + } + + // injected Container's EnvVar + injectedEV := corev1.EnvVar{ + Name: "AGENT_OPTS", + Value: " -javaagent:/sky/agent/skywalking-agent.jar", + } + + injectedPod := &corev1.Pod{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "app", + VolumeMounts: []corev1.VolumeMount{ + injectedSVM, injectedCVM, + }, + Env: []corev1.EnvVar{ + injectedEV, + }, + }, + }, + InitContainers: []corev1.Container{ + injectedIC, + }, + Volumes: []corev1.Volume{ + injectedSV, injectedCV, + }, + }, + } + tests := []struct { + name string + fields fields + args args + }{ + { + name: "test inject function", + fields: fields{ + initcontainer: injectedIC, + sidecarVolume: injectedSV, + sidecarVolumeMount: injectedSVM, + configmapVolume: injectedCV, + configmapVolumeMount: injectedCVM, + env: injectedEV, + injectContainer: "app", + }, + args: args{ + pod: Pod, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := &SidecarInjectField{ + initcontainer: tt.fields.initcontainer, + sidecarVolume: tt.fields.sidecarVolume, + sidecarVolumeMount: tt.fields.sidecarVolumeMount, + configmapVolume: tt.fields.configmapVolume, + configmapVolumeMount: tt.fields.configmapVolumeMount, + env: tt.fields.env, + jvmAgentConfigStr: tt.fields.jvmAgentConfigStr, + needInject: tt.fields.needInject, + injectContainer: tt.fields.injectContainer, + agentOverlay: tt.fields.agentOverlay, + } + s.Inject(tt.args.pod) + if !reflect.DeepEqual(injectedPod, tt.args.pod) { + fmt.Println(injectedPod) + t.Errorf("Inject() got= %v,want %v", tt.args.pod, injectedPod) + } + }) + } +} + +func TestSidecarInjectField_GetInjectStrategy(t *testing.T) { + type fields struct { + initcontainer corev1.Container + sidecarVolume corev1.Volume + sidecarVolumeMount corev1.VolumeMount + configmapVolume corev1.Volume + configmapVolumeMount corev1.VolumeMount + env corev1.EnvVar + jvmAgentConfigStr string + needInject bool + injectContainer string + agentOverlay bool + } + type args struct { + containers []corev1.Container + labels *map[string]string + annotation *map[string]string + } + tests := []struct { + name string + fields fields + args args + }{ + { + name: "test right", + fields: fields{ + needInject: false, + injectContainer: "", + agentOverlay: false, + }, + args: args{ + containers: []corev1.Container{ + { + Name: "container1", + }, + }, + labels: &map[string]string{ + labelKeyagentInjector: "true", + }, + annotation: &map[string]string{ + AnnoInjectContainerName.Name: "container1", + AnnoAgentConfigOverlay.Name: "true", + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := &SidecarInjectField{ + initcontainer: tt.fields.initcontainer, + sidecarVolume: tt.fields.sidecarVolume, + sidecarVolumeMount: tt.fields.sidecarVolumeMount, + configmapVolume: tt.fields.configmapVolume, + configmapVolumeMount: tt.fields.configmapVolumeMount, + env: tt.fields.env, + jvmAgentConfigStr: tt.fields.jvmAgentConfigStr, + needInject: tt.fields.needInject, + injectContainer: tt.fields.injectContainer, + agentOverlay: tt.fields.agentOverlay, + } + s.GetInjectStrategy(tt.args.containers, tt.args.labels, tt.args.annotation) + if !s.needInject || s.injectContainer != "container1" || !s.agentOverlay { + t.Errorf("GetInjectStrategy got= [%v,%v,%v], want [true,container1,true]", s.needInject, + s.injectContainer, s.agentOverlay) + } + }) + } +} + +func TestSidecarInjectField_OverlaySidecar(t *testing.T) { + type fields struct { + initcontainer corev1.Container + sidecarVolume corev1.Volume + sidecarVolumeMount corev1.VolumeMount + configmapVolume corev1.Volume + configmapVolumeMount corev1.VolumeMount + env corev1.EnvVar + jvmAgentConfigStr string + needInject bool + injectContainer string + agentOverlay bool + } + type args struct { + as *Annotations + annotation *map[string]string + } + initcontainer := corev1.Container{ + Name: AnnoInitcontainerName.DefaultValue, + Image: AnnoInitcontainerImage.DefaultValue, + Command: []string{AnnoInitcontainerCommand.DefaultValue}, + Args: []string{AnnoInitcontainerArgsOption.DefaultValue, AnnoInitcontainerArgsCommand. + DefaultValue}, + } + sidecarVolume := corev1.Volume{ + Name: AnnoSidecarVolumeName.DefaultValue, + VolumeSource: corev1.VolumeSource{ + EmptyDir: nil, + }, + } + sidecarVolumeMount := corev1.VolumeMount{ + Name: AnnoSidecarVolumeName.DefaultValue, + MountPath: AnnoSidecarVolumemountMountpath.DefaultValue, + } + configmapVolume := corev1.Volume{ + Name: AnnoConfigmapVolumeName.DefaultValue, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: AnnoConfigmapName.DefaultValue, + }, + }, + }, + } + configmapVolumeMount := corev1.VolumeMount{ + Name: AnnoConfigmapVolumeName.DefaultValue, + MountPath: AnnoConfigmapVolumemountMountpath.DefaultValue, + } + env := corev1.EnvVar{ + Name: AnnoEnvVarName.DefaultValue, + Value: AnnoEnvVarValue.DefaultValue, + } + tests := []struct { + name string + fields fields + args args + want bool + }{ + { + name: "test sidecar overlay", + fields: fields{ + initcontainer: initcontainer, + sidecarVolume: sidecarVolume, + sidecarVolumeMount: sidecarVolumeMount, + configmapVolume: configmapVolume, + configmapVolumeMount: configmapVolumeMount, + env: env, + }, + args: args{ + as: NewAnnotations(), + annotation: &map[string]string{ + AnnoInitcontainerName.Name: "test-inject-agent", + AnnoInitcontainerImage.Name: "apache/skywalking-java-agent:8.5.0-jdk8", + AnnoInitcontainerCommand.Name: "sh", + AnnoInitcontainerArgsOption.Name: "-c", + AnnoInitcontainerArgsCommand.Name: "mkdir -p /skytest/agent && cp -r /skywalking/agent/* /skytest/agent", + AnnoSidecarVolumemountMountpath.Name: "/skytest/agent", + AnnoConfigmapVolumemountMountpath.Name: "/skytest/agent/config", + AnnoEnvVarValue.Name: " -javaagent:/skytest/agent/skywalking-agent.jar", + }, + }, + want: true, + }, + } + + overlaied := &SidecarInjectField{ + initcontainer: initcontainer, + sidecarVolume: sidecarVolume, + sidecarVolumeMount: sidecarVolumeMount, + configmapVolume: configmapVolume, + configmapVolumeMount: configmapVolumeMount, + env: env, + } + overlaied.initcontainer.Name = "test-inject-agent" + overlaied.initcontainer.Image = "apache/skywalking-java-agent:8.5.0-jdk8" + overlaied.initcontainer.Command = []string{"sh"} + overlaied.initcontainer.Args = []string{"-c", "mkdir -p /skytest/agent && cp -r /skywalking/agent/* /skytest/agent"} + overlaied.sidecarVolumeMount.MountPath = "/skytest/agent" + overlaied.configmapVolumeMount.MountPath = "/skytest/agent/config" + overlaied.env.Value = " -javaagent:/skytest/agent/skywalking-agent.jar" + overlaied.initcontainer.VolumeMounts = []corev1.VolumeMount{overlaied.sidecarVolumeMount} + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := &SidecarInjectField{ + initcontainer: tt.fields.initcontainer, + sidecarVolume: tt.fields.sidecarVolume, + sidecarVolumeMount: tt.fields.sidecarVolumeMount, + configmapVolume: tt.fields.configmapVolume, + configmapVolumeMount: tt.fields.configmapVolumeMount, + env: tt.fields.env, + jvmAgentConfigStr: tt.fields.jvmAgentConfigStr, + needInject: tt.fields.needInject, + injectContainer: tt.fields.injectContainer, + agentOverlay: tt.fields.agentOverlay, + } + if got := s.OverlaySidecar(tt.args.as, tt.args.annotation); got != tt.want || !reflect.DeepEqual(overlaied, s) { + t.Errorf("SidecarInjectField.OverlaySidecar() = %v, want %v", got, tt.want) + t.Errorf("after OverlaySidecar,the SidecarInjectField is %v\nwant %v", s, overlaied) + } + }) + } +} + +func TestSidecarInjectField_OverlayAgentConfig(t *testing.T) { + type fields struct { + initcontainer corev1.Container + sidecarVolume corev1.Volume + sidecarVolumeMount corev1.VolumeMount + configmapVolume corev1.Volume + configmapVolumeMount corev1.VolumeMount + env corev1.EnvVar + jvmAgentConfigStr string + needInject bool + injectContainer string + agentOverlay bool + } + type args struct { + as *Annotations + annotation *map[string]string + } + tests := []struct { + name string + fields fields + args args + want bool + }{ + { + name: "test right OverlayAgentConfig", + fields: fields{}, + args: args{ + as: NewAnnotations(), + annotation: &map[string]string{ + AnnoAgentNamespace.Name: "default-namespace", + AnnoAgentServiceName.Name: "test", + AnnoAgentSampleNumber.Name: "6", + AnnoAgentAuthentication.Name: "test", + AnnoAgentSpanLimit.Name: "100", + AnnoAgentIgnoreSuffix.Name: "jpg,.jpeg", + AnnoAgentIsOpenDebugging.Name: "false", + AnnoAgentIsCacheEnhaned.Name: "false", + AnnoAgentClassCache.Name: "MEMORY", + AnnoAgentOperationName.Name: "100", + AnnoAgentForceTLS.Name: "false", + AnnoAgentProfileActive.Name: "false", + AnnoAgentProfileMaxParallel.Name: "10", + AnnoAgentProfileMaxDuration.Name: "10", + AnnoAgentProfileDump.Name: "200", + AnnoAgentProfileSnapshot.Name: "200", + AnnoAgentCollectorService.Name: "localhost:2021", + AnnoAgentLoggingName.Name: "skywalking-api.log", + AnnoAgentLoggingLevel.Name: "INFO", + AnnoAgentLoggingDir.Name: "test", + AnnoAgentLoggingMaxSize.Name: "1000", + AnnoAgentLoggingMaxFiles.Name: "-1", + AnnoAgentStatuscheckExceptions.Name: "test", + AnnoAgentStatuscheckDepth.Name: "10", + AnnoAgentPluginMount.Name: "plugins,activations", + AnnoAgentExcludePlugins.Name: "test", + AnnoAgentPluginJdbc.Name: "false", + AnnoAgentPluginKafkaServers.Name: "127.0.0.1:9092", + AnnoAgentPluginKafkaNamespace.Name: "test", + AnnoAgentPluginSpringannotation.Name: "test", + }, + }, + want: true, + }, + } + finalStr := `agent.namespace=default-namespace,agent.service_name=test,` + + `agent.sample_n_per_3_secs=6,agent.authentication=test,agent.span_limit_per_segment=100,` + + `agent.ignore_suffix='jpg,.jpeg',agent.is_open_debugging_class=false,agent.is_cache_enhanced_class=false,` + + `agent.class_cache_mode=MEMORY,agent.operation_name_threshold=100,agent.force_tls=false,profile.active=false,` + + `profile.max_parallel=10,profile.max_duration=10,profile.dump_max_stack_depth=200,` + + `profile.snapshot_transport_buffer_size=200,collector.backend_service=localhost:2021,` + + `logging.file_name=skywalking-api.log,logging.level=INFO,logging.dir=test,logging.max_file_size=1000,` + + `logging.max_history_files=-1,statuscheck.ignored_exceptions=test,statuscheck.max_recursive_depth=10,` + + `plugin.mount='plugins,activations',plugin.exclude_plugins=test,plugin.jdbc.trace_sql_parameters=false,` + + `plugin.kafka.bootstrap_servers=127.0.0.1:9092,plugin.kafka.namespace=test,` + + `plugin.springannotation.classname_match_regex=test` + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := &SidecarInjectField{ + initcontainer: tt.fields.initcontainer, + sidecarVolume: tt.fields.sidecarVolume, + sidecarVolumeMount: tt.fields.sidecarVolumeMount, + configmapVolume: tt.fields.configmapVolume, + configmapVolumeMount: tt.fields.configmapVolumeMount, + env: tt.fields.env, + jvmAgentConfigStr: tt.fields.jvmAgentConfigStr, + needInject: tt.fields.needInject, + injectContainer: tt.fields.injectContainer, + agentOverlay: tt.fields.agentOverlay, + } + if got := s.OverlayAgentConfig(tt.args.as, tt.args.annotation); got != tt.want || + finalStr != s.jvmAgentConfigStr { + t.Errorf("SidecarInjectField.OverlayAgentConfig() = %v, want %v", got, tt.want) + t.Errorf("SidecarInjectField.OverlayAgentConfig():%s\nwant %s", s.jvmAgentConfigStr, finalStr) + } + }) + } +} + +func TestSidecarInjectField_OverlayPluginsConfig(t *testing.T) { + type fields struct { + initcontainer corev1.Container + sidecarVolume corev1.Volume + sidecarVolumeMount corev1.VolumeMount + configmapVolume corev1.Volume + configmapVolumeMount corev1.VolumeMount + env corev1.EnvVar + jvmAgentConfigStr string + needInject bool + injectContainer string + agentOverlay bool + } + type args struct { + annotation *map[string]string + } + tests := []struct { + name string + fields fields + args args + want bool + }{ + { + name: "test right OverlayPluginsConfig", + fields: fields{}, + args: args{ + annotation: &map[string]string{ + otherPluginsAnnotationPrefix + "plugin.influxdb.trace_influxql": "false", + otherPluginsAnnotationPrefix + "plugin.mongodb.trace_param": "true", + }, + }, + want: true, + }, + } + // avoid random traversal of map type + finalStr1 := `plugin.influxdb.trace_influxql=false,plugin.mongodb.trace_param=true` + finalStr2 := `plugin.mongodb.trace_param=true,plugin.influxdb.trace_influxql=false` + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := &SidecarInjectField{ + initcontainer: tt.fields.initcontainer, + sidecarVolume: tt.fields.sidecarVolume, + sidecarVolumeMount: tt.fields.sidecarVolumeMount, + configmapVolume: tt.fields.configmapVolume, + configmapVolumeMount: tt.fields.configmapVolumeMount, + env: tt.fields.env, + jvmAgentConfigStr: tt.fields.jvmAgentConfigStr, + needInject: tt.fields.needInject, + injectContainer: tt.fields.injectContainer, + agentOverlay: tt.fields.agentOverlay, + } + if got := s.OverlayPluginsConfig(tt.args.annotation); got != tt.want || + (s.jvmAgentConfigStr != finalStr1 && s.jvmAgentConfigStr != finalStr2) { + t.Errorf("SidecarInjectField.OverlayPluginsConfig() = %v, want %v", got, tt.want) + t.Errorf("SidecarInjectField.OverlayPluginsConfig():%s\nwant %s or %s", + s.jvmAgentConfigStr, finalStr1, finalStr2) + } + }) + } +} diff --git a/pkg/operator/injector/validate_test.go b/pkg/operator/injector/validate_test.go new file mode 100644 index 00000000..31e3febe --- /dev/null +++ b/pkg/operator/injector/validate_test.go @@ -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. + +package injector + +import ( + "testing" +) + +func TestValidateBool(t *testing.T) { + type args struct { + annotation string + value string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "test true", + args: args{ + annotation: "test annotation", + value: "true", + }, + wantErr: false, + }, + { + name: "test false", + args: args{ + annotation: "test annotation", + value: "false", + }, + wantErr: false, + }, + { + name: "test no", + args: args{ + annotation: "test annotation", + value: "no", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := ValidateBool(tt.args.annotation, tt.args.value); (err != nil) != tt.wantErr { + t.Errorf("ValidateBool() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestValidateInt(t *testing.T) { + type args struct { + annotation string + value string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "test 1", + args: args{ + annotation: "test annotation", + value: "1", + }, + wantErr: false, + }, + { + name: "test -1", + args: args{ + annotation: "test annotation", + value: "-1", + }, + wantErr: false, + }, + { + name: "test other", + args: args{ + annotation: "test annotation", + value: "true", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := ValidateInt(tt.args.annotation, tt.args.value); (err != nil) != tt.wantErr { + t.Errorf("ValidateInt() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestValidateClassCacheMode(t *testing.T) { + type args struct { + annotation string + value string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "test MEMORY", + args: args{ + annotation: "test annotation", + value: "MEMORY", + }, + wantErr: false, + }, + { + name: "test FILE", + args: args{ + annotation: "test annotation", + value: "FILE", + }, + wantErr: false, + }, + { + name: "test CACHE", + args: args{ + annotation: "test annotation", + value: "CACHE", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := ValidateClassCacheMode(tt.args.annotation, tt.args.value); (err != nil) != tt.wantErr { + t.Errorf("ValidateClassCacheMode() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestValidateIpandPort(t *testing.T) { + type args struct { + annotation string + value string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "valid ip and valid port", + args: args{ + annotation: "test annotation", + value: "127.0.0.1:8080", + }, + wantErr: false, + }, + { + name: "valid ip and valid port", + args: args{ + annotation: "test annotation", + value: "localhost:8080", + }, + wantErr: false, + }, + { + name: "invalid ip and valid port", + args: args{ + annotation: "test annotation", + value: "192.0.1.288:8080", + }, + wantErr: true, + }, + { + name: "valid ip and invalid port", + args: args{ + annotation: "test annotation", + value: "192.0.1.255:88888", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := ValidateIpandPort(tt.args.annotation, tt.args.value); (err != nil) != tt.wantErr { + t.Errorf("ValidateIpandPort() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestValidateLoggingLevel(t *testing.T) { + type args struct { + annotation string + value string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "test TRACE", + args: args{ + annotation: "test annotation", + value: "TRACE", + }, + wantErr: false, + }, + { + name: "test DEBUG", + args: args{ + annotation: "test annotation", + value: "DEBUG", + }, + wantErr: false, + }, + { + name: "test INFO", + args: args{ + annotation: "test annotation", + value: "INFO", + }, + wantErr: false, + }, + { + name: "test WARN", + args: args{ + annotation: "test annotation", + value: "WARN", + }, + wantErr: false, + }, + { + name: "test ERROR", + args: args{ + annotation: "test annotation", + value: "ERROR", + }, + wantErr: false, + }, + { + name: "test OFF", + args: args{ + annotation: "test annotation", + value: "OFF", + }, + wantErr: false, + }, + { + name: "test other", + args: args{ + annotation: "test annotation", + value: "other", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := ValidateLoggingLevel(tt.args.annotation, tt.args.value); (err != nil) != tt.wantErr { + t.Errorf("ValidateLoggingLevel() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} From 0e01a8f52dabf479b2b7493dfd0e5661619b1415 Mon Sep 17 00:00:00 2001 From: dashanji <952129620@qq.com> Date: Sun, 15 Aug 2021 11:55:50 +0800 Subject: [PATCH 08/13] update label --- pkg/operator/injector/injector.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/operator/injector/injector.go b/pkg/operator/injector/injector.go index 9a5e1e3a..3c6a028c 100644 --- a/pkg/operator/injector/injector.go +++ b/pkg/operator/injector/injector.go @@ -32,7 +32,7 @@ import ( ) const ( - labelKeyagentInjector = "swck-agent-injected" + labelKeyagentInjector = "swck-java-agent-injected" defaultConfigmapNamespace = "skywalking-swck-system" agentConfigAnnotationPrefix = "agent.skywalking.apache.org/" // If user want to use other Plugins' config ,the annotation must have the following form @@ -138,7 +138,7 @@ func (s *SidecarInjectField) GetInjectStrategy(containers []corev1.Container, la s.injectContainer = "" s.agentOverlay = false - // set needInject's value , if the pod has the label "swck-agent-injected=true",means need inject + // set needInject's value , if the pod has the label "swck-java-agent-injected=true",means need inject if *labels == nil { labels = new(map[string]string) s.needInject = false @@ -466,7 +466,7 @@ func (r *PodInjector) Handle(ctx context.Context, req admission.Request) admissi log.Info("inject successfully!") } } else { - // if the pod don't have the label "swck-agent-injected=true",return ok + // if the pod don't have the label "swck-java-agent-injected=true",return ok log.Info("don't inject agent!") return admission.Allowed("ok") } From 09e60b045d70096c1d98db9cd33095ca3e7cac26 Mon Sep 17 00:00:00 2001 From: dashanji <952129620@qq.com> Date: Sun, 15 Aug 2021 16:04:53 +0800 Subject: [PATCH 09/13] fix lint error --- pkg/operator/injector/injector.go | 16 +++++++--------- pkg/operator/injector/injector_test.go | 20 ++++++++++---------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/pkg/operator/injector/injector.go b/pkg/operator/injector/injector.go index 3c6a028c..a33b4564 100644 --- a/pkg/operator/injector/injector.go +++ b/pkg/operator/injector/injector.go @@ -47,6 +47,13 @@ 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 @@ -64,15 +71,8 @@ type SidecarInjectField struct { // the string is used to set jvm agent ,just like following // -javaagent: /sky/agent/skywalking-agent,jar=jvmAgentConfigStr jvmAgentConfigStr string - // determine whether to inject , default is not to inject - needInject bool // determine which container to inject , default is to inject all containers injectContainer string - // 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 } // NewSidecarInjectField will create a new SidecarInjectField @@ -452,11 +452,9 @@ func (r *PodInjector) Handle(ctx context.Context, req admission.Request) admissi case s.agentOverlay && (!s.OverlayAgentConfig(as, &pod.ObjectMeta.Annotations) || !s.OverlayPluginsConfig(&pod.ObjectMeta.Annotations)): log.Info("overlay agent config error!please look the error annotation!") - break // configmap will always overwrite the original agent.config in image case !s.CreateConfigmap(ctx, r.Client, req.Namespace, &pod.ObjectMeta.Annotations): log.Info("create configmap error!please look the error annotation!") - break // add jvmStr to EnvVar and do real injection default: if s.jvmAgentConfigStr != "" { diff --git a/pkg/operator/injector/injector_test.go b/pkg/operator/injector/injector_test.go index 2ea9e5dd..d5d5798b 100644 --- a/pkg/operator/injector/injector_test.go +++ b/pkg/operator/injector/injector_test.go @@ -27,6 +27,8 @@ import ( func TestSidecarInjectField_Inject(t *testing.T) { type fields struct { + needInject bool + agentOverlay bool initcontainer corev1.Container sidecarVolume corev1.Volume sidecarVolumeMount corev1.VolumeMount @@ -34,9 +36,7 @@ func TestSidecarInjectField_Inject(t *testing.T) { configmapVolumeMount corev1.VolumeMount env corev1.EnvVar jvmAgentConfigStr string - needInject bool injectContainer string - agentOverlay bool } type args struct { pod *corev1.Pod @@ -164,6 +164,8 @@ func TestSidecarInjectField_Inject(t *testing.T) { func TestSidecarInjectField_GetInjectStrategy(t *testing.T) { type fields struct { + needInject bool + agentOverlay bool initcontainer corev1.Container sidecarVolume corev1.Volume sidecarVolumeMount corev1.VolumeMount @@ -171,9 +173,7 @@ func TestSidecarInjectField_GetInjectStrategy(t *testing.T) { configmapVolumeMount corev1.VolumeMount env corev1.EnvVar jvmAgentConfigStr string - needInject bool injectContainer string - agentOverlay bool } type args struct { containers []corev1.Container @@ -233,6 +233,8 @@ func TestSidecarInjectField_GetInjectStrategy(t *testing.T) { func TestSidecarInjectField_OverlaySidecar(t *testing.T) { type fields struct { + needInject bool + agentOverlay bool initcontainer corev1.Container sidecarVolume corev1.Volume sidecarVolumeMount corev1.VolumeMount @@ -240,9 +242,7 @@ func TestSidecarInjectField_OverlaySidecar(t *testing.T) { configmapVolumeMount corev1.VolumeMount env corev1.EnvVar jvmAgentConfigStr string - needInject bool injectContainer string - agentOverlay bool } type args struct { as *Annotations @@ -356,6 +356,8 @@ func TestSidecarInjectField_OverlaySidecar(t *testing.T) { func TestSidecarInjectField_OverlayAgentConfig(t *testing.T) { type fields struct { + needInject bool + agentOverlay bool initcontainer corev1.Container sidecarVolume corev1.Volume sidecarVolumeMount corev1.VolumeMount @@ -363,9 +365,7 @@ func TestSidecarInjectField_OverlayAgentConfig(t *testing.T) { configmapVolumeMount corev1.VolumeMount env corev1.EnvVar jvmAgentConfigStr string - needInject bool injectContainer string - agentOverlay bool } type args struct { as *Annotations @@ -454,6 +454,8 @@ func TestSidecarInjectField_OverlayAgentConfig(t *testing.T) { func TestSidecarInjectField_OverlayPluginsConfig(t *testing.T) { type fields struct { + needInject bool + agentOverlay bool initcontainer corev1.Container sidecarVolume corev1.Volume sidecarVolumeMount corev1.VolumeMount @@ -461,9 +463,7 @@ func TestSidecarInjectField_OverlayPluginsConfig(t *testing.T) { configmapVolumeMount corev1.VolumeMount env corev1.EnvVar jvmAgentConfigStr string - needInject bool injectContainer string - agentOverlay bool } type args struct { annotation *map[string]string From 9950ca646b172eb4076fa29e7bd914bdf0a1037b Mon Sep 17 00:00:00 2001 From: dashanji <952129620@qq.com> Date: Sun, 22 Aug 2021 21:17:47 +0800 Subject: [PATCH 10/13] 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 --- apis/operator/v1alpha1/javaagent_webhook.go | 78 +++ .../v1alpha1/zz_generated.deepcopy.go | 17 +- cmd/manager/manager.go | 15 +- config/operator/configmap/configmap.yaml | 242 +++++++-- config/operator/rbac/role.yaml | 8 + ...nsSelector.yaml => ns_selector_patch.yaml} | 0 controllers/operator/configmap_controller.go | 121 +++++ main.go | 4 +- pkg/kubernetes/apply.go | 37 +- pkg/operator/injector/annotation.go | 141 +++-- pkg/operator/injector/configmap.go | 113 ++++ pkg/operator/injector/constants.go | 74 --- pkg/operator/injector/injection.go | 228 ++++++++ pkg/operator/injector/injector.go | 487 ++++++----------- pkg/operator/injector/injector_test.go | 514 ------------------ pkg/operator/injector/validate.go | 69 ++- .../injector/templates/annotations.yaml | 390 +++++++++++++ .../injector/templates/configmap.yaml | 47 ++ pkg/operator/repo/assets.gen.go | 480 ++++++++++++++++ 19 files changed, 2001 insertions(+), 1064 deletions(-) create mode 100644 apis/operator/v1alpha1/javaagent_webhook.go rename config/operator/webhook/{add_nsSelector.yaml => ns_selector_patch.yaml} (100%) create mode 100644 controllers/operator/configmap_controller.go create mode 100644 pkg/operator/injector/configmap.go delete mode 100644 pkg/operator/injector/constants.go create mode 100644 pkg/operator/injector/injection.go delete mode 100644 pkg/operator/injector/injector_test.go create mode 100644 pkg/operator/manifests/injector/templates/annotations.yaml create mode 100644 pkg/operator/manifests/injector/templates/configmap.yaml diff --git a/apis/operator/v1alpha1/javaagent_webhook.go b/apis/operator/v1alpha1/javaagent_webhook.go new file mode 100644 index 00000000..abf29603 --- /dev/null +++ b/apis/operator/v1alpha1/javaagent_webhook.go @@ -0,0 +1,78 @@ +// 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") + +// 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" +// +kubebuilder:webhook:path=/mutate-v1-pod,mutating=true,failurePolicy=fail,groups="",resources=pods,verbs=create;update,versions=v1,name=mpod.kb.io +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() +} + +// PodInjector 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 32409ca6..5ce96ab8 100644 --- a/apis/operator/v1alpha1/zz_generated.deepcopy.go +++ b/apis/operator/v1alpha1/zz_generated.deepcopy.go @@ -24,7 +24,7 @@ package v1alpha1 import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - v1 "k8s.io/api/networking/v1" + "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -180,6 +180,21 @@ func (in *Ingress) DeepCopy() *Ingress { return out } +// 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 diff --git a/cmd/manager/manager.go b/cmd/manager/manager.go index 10cba446..64fdbb67 100644 --- a/cmd/manager/manager.go +++ b/cmd/manager/manager.go @@ -23,14 +23,13 @@ import ( "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" - "github.com/apache/skywalking-swck/pkg/operator/injector" + "github.com/apache/skywalking-swck/pkg/operator/repo" // +kubebuilder:scaffold:imports ) @@ -105,6 +104,16 @@ func main() { 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") @@ -122,7 +131,7 @@ func main() { setupLog.Info("registering /mutate-v1-pod webhook") mgr.GetWebhookServer().Register("/mutate-v1-pod", &webhook.Admission{ - Handler: &injector.PodInjector{Client: mgr.GetClient()}}) + 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 index 7e53c523..58c9d81f 100644 --- a/config/operator/configmap/configmap.yaml +++ b/config/operator/configmap/configmap.yaml @@ -15,6 +15,7 @@ # specific language governing permissions and limitations # under the License. + apiVersion: v1 kind: ConfigMap metadata: @@ -39,100 +40,243 @@ data: # limitations under the License. # The agent namespace - agent.namespace=${SW_AGENT_NAMESPACE:default-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:xxxx} + 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:150} + 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:true} + 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} + 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} + 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} + 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} - - # 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.max_duration=${SW_AGENT_PROFILE_DURATION:10} - - # Max dump thread stack depth - # profile.dump_max_stack_depth=${SW_AGENT_PROFILE_DUMP_MAX_STACK_DEPTH:500} + agent.force_tls=${SW_AGENT_FORCE_TLS:false} - # Snapshot transport to backend buffer size - # profile.snapshot_transport_buffer_size=${SW_AGENT_PROFILE_SNAPSHOT_TRANSPORT_BUFFER_SIZE:50} + # 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} - - # Logging file_name - logging.file_name=${SW_LOGGING_FILE_NAME:skywalking-api.log} + # 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 dir - # logging.dir=${SW_LOGGING_DIR:""} - + # 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} - + 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} + 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:} - + 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} - - # Mount the specific folders of the plugins. Plugins in mounted folders would work. - plugin.mount=${SW_MOUNT_FOLDERS:plugins,activations} - - # Exclude activated plugins - # plugin.exclude_plugins=${SW_EXCLUDE_PLUGINS:} + statuscheck.max_recursive_depth=${SW_STATUSCHECK_MAX_RECURSIVE_DEPTH:1} - # 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} + # Max element count in the correlation context + correlation.element_max_number=${SW_CORRELATION_ELEMENT_MAX_NUMBER:3} - # Kafka producer configuration - # plugin.kafka.bootstrap_servers=${SW_KAFKA_BOOTSTRAP_SERVERS:localhost:9092} - # if you want to set namespace. please make sure the OAP server has set it in Kafka fetcher module - # plugin.kafka.namespace=${SW_KAFKA_NAMESPACE:""} + # 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. - # Match spring bean with regex expression for classname - # plugin.springannotation.classname_match_regex=${SW_SPRINGANNOTATION_CLASSNAME_MATCH_REGEX:} + 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/rbac/role.yaml b/config/operator/rbac/role.yaml index ae23be34..94f4c1b4 100644 --- a/config/operator/rbac/role.yaml +++ b/config/operator/rbac/role.yaml @@ -35,6 +35,14 @@ rules: - patch - update - watch +- apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - patch + - update - apiGroups: - "" resources: diff --git a/config/operator/webhook/add_nsSelector.yaml b/config/operator/webhook/ns_selector_patch.yaml similarity index 100% rename from config/operator/webhook/add_nsSelector.yaml rename to config/operator/webhook/ns_selector_patch.yaml diff --git a/controllers/operator/configmap_controller.go b/controllers/operator/configmap_controller.go new file mode 100644 index 00000000..e8caa606 --- /dev/null +++ b/controllers/operator/configmap_controller.go @@ -0,0 +1,121 @@ +// 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/apache/skywalking-swck/pkg/kubernetes" + "github.com/apache/skywalking-swck/pkg/operator/injector" + "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" +) + +// 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/main.go b/main.go index 98c00243..2efbf53f 100644 --- a/main.go +++ b/main.go @@ -23,7 +23,6 @@ import ( "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" @@ -31,7 +30,6 @@ import ( operatorv1alpha1 "github.com/apache/skywalking-swck/apis/operator/v1alpha1" controllers "github.com/apache/skywalking-swck/controllers/operator" operatorcontroller "github.com/apache/skywalking-swck/controllers/operator" - "github.com/apache/skywalking-swck/pkg/operator/injector" "github.com/apache/skywalking-swck/pkg/operator/repo" // +kubebuilder:scaffold:imports ) @@ -122,7 +120,7 @@ func main() { setupLog.Info("registering /mutate-v1-pod webhook") mgr.GetWebhookServer().Register("/mutate-v1-pod", &webhook.Admission{ - Handler: &injector.PodInjector{Client: mgr.GetClient()}}) + Handler: &operatorv1alpha1.Javaagent{Client: mgr.GetClient()}}) setupLog.Info("/mutate-v1-pod webhook is registered") setupLog.Info("starting manager") diff --git a/pkg/kubernetes/apply.go b/pkg/kubernetes/apply.go index 0bc70f1c..a877dce2 100644 --- a/pkg/kubernetes/apply.go +++ b/pkg/kubernetes/apply.go @@ -55,7 +55,7 @@ func (a *Application) ApplyAll(ctx context.Context, manifestFiles []string, log 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 @@ func (a *Application) ApplyAll(ctx context.Context, manifestFiles []string, log } // 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 @@ func (a *Application) Apply(ctx context.Context, manifest string, log logr.Logge 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 @@ func (a *Application) apply(ctx context.Context, obj *unstructured.Unstructured, 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 index d5914fb3..e2835c34 100644 --- a/pkg/operator/injector/annotation.go +++ b/pkg/operator/injector/annotation.go @@ -17,90 +17,78 @@ package injector -//Annotation is used to set default value +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 string - DefaultValue string + // 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 is used to set overlaied value -type Annotations map[Annotation]string +// Annotations are +type Annotations struct { + Annotations []Annotation +} + +//AnnotationOverlay is used to set overlaied value +type AnnotationOverlay map[Annotation]string -func setDefaultAnnotation(name, value string) Annotation { - return Annotation{ - Name: name, - DefaultValue: value, +// 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 } -const ( - namePrefix = "skywalking-swck-" -) - -// nolint -var ( - //set sidecar's basic information - AnnoInitcontainerName = setDefaultAnnotation(SidecarInitcontainerName, "inject-sky-agent") - AnnoInitcontainerImage = setDefaultAnnotation(SidecarInitcontainerImage, - "apache/skywalking-java-agent:8.6.0-jdk8") - AnnoInitcontainerCommand = setDefaultAnnotation(SidecarInitcontainerCommand, "sh") - AnnoInitcontainerArgsOption = setDefaultAnnotation(SidecarInitcontainerArgsOption, "-c") - AnnoInitcontainerArgsCommand = setDefaultAnnotation(SidecarInitcontainerArgsCommand, - "mkdir -p /sky/agent && cp -r /skywalking/agent/* /sky/agent") - AnnoSidecarVolumeName = setDefaultAnnotation(SidecarVolumeName, "sky-agent") - AnnoSidecarVolumemountMountpath = setDefaultAnnotation(SidecarVolumemountMountpath, "/sky/agent") - AnnoConfigmapName = setDefaultAnnotation(ConfigmapName, namePrefix+"java-agent-configmap") - AnnoConfigmapVolumeName = setDefaultAnnotation(ConfigmapVolumeName, "java-agent-configmap-volume") - AnnoConfigmapVolumemountMountpath = setDefaultAnnotation(ConfigmapVolumemountMountpath, "/sky/agent/config") - AnnoEnvVarName = setDefaultAnnotation(SidecarEnvVarName, "AGENT_OPTS") - AnnoEnvVarValue = setDefaultAnnotation(SidecarEnvValue, - "-javaagent:/sky/agent/skywalking-agent.jar") - AnnoInjectContainerName = setDefaultAnnotation(SidecarInjectContainerName, "") - //set nil - AnnoInjectErrorInfo = setDefaultAnnotation(SidecarInjectErrorInfo, "") - AnnoAgentConfigOverlay = setDefaultAnnotation(SidecarAgentConfigOverlay, "false") - //set agent config - AnnoAgentNamespace = setDefaultAnnotation(AgentNamespace, "default-namespace") - AnnoAgentServiceName = setDefaultAnnotation(AgentServiceName, "") - AnnoAgentSampleNumber = setDefaultAnnotation(AgentSampleNumber, "-1") - AnnoAgentAuthentication = setDefaultAnnotation(AgentAuthentication, "xxxx") - AnnoAgentSpanLimit = setDefaultAnnotation(AgentSpanLimit, "150") - AnnoAgentIgnoreSuffix = setDefaultAnnotation(AgentIgnoreSuffix, - ".jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg") - AnnoAgentIsOpenDebugging = setDefaultAnnotation(AgentIsOpenDebugging, "true") - AnnoAgentIsCacheEnhaned = setDefaultAnnotation(AgentIsCacheEnhaned, "false") - AnnoAgentClassCache = setDefaultAnnotation(AgentClassCache, "MEMORY") - AnnoAgentOperationName = setDefaultAnnotation(AgentOperationName, "150") - AnnoAgentForceTLS = setDefaultAnnotation(AgentForceTLS, "false") - AnnoAgentProfileActive = setDefaultAnnotation(AgentProfileActive, "true") - AnnoAgentProfileMaxParallel = setDefaultAnnotation(AgentProfileMaxParallel, "5") - AnnoAgentProfileMaxDuration = setDefaultAnnotation(AgentProfileMaxDuration, "10") - AnnoAgentProfileDump = setDefaultAnnotation(AgentProfileDump, "500") - AnnoAgentProfileSnapshot = setDefaultAnnotation(AgentProfileSnapshot, "50") - AnnoAgentCollectorService = setDefaultAnnotation(AgentCollectorService, "127.0.0.1:11800") - AnnoAgentLoggingName = setDefaultAnnotation(AgentLoggingName, "skywalking-api.log") - AnnoAgentLoggingLevel = setDefaultAnnotation(AgentLoggingLevel, "INFO") - AnnoAgentLoggingDir = setDefaultAnnotation(AgentLoggingDir, "") - AnnoAgentLoggingMaxSize = setDefaultAnnotation(AgentLoggingMaxSize, "314572800") - AnnoAgentLoggingMaxFiles = setDefaultAnnotation(AgentLoggingMaxFiles, "-1") - AnnoAgentStatuscheckExceptions = setDefaultAnnotation(AgentStatuscheckExceptions, "") - AnnoAgentStatuscheckDepth = setDefaultAnnotation(AgentStatuscheckDepth, "1") - AnnoAgentPluginMount = setDefaultAnnotation(AgentPluginMount, "plugins,activations") - AnnoAgentExcludePlugins = setDefaultAnnotation(AgentExcludePlugins, "") - AnnoAgentPluginJdbc = setDefaultAnnotation(AgentPluginJdbc, "false") - AnnoAgentPluginKafkaServers = setDefaultAnnotation(AgentPluginKafkaServers, "localhost:9092") - AnnoAgentPluginKafkaNamespace = setDefaultAnnotation(AgentPluginKafkaNamespace, "") - AnnoAgentPluginSpringannotation = setDefaultAnnotation(AgentPluginSpringannotation, "") -) +// 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 +} -//NewAnnotations will create a new Annotations -func NewAnnotations() *Annotations { - a := make(Annotations) +//NewAnnotationOverlay will create a new AnnotationOverlay +func NewAnnotationOverlay() *AnnotationOverlay { + a := make(AnnotationOverlay) return &a } //GetFinalValue will get overlaied value first , then default -func (as *Annotations) GetFinalValue(a Annotation) string { +func (as *AnnotationOverlay) GetFinalValue(a Annotation) string { ov := a.DefaultValue if v, ok := (*as)[a]; ok { ov = v @@ -109,10 +97,11 @@ func (as *Annotations) GetFinalValue(a Annotation) string { } //SetOverlay will set overlaied value -func (as *Annotations) SetOverlay(annotations *map[string]string, a Annotation) error { - if v, ok := (*annotations)[a.Name]; ok { +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 - if f, funok := AnnotationValidate[a.Name]; funok { + f := FindValidateFunc(a.ValidateFunc) + if f != nil { err := f(a.Name, v) //validate error if err != nil { @@ -126,7 +115,7 @@ func (as *Annotations) SetOverlay(annotations *map[string]string, a Annotation) } //GetOverlayValue will get overlaied value, if not then return "" -func (as *Annotations) GetOverlayValue(a Annotation) string { +func (as *AnnotationOverlay) GetOverlayValue(a Annotation) string { if v, ok := (*as)[a]; ok { return v } diff --git a/pkg/operator/injector/configmap.go b/pkg/operator/injector/configmap.go new file mode 100644 index 00000000..046b603c --- /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.LastIndex(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/constants.go b/pkg/operator/injector/constants.go deleted file mode 100644 index 1ee9937d..00000000 --- a/pkg/operator/injector/constants.go +++ /dev/null @@ -1,74 +0,0 @@ -// 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 - -// nolint -const ( - //the annotation that contain the sidecar's basic information,such as agent container..etc - SidecarInitcontainerName = "sidecar.skywalking.apache.org/initcontainers.name" - SidecarInitcontainerImage = "sidecar.skywalking.apache.org/initcontainers.image" - SidecarInitcontainerCommand = "sidecar.skywalking.apache.org/initcontainers.command" - SidecarInitcontainerArgsOption = "sidecar.skywalking.apache.org/initcontainers.args.option" - SidecarInitcontainerArgsCommand = "sidecar.skywalking.apache.org/initcontainers.args.command" - SidecarVolumeName = "sidecar.skywalking.apache.org/volume.name" - SidecarVolumemountMountpath = "sidecar.skywalking.apache.org/containers.volumemounts.mountpath" - ConfigmapName = "sidecar.skywalking.apache.org/configmap.name" - ConfigmapVolumeName = "sidecar.skywalking.apache.org/configmap.volume.name" - ConfigmapVolumemountMountpath = "sidecar.skywalking.apache.org/configmap.volumemounts.mountpath" - SidecarEnvVarName = "sidecar.skywalking.apache.org/envvar.name" - SidecarEnvValue = "sidecar.skywalking.apache.org/envvar.value" - SidecarInjectContainerName = "sidecar.skywalking.apache.org/sidecar.containers.name" - - //the annotation that specify the reason for injection failure - SidecarInjectErrorInfo = "sidecar.skywalking.apache.org/error" - - //the annotation that open or close agent overlay - SidecarAgentConfigOverlay = "sidecar.skywalking.apache.org/agent.config.overlay" - - //the annotation that specify the agent config - AgentNamespace = "agent.skywalking.apache.org/agent.namespace" - AgentServiceName = "agent.skywalking.apache.org/agent.service_name" - AgentSampleNumber = "agent.skywalking.apache.org/agent.sample_n_per_3_secs" - AgentAuthentication = "agent.skywalking.apache.org/agent.authentication" - AgentSpanLimit = "agent.skywalking.apache.org/agent.span_limit_per_segment" - AgentIgnoreSuffix = "agent.skywalking.apache.org/agent.ignore_suffix" - AgentIsOpenDebugging = "agent.skywalking.apache.org/agent.is_open_debugging_class" - AgentIsCacheEnhaned = "agent.skywalking.apache.org/agent.is_cache_enhanced_class" - AgentClassCache = "agent.skywalking.apache.org/agent.class_cache_mode" - AgentOperationName = "agent.skywalking.apache.org/agent.operation_name_threshold" - AgentForceTLS = "agent.skywalking.apache.org/agent.force_tls" - AgentProfileActive = "agent.skywalking.apache.org/profile.active" - AgentProfileMaxParallel = "agent.skywalking.apache.org/profile.max_parallel" - AgentProfileMaxDuration = "agent.skywalking.apache.org/profile.max_duration" - AgentProfileDump = "agent.skywalking.apache.org/profile.dump_max_stack_depth" - AgentProfileSnapshot = "agent.skywalking.apache.org/profile.snapshot_transport_buffer_size" - AgentCollectorService = "agent.skywalking.apache.org/collector.backend_service" - AgentLoggingName = "agent.skywalking.apache.org/logging.file_name" - AgentLoggingLevel = "agent.skywalking.apache.org/logging.level" - AgentLoggingDir = "agent.skywalking.apache.org/logging.dir" - AgentLoggingMaxSize = "agent.skywalking.apache.org/logging.max_file_size" - AgentLoggingMaxFiles = "agent.skywalking.apache.org/logging.max_history_files" - AgentStatuscheckExceptions = "agent.skywalking.apache.org/statuscheck.ignored_exceptions" - AgentStatuscheckDepth = "agent.skywalking.apache.org/statuscheck.max_recursive_depth" - AgentPluginMount = "agent.skywalking.apache.org/plugin.mount" - AgentExcludePlugins = "agent.skywalking.apache.org/plugin.exclude_plugins" - AgentPluginJdbc = "agent.skywalking.apache.org/plugin.jdbc.trace_sql_parameters" - AgentPluginKafkaServers = "agent.skywalking.apache.org/plugin.kafka.bootstrap_servers" - AgentPluginKafkaNamespace = "agent.skywalking.apache.org/plugin.kafka.namespace" - AgentPluginSpringannotation = "agent.skywalking.apache.org/plugin.springannotation.classname_match_regex" -) diff --git a/pkg/operator/injector/injection.go b/pkg/operator/injector/injection.go new file mode 100644 index 00000000..39962cb3 --- /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" + "sigs.k8s.io/controller-runtime/pkg/client" + + corev1 "k8s.io/api/core/v1" + "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 +// 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 is similar to OverlayAgent , but it don't hava validate function +// 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}, "=") + } + 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 index a33b4564..333079a9 100644 --- a/pkg/operator/injector/injector.go +++ b/pkg/operator/injector/injector.go @@ -19,27 +19,34 @@ package injector import ( "context" - "encoding/json" "fmt" - "net/http" "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" - "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) const ( - labelKeyagentInjector = "swck-java-agent-injected" - defaultConfigmapNamespace = "skywalking-swck-system" - agentConfigAnnotationPrefix = "agent.skywalking.apache.org/" + // 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" - otherPluginsAnnotationPrefix = "plugins.skywalking.apache.org/" + pluginsAnnotationPrefix = "plugins.skywalking.apache.org/" ) // log is for logging in this package. @@ -48,31 +55,31 @@ 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 + 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 + 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 + SidecarVolume corev1.Volume // sidecarVolumeMount is a path that specifies a shared directory - sidecarVolumeMount corev1.VolumeMount + SidecarVolumeMount corev1.VolumeMount // configmapVolume is volume that provide user with configmap - configmapVolume corev1.Volume + 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 + ConfigmapVolumeMount corev1.VolumeMount // env is used to set java agent’s parameters - env corev1.EnvVar + Env corev1.EnvVar // the string is used to set jvm agent ,just like following // -javaagent: /sky/agent/skywalking-agent,jar=jvmAgentConfigStr - jvmAgentConfigStr string + JvmAgentConfigStr string // determine which container to inject , default is to inject all containers - injectContainer string + InjectContainer string } // NewSidecarInjectField will create a new SidecarInjectField @@ -84,116 +91,114 @@ func NewSidecarInjectField() *SidecarInjectField { 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) + pod.Spec.InitContainers = append(pod.Spec.InitContainers, s.Initcontainer) } else { - pod.Spec.InitContainers = []corev1.Container{s.initcontainer} + 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) + pod.Spec.Volumes = append(pod.Spec.Volumes, s.SidecarVolume, s.ConfigmapVolume) } else { - pod.Spec.Volumes = []corev1.Volume{s.sidecarVolume, s.configmapVolume} + 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, c := range pod.Spec.Containers { - // choose a specific container to inject - if s.injectContainer != "" && c.Name == s.injectContainer { - if c.VolumeMounts != nil { - pod.Spec.Containers[i].VolumeMounts = append(pod.Spec.Containers[i].VolumeMounts, - s.sidecarVolumeMount, s.configmapVolumeMount) - } else { - pod.Spec.Containers[i].VolumeMounts = []corev1.VolumeMount{s.sidecarVolumeMount, - s.configmapVolumeMount} - } - if c.Env != nil { - pod.Spec.Containers[i].Env = append(pod.Spec.Containers[i].Env, s.env) - } else { - pod.Spec.Containers[i].Env = []corev1.EnvVar{s.env} - } - break + for i := range containers { + if (*containers[i]).VolumeMounts != nil { + (*containers[i]).VolumeMounts = append((*containers[i]).VolumeMounts, + s.SidecarVolumeMount, s.ConfigmapVolumeMount) } else { - if c.VolumeMounts != nil { - pod.Spec.Containers[i].VolumeMounts = append(pod.Spec.Containers[i].VolumeMounts, - s.sidecarVolumeMount, s.configmapVolumeMount) - } else { - pod.Spec.Containers[i].VolumeMounts = []corev1.VolumeMount{s.sidecarVolumeMount, - s.configmapVolumeMount} - } - if c.Env != nil { - pod.Spec.Containers[i].Env = append(pod.Spec.Containers[i].Env, s.env) - } else { - pod.Spec.Containers[i].Env = []corev1.EnvVar{s.env} - } + (*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(containers []corev1.Container, labels, +func (s *SidecarInjectField) GetInjectStrategy(a Annotations, labels, annotation *map[string]string) { // set default value - s.needInject = false - s.injectContainer = "" - s.agentOverlay = false + 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 + // set NeedInject's value , if the pod has the label "swck-java-agent-injected=true",means need inject if *labels == nil { - labels = new(map[string]string) - s.needInject = false + return } - switch strings.ToLower((*labels)[labelKeyagentInjector]) { - case "true": - s.needInject = true + if strings.ToLower((*labels)[labelKeyagentInjector]) == "true" { + s.NeedInject = true } - // set injectContainer's value if *annotation == nil { - annotation = new(map[string]string) - s.injectContainer = "" - s.agentOverlay = false + return } - // validate the container is or not exist - if v, ok := (*annotation)[AnnoInjectContainerName.Name]; ok { - for _, c := range containers { - if c.Name == v { - s.injectContainer = v - break - } + // 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 } } +} - // set agentOverlay's value - switch strings.ToLower((*annotation)[AnnoAgentConfigOverlay.Name]) { - case "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)[AnnoInjectErrorInfo.Name] = errorInfo + (*annotation)[sidecarInjectErrorAnno] = errorInfo } // SidecarOverlayandGetValue get final value of sidecar -func (s *SidecarInjectField) SidecarOverlayandGetValue(as *Annotations, annotation *map[string]string, +func (s *SidecarInjectField) SidecarOverlayandGetValue(ao *AnnotationOverlay, annotation *map[string]string, a Annotation) (string, bool) { if _, ok := (*annotation)[a.Name]; ok { - err := as.SetOverlay(annotation, a) + err := ao.SetOverlay(annotation, a) if err != nil { s.injectErrorAnnotation(annotation, err.Error()) return "", false } } - return as.GetFinalValue(a), true + return ao.GetFinalValue(a), true } -func (s *SidecarInjectField) setValue(config *string, as *Annotations, annotation *map[string]string, +func (s *SidecarInjectField) setValue(config *string, ao *AnnotationOverlay, annotation *map[string]string, a Annotation) bool { - if v, ok := s.SidecarOverlayandGetValue(as, annotation, a); ok { + if v, ok := s.SidecarOverlayandGetValue(ao, annotation, a); ok { *config = v return true } @@ -201,287 +206,157 @@ func (s *SidecarInjectField) setValue(config *string, as *Annotations, annotatio } // OverlaySidecar overlays default config -func (s *SidecarInjectField) OverlaySidecar(as *Annotations, annotation *map[string]string) bool { - var ( - command string - argOption string - argCommand string - configmapName string - ) - - switch { - case !s.setValue(&s.initcontainer.Name, as, annotation, AnnoInitcontainerName): - return false - case !s.setValue(&s.initcontainer.Image, as, annotation, AnnoInitcontainerImage): - return false - case !s.setValue(&command, as, annotation, AnnoInitcontainerCommand): - return false - case !s.setValue(&argOption, as, annotation, AnnoInitcontainerArgsOption): - return false - case !s.setValue(&argCommand, as, annotation, AnnoInitcontainerArgsCommand): - return false - case !s.setValue(&s.sidecarVolume.Name, as, annotation, AnnoSidecarVolumeName): - return false - case !s.setValue(&s.sidecarVolumeMount.Name, as, annotation, AnnoSidecarVolumeName): - return false - case !s.setValue(&s.sidecarVolumeMount.MountPath, as, annotation, AnnoSidecarVolumemountMountpath): - return false - case !s.setValue(&configmapName, as, annotation, AnnoConfigmapName): - return false - case !s.setValue(&s.configmapVolume.Name, as, annotation, AnnoConfigmapVolumeName): - return false - case !s.setValue(&s.configmapVolumeMount.Name, as, annotation, AnnoConfigmapVolumeName): - return false - case !s.setValue(&s.configmapVolumeMount.MountPath, as, annotation, AnnoConfigmapVolumemountMountpath): - return false - case !s.setValue(&s.env.Name, as, annotation, AnnoEnvVarName): - return false - case !s.setValue(&s.env.Value, as, annotation, AnnoEnvVarValue): - return false +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, } - - s.initcontainer.Command = []string{command} - s.initcontainer.Args = []string{argOption, argCommand} - s.initcontainer.VolumeMounts = []corev1.VolumeMount{s.sidecarVolumeMount} + 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 - - s.configmapVolume.VolumeSource = corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: configmapName, - }, - }, - } + s.SidecarVolume.VolumeSource.EmptyDir = nil return true } // AgentOverlayandGetValue will do real annotation overlay -func (s *SidecarInjectField) AgentOverlayandGetValue(as *Annotations, annotation *map[string]string, +func (s *SidecarInjectField) AgentOverlayandGetValue(ao *AnnotationOverlay, annotation *map[string]string, a Annotation) (string, bool) { if _, ok := (*annotation)[a.Name]; ok { - err := as.SetOverlay(annotation, a) + err := ao.SetOverlay(annotation, a) if err != nil { s.injectErrorAnnotation(annotation, err.Error()) return "", false } } - return as.GetOverlayValue(a), true + return ao.GetOverlayValue(a), true } -func (s *SidecarInjectField) setJvmAgentStr(as *Annotations, annotation *map[string]string, a Annotation, - specialStr bool) bool { - v, ok := s.AgentOverlayandGetValue(as, annotation, a) +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, agentConfigAnnotationPrefix) - if specialStr { + 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}, ",") + if s.JvmAgentConfigStr != "" { + s.JvmAgentConfigStr = strings.Join([]string{s.JvmAgentConfigStr, config}, ",") } else { - s.jvmAgentConfigStr = config + s.JvmAgentConfigStr = config } } return ok } -// OverlayAgentConfig overlays agent config -func (s *SidecarInjectField) OverlayAgentConfig(as *Annotations, annotation *map[string]string) bool { +// OverlayAgent overlays agent +func (s *SidecarInjectField) OverlayAgent(a Annotations, ao *AnnotationOverlay, annotation *map[string]string) bool { // jvmAgentConfigStr init - s.jvmAgentConfigStr = "" - - switch { - case !s.setJvmAgentStr(as, annotation, AnnoAgentNamespace, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentServiceName, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentSampleNumber, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentAuthentication, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentSpanLimit, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentIgnoreSuffix, true): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentIsOpenDebugging, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentIsCacheEnhaned, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentClassCache, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentOperationName, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentForceTLS, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentProfileActive, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentProfileMaxParallel, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentProfileMaxDuration, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentProfileDump, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentProfileSnapshot, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentCollectorService, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentLoggingName, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentLoggingLevel, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentLoggingDir, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentLoggingMaxSize, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentLoggingMaxFiles, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentStatuscheckExceptions, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentStatuscheckDepth, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentPluginMount, true): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentExcludePlugins, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentPluginJdbc, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentPluginKafkaServers, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentPluginKafkaNamespace, false): - return false - case !s.setJvmAgentStr(as, annotation, AnnoAgentPluginSpringannotation, false): - return false + s.JvmAgentConfigStr = "" + anno := GetAnnotationsByPrefix(a, agentAnnotationPrefix) + for _, v := range anno.Annotations { + if !s.setJvmAgentStr(ao, annotation, v) { + return false + } } - return true } -// OverlayPluginsConfig will add Plugins' config to JvmAgentStr without verification +// 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) OverlayPluginsConfig(annotation *map[string]string) bool { +func (s *SidecarInjectField) OverlayPlugins(annotation *map[string]string) { for k, v := range *annotation { - if strings.HasPrefix(k, otherPluginsAnnotationPrefix) { - configName := strings.TrimPrefix(k, otherPluginsAnnotationPrefix) + 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}, ",") + if s.JvmAgentConfigStr != "" { + s.JvmAgentConfigStr = strings.Join([]string{s.JvmAgentConfigStr, config}, ",") } else { - s.jvmAgentConfigStr = config + s.JvmAgentConfigStr = config } } } - return true } -// CreateConfigmap will find a configmap to set agent config -// if not exist , then create a configmap +// 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 + 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 configmap not exist , get configmap from defaultConfigmapNamespace - if err != nil { - defaultConfigmap := &corev1.ConfigMap{} - if err := kubeclient.Get(ctx, client.ObjectKey{Namespace: defaultConfigmapNamespace, - Name: AnnoConfigmapName.DefaultValue}, defaultConfigmap); err != nil { - log.Info(err.Error()) - s.injectErrorAnnotation(annotation, fmt.Sprintf("get configmap %s from namespace %s error[%s]", - AnnoConfigmapName.DefaultValue, defaultConfigmapNamespace, err.Error())) - return false - } - // create new configmap and update namespace - injectConfigmap := corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: configmapName, - Namespace: namespace, - }, - Data: defaultConfigmap.Data, - } - - if err := kubeclient.Create(ctx, &injectConfigmap); err != nil { - log.Info(err.Error()) - s.injectErrorAnnotation(annotation, fmt.Sprintf("create configmap %s in namespace %s error[%s]", - configmapName, namespace, err.Error())) - return false + 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) } - return true -} - -// PodInjector injects agent into Pods -type PodInjector struct { - Client client.Client - decoder *admission.Decoder -} - -// Handle will process every coming pod under the -// specified namespace which labeled "swck-injection=enabled" -func (r *PodInjector) 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) + // 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 } - // init Annotations to store the overlaied value - as := NewAnnotations() - - // init SidecarInjectField and get injected strategy from annotations - s := NewSidecarInjectField() - s.GetInjectStrategy(pod.Spec.Containers, &pod.ObjectMeta.Labels, &pod.ObjectMeta.Annotations) - - if s.needInject { - log.Info("will inject agent,please wait for a moment!") - // the overlation function is always on - s.OverlaySidecar(as, &pod.ObjectMeta.Annotations) - switch { - // only if user choose to overlay agent config in annotations, then start agent and plugins' overlay - case s.agentOverlay && (!s.OverlayAgentConfig(as, &pod.ObjectMeta.Annotations) || - !s.OverlayPluginsConfig(&pod.ObjectMeta.Annotations)): - log.Info("overlay agent config error!please look the error annotation!") - // configmap will always overwrite the original agent.config in image - case !s.CreateConfigmap(ctx, r.Client, req.Namespace, &pod.ObjectMeta.Annotations): - log.Info("create configmap error!please look the error annotation!") - // add jvmStr to EnvVar and do real injection - default: - if s.jvmAgentConfigStr != "" { - s.env.Value = strings.Join([]string{s.env.Value, s.jvmAgentConfigStr}, "=") - } - s.Inject(pod) - log.Info("inject successfully!") - } - } else { - // if the pod don't have the label "swck-java-agent-injected=true",return ok - log.Info("don't inject agent!") - return admission.Allowed("ok") + // 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, } - marshaledPod, err := json.Marshal(pod) - if err != nil { - return admission.Errored(http.StatusInternalServerError, err) + // 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 admission.PatchResponseFromRaw(req.Object.Raw, marshaledPod) -} - -// PodInjector implements admission.DecoderInjector. -// A decoder will be automatically injected. - -// InjectDecoder injects the decoder. -func (r *PodInjector) InjectDecoder(d *admission.Decoder) error { - r.decoder = d - return nil + return true } diff --git a/pkg/operator/injector/injector_test.go b/pkg/operator/injector/injector_test.go deleted file mode 100644 index d5d5798b..00000000 --- a/pkg/operator/injector/injector_test.go +++ /dev/null @@ -1,514 +0,0 @@ -// 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" - "testing" - - corev1 "k8s.io/api/core/v1" -) - -func TestSidecarInjectField_Inject(t *testing.T) { - type fields struct { - needInject bool - agentOverlay bool - initcontainer corev1.Container - sidecarVolume corev1.Volume - sidecarVolumeMount corev1.VolumeMount - configmapVolume corev1.Volume - configmapVolumeMount corev1.VolumeMount - env corev1.EnvVar - jvmAgentConfigStr string - injectContainer string - } - type args struct { - pod *corev1.Pod - } - - Pod := &corev1.Pod{ - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "app", - }, - }, - }, - } - - // injected sidecar Volumes - injectedSV := corev1.Volume{ - Name: "sky-agent", - VolumeSource: corev1.VolumeSource{EmptyDir: nil}, - } - - // injected configmap Volumes - injectedCV := corev1.Volume{ - Name: "java-agent-configmap-volume", - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: "java-agent-configmap", - }, - }, - }, - } - - // injected Sidecar's VolumeMount - injectedSVM := corev1.VolumeMount{ - MountPath: "/sky/agent", - Name: "sky-agent", - } - - // injected Configmap's VolumeMount - injectedCVM := corev1.VolumeMount{ - Name: "java-agent-configmap-volume", - MountPath: "/sky/agent/config", - } - - // injected InitContainer - injectedIC := corev1.Container{ - Name: "inject-sky-agent", - Image: "apache/skywalking-java-agent:8.6.0-jdk8", - Command: []string{"sh"}, - Args: []string{"-c", "mkdir -p /sky/agent && cp -r /skywalking/agent/* /sky/agent"}, - VolumeMounts: []corev1.VolumeMount{injectedSVM}, - } - - // injected Container's EnvVar - injectedEV := corev1.EnvVar{ - Name: "AGENT_OPTS", - Value: " -javaagent:/sky/agent/skywalking-agent.jar", - } - - injectedPod := &corev1.Pod{ - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "app", - VolumeMounts: []corev1.VolumeMount{ - injectedSVM, injectedCVM, - }, - Env: []corev1.EnvVar{ - injectedEV, - }, - }, - }, - InitContainers: []corev1.Container{ - injectedIC, - }, - Volumes: []corev1.Volume{ - injectedSV, injectedCV, - }, - }, - } - tests := []struct { - name string - fields fields - args args - }{ - { - name: "test inject function", - fields: fields{ - initcontainer: injectedIC, - sidecarVolume: injectedSV, - sidecarVolumeMount: injectedSVM, - configmapVolume: injectedCV, - configmapVolumeMount: injectedCVM, - env: injectedEV, - injectContainer: "app", - }, - args: args{ - pod: Pod, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - s := &SidecarInjectField{ - initcontainer: tt.fields.initcontainer, - sidecarVolume: tt.fields.sidecarVolume, - sidecarVolumeMount: tt.fields.sidecarVolumeMount, - configmapVolume: tt.fields.configmapVolume, - configmapVolumeMount: tt.fields.configmapVolumeMount, - env: tt.fields.env, - jvmAgentConfigStr: tt.fields.jvmAgentConfigStr, - needInject: tt.fields.needInject, - injectContainer: tt.fields.injectContainer, - agentOverlay: tt.fields.agentOverlay, - } - s.Inject(tt.args.pod) - if !reflect.DeepEqual(injectedPod, tt.args.pod) { - fmt.Println(injectedPod) - t.Errorf("Inject() got= %v,want %v", tt.args.pod, injectedPod) - } - }) - } -} - -func TestSidecarInjectField_GetInjectStrategy(t *testing.T) { - type fields struct { - needInject bool - agentOverlay bool - initcontainer corev1.Container - sidecarVolume corev1.Volume - sidecarVolumeMount corev1.VolumeMount - configmapVolume corev1.Volume - configmapVolumeMount corev1.VolumeMount - env corev1.EnvVar - jvmAgentConfigStr string - injectContainer string - } - type args struct { - containers []corev1.Container - labels *map[string]string - annotation *map[string]string - } - tests := []struct { - name string - fields fields - args args - }{ - { - name: "test right", - fields: fields{ - needInject: false, - injectContainer: "", - agentOverlay: false, - }, - args: args{ - containers: []corev1.Container{ - { - Name: "container1", - }, - }, - labels: &map[string]string{ - labelKeyagentInjector: "true", - }, - annotation: &map[string]string{ - AnnoInjectContainerName.Name: "container1", - AnnoAgentConfigOverlay.Name: "true", - }, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - s := &SidecarInjectField{ - initcontainer: tt.fields.initcontainer, - sidecarVolume: tt.fields.sidecarVolume, - sidecarVolumeMount: tt.fields.sidecarVolumeMount, - configmapVolume: tt.fields.configmapVolume, - configmapVolumeMount: tt.fields.configmapVolumeMount, - env: tt.fields.env, - jvmAgentConfigStr: tt.fields.jvmAgentConfigStr, - needInject: tt.fields.needInject, - injectContainer: tt.fields.injectContainer, - agentOverlay: tt.fields.agentOverlay, - } - s.GetInjectStrategy(tt.args.containers, tt.args.labels, tt.args.annotation) - if !s.needInject || s.injectContainer != "container1" || !s.agentOverlay { - t.Errorf("GetInjectStrategy got= [%v,%v,%v], want [true,container1,true]", s.needInject, - s.injectContainer, s.agentOverlay) - } - }) - } -} - -func TestSidecarInjectField_OverlaySidecar(t *testing.T) { - type fields struct { - needInject bool - agentOverlay bool - initcontainer corev1.Container - sidecarVolume corev1.Volume - sidecarVolumeMount corev1.VolumeMount - configmapVolume corev1.Volume - configmapVolumeMount corev1.VolumeMount - env corev1.EnvVar - jvmAgentConfigStr string - injectContainer string - } - type args struct { - as *Annotations - annotation *map[string]string - } - initcontainer := corev1.Container{ - Name: AnnoInitcontainerName.DefaultValue, - Image: AnnoInitcontainerImage.DefaultValue, - Command: []string{AnnoInitcontainerCommand.DefaultValue}, - Args: []string{AnnoInitcontainerArgsOption.DefaultValue, AnnoInitcontainerArgsCommand. - DefaultValue}, - } - sidecarVolume := corev1.Volume{ - Name: AnnoSidecarVolumeName.DefaultValue, - VolumeSource: corev1.VolumeSource{ - EmptyDir: nil, - }, - } - sidecarVolumeMount := corev1.VolumeMount{ - Name: AnnoSidecarVolumeName.DefaultValue, - MountPath: AnnoSidecarVolumemountMountpath.DefaultValue, - } - configmapVolume := corev1.Volume{ - Name: AnnoConfigmapVolumeName.DefaultValue, - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: AnnoConfigmapName.DefaultValue, - }, - }, - }, - } - configmapVolumeMount := corev1.VolumeMount{ - Name: AnnoConfigmapVolumeName.DefaultValue, - MountPath: AnnoConfigmapVolumemountMountpath.DefaultValue, - } - env := corev1.EnvVar{ - Name: AnnoEnvVarName.DefaultValue, - Value: AnnoEnvVarValue.DefaultValue, - } - tests := []struct { - name string - fields fields - args args - want bool - }{ - { - name: "test sidecar overlay", - fields: fields{ - initcontainer: initcontainer, - sidecarVolume: sidecarVolume, - sidecarVolumeMount: sidecarVolumeMount, - configmapVolume: configmapVolume, - configmapVolumeMount: configmapVolumeMount, - env: env, - }, - args: args{ - as: NewAnnotations(), - annotation: &map[string]string{ - AnnoInitcontainerName.Name: "test-inject-agent", - AnnoInitcontainerImage.Name: "apache/skywalking-java-agent:8.5.0-jdk8", - AnnoInitcontainerCommand.Name: "sh", - AnnoInitcontainerArgsOption.Name: "-c", - AnnoInitcontainerArgsCommand.Name: "mkdir -p /skytest/agent && cp -r /skywalking/agent/* /skytest/agent", - AnnoSidecarVolumemountMountpath.Name: "/skytest/agent", - AnnoConfigmapVolumemountMountpath.Name: "/skytest/agent/config", - AnnoEnvVarValue.Name: " -javaagent:/skytest/agent/skywalking-agent.jar", - }, - }, - want: true, - }, - } - - overlaied := &SidecarInjectField{ - initcontainer: initcontainer, - sidecarVolume: sidecarVolume, - sidecarVolumeMount: sidecarVolumeMount, - configmapVolume: configmapVolume, - configmapVolumeMount: configmapVolumeMount, - env: env, - } - overlaied.initcontainer.Name = "test-inject-agent" - overlaied.initcontainer.Image = "apache/skywalking-java-agent:8.5.0-jdk8" - overlaied.initcontainer.Command = []string{"sh"} - overlaied.initcontainer.Args = []string{"-c", "mkdir -p /skytest/agent && cp -r /skywalking/agent/* /skytest/agent"} - overlaied.sidecarVolumeMount.MountPath = "/skytest/agent" - overlaied.configmapVolumeMount.MountPath = "/skytest/agent/config" - overlaied.env.Value = " -javaagent:/skytest/agent/skywalking-agent.jar" - overlaied.initcontainer.VolumeMounts = []corev1.VolumeMount{overlaied.sidecarVolumeMount} - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - s := &SidecarInjectField{ - initcontainer: tt.fields.initcontainer, - sidecarVolume: tt.fields.sidecarVolume, - sidecarVolumeMount: tt.fields.sidecarVolumeMount, - configmapVolume: tt.fields.configmapVolume, - configmapVolumeMount: tt.fields.configmapVolumeMount, - env: tt.fields.env, - jvmAgentConfigStr: tt.fields.jvmAgentConfigStr, - needInject: tt.fields.needInject, - injectContainer: tt.fields.injectContainer, - agentOverlay: tt.fields.agentOverlay, - } - if got := s.OverlaySidecar(tt.args.as, tt.args.annotation); got != tt.want || !reflect.DeepEqual(overlaied, s) { - t.Errorf("SidecarInjectField.OverlaySidecar() = %v, want %v", got, tt.want) - t.Errorf("after OverlaySidecar,the SidecarInjectField is %v\nwant %v", s, overlaied) - } - }) - } -} - -func TestSidecarInjectField_OverlayAgentConfig(t *testing.T) { - type fields struct { - needInject bool - agentOverlay bool - initcontainer corev1.Container - sidecarVolume corev1.Volume - sidecarVolumeMount corev1.VolumeMount - configmapVolume corev1.Volume - configmapVolumeMount corev1.VolumeMount - env corev1.EnvVar - jvmAgentConfigStr string - injectContainer string - } - type args struct { - as *Annotations - annotation *map[string]string - } - tests := []struct { - name string - fields fields - args args - want bool - }{ - { - name: "test right OverlayAgentConfig", - fields: fields{}, - args: args{ - as: NewAnnotations(), - annotation: &map[string]string{ - AnnoAgentNamespace.Name: "default-namespace", - AnnoAgentServiceName.Name: "test", - AnnoAgentSampleNumber.Name: "6", - AnnoAgentAuthentication.Name: "test", - AnnoAgentSpanLimit.Name: "100", - AnnoAgentIgnoreSuffix.Name: "jpg,.jpeg", - AnnoAgentIsOpenDebugging.Name: "false", - AnnoAgentIsCacheEnhaned.Name: "false", - AnnoAgentClassCache.Name: "MEMORY", - AnnoAgentOperationName.Name: "100", - AnnoAgentForceTLS.Name: "false", - AnnoAgentProfileActive.Name: "false", - AnnoAgentProfileMaxParallel.Name: "10", - AnnoAgentProfileMaxDuration.Name: "10", - AnnoAgentProfileDump.Name: "200", - AnnoAgentProfileSnapshot.Name: "200", - AnnoAgentCollectorService.Name: "localhost:2021", - AnnoAgentLoggingName.Name: "skywalking-api.log", - AnnoAgentLoggingLevel.Name: "INFO", - AnnoAgentLoggingDir.Name: "test", - AnnoAgentLoggingMaxSize.Name: "1000", - AnnoAgentLoggingMaxFiles.Name: "-1", - AnnoAgentStatuscheckExceptions.Name: "test", - AnnoAgentStatuscheckDepth.Name: "10", - AnnoAgentPluginMount.Name: "plugins,activations", - AnnoAgentExcludePlugins.Name: "test", - AnnoAgentPluginJdbc.Name: "false", - AnnoAgentPluginKafkaServers.Name: "127.0.0.1:9092", - AnnoAgentPluginKafkaNamespace.Name: "test", - AnnoAgentPluginSpringannotation.Name: "test", - }, - }, - want: true, - }, - } - finalStr := `agent.namespace=default-namespace,agent.service_name=test,` + - `agent.sample_n_per_3_secs=6,agent.authentication=test,agent.span_limit_per_segment=100,` + - `agent.ignore_suffix='jpg,.jpeg',agent.is_open_debugging_class=false,agent.is_cache_enhanced_class=false,` + - `agent.class_cache_mode=MEMORY,agent.operation_name_threshold=100,agent.force_tls=false,profile.active=false,` + - `profile.max_parallel=10,profile.max_duration=10,profile.dump_max_stack_depth=200,` + - `profile.snapshot_transport_buffer_size=200,collector.backend_service=localhost:2021,` + - `logging.file_name=skywalking-api.log,logging.level=INFO,logging.dir=test,logging.max_file_size=1000,` + - `logging.max_history_files=-1,statuscheck.ignored_exceptions=test,statuscheck.max_recursive_depth=10,` + - `plugin.mount='plugins,activations',plugin.exclude_plugins=test,plugin.jdbc.trace_sql_parameters=false,` + - `plugin.kafka.bootstrap_servers=127.0.0.1:9092,plugin.kafka.namespace=test,` + - `plugin.springannotation.classname_match_regex=test` - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - s := &SidecarInjectField{ - initcontainer: tt.fields.initcontainer, - sidecarVolume: tt.fields.sidecarVolume, - sidecarVolumeMount: tt.fields.sidecarVolumeMount, - configmapVolume: tt.fields.configmapVolume, - configmapVolumeMount: tt.fields.configmapVolumeMount, - env: tt.fields.env, - jvmAgentConfigStr: tt.fields.jvmAgentConfigStr, - needInject: tt.fields.needInject, - injectContainer: tt.fields.injectContainer, - agentOverlay: tt.fields.agentOverlay, - } - if got := s.OverlayAgentConfig(tt.args.as, tt.args.annotation); got != tt.want || - finalStr != s.jvmAgentConfigStr { - t.Errorf("SidecarInjectField.OverlayAgentConfig() = %v, want %v", got, tt.want) - t.Errorf("SidecarInjectField.OverlayAgentConfig():%s\nwant %s", s.jvmAgentConfigStr, finalStr) - } - }) - } -} - -func TestSidecarInjectField_OverlayPluginsConfig(t *testing.T) { - type fields struct { - needInject bool - agentOverlay bool - initcontainer corev1.Container - sidecarVolume corev1.Volume - sidecarVolumeMount corev1.VolumeMount - configmapVolume corev1.Volume - configmapVolumeMount corev1.VolumeMount - env corev1.EnvVar - jvmAgentConfigStr string - injectContainer string - } - type args struct { - annotation *map[string]string - } - tests := []struct { - name string - fields fields - args args - want bool - }{ - { - name: "test right OverlayPluginsConfig", - fields: fields{}, - args: args{ - annotation: &map[string]string{ - otherPluginsAnnotationPrefix + "plugin.influxdb.trace_influxql": "false", - otherPluginsAnnotationPrefix + "plugin.mongodb.trace_param": "true", - }, - }, - want: true, - }, - } - // avoid random traversal of map type - finalStr1 := `plugin.influxdb.trace_influxql=false,plugin.mongodb.trace_param=true` - finalStr2 := `plugin.mongodb.trace_param=true,plugin.influxdb.trace_influxql=false` - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - s := &SidecarInjectField{ - initcontainer: tt.fields.initcontainer, - sidecarVolume: tt.fields.sidecarVolume, - sidecarVolumeMount: tt.fields.sidecarVolumeMount, - configmapVolume: tt.fields.configmapVolume, - configmapVolumeMount: tt.fields.configmapVolumeMount, - env: tt.fields.env, - jvmAgentConfigStr: tt.fields.jvmAgentConfigStr, - needInject: tt.fields.needInject, - injectContainer: tt.fields.injectContainer, - agentOverlay: tt.fields.agentOverlay, - } - if got := s.OverlayPluginsConfig(tt.args.annotation); got != tt.want || - (s.jvmAgentConfigStr != finalStr1 && s.jvmAgentConfigStr != finalStr2) { - t.Errorf("SidecarInjectField.OverlayPluginsConfig() = %v, want %v", got, tt.want) - t.Errorf("SidecarInjectField.OverlayPluginsConfig():%s\nwant %s or %s", - s.jvmAgentConfigStr, finalStr1, finalStr2) - } - }) - } -} diff --git a/pkg/operator/injector/validate.go b/pkg/operator/injector/validate.go index 557a7b6b..b33c734e 100644 --- a/pkg/operator/injector/validate.go +++ b/pkg/operator/injector/validate.go @@ -19,38 +19,46 @@ package injector import ( "fmt" + "reflect" "regexp" + "runtime" "strconv" "strings" ) -type annotationValidateFunc func(annotation, value string) error +// AnnotationValidateFunc is the type of validate function +type AnnotationValidateFunc func(annotation, value string) error var ( - //AnnotationValidate is a map between an Annotation and its validate function - AnnotationValidate = map[string]annotationValidateFunc{ - AgentSampleNumber: ValidateInt, - AgentSpanLimit: ValidateInt, - AgentIsOpenDebugging: ValidateBool, - AgentIsCacheEnhaned: ValidateBool, - AgentClassCache: ValidateClassCacheMode, - AgentOperationName: ValidateInt, - AgentForceTLS: ValidateBool, - AgentProfileActive: ValidateBool, - AgentProfileMaxParallel: ValidateInt, - AgentProfileMaxDuration: ValidateInt, - AgentProfileDump: ValidateInt, - AgentProfileSnapshot: ValidateInt, - AgentCollectorService: ValidateIpandPort, - AgentLoggingLevel: ValidateLoggingLevel, - AgentLoggingMaxSize: ValidateInt, - AgentLoggingMaxFiles: ValidateInt, - AgentStatuscheckDepth: ValidateInt, - AgentPluginJdbc: ValidateBool, - AgentPluginKafkaServers: ValidateIpandPort, + //AnnotationValidateFuncs define all validate functions + AnnotationValidateFuncs = []AnnotationValidateFunc{ + ValidateBool, + ValidateInt, + ValidateClassCacheMode, + ValidateIpandPort, + ValidateLoggingLevel, + ValidateResolver, + ValidateOutput, } ) +// 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 +} + //ValidateBool validates an annotation's value is bool func ValidateBool(annotation, value string) error { _, err := strconv.ParseBool(value) @@ -79,7 +87,6 @@ func ValidateClassCacheMode(annotation, value string) error { //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])\.`+ @@ -105,3 +112,19 @@ func ValidateLoggingLevel(annotation, value string) error { } return nil } + +//ValidateResolver validates logging.resolver +func ValidateResolver(annotation, value string) error { + if !strings.EqualFold(value, "PATTERN") && !strings.EqualFold(value, "JSON") { + return fmt.Errorf("%s error:the mode is not PATTERN or JSON", annotation) + } + return nil +} + +//ValidateOutput validates logging.output +func ValidateOutput(annotation, value string) error { + if !strings.EqualFold(value, "FILE") && !strings.EqualFold(value, "CONSOLE") { + return fmt.Errorf("%s error:the mode is not FILE or CONSOLE", 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 00000000..031af4a2 --- /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: nil + validateFunc: nil + 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: ValidateInt + 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: ValidateInt + 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: ValidateBool + useQuotes: nil + envName: SW_AGENT_OPEN_DEBUG + + - name: agent.skywalking.apache.org/agent.is_cache_enhanced_class + defaultValue: false + validateFunc: ValidateBool + useQuotes: nil + envName: SW_AGENT_CACHE_CLASS + + - name: agent.skywalking.apache.org/agent.class_cache_mode + defaultValue: MEMORY + validateFunc: ValidateClassCacheMode + useQuotes: nil + envName: SW_AGENT_CLASS_CACHE_MODE + + - name: agent.skywalking.apache.org/agent.cause_exception_depth + defaultValue: 5 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_CAUSE_EXCEPTION_DEPTH + + - name: agent.skywalking.apache.org/agent.force_reconnection_period + defaultValue: 1 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_FORCE_RECONNECTION_PERIOD + + - name: agent.skywalking.apache.org/agent.operation_name_threshold + defaultValue: 150 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_OPERATION_NAME_THRESHOLD + + - name: agent.skywalking.apache.org/agent.keep_tracing + defaultValue: false + validateFunc: ValidateBool + useQuotes: nil + envName: SW_AGENT_KEEP_TRACING + + - name: agent.skywalking.apache.org/agent.force_tls + defaultValue: false + validateFunc: ValidateBool + useQuotes: nil + envName: SW_AGENT_FORCE_TLS + + - name: agent.skywalking.apache.org/osinfo.ipv4_list_size + defaultValue: 10 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_OSINFO_IPV4_LIST_SIZE + + - name: agent.skywalking.apache.org/collector.grpc_channel_check_interval + defaultValue: 30 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_COLLECTOR_GRPC_CHANNEL_CHECK_INTERVAL + + - name: agent.skywalking.apache.org/collector.heartbeat_period + defaultValue: 30 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_COLLECTOR_HEARTBEAT_PERIOD + + - name: agent.skywalking.apache.org/collector.properties_report_period_factor + defaultValue: 10 + validateFunc: ValidateInt + 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: ValidateInt + useQuotes: nil + envName: SW_AGENT_COLLECTOR_GRPC_UPSTREAM_TIMEOUT + + - name: agent.skywalking.apache.org/collector.get_profile_task_interval + defaultValue: 20 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_COLLECTOR_GET_PROFILE_TASK_INTERVAL + + - name: agent.skywalking.apache.org/collector.get_agent_dynamic_config_interval + defaultValue: 20 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_COLLECTOR_GET_AGENT_DYNAMIC_CONFIG_INTERVAL + + - name: agent.skywalking.apache.org/collector.is_resolve_dns_periodically + defaultValue: false + validateFunc: ValidateBool + useQuotes: nil + envName: SW_AGENT_COLLECTOR_IS_RESOLVE_DNS_PERIODICALLY + + - name: agent.skywalking.apache.org/logging.level + defaultValue: INFO + validateFunc: ValidateLoggingLevel + 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: ValidateOutput + 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: ValidateResolver + 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: ValidateInt + useQuotes: nil + envName: SW_LOGGING_MAX_FILE_SIZE + + - name: agent.skywalking.apache.org/logging.max_history_files + defaultValue: -1 + validateFunc: ValidateInt + 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: ValidateInt + useQuotes: nil + envName: SW_STATUSCHECK_MAX_RECURSIVE_DEPTH + + - name: agent.skywalking.apache.org/correlation.element_max_number + defaultValue: 3 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_CORRELATION_ELEMENT_MAX_NUMBER + + - name: agent.skywalking.apache.org/correlation.value_max_length + defaultValue: 128 + validateFunc: ValidateInt + 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: ValidateInt + useQuotes: nil + envName: SW_JVM_BUFFER_SIZE + + - name: agent.skywalking.apache.org/buffer.channel_size + defaultValue: 5 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_BUFFER_CHANNEL_SIZE + + - name: agent.skywalking.apache.org/buffer.buffer_size + defaultValue: 300 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_BUFFER_BUFFER_SIZE + + - name: agent.skywalking.apache.org/profile.active + defaultValue: true + validateFunc: ValidateBool + useQuotes: nil + envName: SW_AGENT_PROFILE_ACTIVE + + - name: agent.skywalking.apache.org/profile.max_parallel + defaultValue: 5 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_PROFILE_MAX_PARALLEL + + - name: agent.skywalking.apache.org/profile.duration + defaultValue: 10 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_PROFILE_DURATION + + - name: agent.skywalking.apache.org/profile.dump_max_stack_depth + defaultValue: 500 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_PROFILE_DUMP_MAX_STACK_DEPTH + + - name: agent.skywalking.apache.org/profile.snapshot_transport_buffer_size + defaultValue: 50 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_PROFILE_SNAPSHOT_TRANSPORT_BUFFER_SIZE + + - name: agent.skywalking.apache.org/meter.active + defaultValue: true + validateFunc: ValidateBool + useQuotes: nil + envName: SW_METER_ACTIVE + + - name: agent.skywalking.apache.org/meter.report_interval + defaultValue: 20 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_METER_REPORT_INTERVAL + + - name: agent.skywalking.apache.org/meter.max_meter_size + defaultValue: 500 + validateFunc: ValidateInt + 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 00000000..e3b6017b --- /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 ec575a65..46d8620b 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 (12.09kB) +// 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 @@ func fetcherTemplatesService_accountYaml() (*asset, error) { 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: nil + validateFunc: nil + 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: ValidateInt + 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: ValidateInt + 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: ValidateBool + useQuotes: nil + envName: SW_AGENT_OPEN_DEBUG + + - name: agent.skywalking.apache.org/agent.is_cache_enhanced_class + defaultValue: false + validateFunc: ValidateBool + useQuotes: nil + envName: SW_AGENT_CACHE_CLASS + + - name: agent.skywalking.apache.org/agent.class_cache_mode + defaultValue: MEMORY + validateFunc: ValidateClassCacheMode + useQuotes: nil + envName: SW_AGENT_CLASS_CACHE_MODE + + - name: agent.skywalking.apache.org/agent.cause_exception_depth + defaultValue: 5 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_CAUSE_EXCEPTION_DEPTH + + - name: agent.skywalking.apache.org/agent.force_reconnection_period + defaultValue: 1 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_FORCE_RECONNECTION_PERIOD + + - name: agent.skywalking.apache.org/agent.operation_name_threshold + defaultValue: 150 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_OPERATION_NAME_THRESHOLD + + - name: agent.skywalking.apache.org/agent.keep_tracing + defaultValue: false + validateFunc: ValidateBool + useQuotes: nil + envName: SW_AGENT_KEEP_TRACING + + - name: agent.skywalking.apache.org/agent.force_tls + defaultValue: false + validateFunc: ValidateBool + useQuotes: nil + envName: SW_AGENT_FORCE_TLS + + - name: agent.skywalking.apache.org/osinfo.ipv4_list_size + defaultValue: 10 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_OSINFO_IPV4_LIST_SIZE + + - name: agent.skywalking.apache.org/collector.grpc_channel_check_interval + defaultValue: 30 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_COLLECTOR_GRPC_CHANNEL_CHECK_INTERVAL + + - name: agent.skywalking.apache.org/collector.heartbeat_period + defaultValue: 30 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_COLLECTOR_HEARTBEAT_PERIOD + + - name: agent.skywalking.apache.org/collector.properties_report_period_factor + defaultValue: 10 + validateFunc: ValidateInt + 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: ValidateInt + useQuotes: nil + envName: SW_AGENT_COLLECTOR_GRPC_UPSTREAM_TIMEOUT + + - name: agent.skywalking.apache.org/collector.get_profile_task_interval + defaultValue: 20 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_COLLECTOR_GET_PROFILE_TASK_INTERVAL + + - name: agent.skywalking.apache.org/collector.get_agent_dynamic_config_interval + defaultValue: 20 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_COLLECTOR_GET_AGENT_DYNAMIC_CONFIG_INTERVAL + + - name: agent.skywalking.apache.org/collector.is_resolve_dns_periodically + defaultValue: false + validateFunc: ValidateBool + useQuotes: nil + envName: SW_AGENT_COLLECTOR_IS_RESOLVE_DNS_PERIODICALLY + + - name: agent.skywalking.apache.org/logging.level + defaultValue: INFO + validateFunc: ValidateLoggingLevel + 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: ValidateOutput + 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: ValidateResolver + 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: ValidateInt + useQuotes: nil + envName: SW_LOGGING_MAX_FILE_SIZE + + - name: agent.skywalking.apache.org/logging.max_history_files + defaultValue: -1 + validateFunc: ValidateInt + 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: ValidateInt + useQuotes: nil + envName: SW_STATUSCHECK_MAX_RECURSIVE_DEPTH + + - name: agent.skywalking.apache.org/correlation.element_max_number + defaultValue: 3 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_CORRELATION_ELEMENT_MAX_NUMBER + + - name: agent.skywalking.apache.org/correlation.value_max_length + defaultValue: 128 + validateFunc: ValidateInt + 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: ValidateInt + useQuotes: nil + envName: SW_JVM_BUFFER_SIZE + + - name: agent.skywalking.apache.org/buffer.channel_size + defaultValue: 5 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_BUFFER_CHANNEL_SIZE + + - name: agent.skywalking.apache.org/buffer.buffer_size + defaultValue: 300 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_BUFFER_BUFFER_SIZE + + - name: agent.skywalking.apache.org/profile.active + defaultValue: true + validateFunc: ValidateBool + useQuotes: nil + envName: SW_AGENT_PROFILE_ACTIVE + + - name: agent.skywalking.apache.org/profile.max_parallel + defaultValue: 5 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_PROFILE_MAX_PARALLEL + + - name: agent.skywalking.apache.org/profile.duration + defaultValue: 10 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_PROFILE_DURATION + + - name: agent.skywalking.apache.org/profile.dump_max_stack_depth + defaultValue: 500 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_PROFILE_DUMP_MAX_STACK_DEPTH + + - name: agent.skywalking.apache.org/profile.snapshot_transport_buffer_size + defaultValue: 50 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_AGENT_PROFILE_SNAPSHOT_TRANSPORT_BUFFER_SIZE + + - name: agent.skywalking.apache.org/meter.active + defaultValue: true + validateFunc: ValidateBool + useQuotes: nil + envName: SW_METER_ACTIVE + + - name: agent.skywalking.apache.org/meter.report_interval + defaultValue: 20 + validateFunc: ValidateInt + useQuotes: nil + envName: SW_METER_REPORT_INTERVAL + + - name: agent.skywalking.apache.org/meter.max_meter_size + defaultValue: 500 + validateFunc: ValidateInt + 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{0xf9, 0xc2, 0xdf, 0xf4, 0x18, 0x79, 0xe0, 0xe9, 0xef, 0x5, 0x66, 0x53, 0xb7, 0x97, 0x36, 0x11, 0x62, 0xea, 0xc2, 0xfc, 0xb8, 0xd0, 0x11, 0xa5, 0xbb, 0x7e, 0x58, 0x90, 0x37, 0x64, 0x3a, 0xa3}} + 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 @@ var _bindata = map[string]func() (*asset, error){ "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 @@ var _bintree = &bintree{nil, map[string]*bintree{ "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{}}, From 31789d8025a705f903916f919c89e97b98601450 Mon Sep 17 00:00:00 2001 From: dashanji <952129620@qq.com> Date: Mon, 23 Aug 2021 01:24:59 +0800 Subject: [PATCH 11/13] fix bug --- Makefile | 2 +- apis/operator/v1alpha1/javaagent_webhook.go | 6 +- apis/operator/v1alpha1/oapserver_webhook.go | 5 -- .../v1alpha1/zz_generated.deepcopy.go | 2 +- cmd/manager/manager.go | 1 - config/operator/webhook/kustomization.yaml | 2 +- controllers/operator/configmap_controller.go | 5 +- go.sum | 84 ------------------- pkg/operator/injector/configmap.go | 2 +- pkg/operator/injector/injection.go | 3 +- 10 files changed, 12 insertions(+), 100 deletions(-) diff --git a/Makefile b/Makefile index 27f6156a..c0f0ecb4 100644 --- a/Makefile +++ b/Makefile @@ -98,7 +98,7 @@ adapter-deploy: # 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 index abf29603..35ef715c 100644 --- a/apis/operator/v1alpha1/javaagent_webhook.go +++ b/apis/operator/v1alpha1/javaagent_webhook.go @@ -32,6 +32,9 @@ import ( // 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 @@ -40,7 +43,6 @@ type Javaagent struct { // Handle will process every coming pod under the // specified namespace which labeled "swck-injection=enabled" -// +kubebuilder:webhook:path=/mutate-v1-pod,mutating=true,failurePolicy=fail,groups="",resources=pods,verbs=create;update,versions=v1,name=mpod.kb.io func (r *Javaagent) Handle(ctx context.Context, req admission.Request) admission.Response { pod := &corev1.Pod{} @@ -68,7 +70,7 @@ func (r *Javaagent) Handle(ctx context.Context, req admission.Request) admission return ip.Run() } -// PodInjector implements admission.DecoderInjector. +// Javaagent implements admission.DecoderInjector. // A decoder will be automatically injected. // InjectDecoder injects the decoder. diff --git a/apis/operator/v1alpha1/oapserver_webhook.go b/apis/operator/v1alpha1/oapserver_webhook.go index 1de388d8..c0e09a82 100644 --- a/apis/operator/v1alpha1/oapserver_webhook.go +++ b/apis/operator/v1alpha1/oapserver_webhook.go @@ -37,11 +37,6 @@ func (r *OAPServer) SetupWebhookWithManager(mgr ctrl.Manager) error { Complete() } -// nolint: lll -// this line is to have controller-gen generate the webhook configuration, -// the real path /mutate-v1-pod is handled in injector.go -// +kubebuilder:webhook:path=/mutate-v1-pod,mutating=true,failurePolicy=fail,groups="",resources=pods,verbs=create;update,versions=v1,name=mpod.kb.io - // nolint: lll // +kubebuilder:webhook:path=/mutate-operator-skywalking-apache-org-v1alpha1-oapserver,mutating=true,failurePolicy=fail,groups=operator.skywalking.apache.org,resources=oapservers,verbs=create;update,versions=v1alpha1,name=moapserver.kb.io diff --git a/apis/operator/v1alpha1/zz_generated.deepcopy.go b/apis/operator/v1alpha1/zz_generated.deepcopy.go index 5ce96ab8..27953b16 100644 --- a/apis/operator/v1alpha1/zz_generated.deepcopy.go +++ b/apis/operator/v1alpha1/zz_generated.deepcopy.go @@ -24,7 +24,7 @@ package v1alpha1 import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - "k8s.io/api/networking/v1" + v1 "k8s.io/api/networking/v1" "k8s.io/apimachinery/pkg/runtime" ) diff --git a/cmd/manager/manager.go b/cmd/manager/manager.go index 64fdbb67..5446df37 100644 --- a/cmd/manager/manager.go +++ b/cmd/manager/manager.go @@ -29,7 +29,6 @@ import ( operatorv1alpha1 "github.com/apache/skywalking-swck/apis/operator/v1alpha1" operatorcontroller "github.com/apache/skywalking-swck/controllers/operator" - "github.com/apache/skywalking-swck/pkg/operator/repo" // +kubebuilder:scaffold:imports ) diff --git a/config/operator/webhook/kustomization.yaml b/config/operator/webhook/kustomization.yaml index e8fb8387..ee44e46f 100644 --- a/config/operator/webhook/kustomization.yaml +++ b/config/operator/webhook/kustomization.yaml @@ -20,7 +20,7 @@ resources: - manifests.yaml patchesStrategicMerge: -- add_nsSelector.yaml +- ns_selector_patch.yaml configurations: - kustomizeconfig.yaml diff --git a/controllers/operator/configmap_controller.go b/controllers/operator/configmap_controller.go index e8caa606..6bd7bb25 100644 --- a/controllers/operator/configmap_controller.go +++ b/controllers/operator/configmap_controller.go @@ -21,8 +21,6 @@ import ( "context" "fmt" - "github.com/apache/skywalking-swck/pkg/kubernetes" - "github.com/apache/skywalking-swck/pkg/operator/injector" "github.com/go-logr/logr" core "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -31,6 +29,9 @@ import ( "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 diff --git a/go.sum b/go.sum index 27f1b017..089cdf85 100644 --- a/go.sum +++ b/go.sum @@ -1,16 +1,13 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.51.0 h1:PvKAVQWCtlGUSlZkGW3QLelKaWq7KYv/MW1EboG8bfM= cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0 h1:3ithwDMr7/3vpAMXiH+ZQnYbuIsh+OPhUPMFC9enmn0= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= @@ -72,7 +69,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/apache/skywalking-cli v0.0.0-20201125155244-ffee47d2e83d h1:vJeCfqKTLGQXGUy3+dYRNclCJgRsj3VQiCff/+yvfMA= github.com/apache/skywalking-cli v0.0.0-20201125155244-ffee47d2e83d/go.mod h1:kUqj2ESaiYz89JFJUr+cL6EDmzlEYSrlEMOkWg9wuS4= github.com/apache/skywalking-cli v0.0.0-20210209032327-04a0ce08990f h1:DknnvUn5ZR1hRtS42stGr3O6REwBFh6iyotoCJ2jFZ8= github.com/apache/skywalking-cli v0.0.0-20210209032327-04a0ce08990f/go.mod h1:EMKZ5MAEnCrNTPxqWu3s1QgnoUDQEO0oS+ohNB09JE8= @@ -84,15 +80,12 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/blang/semver v3.5.0+incompatible h1:CGxCgetQ64DKk7rdZ++Vfnb1+ogGNnB17OJKJXD2Cfs= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= @@ -146,13 +139,11 @@ github.com/emicklei/go-restful-swagger12 v0.0.0-20201014110547-68ccff494617 h1:j github.com/emicklei/go-restful-swagger12 v0.0.0-20201014110547-68ccff494617/go.mod h1:qr0VowGBT4CS4Q8vFF8BSeKz34PuqKGxs/L0IAQA9DQ= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -171,9 +162,7 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0 h1:QvGt2nLcHH0WK9orKa+ppBPAxREcH364nPUedEpK0TY= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.3.0 h1:q4c+kbcR0d5rSurhBR8dIgieOaYpXtsdTYfx22Cu6rs= github.com/go-logr/logr v0.3.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= @@ -231,12 +220,10 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7 h1:5ZkaAPbicIKTF2I64qf5Fh8Aa83Q/dnOafMYV0OMwjA= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -247,7 +234,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= @@ -257,7 +243,6 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= @@ -265,15 +250,12 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -285,7 +267,6 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -321,7 +302,6 @@ github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= @@ -330,7 +310,6 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= @@ -344,7 +323,6 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -355,11 +333,9 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -390,7 +366,6 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= @@ -433,16 +408,13 @@ github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXW github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4= github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs= github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= @@ -451,7 +423,6 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -461,28 +432,22 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= @@ -497,7 +462,6 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= @@ -514,14 +478,12 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -531,9 +493,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= @@ -556,7 +516,6 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5 h1:Gqga3zA9tdAcfqobUGjSoCob5L3f8Dt5EuOp3ihNZko= go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5/go.mod h1:skWido08r9w6Lq/w70DO5XYIKMu4QFu1+4VsqLQuJy8= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489 h1:1JFLBqwIgdyHN1ZtgjTBwO+blA6gVOmZurpiMEsETKo= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= @@ -567,22 +526,18 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM= go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= @@ -592,13 +547,11 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -620,7 +573,6 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= @@ -664,15 +616,12 @@ golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6 h1:pE8b58s1HRDMi8RDc79m0HISf9D4TzseP40cEA6IGfs= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -697,12 +646,10 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -729,18 +676,13 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c h1:fqgJT0MGcGpPgpWU7VRdRjuArfcOvC4AoJmILihzhDg= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -788,10 +730,8 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200616133436-c1934b75d054 h1:HHeAlu5H9b71C+Fx0K+1dGgVFN1DM1/wz4aoGOA5qS8= golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -808,10 +748,8 @@ google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/ google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= @@ -833,7 +771,6 @@ google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4 google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a h1:pOwg4OoaRYScjmR4LlLgdtnyoHYTSAVhhqe5uPdpII8= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -847,7 +784,6 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= @@ -858,7 +794,6 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogR gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= @@ -871,13 +806,10 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= @@ -889,32 +821,25 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.19.2/go.mod h1:IQpK0zFQ1xc5iNIQPqzgoOwuFugaYHK4iCknlAQP9nI= -k8s.io/api v0.19.3 h1:GN6ntFnv44Vptj/b+OnMW7FmzkpDoIDLZRvKX3XH9aU= k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs= k8s.io/api v0.20.1 h1:ud1c3W3YNzGd6ABJlbFfKXBKXO+1KdGfcgGGNgFR03E= k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= -k8s.io/apiextensions-apiserver v0.19.2 h1:oG84UwiDsVDu7dlsGQs5GySmQHCzMhknfhFExJMz9tA= k8s.io/apiextensions-apiserver v0.19.2/go.mod h1:EYNjpqIAvNZe+svXVx9j4uBaVhTB4C94HkY3w058qcg= k8s.io/apiextensions-apiserver v0.20.1 h1:ZrXQeslal+6zKM/HjDXLzThlz/vPSxrfK3OqL8txgVQ= k8s.io/apiextensions-apiserver v0.20.1/go.mod h1:ntnrZV+6a3dB504qwC5PN/Yg9PBiDNt1EVqbW2kORVk= k8s.io/apimachinery v0.19.2/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= -k8s.io/apimachinery v0.19.3 h1:bpIQXlKjB4cB/oNpnNnV+BybGPR7iP5oYpsOTEJ4hgc= k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apimachinery v0.20.1 h1:LAhz8pKbgR8tUwn7boK+b2HZdt7MiTu2mkYtFMUjTRQ= k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apiserver v0.19.2/go.mod h1:FreAq0bJ2vtZFj9Ago/X0oNGC51GfubKK/ViOKfVAOA= -k8s.io/apiserver v0.19.3 h1:H7KUbLD74rh8NOPMLBJPSEG3Djqcv6Zxn5Ud0AL5u/k= k8s.io/apiserver v0.19.3/go.mod h1:bx6dMm+H6ifgKFpCQT/SAhPwhzoeIMlHIaibomUDec0= k8s.io/apiserver v0.20.1 h1:yEqdkxlnQbxi/3e74cp0X16h140fpvPrNnNRAJBDuBk= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= -k8s.io/client-go v0.19.2 h1:gMJuU3xJZs86L1oQ99R4EViAADUPMHHtS9jFshasHSc= k8s.io/client-go v0.19.2/go.mod h1:S5wPhCqyDNAlzM9CnEdgTGV4OqhsW3jGO1UM1epwfJA= -k8s.io/client-go v0.19.3 h1:ctqR1nQ52NUs6LpI0w+a5U+xjYwflFwA13OJKcicMxg= k8s.io/client-go v0.19.3/go.mod h1:+eEMktZM+MG0KO+PTkci8xnbCZHvj9TqR6Q1XDUIJOM= k8s.io/client-go v0.20.1 h1:Qquik0xNFbK9aUG92pxHYsyfea5/RPO9o9bSywNor+M= k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= @@ -922,7 +847,6 @@ k8s.io/code-generator v0.19.2/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZ k8s.io/code-generator v0.19.3/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= k8s.io/code-generator v0.20.1/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg= k8s.io/component-base v0.19.2/go.mod h1:g5LrsiTiabMLZ40AR6Hl45f088DevyGY+cCE2agEIVo= -k8s.io/component-base v0.19.3 h1:c+DzDNAQFlaoyX+yv8YuWi8xmlQvvY5DnJGbaz5U74o= k8s.io/component-base v0.19.3/go.mod h1:WhLWSIefQn8W8jxSLl5WNiR6z8oyMe/8Zywg7alOkRc= k8s.io/component-base v0.20.1 h1:6OQaHr205NSl24t5wOF2IhdrlxZTWEZwuGlLvBgaeIg= k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= @@ -931,38 +855,30 @@ k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8 k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.3.0 h1:WmkrnW7fdrm0/DMClc+HIxtftvxVIPAhlVwMQo5yLco= k8s.io/klog/v2 v2.3.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6 h1:+WnxoVtG8TMiudHBSEtrVL1egv36TkkJm+bA8AxicmQ= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd h1:sOHNzJIkytDF6qadMNKhhDRpc6ODik8lVC6nOur7B2c= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= -k8s.io/metrics v0.19.3 h1:p/goUqtdCslX76mSNowzZkNxiKzNRQW4bUP02U34+QQ= k8s.io/metrics v0.19.3/go.mod h1:Eap/Lk1FiAIjkaArFuv41v+ph6dbDpVGwAg7jMI+4vg= k8s.io/metrics v0.20.1 h1:c03Mn9FpIOV3r5WSkF4VelFdlIGH9UYR4onIxrMBnHI= k8s.io/metrics v0.20.1/go.mod h1:JhpBE/fad3yRGsgEpiZz5FQQM5wJ18OTLkD7Tv40c0s= -k8s.io/utils v0.0.0-20200729134348-d5654de09c73 h1:uJmqzgNWG7XyClnU/mLPBWwfKKF1K8Hf8whTseBgJcg= k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20200912215256-4140de9c8800 h1:9ZNvfPvVIEsp/T1ez4GQuzCcCTEQWhovSofhqR73A6g= k8s.io/utils v0.0.0-20200912215256-4140de9c8800/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9 h1:rusRLrDhjBp6aYtl9sGEvQJr6faoHoDLd0YcUBTZguI= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9/go.mod h1:dzAXnQbTRyDlZPJX2SUPEqvnB+j7AJjtlox7PEwigU0= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14 h1:TihvEz9MPj2u0KWds6E2OBUXfwaL4qRJ33c7HGiJpqk= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/controller-runtime v0.7.0 h1:bU20IBBEPccWz5+zXpLnpVsgBYxqclaHu1pVDl/gEt8= sigs.k8s.io/controller-runtime v0.7.0/go.mod h1:pJ3YBrJiAqMAZKi6UVGuE98ZrroV1p+pIhoHsMm9wdU= -sigs.k8s.io/structured-merge-diff/v4 v4.0.1 h1:YXTMot5Qz/X1iBRJhAt+vI+HVttY0WkSqqhKxQ0xVbA= sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.2 h1:YHQV7Dajm86OuqnIR6zAelnDWBRjo+YhYV9PmGrh1s8= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -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= diff --git a/pkg/operator/injector/configmap.go b/pkg/operator/injector/configmap.go index 046b603c..cdca73c0 100644 --- a/pkg/operator/injector/configmap.go +++ b/pkg/operator/injector/configmap.go @@ -85,7 +85,7 @@ func ValidateConfigmap(configmap *corev1.ConfigMap) (bool, error) { // if option has environment variable like SW_AGENT_NAME if strings.Contains(str[i], ":") { - valueStart := strings.LastIndex(str[i], ":") + valueStart := strings.Index(str[i], ":") valueEnd := strings.Index(str[i], "}") if valueStart == -1 || valueEnd == -1 || valueStart >= valueEnd { continue diff --git a/pkg/operator/injector/injection.go b/pkg/operator/injector/injection.go index 39962cb3..ac0cfaf9 100644 --- a/pkg/operator/injector/injection.go +++ b/pkg/operator/injector/injection.go @@ -24,9 +24,8 @@ import ( "strings" "github.com/go-logr/logr" - "sigs.k8s.io/controller-runtime/pkg/client" - corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) From 93119eee3fad6895c6d04aa40ca6004ed8022b4e Mon Sep 17 00:00:00 2001 From: dashanji <952129620@qq.com> Date: Tue, 14 Sep 2021 20:54:40 +0800 Subject: [PATCH 12/13] 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. --- go.sum | 86 +++++- pkg/operator/injector/injection.go | 5 +- pkg/operator/injector/injector.go | 28 ++ pkg/operator/injector/validate.go | 60 +--- pkg/operator/injector/validate_test.go | 282 ------------------ .../injector/templates/annotations.yaml | 78 ++--- pkg/operator/repo/assets.gen.go | 82 ++--- 7 files changed, 201 insertions(+), 420 deletions(-) delete mode 100644 pkg/operator/injector/validate_test.go diff --git a/go.sum b/go.sum index 089cdf85..84035238 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,16 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.51.0 h1:PvKAVQWCtlGUSlZkGW3QLelKaWq7KYv/MW1EboG8bfM= cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0 h1:3ithwDMr7/3vpAMXiH+ZQnYbuIsh+OPhUPMFC9enmn0= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= @@ -69,6 +72,7 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/apache/skywalking-cli v0.0.0-20201125155244-ffee47d2e83d h1:vJeCfqKTLGQXGUy3+dYRNclCJgRsj3VQiCff/+yvfMA= github.com/apache/skywalking-cli v0.0.0-20201125155244-ffee47d2e83d/go.mod h1:kUqj2ESaiYz89JFJUr+cL6EDmzlEYSrlEMOkWg9wuS4= github.com/apache/skywalking-cli v0.0.0-20210209032327-04a0ce08990f h1:DknnvUn5ZR1hRtS42stGr3O6REwBFh6iyotoCJ2jFZ8= github.com/apache/skywalking-cli v0.0.0-20210209032327-04a0ce08990f/go.mod h1:EMKZ5MAEnCrNTPxqWu3s1QgnoUDQEO0oS+ohNB09JE8= @@ -80,12 +84,15 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blang/semver v3.5.0+incompatible h1:CGxCgetQ64DKk7rdZ++Vfnb1+ogGNnB17OJKJXD2Cfs= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= @@ -139,11 +146,13 @@ github.com/emicklei/go-restful-swagger12 v0.0.0-20201014110547-68ccff494617 h1:j github.com/emicklei/go-restful-swagger12 v0.0.0-20201014110547-68ccff494617/go.mod h1:qr0VowGBT4CS4Q8vFF8BSeKz34PuqKGxs/L0IAQA9DQ= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -162,7 +171,9 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0 h1:QvGt2nLcHH0WK9orKa+ppBPAxREcH364nPUedEpK0TY= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.3.0 h1:q4c+kbcR0d5rSurhBR8dIgieOaYpXtsdTYfx22Cu6rs= github.com/go-logr/logr v0.3.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= @@ -220,10 +231,12 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7 h1:5ZkaAPbicIKTF2I64qf5Fh8Aa83Q/dnOafMYV0OMwjA= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -234,6 +247,7 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= @@ -243,6 +257,7 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= @@ -250,12 +265,15 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -267,6 +285,7 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -302,6 +321,7 @@ github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= @@ -310,6 +330,7 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= @@ -323,6 +344,7 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -333,9 +355,11 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -366,6 +390,7 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= @@ -408,13 +433,16 @@ github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXW github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4= github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs= github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= @@ -423,6 +451,7 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -432,22 +461,28 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= @@ -462,6 +497,7 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= @@ -478,12 +514,14 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -493,7 +531,9 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= @@ -516,6 +556,7 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5 h1:Gqga3zA9tdAcfqobUGjSoCob5L3f8Dt5EuOp3ihNZko= go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5/go.mod h1:skWido08r9w6Lq/w70DO5XYIKMu4QFu1+4VsqLQuJy8= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489 h1:1JFLBqwIgdyHN1ZtgjTBwO+blA6gVOmZurpiMEsETKo= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= @@ -526,18 +567,22 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM= go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= @@ -547,11 +592,13 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -573,6 +620,7 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= @@ -616,12 +664,15 @@ golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6 h1:pE8b58s1HRDMi8RDc79m0HISf9D4TzseP40cEA6IGfs= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -646,10 +697,12 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f h1:25KHgbfyiSm6vwQLbM3zZIe1v9p/3ea4Rz+nnM5K/i4= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -676,13 +729,18 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c h1:fqgJT0MGcGpPgpWU7VRdRjuArfcOvC4AoJmILihzhDg= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -730,8 +788,10 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200616133436-c1934b75d054 h1:HHeAlu5H9b71C+Fx0K+1dGgVFN1DM1/wz4aoGOA5qS8= golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -748,8 +808,10 @@ google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/ google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= @@ -771,6 +833,7 @@ google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4 google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a h1:pOwg4OoaRYScjmR4LlLgdtnyoHYTSAVhhqe5uPdpII8= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -784,6 +847,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= @@ -794,6 +858,7 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogR gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= @@ -806,10 +871,13 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= @@ -821,25 +889,32 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.19.2/go.mod h1:IQpK0zFQ1xc5iNIQPqzgoOwuFugaYHK4iCknlAQP9nI= +k8s.io/api v0.19.3 h1:GN6ntFnv44Vptj/b+OnMW7FmzkpDoIDLZRvKX3XH9aU= k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs= k8s.io/api v0.20.1 h1:ud1c3W3YNzGd6ABJlbFfKXBKXO+1KdGfcgGGNgFR03E= k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= +k8s.io/apiextensions-apiserver v0.19.2 h1:oG84UwiDsVDu7dlsGQs5GySmQHCzMhknfhFExJMz9tA= k8s.io/apiextensions-apiserver v0.19.2/go.mod h1:EYNjpqIAvNZe+svXVx9j4uBaVhTB4C94HkY3w058qcg= k8s.io/apiextensions-apiserver v0.20.1 h1:ZrXQeslal+6zKM/HjDXLzThlz/vPSxrfK3OqL8txgVQ= k8s.io/apiextensions-apiserver v0.20.1/go.mod h1:ntnrZV+6a3dB504qwC5PN/Yg9PBiDNt1EVqbW2kORVk= k8s.io/apimachinery v0.19.2/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= +k8s.io/apimachinery v0.19.3 h1:bpIQXlKjB4cB/oNpnNnV+BybGPR7iP5oYpsOTEJ4hgc= k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apimachinery v0.20.1 h1:LAhz8pKbgR8tUwn7boK+b2HZdt7MiTu2mkYtFMUjTRQ= k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apiserver v0.19.2/go.mod h1:FreAq0bJ2vtZFj9Ago/X0oNGC51GfubKK/ViOKfVAOA= +k8s.io/apiserver v0.19.3 h1:H7KUbLD74rh8NOPMLBJPSEG3Djqcv6Zxn5Ud0AL5u/k= k8s.io/apiserver v0.19.3/go.mod h1:bx6dMm+H6ifgKFpCQT/SAhPwhzoeIMlHIaibomUDec0= k8s.io/apiserver v0.20.1 h1:yEqdkxlnQbxi/3e74cp0X16h140fpvPrNnNRAJBDuBk= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= +k8s.io/client-go v0.19.2 h1:gMJuU3xJZs86L1oQ99R4EViAADUPMHHtS9jFshasHSc= k8s.io/client-go v0.19.2/go.mod h1:S5wPhCqyDNAlzM9CnEdgTGV4OqhsW3jGO1UM1epwfJA= +k8s.io/client-go v0.19.3 h1:ctqR1nQ52NUs6LpI0w+a5U+xjYwflFwA13OJKcicMxg= k8s.io/client-go v0.19.3/go.mod h1:+eEMktZM+MG0KO+PTkci8xnbCZHvj9TqR6Q1XDUIJOM= k8s.io/client-go v0.20.1 h1:Qquik0xNFbK9aUG92pxHYsyfea5/RPO9o9bSywNor+M= k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= @@ -847,6 +922,7 @@ k8s.io/code-generator v0.19.2/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZ k8s.io/code-generator v0.19.3/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= k8s.io/code-generator v0.20.1/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg= k8s.io/component-base v0.19.2/go.mod h1:g5LrsiTiabMLZ40AR6Hl45f088DevyGY+cCE2agEIVo= +k8s.io/component-base v0.19.3 h1:c+DzDNAQFlaoyX+yv8YuWi8xmlQvvY5DnJGbaz5U74o= k8s.io/component-base v0.19.3/go.mod h1:WhLWSIefQn8W8jxSLl5WNiR6z8oyMe/8Zywg7alOkRc= k8s.io/component-base v0.20.1 h1:6OQaHr205NSl24t5wOF2IhdrlxZTWEZwuGlLvBgaeIg= k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= @@ -855,30 +931,38 @@ k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8 k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.3.0 h1:WmkrnW7fdrm0/DMClc+HIxtftvxVIPAhlVwMQo5yLco= k8s.io/klog/v2 v2.3.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6 h1:+WnxoVtG8TMiudHBSEtrVL1egv36TkkJm+bA8AxicmQ= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd h1:sOHNzJIkytDF6qadMNKhhDRpc6ODik8lVC6nOur7B2c= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= +k8s.io/metrics v0.19.3 h1:p/goUqtdCslX76mSNowzZkNxiKzNRQW4bUP02U34+QQ= k8s.io/metrics v0.19.3/go.mod h1:Eap/Lk1FiAIjkaArFuv41v+ph6dbDpVGwAg7jMI+4vg= k8s.io/metrics v0.20.1 h1:c03Mn9FpIOV3r5WSkF4VelFdlIGH9UYR4onIxrMBnHI= k8s.io/metrics v0.20.1/go.mod h1:JhpBE/fad3yRGsgEpiZz5FQQM5wJ18OTLkD7Tv40c0s= +k8s.io/utils v0.0.0-20200729134348-d5654de09c73 h1:uJmqzgNWG7XyClnU/mLPBWwfKKF1K8Hf8whTseBgJcg= k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20200912215256-4140de9c8800 h1:9ZNvfPvVIEsp/T1ez4GQuzCcCTEQWhovSofhqR73A6g= k8s.io/utils v0.0.0-20200912215256-4140de9c8800/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9 h1:rusRLrDhjBp6aYtl9sGEvQJr6faoHoDLd0YcUBTZguI= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9/go.mod h1:dzAXnQbTRyDlZPJX2SUPEqvnB+j7AJjtlox7PEwigU0= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14 h1:TihvEz9MPj2u0KWds6E2OBUXfwaL4qRJ33c7HGiJpqk= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/controller-runtime v0.7.0 h1:bU20IBBEPccWz5+zXpLnpVsgBYxqclaHu1pVDl/gEt8= sigs.k8s.io/controller-runtime v0.7.0/go.mod h1:pJ3YBrJiAqMAZKi6UVGuE98ZrroV1p+pIhoHsMm9wdU= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1 h1:YXTMot5Qz/X1iBRJhAt+vI+HVttY0WkSqqhKxQ0xVbA= sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.2 h1:YHQV7Dajm86OuqnIR6zAelnDWBRjo+YhYV9PmGrh1s8= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +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/pkg/operator/injector/injection.go b/pkg/operator/injector/injection.go index ac0cfaf9..d2430f75 100644 --- a/pkg/operator/injector/injection.go +++ b/pkg/operator/injector/injection.go @@ -41,7 +41,7 @@ type Injection interface { // 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 +// 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 @@ -133,7 +133,7 @@ type OverlayPlugins struct { next Injection } -// OverlayPlugins is similar to OverlayAgent , but it don't hava validate function +// 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 { @@ -143,6 +143,7 @@ func (op *OverlayPlugins) execute(ipd *InjectProcessData) admission.Response { 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) { diff --git a/pkg/operator/injector/injector.go b/pkg/operator/injector/injector.go index 333079a9..787a28aa 100644 --- a/pkg/operator/injector/injector.go +++ b/pkg/operator/injector/injector.go @@ -47,6 +47,11 @@ const ( // 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 specify a specific plugin + // such as optional.skywaking.apache.org/customize-enhance-plugin-8.7.0 + // Notice , If the injected container's image don't has the optional plugin , + // the container will panic + optionsAnnotationPrefix = "optional.skywalking.apache.org/" ) // log is for logging in this package. @@ -293,6 +298,29 @@ func (s *SidecarInjectField) OverlayAgent(a Annotations, ao *AnnotationOverlay, 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 optional plugins' version +// such as spring-cloud-gateway-2.0.x or spring-cloud-gateway-2.1.x +// the final command will be "mv /optional-plugins/*spring-cloud-gateway-2.0.x* /plugins/" +func (s *SidecarInjectField) OverlayOptional(annotation *map[string]string) { + sourcePath := strings.Join([]string{s.SidecarVolumeMount.MountPath, "optional-plugins/"}, "/") + targetPath := strings.Join([]string{s.SidecarVolumeMount.MountPath, "plugins/"}, "/") + + for k, v := range *annotation { + if strings.HasPrefix(k, optionsAnnotationPrefix) { + optionalName := strings.TrimPrefix(k, optionsAnnotationPrefix) + command := strings.Join([]string{"cp", sourcePath}, " ") + if strings.ToLower(v) == "true" { + realName := strings.Join([]string{"*", "*"}, optionalName) + command = command + realName + " " + 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. diff --git a/pkg/operator/injector/validate.go b/pkg/operator/injector/validate.go index b33c734e..c6f9e48f 100644 --- a/pkg/operator/injector/validate.go +++ b/pkg/operator/injector/validate.go @@ -22,7 +22,6 @@ import ( "reflect" "regexp" "runtime" - "strconv" "strings" ) @@ -32,13 +31,8 @@ type AnnotationValidateFunc func(annotation, value string) error var ( //AnnotationValidateFuncs define all validate functions AnnotationValidateFuncs = []AnnotationValidateFunc{ - ValidateBool, - ValidateInt, - ValidateClassCacheMode, + ValidateServiceName, ValidateIpandPort, - ValidateLoggingLevel, - ValidateResolver, - ValidateOutput, } ) @@ -59,28 +53,10 @@ func FindValidateFunc(funcName string) AnnotationValidateFunc { return nil } -//ValidateBool validates an annotation's value is bool -func ValidateBool(annotation, value string) error { - _, err := strconv.ParseBool(value) - if err != nil { - return fmt.Errorf("%s error:%s", annotation, err.Error()) - } - return nil -} - -//ValidateInt validates an annotation's value is int -func ValidateInt(annotation, value string) error { - _, err := strconv.ParseInt(value, 10, 32) - if err != nil { - return fmt.Errorf("%s error:%s", annotation, err.Error()) - } - return nil -} - -//ValidateClassCacheMode validates an annotation's value is right cache mode -func ValidateClassCacheMode(annotation, value string) error { - if !strings.EqualFold(value, "MEMORY") && !strings.EqualFold(value, "FILE") { - return fmt.Errorf("%s error:the mode is not MEMORY or FILE", annotation) +//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 } @@ -102,29 +78,3 @@ func ValidateIpandPort(annotation, value string) error { } return nil } - -//ValidateLoggingLevel validates an annotation's value is right logging level -func ValidateLoggingLevel(annotation, value string) error { - if !strings.EqualFold(value, "TRACE") && !strings.EqualFold(value, "DEBUG") && - !strings.EqualFold(value, "INFO") && !strings.EqualFold(value, "WARN") && - !strings.EqualFold(value, "ERROR") && !strings.EqualFold(value, "OFF") { - return fmt.Errorf("%s error:the Level is not in [TRACE,DEBUG,INFO,WARN,ERROR,OFF]", annotation) - } - return nil -} - -//ValidateResolver validates logging.resolver -func ValidateResolver(annotation, value string) error { - if !strings.EqualFold(value, "PATTERN") && !strings.EqualFold(value, "JSON") { - return fmt.Errorf("%s error:the mode is not PATTERN or JSON", annotation) - } - return nil -} - -//ValidateOutput validates logging.output -func ValidateOutput(annotation, value string) error { - if !strings.EqualFold(value, "FILE") && !strings.EqualFold(value, "CONSOLE") { - return fmt.Errorf("%s error:the mode is not FILE or CONSOLE", annotation) - } - return nil -} diff --git a/pkg/operator/injector/validate_test.go b/pkg/operator/injector/validate_test.go deleted file mode 100644 index 31e3febe..00000000 --- a/pkg/operator/injector/validate_test.go +++ /dev/null @@ -1,282 +0,0 @@ -// 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 ( - "testing" -) - -func TestValidateBool(t *testing.T) { - type args struct { - annotation string - value string - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "test true", - args: args{ - annotation: "test annotation", - value: "true", - }, - wantErr: false, - }, - { - name: "test false", - args: args{ - annotation: "test annotation", - value: "false", - }, - wantErr: false, - }, - { - name: "test no", - args: args{ - annotation: "test annotation", - value: "no", - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := ValidateBool(tt.args.annotation, tt.args.value); (err != nil) != tt.wantErr { - t.Errorf("ValidateBool() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestValidateInt(t *testing.T) { - type args struct { - annotation string - value string - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "test 1", - args: args{ - annotation: "test annotation", - value: "1", - }, - wantErr: false, - }, - { - name: "test -1", - args: args{ - annotation: "test annotation", - value: "-1", - }, - wantErr: false, - }, - { - name: "test other", - args: args{ - annotation: "test annotation", - value: "true", - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := ValidateInt(tt.args.annotation, tt.args.value); (err != nil) != tt.wantErr { - t.Errorf("ValidateInt() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestValidateClassCacheMode(t *testing.T) { - type args struct { - annotation string - value string - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "test MEMORY", - args: args{ - annotation: "test annotation", - value: "MEMORY", - }, - wantErr: false, - }, - { - name: "test FILE", - args: args{ - annotation: "test annotation", - value: "FILE", - }, - wantErr: false, - }, - { - name: "test CACHE", - args: args{ - annotation: "test annotation", - value: "CACHE", - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := ValidateClassCacheMode(tt.args.annotation, tt.args.value); (err != nil) != tt.wantErr { - t.Errorf("ValidateClassCacheMode() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestValidateIpandPort(t *testing.T) { - type args struct { - annotation string - value string - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "valid ip and valid port", - args: args{ - annotation: "test annotation", - value: "127.0.0.1:8080", - }, - wantErr: false, - }, - { - name: "valid ip and valid port", - args: args{ - annotation: "test annotation", - value: "localhost:8080", - }, - wantErr: false, - }, - { - name: "invalid ip and valid port", - args: args{ - annotation: "test annotation", - value: "192.0.1.288:8080", - }, - wantErr: true, - }, - { - name: "valid ip and invalid port", - args: args{ - annotation: "test annotation", - value: "192.0.1.255:88888", - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := ValidateIpandPort(tt.args.annotation, tt.args.value); (err != nil) != tt.wantErr { - t.Errorf("ValidateIpandPort() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func TestValidateLoggingLevel(t *testing.T) { - type args struct { - annotation string - value string - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "test TRACE", - args: args{ - annotation: "test annotation", - value: "TRACE", - }, - wantErr: false, - }, - { - name: "test DEBUG", - args: args{ - annotation: "test annotation", - value: "DEBUG", - }, - wantErr: false, - }, - { - name: "test INFO", - args: args{ - annotation: "test annotation", - value: "INFO", - }, - wantErr: false, - }, - { - name: "test WARN", - args: args{ - annotation: "test annotation", - value: "WARN", - }, - wantErr: false, - }, - { - name: "test ERROR", - args: args{ - annotation: "test annotation", - value: "ERROR", - }, - wantErr: false, - }, - { - name: "test OFF", - args: args{ - annotation: "test annotation", - value: "OFF", - }, - wantErr: false, - }, - { - name: "test other", - args: args{ - annotation: "test annotation", - value: "other", - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := ValidateLoggingLevel(tt.args.annotation, tt.args.value); (err != nil) != tt.wantErr { - t.Errorf("ValidateLoggingLevel() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} diff --git a/pkg/operator/manifests/injector/templates/annotations.yaml b/pkg/operator/manifests/injector/templates/annotations.yaml index 031af4a2..506db076 100644 --- a/pkg/operator/manifests/injector/templates/annotations.yaml +++ b/pkg/operator/manifests/injector/templates/annotations.yaml @@ -108,8 +108,8 @@ annotations: envName: SW_AGENT_NAMESPACE - name: agent.skywalking.apache.org/agent.service_name - defaultValue: nil - validateFunc: nil + defaultValue: Your_ApplicationName + validateFunc: ValidateServiceName useQuotes: nil envName: SW_AGENT_NAME @@ -121,7 +121,7 @@ annotations: - name: agent.skywalking.apache.org/agent.sample_n_per_3_secs defaultValue: -1 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_SAMPLE @@ -133,7 +133,7 @@ annotations: - name: agent.skywalking.apache.org/agent.span_limit_per_segment defaultValue: 300 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_SPAN_LIMIT @@ -145,73 +145,73 @@ annotations: - name: agent.skywalking.apache.org/agent.is_open_debugging_class defaultValue: true - validateFunc: ValidateBool + validateFunc: nil useQuotes: nil envName: SW_AGENT_OPEN_DEBUG - name: agent.skywalking.apache.org/agent.is_cache_enhanced_class defaultValue: false - validateFunc: ValidateBool + validateFunc: nil useQuotes: nil envName: SW_AGENT_CACHE_CLASS - name: agent.skywalking.apache.org/agent.class_cache_mode defaultValue: MEMORY - validateFunc: ValidateClassCacheMode + validateFunc: nil useQuotes: nil envName: SW_AGENT_CLASS_CACHE_MODE - name: agent.skywalking.apache.org/agent.cause_exception_depth defaultValue: 5 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_CAUSE_EXCEPTION_DEPTH - name: agent.skywalking.apache.org/agent.force_reconnection_period defaultValue: 1 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_FORCE_RECONNECTION_PERIOD - name: agent.skywalking.apache.org/agent.operation_name_threshold defaultValue: 150 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_OPERATION_NAME_THRESHOLD - name: agent.skywalking.apache.org/agent.keep_tracing defaultValue: false - validateFunc: ValidateBool + validateFunc: nil useQuotes: nil envName: SW_AGENT_KEEP_TRACING - name: agent.skywalking.apache.org/agent.force_tls defaultValue: false - validateFunc: ValidateBool + validateFunc: nil useQuotes: nil envName: SW_AGENT_FORCE_TLS - name: agent.skywalking.apache.org/osinfo.ipv4_list_size defaultValue: 10 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_OSINFO_IPV4_LIST_SIZE - name: agent.skywalking.apache.org/collector.grpc_channel_check_interval defaultValue: 30 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_COLLECTOR_GRPC_CHANNEL_CHECK_INTERVAL - name: agent.skywalking.apache.org/collector.heartbeat_period defaultValue: 30 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_COLLECTOR_HEARTBEAT_PERIOD - name: agent.skywalking.apache.org/collector.properties_report_period_factor defaultValue: 10 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_COLLECTOR_PROPERTIES_REPORT_PERIOD_FACTOR @@ -223,31 +223,31 @@ annotations: - name: agent.skywalking.apache.org/collector.grpc_upstream_timeout defaultValue: 30 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_COLLECTOR_GRPC_UPSTREAM_TIMEOUT - name: agent.skywalking.apache.org/collector.get_profile_task_interval defaultValue: 20 - validateFunc: ValidateInt + 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: ValidateInt + 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: ValidateBool + validateFunc: nil useQuotes: nil envName: SW_AGENT_COLLECTOR_IS_RESOLVE_DNS_PERIODICALLY - name: agent.skywalking.apache.org/logging.level defaultValue: INFO - validateFunc: ValidateLoggingLevel + validateFunc: nil useQuotes: nil envName: SW_LOGGING_LEVEL @@ -259,7 +259,7 @@ annotations: - name: agent.skywalking.apache.org/logging.output defaultValue: FILE - validateFunc: ValidateOutput + validateFunc: nil useQuotes: nil envName: SW_LOGGING_OUTPUT @@ -271,7 +271,7 @@ annotations: - name: agent.skywalking.apache.org/logging.resolver defaultValue: PATTERN - validateFunc: ValidateResolver + validateFunc: nil useQuotes: nil envName: SW_LOGGING_RESOLVER @@ -283,13 +283,13 @@ annotations: - name: agent.skywalking.apache.org/logging.max_file_size defaultValue: 314572800 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_LOGGING_MAX_FILE_SIZE - name: agent.skywalking.apache.org/logging.max_history_files defaultValue: -1 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_LOGGING_MAX_HISTORY_FILES @@ -301,19 +301,19 @@ annotations: - name: agent.skywalking.apache.org/statuscheck.max_recursive_depth defaultValue: 1 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_STATUSCHECK_MAX_RECURSIVE_DEPTH - name: agent.skywalking.apache.org/correlation.element_max_number defaultValue: 3 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_CORRELATION_ELEMENT_MAX_NUMBER - name: agent.skywalking.apache.org/correlation.value_max_length defaultValue: 128 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_CORRELATION_VALUE_MAX_LENGTH @@ -325,66 +325,66 @@ annotations: - name: agent.skywalking.apache.org/jvm.buffer_size defaultValue: 600 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_JVM_BUFFER_SIZE - name: agent.skywalking.apache.org/buffer.channel_size defaultValue: 5 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_BUFFER_CHANNEL_SIZE - name: agent.skywalking.apache.org/buffer.buffer_size defaultValue: 300 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_BUFFER_BUFFER_SIZE - name: agent.skywalking.apache.org/profile.active defaultValue: true - validateFunc: ValidateBool + validateFunc: nil useQuotes: nil envName: SW_AGENT_PROFILE_ACTIVE - name: agent.skywalking.apache.org/profile.max_parallel defaultValue: 5 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_PROFILE_MAX_PARALLEL - name: agent.skywalking.apache.org/profile.duration defaultValue: 10 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_PROFILE_DURATION - name: agent.skywalking.apache.org/profile.dump_max_stack_depth defaultValue: 500 - validateFunc: ValidateInt + 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: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_PROFILE_SNAPSHOT_TRANSPORT_BUFFER_SIZE - name: agent.skywalking.apache.org/meter.active defaultValue: true - validateFunc: ValidateBool + validateFunc: nil useQuotes: nil envName: SW_METER_ACTIVE - name: agent.skywalking.apache.org/meter.report_interval defaultValue: 20 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_METER_REPORT_INTERVAL - name: agent.skywalking.apache.org/meter.max_meter_size defaultValue: 500 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_METER_MAX_METER_SIZE diff --git a/pkg/operator/repo/assets.gen.go b/pkg/operator/repo/assets.gen.go index 46d8620b..910ee988 100644 --- a/pkg/operator/repo/assets.gen.go +++ b/pkg/operator/repo/assets.gen.go @@ -21,7 +21,7 @@ // fetcher/templates/configmap.yaml (3.082kB) // fetcher/templates/deployment.yaml (2.084kB) // fetcher/templates/service_account.yaml (1.088kB) -// injector/templates/annotations.yaml (12.09kB) +// 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) @@ -508,8 +508,8 @@ annotations: envName: SW_AGENT_NAMESPACE - name: agent.skywalking.apache.org/agent.service_name - defaultValue: nil - validateFunc: nil + defaultValue: Your_ApplicationName + validateFunc: ValidateServiceName useQuotes: nil envName: SW_AGENT_NAME @@ -521,7 +521,7 @@ annotations: - name: agent.skywalking.apache.org/agent.sample_n_per_3_secs defaultValue: -1 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_SAMPLE @@ -533,7 +533,7 @@ annotations: - name: agent.skywalking.apache.org/agent.span_limit_per_segment defaultValue: 300 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_SPAN_LIMIT @@ -545,73 +545,73 @@ annotations: - name: agent.skywalking.apache.org/agent.is_open_debugging_class defaultValue: true - validateFunc: ValidateBool + validateFunc: nil useQuotes: nil envName: SW_AGENT_OPEN_DEBUG - name: agent.skywalking.apache.org/agent.is_cache_enhanced_class defaultValue: false - validateFunc: ValidateBool + validateFunc: nil useQuotes: nil envName: SW_AGENT_CACHE_CLASS - name: agent.skywalking.apache.org/agent.class_cache_mode defaultValue: MEMORY - validateFunc: ValidateClassCacheMode + validateFunc: nil useQuotes: nil envName: SW_AGENT_CLASS_CACHE_MODE - name: agent.skywalking.apache.org/agent.cause_exception_depth defaultValue: 5 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_CAUSE_EXCEPTION_DEPTH - name: agent.skywalking.apache.org/agent.force_reconnection_period defaultValue: 1 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_FORCE_RECONNECTION_PERIOD - name: agent.skywalking.apache.org/agent.operation_name_threshold defaultValue: 150 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_OPERATION_NAME_THRESHOLD - name: agent.skywalking.apache.org/agent.keep_tracing defaultValue: false - validateFunc: ValidateBool + validateFunc: nil useQuotes: nil envName: SW_AGENT_KEEP_TRACING - name: agent.skywalking.apache.org/agent.force_tls defaultValue: false - validateFunc: ValidateBool + validateFunc: nil useQuotes: nil envName: SW_AGENT_FORCE_TLS - name: agent.skywalking.apache.org/osinfo.ipv4_list_size defaultValue: 10 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_OSINFO_IPV4_LIST_SIZE - name: agent.skywalking.apache.org/collector.grpc_channel_check_interval defaultValue: 30 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_COLLECTOR_GRPC_CHANNEL_CHECK_INTERVAL - name: agent.skywalking.apache.org/collector.heartbeat_period defaultValue: 30 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_COLLECTOR_HEARTBEAT_PERIOD - name: agent.skywalking.apache.org/collector.properties_report_period_factor defaultValue: 10 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_COLLECTOR_PROPERTIES_REPORT_PERIOD_FACTOR @@ -623,31 +623,31 @@ annotations: - name: agent.skywalking.apache.org/collector.grpc_upstream_timeout defaultValue: 30 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_COLLECTOR_GRPC_UPSTREAM_TIMEOUT - name: agent.skywalking.apache.org/collector.get_profile_task_interval defaultValue: 20 - validateFunc: ValidateInt + 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: ValidateInt + 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: ValidateBool + validateFunc: nil useQuotes: nil envName: SW_AGENT_COLLECTOR_IS_RESOLVE_DNS_PERIODICALLY - name: agent.skywalking.apache.org/logging.level defaultValue: INFO - validateFunc: ValidateLoggingLevel + validateFunc: nil useQuotes: nil envName: SW_LOGGING_LEVEL @@ -659,7 +659,7 @@ annotations: - name: agent.skywalking.apache.org/logging.output defaultValue: FILE - validateFunc: ValidateOutput + validateFunc: nil useQuotes: nil envName: SW_LOGGING_OUTPUT @@ -671,7 +671,7 @@ annotations: - name: agent.skywalking.apache.org/logging.resolver defaultValue: PATTERN - validateFunc: ValidateResolver + validateFunc: nil useQuotes: nil envName: SW_LOGGING_RESOLVER @@ -683,13 +683,13 @@ annotations: - name: agent.skywalking.apache.org/logging.max_file_size defaultValue: 314572800 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_LOGGING_MAX_FILE_SIZE - name: agent.skywalking.apache.org/logging.max_history_files defaultValue: -1 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_LOGGING_MAX_HISTORY_FILES @@ -701,19 +701,19 @@ annotations: - name: agent.skywalking.apache.org/statuscheck.max_recursive_depth defaultValue: 1 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_STATUSCHECK_MAX_RECURSIVE_DEPTH - name: agent.skywalking.apache.org/correlation.element_max_number defaultValue: 3 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_CORRELATION_ELEMENT_MAX_NUMBER - name: agent.skywalking.apache.org/correlation.value_max_length defaultValue: 128 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_CORRELATION_VALUE_MAX_LENGTH @@ -725,67 +725,67 @@ annotations: - name: agent.skywalking.apache.org/jvm.buffer_size defaultValue: 600 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_JVM_BUFFER_SIZE - name: agent.skywalking.apache.org/buffer.channel_size defaultValue: 5 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_BUFFER_CHANNEL_SIZE - name: agent.skywalking.apache.org/buffer.buffer_size defaultValue: 300 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_BUFFER_BUFFER_SIZE - name: agent.skywalking.apache.org/profile.active defaultValue: true - validateFunc: ValidateBool + validateFunc: nil useQuotes: nil envName: SW_AGENT_PROFILE_ACTIVE - name: agent.skywalking.apache.org/profile.max_parallel defaultValue: 5 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_PROFILE_MAX_PARALLEL - name: agent.skywalking.apache.org/profile.duration defaultValue: 10 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_PROFILE_DURATION - name: agent.skywalking.apache.org/profile.dump_max_stack_depth defaultValue: 500 - validateFunc: ValidateInt + 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: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_AGENT_PROFILE_SNAPSHOT_TRANSPORT_BUFFER_SIZE - name: agent.skywalking.apache.org/meter.active defaultValue: true - validateFunc: ValidateBool + validateFunc: nil useQuotes: nil envName: SW_METER_ACTIVE - name: agent.skywalking.apache.org/meter.report_interval defaultValue: 20 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_METER_REPORT_INTERVAL - name: agent.skywalking.apache.org/meter.max_meter_size defaultValue: 500 - validateFunc: ValidateInt + validateFunc: nil useQuotes: nil envName: SW_METER_MAX_METER_SIZE `) @@ -801,7 +801,7 @@ func injectorTemplatesAnnotationsYaml() (*asset, error) { } 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{0xf9, 0xc2, 0xdf, 0xf4, 0x18, 0x79, 0xe0, 0xe9, 0xef, 0x5, 0x66, 0x53, 0xb7, 0x97, 0x36, 0x11, 0x62, 0xea, 0xc2, 0xfc, 0xb8, 0xd0, 0x11, 0xa5, 0xbb, 0x7e, 0x58, 0x90, 0x37, 0x64, 0x3a, 0xa3}} + 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 } From 8da63203cda8b172dbc4e4f49efc4a8e3f648e65 Mon Sep 17 00:00:00 2001 From: dashanji <952129620@qq.com> Date: Wed, 15 Sep 2021 00:36:14 +0800 Subject: [PATCH 13/13] add optional-reporter --- pkg/operator/injector/injector.go | 36 ++++++++++++++++++------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/pkg/operator/injector/injector.go b/pkg/operator/injector/injector.go index 787a28aa..b048d1fe 100644 --- a/pkg/operator/injector/injector.go +++ b/pkg/operator/injector/injector.go @@ -47,11 +47,14 @@ const ( // 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 specify a specific plugin - // such as optional.skywaking.apache.org/customize-enhance-plugin-8.7.0 + // 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 - optionsAnnotationPrefix = "optional.skywalking.apache.org/" + 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. @@ -300,22 +303,25 @@ func (s *SidecarInjectField) OverlayAgent(a Annotations, ao *AnnotationOverlay, // 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 optional plugins' version -// such as spring-cloud-gateway-2.0.x or spring-cloud-gateway-2.1.x -// the final command will be "mv /optional-plugins/*spring-cloud-gateway-2.0.x* /plugins/" +// 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) { - sourcePath := strings.Join([]string{s.SidecarVolumeMount.MountPath, "optional-plugins/"}, "/") + 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 { - if strings.HasPrefix(k, optionsAnnotationPrefix) { - optionalName := strings.TrimPrefix(k, optionsAnnotationPrefix) - command := strings.Join([]string{"cp", sourcePath}, " ") - if strings.ToLower(v) == "true" { - realName := strings.Join([]string{"*", "*"}, optionalName) - command = command + realName + " " + targetPath - s.Initcontainer.Args[1] = strings.Join([]string{s.Initcontainer.Args[1], command}, " && ") - } + 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}, " && ") } }