blob: c7c050f5e46e63dc6bf0e11828bb69a33e0cc2a7 [file] [log] [blame]
// 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"
"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"
"github.com/apache/skywalking-swck/operator/apis/operator/v1alpha1"
)
// log is for logging in this package.
var javaagentInjectorLog = logf.Log.WithName("javaagent_injector")
// nolint: lll
// +kubebuilder:webhook:admissionReviewVersions=v1,sideEffects=None,path=/mutate-v1-pod,mutating=true,failurePolicy=fail,groups="",resources=pods,verbs=create;update,versions=v1,name=mpod.kb.io
// JavaagentInjector injects java agent into Pods
type JavaagentInjector struct {
Client client.Client
decoder *admission.Decoder
}
// Handle will process every coming pod under the
// specified namespace which labeled "swck-injection=enabled"
func (r *JavaagentInjector) Handle(ctx context.Context, req admission.Request) admission.Response {
pod := &corev1.Pod{}
if err := r.decoder.Decode(req, pod); err != nil {
return admission.Errored(http.StatusBadRequest, err)
}
// set Annotations to avoid repeated judgments
if pod.Annotations == nil {
pod.Annotations = map[string]string{}
}
swAgentL := r.findMatchedSwAgentL(ctx, req, pod)
// initialize all annotation types that can be overridden
anno, err := NewAnnotations()
if err != nil {
javaagentInjectorLog.Error(err, "get NewAnnotations error")
}
// initialize Annotations to store the overlaied value
ao := NewAnnotationOverlay()
// initialize SidecarInjectField and get injected strategy from annotations
s := NewSidecarInjectField()
// initialize InjectProcess as a call chain
ip := NewInjectProcess(ctx, s, anno, ao, swAgentL, pod, req, javaagentInjectorLog, r.Client)
// do real injection
return ip.Run()
}
func (r *JavaagentInjector) findMatchedSwAgentL(ctx context.Context, req admission.Request, pod *corev1.Pod) *v1alpha1.SwAgentList {
swAgentList := &v1alpha1.SwAgentList{}
if err := r.Client.List(ctx, swAgentList, client.InNamespace(req.Namespace)); err != nil {
javaagentInjectorLog.Error(err, "get SwAgent error")
}
// selector
var availableSwAgentL []v1alpha1.SwAgent
for _, swAgent := range swAgentList.Items {
isMatch := true
if len(swAgent.Spec.Selector) != 0 {
for k, v := range swAgent.Spec.Selector {
if !strings.EqualFold(v, pod.Labels[k]) {
isMatch = false
}
}
}
if isMatch {
availableSwAgentL = append(availableSwAgentL, swAgent)
}
}
swAgentList.Items = availableSwAgentL
return swAgentList
}
// Javaagent implements admission.DecoderInjector.
// A decoder will be automatically injected.
// InjectDecoder injects the decoder.
func (r *JavaagentInjector) InjectDecoder(d *admission.Decoder) error {
r.decoder = d
return nil
}