blob: 384236e693bcb91325b9725e6489cff7033088ee [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package webhook
import (
"context"
"reflect"
dubbo_cp "github.com/apache/dubbo-kubernetes/pkg/config/app/dubbo-cp"
"github.com/apache/dubbo-kubernetes/pkg/core/logger"
admissionregistrationV1 "k8s.io/api/admissionregistration/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
type Client interface {
UpdateWebhookConfig(options *dubbo_cp.Config, CertPem string)
GetNamespaceLabels(namespace string) map[string]string
ListServices(namespace string, listOptions metav1.ListOptions) *v1.ServiceList
GetKubClient() kubernetes.Interface
}
type ClientImpl struct {
kubeClient kubernetes.Interface
}
func NewClient(kubeClient kubernetes.Interface) Client {
return &ClientImpl{
kubeClient: kubeClient,
}
}
func (c *ClientImpl) GetNamespaceLabels(namespace string) map[string]string {
ns, err := c.kubeClient.CoreV1().Namespaces().Get(context.TODO(), namespace, metav1.GetOptions{})
if err != nil {
logger.Sugar().Warnf("[Authority] Failed to validate token. " + err.Error())
return map[string]string{}
}
if ns.Labels != nil {
return ns.Labels
}
return map[string]string{}
}
func (c *ClientImpl) ListServices(namespace string, listOptions metav1.ListOptions) *v1.ServiceList {
serviceList, err := c.kubeClient.CoreV1().Services(namespace).List(context.Background(), listOptions)
if err != nil {
logger.Sugar().Warnf("[Webhook] Unable to list services. " + err.Error())
return nil
}
return serviceList
}
func (c *ClientImpl) UpdateWebhookConfig(options *dubbo_cp.Config, CertPem string) {
path := "/mutating-services"
failurePolicy := admissionregistrationV1.Ignore
sideEffects := admissionregistrationV1.SideEffectClassNone
bundle := CertPem
mwConfig, err := c.kubeClient.AdmissionregistrationV1().MutatingWebhookConfigurations().Get(context.TODO(), "dubbo-cp", metav1.GetOptions{})
if err != nil {
logger.Sugar().Warnf("[Webhook] Unable to find dubbo-cp webhook config. Will create. " + err.Error())
mwConfig = &admissionregistrationV1.MutatingWebhookConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: "dubbo-cp",
},
Webhooks: []admissionregistrationV1.MutatingWebhook{
{
Name: "dubbo-cp" + ".k8s.io",
ClientConfig: admissionregistrationV1.WebhookClientConfig{
Service: &admissionregistrationV1.ServiceReference{
Name: options.KubeConfig.ServiceName,
Namespace: options.KubeConfig.Namespace,
Port: &options.Webhook.Port,
Path: &path,
},
CABundle: []byte(bundle),
},
FailurePolicy: &failurePolicy,
Rules: []admissionregistrationV1.RuleWithOperations{
{
Operations: []admissionregistrationV1.OperationType{
admissionregistrationV1.Create,
},
Rule: admissionregistrationV1.Rule{
APIGroups: []string{""},
APIVersions: []string{"v1"},
Resources: []string{"pods"},
},
},
},
// TODO add it or not?
//NamespaceSelector: &metav1.LabelSelector{
// MatchLabels: map[string]string{
// "dubbo-injection": "enabled",
// },
//},
//ObjectSelector: &metav1.LabelSelector{
// MatchLabels: map[string]string{
// "dubbo-injection": "enabled",
// },
//},
SideEffects: &sideEffects,
AdmissionReviewVersions: []string{"v1"},
},
},
}
_, err := c.kubeClient.AdmissionregistrationV1().MutatingWebhookConfigurations().Create(context.TODO(), mwConfig, metav1.CreateOptions{})
if err != nil {
logger.Sugar().Warnf("[Webhook] Failed to create webhook config. " + err.Error())
} else {
logger.Sugar().Info("[Webhook] Create webhook config success.")
}
return
}
if reflect.DeepEqual(mwConfig.Webhooks[0].ClientConfig.CABundle, []byte(bundle)) {
logger.Sugar().Info("[Webhook] Ignore override webhook config. Cause: Already exist.")
return
}
mwConfig.Webhooks[0].ClientConfig.CABundle = []byte(bundle)
_, err = c.kubeClient.AdmissionregistrationV1().MutatingWebhookConfigurations().Update(context.TODO(), mwConfig, metav1.UpdateOptions{})
if err != nil {
logger.Sugar().Warnf("[Webhook] Failed to update webhook config. " + err.Error())
} else {
logger.Sugar().Info("[Webhook] Update webhook config success.")
}
}
func (c *ClientImpl) GetKubClient() kubernetes.Interface {
return c.kubeClient
}