Skip to content

Latest commit

 

History

History
136 lines (95 loc) · 6.69 KB

File metadata and controls

136 lines (95 loc) · 6.69 KB

4. Add the direct controller

This document describes how to add a new direct controller, and how to configure controller routing.

Controller Routing Logic

A top-level parent controller routes reconciliation to one of three underlying controllers: Terraform (TF), DCL, or Direct. The controller is selected using the following order of precedence:

  1. Resource Annotation (deprecated): A resource can specify a controller directly using the annotation cnrm.cloud.google.com/reconciler: direct. This is supported for backward compatibility, but its use is discouraged and it will be deprecated in the future.

  2. ConfigConnectorContext Override: The ConfigConnectorContext resource allows for overriding the controller for a specific resource GroupKind using the spec.experiments.controllerOverrides field.

  3. Static Configuration: A static map in pkg/controller/resourceconfig/static_config.go defines the default and supported controllers for each resource. This is the default mechanism if no overrides are specified.

You can use a script to update the static configuration, which will be covered in the scenarios below.

Generate the controller template

Run the following command to generate a controller template:

cd dev/tools/controllerbuilder
go run main.go generate-controller --service <YOUR_SERVICE> --api-version <VERSION> --resource <YOUR_RESOURCE>:<PROTO_RESOURCE>

Fix the generated code to make your controller run.

4.1 Implement the model interface

The controller template has implemented the model interfacefind, create, update, deleteand export. You may need to update the code to fit your resource.

4.2 Resolve resource references

Most Config Connector resources need references like spec.projectRef. You should add those references in AdapterForObject using functions Resolve<RefResource>.

If there is no previous reference method, you may need to add a new Resolve<RefResource>.

Check the validation guide to make sure your validation is complete.

4.3 Configure and verify your controller

This section covers how to configure the controller routing for your resource and verify it. The static controller configuration is generated by a script that inspects your CRD definitions and controller code.

There are three main scenarios:

  1. Adding a new direct resource at alpha.
  2. Migrating an existing TF/DCL-based resource to direct.
  3. Promoting an alpha direct resource to beta.

General Workflow

The general workflow for updating the controller configuration is:

  1. Ensure your CRD file (config/crds/resources/<crd_file>.yaml) is up-to-date. For migrated resources, this includes ensuring the cnrm.cloud.google.com/tf2crd or cnrm.cloud.google.com/dcl2crd labels are set correctly.
  2. Ensure your direct controller implementation calls RegisterModel for your resource's GVK.
  3. Run the generation script:
    ./dev/tasks/generate_static_config.py
    This will automatically update pkg/controller/resourceconfig/static_config.go.

Scenario 1: Adding a new alpha direct resource

For a new resource that will only have a direct controller, the script will automatically configure it as the default and only controller, as long as the CRD does not have tf2crd or dcl2crd labels.

  1. Generate the static controller configuration: After creating your CRD and direct controller, run the script.

    ./dev/tasks/generate_static_config.py
  2. Verify the controller: Run the MockGCP tests. Since direct is the default, no special environment variables are needed.

    hack/compare-mock fixtures/<your_resource_test>

Scenario 2: Migrating an existing TF/DCL resource to direct

When migrating an existing resource, you'll want to support both the old (TF/DCL) and new (direct) controllers. The old controller will remain the default. The script handles this automatically if the tf2crd or dcl2crd label is present on the CRD.

  1. Generate the static controller configuration: After adding your direct controller with RegisterModel, run the script. It will detect the existing tf2crd or dcl2crd label on the CRD and add direct as a supported controller, while keeping the original as the default.

    ./dev/tasks/generate_static_config.py
  2. Verify the direct controller: To test your new direct controller, you need to override the default routing. You can do this in two ways:

    • Using an environment variable (for testing): Set the KCC_USE_DIRECT_RECONCILERS environment variable to force the use of the direct controller for your resource kind.

      KCC_USE_DIRECT_RECONCILERS=<YOUR_KIND> hack/compare-mock fixtures/<your_resource_test>

      Note: Differences in http.logs such as user-agent and method url are expected. Please regenerate test logs before compare-mock.

    • Using a ConfigConnectorContext override (for cluster-wide testing): You can create a ConfigConnectorContext object in your test namespace to override the controller for your resource.

      apiVersion: core.cnrm.cloud.google.com/v1beta1
      kind: ConfigConnectorContext
      metadata:
        name: configconnectorcontext.core.cnrm.cloud.google.com
        namespace: ${NAMESPACE}
      spec:
        experiments:
          controllerOverrides:
          - group: <GROUP>
            kind: <KIND>
            controller: direct

Scenario 3: Promoting an alpha direct resource to beta

When you promote a resource from alpha to beta, you will typically make the direct controller the default for the new beta version.

  1. Update the CRD for the beta version: When you create the v1beta1 CRD, ensure it does not have the cnrm.cloud.google.com/tf2crd or cnrm.cloud.google.com/dcl2crd labels. This will signal to the generation script that direct should be the default.

  2. Generate the static controller configuration: Run the script. It will generate the configuration for the new v1beta1 version with direct as the default controller.

    ./dev/tasks/generate_static_config.py
  3. Verify the controller: Update your test fixtures to use apiVersion: <GROUP>/v1beta1. Then run the MockGCP tests.

    hack/compare-mock fixtures/<your_resource_test>

Exit Criteria

  • The PRs shall pass the MockGCP tests.
  • For Beta resource, the roundtrip fuzz tests shall cover all the fields in spec and status.observedState fields. Example