Service Catalog migration to CRDs

Implemented features

The API server custom features were migrated to the admission webhook approach.

The table converter API server feature was migrated to the Additional Printer Columns feature.

Project changes

The architecture after the migration looks as follows:

The Service Catalog resources are grouped under the svcat name. With that feature, you can list them with the kubectl get svcat command.

Chart changes

The following files were added to the Service Catalog helm chart:

These files were deleted from the Service Catalog helm chart because they are not necessary anymore due to the API server removal:

All the webhook server configuration can be found under the webhook field in the chart’s values.yaml file.

Code changes

The following code changes were introduced to the Service Catalog:

All of the webhook logic is covered by the unit tests. The API server tests were deleted.

Implementation

Mutating and validating admission webhooks are registered in the chart’s file webhook-register.yaml. For example, the registration of the Service Instances looks as follows:

apiVersion: admissionregistration.k8s.io/v1beta1
kind: MutatingWebhookConfiguration
metadata:
  name: -webhook
  namespace: ""
webhooks:
- name: mutating.serviceinstances.servicecatalog.k8s.io
  clientConfig:
    caBundle: 
    service:
      name: -webhook
      namespace: ""
      path: "/mutating-serviceinstances"
  failurePolicy: Fail
  rules:
  - operations: [ "CREATE", "UPDATE" ]
    apiGroups: ["servicecatalog.k8s.io"]
    apiVersions: ["v1beta1"]
    resources: ["serviceinstances"]

---

apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
metadata:
  name: -validating-webhook
  namespace: ""
webhooks:
- name: validating.serviceinstances.servicecatalog.k8s.io
  clientConfig:
    caBundle: 
    service:
      name: -webhook
      namespace: ""
      path: "/validating-serviceinstances"
  failurePolicy: Fail
  rules:
  - operations: [ "CREATE", "UPDATE" ]
    apiGroups: ["servicecatalog.k8s.io"]
    apiVersions: ["v1beta1"]
    resources: ["serviceinstances"]

NOTE: Each kind is registered separately in the webhooks array.

If the resource is registered, the webhook logic will be triggered when the registered operation on this resource occurs. The example of the webhook logic implementation looks as follows:

// Handle admission requests.
func (h *CreateUpdateHandler) Handle(ctx context.Context, req admission.Request) admission.Response {
	si := &sc.ServiceInstance{}
	webhookutil.MatchKinds(si, req.Kind)
	h.decoder.Decode(req, si)

	switch req.Operation {
	case admissionTypes.Create:
		h.mutateOnCreate(ctx, req, mutated)
	case admissionTypes.Update:
		oldObj := &sc.ServiceInstance{}
		h.decoder.DecodeRaw(req.OldObject, oldObj)
		h.mutateOnUpdate(ctx, req, oldObj, mutated)
	default:
		return admission.Allowed("action not taken")
	}

	rawMutated, err := json.Marshal(mutated)
	return admission.PatchResponseFromRaw(req.AdmissionRequest.Object.Raw, rawMutated)
}

NOTE: The webhook implementation logic is common for all of the resources.

For the webhook server implementation, the sigs.k8s.io/controller-runtime dependency is used in the latest version - v0.2.0-beta.0.