mirror of https://github.com/linkerd/linkerd2.git
114 lines
3.4 KiB
Go
114 lines
3.4 KiB
Go
package injector
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/base64"
|
|
"io/ioutil"
|
|
"text/template"
|
|
|
|
yaml "github.com/ghodss/yaml"
|
|
"github.com/linkerd/linkerd2/controller/proxy-injector/tmpl"
|
|
k8sPkg "github.com/linkerd/linkerd2/pkg/k8s"
|
|
log "github.com/sirupsen/logrus"
|
|
arv1beta1 "k8s.io/api/admissionregistration/v1beta1"
|
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/client-go/kubernetes"
|
|
)
|
|
|
|
// WebhookConfig creates the MutatingWebhookConfiguration of the webhook.
|
|
type WebhookConfig struct {
|
|
controllerNamespace string
|
|
webhookServiceName string
|
|
trustAnchor []byte
|
|
configTemplate *template.Template
|
|
k8sAPI kubernetes.Interface
|
|
}
|
|
|
|
// NewWebhookConfig returns a new instance of initiator.
|
|
func NewWebhookConfig(client kubernetes.Interface, controllerNamespace, webhookServiceName, trustAnchorFile string) (*WebhookConfig, error) {
|
|
trustAnchor, err := ioutil.ReadFile(trustAnchorFile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
t := template.New(k8sPkg.ProxyInjectorWebhookConfig)
|
|
|
|
return &WebhookConfig{
|
|
controllerNamespace: controllerNamespace,
|
|
webhookServiceName: webhookServiceName,
|
|
trustAnchor: trustAnchor,
|
|
configTemplate: template.Must(t.Parse(tmpl.MutatingWebhookConfigurationSpec)),
|
|
k8sAPI: client,
|
|
}, nil
|
|
}
|
|
|
|
// CreateOrUpdate sends the request to either create or update the
|
|
// MutatingWebhookConfiguration resource. During an update, only the CA bundle
|
|
// is changed.
|
|
func (w *WebhookConfig) CreateOrUpdate() (*arv1beta1.MutatingWebhookConfiguration, error) {
|
|
mwc, exist, err := w.exist()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !exist {
|
|
return w.create()
|
|
}
|
|
|
|
return w.update(mwc)
|
|
}
|
|
|
|
// exist returns true if the mutating webhook configuration exists. Otherwise,
|
|
// it returns false.
|
|
func (w *WebhookConfig) exist() (*arv1beta1.MutatingWebhookConfiguration, bool, error) {
|
|
mwc, err := w.k8sAPI.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Get(k8sPkg.ProxyInjectorWebhookConfig, metav1.GetOptions{})
|
|
if err != nil {
|
|
if apierrors.IsNotFound(err) {
|
|
return nil, false, nil
|
|
}
|
|
|
|
return nil, false, err
|
|
}
|
|
|
|
return mwc, true, nil
|
|
}
|
|
|
|
func (w *WebhookConfig) create() (*arv1beta1.MutatingWebhookConfiguration, error) {
|
|
var (
|
|
buf = &bytes.Buffer{}
|
|
spec = struct {
|
|
WebhookConfigName string
|
|
WebhookServiceName string
|
|
ControllerNamespace string
|
|
CABundle string
|
|
ProxyAutoInjectLabel string
|
|
}{
|
|
WebhookConfigName: k8sPkg.ProxyInjectorWebhookConfig,
|
|
WebhookServiceName: w.webhookServiceName,
|
|
ControllerNamespace: w.controllerNamespace,
|
|
CABundle: base64.StdEncoding.EncodeToString(w.trustAnchor),
|
|
ProxyAutoInjectLabel: k8sPkg.ProxyAutoInjectLabel,
|
|
}
|
|
)
|
|
if err := w.configTemplate.Execute(buf, spec); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var config arv1beta1.MutatingWebhookConfiguration
|
|
if err := yaml.Unmarshal(buf.Bytes(), &config); err != nil {
|
|
log.Infof("failed to unmarshal mutating webhook configuration: %s\n%s\n", err, buf.String())
|
|
return nil, err
|
|
}
|
|
|
|
return w.k8sAPI.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Create(&config)
|
|
}
|
|
|
|
func (w *WebhookConfig) update(mwc *arv1beta1.MutatingWebhookConfiguration) (*arv1beta1.MutatingWebhookConfiguration, error) {
|
|
for i := 0; i < len(mwc.Webhooks); i++ {
|
|
mwc.Webhooks[i].ClientConfig.CABundle = w.trustAnchor
|
|
}
|
|
|
|
return w.k8sAPI.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Update(mwc)
|
|
}
|