Webhookの実装

Webhookマニフェストの生成で解説したように、テナントコントローラではリソースの作成時にデフォルト値を設定するためのWebhookと、リソースの更新時にバリデーションするためのWebhookを作成します。

これらのWebhookの実装は非常に簡単で、controller-genで生成された関数に必要な処理を書いていくだけです。

デフォルト値設定のWebhook

まずはデフォルト値を設定するWebhookの実装です。

tenant_webhook.go

// Default implements webhook.Defaulter so a webhook will be registered for the type
func (r *Tenant) Default() {
    tenantlog.Info("default", "name", r.Name)

    // TODO(user): fill in your defaulting logic.
    if r.Spec.NamespacePrefix == "" {
        r.Spec.NamespacePrefix = r.Name + "-"
    }
}

namespacePrefixフィールドが空だった場合は、テナントの名前に-を連結した文字列をnamespacePrefixとして利用します。

バリデーションのWebhook

次にバリデーションWebhookの実装です。

tenant_webhook.go

// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (r *Tenant) ValidateCreate() error {
    tenantlog.Info("validate create", "name", r.Name)

    // TODO(user): fill in your validation logic upon object creation.
    return nil
}

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (r *Tenant) ValidateUpdate(old runtime.Object) error {
    tenantlog.Info("validate update", "name", r.Name)

    // TODO(user): fill in your validation logic upon object update.
    oldTenant := old.(*Tenant)
    if r.Spec.NamespacePrefix != oldTenant.Spec.NamespacePrefix {
        return errors.New("spec.namespacePrefix field should not be changed")
    }
    return nil
}

// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (r *Tenant) ValidateDelete() error {
    tenantlog.Info("validate delete", "name", r.Name)

    // TODO(user): fill in your validation logic upon object deletion.
    return nil
}

今回はCreateとDelete時のバリデーションをおこなわないため、ValidateUpdate関数のみを実装します。 更新前のリソースが引数で渡ってくるので、namespacePrefixフィールドが変更されていればバリデーションエラーとします。

このようなバリデーションを実装することで、途中でnamespacePrefixを変更できないようにすることが可能です。

動作確認

Webhookの動作確認をしてみましょう。

Webhookの実装をおこなったカスタムコントローラをKubernetesクラスタにデプロイし、下記のようなnamespacePrefixを指定していないマニフェストを適用します。

apiVersion: multitenancy.example.com/v1
kind: Tenant
metadata:
  name: sample
spec:
  namespaces:
    - test1
  admin:
    kind: ServiceAccount
    name: default
    namespace: default

作成されたリソースを確認して、namespacePrefixに"sample-"という文字列が入っていれば成功です。

$ kubectl get tenant sample
NAME     ADMIN     PREFIX    READY
sample   default   sample-   True

続いてバリデーションWebhookの動作も確認してみましょう。

先ほど作成したリソースをeditしてnamespacePrefixを別の名前に変更しようとしたときに、下記のようなエラーが発生すれば成功です。

$ kubectl edit tenant sample
error: tenants.multitenancy.example.com "sample" could not be patched: admission webhook "vtenant.kb.io" denied the request: spec.namespacePrefix field should not be changed
You can run `kubectl replace -f /tmp/kubectl-edit-bwuei.yaml` to try this update again.

results matching ""

    No results matching ""