Ignore unspecified fields


This document explains how to change the default spec fields populating behavior using cnrm.cloud.google.com/state-into-spec annotation, and when you need to change it.

As explained in Manage fields externally, when Config Connector creates a resource on Google Cloud, fields left unspecified in the spec take on values from the API unless they are not readable (for example, are not available by using a GET HTTP request).

This means, by default, fields which haven't been specified in your original YAML always appear in the Kubernetes resource's spec. This means when you do kubectl get <resource kind> <resource name> -oyaml, many fields in the resource spec are not in your applied YAML.

As an example, assume the CRD schema allows you to specify two fields named foo and bar in spec, while your applied YAML file has only foo specified:

spec:
  foo: "foo"

You'll notice another field named bar appears in the Kubernetes resource if the YAML is applied successfully and the resource is UpToDate:

spec:
  foo: "foo"
  bar: "bar"

Due to the complexity of interaction between Config Connector and Google Cloud APIs, you might want to change this default behavior and skip populating the resource spec with unspecified fields.

Skip populating unspecified fields into spec

When creating your YAML file, you can specify the value of the cnrm.cloud.google.com/state-into-spec annotation as absent. This skips populating unspecified fields into the Kubernetes resource spec:

metadata:
  annotations:
    cnrm.cloud.google.com/state-into-spec: absent

This annotation has a default value of merge if not specified, which means Config Connector populates all unspecified fields into spec. This annotation is immutable, which means you can't update the annotation value of an existing Config Connector resource.

If you have already created the resource, but want to change the value of this annotation for a different populating behavior, you must follow these steps:

  1. Edit and add annotation cnrm.cloud.google.com/deletion-policy: abandon to the existing Kubernetes resource to make sure deletion in next step won't delete the underlying Google Cloud resource.

  2. Delete the resource from the Kubernetes cluster.

  3. Add annotation cnrm.cloud.google.com/state-into-spec: absent into the YAML of the resource.

  4. (Optional) remove cnrm.cloud.google.com/deletion-policy: abandon from the YAML.

  5. Apply the updated YAML.

To further explain the difference introduced by this annotation, assume there is a spec with the following schema:

foo1: string
foo2: string
bars:
- bar:
    br1: string
    br2: string
barz:
  bz1: string
  bz2: string

Also assume you have specified the spec in your YAML as:

spec:
  foo1: "foo1"
  bars:
  - br1: "1_br1"
  - br1: "2_br1"
  barz:
    bz1: "bz1"

Then by default, the populated spec in the created Kubernetes resource might be:

spec:
  foo1: "foo1"
  foo2: "foo2"
  bars:
  - br1: "1_br1"
    br2: "1_br2"
  - br1: "2_br1"
    br2: "2_br2"
  barz:
    bz1: "bz1"
    bz2: "bz2"

While if you set cnrm.cloud.google.com/state-into-spec: absent, the final spec in the created Kubernetes resource will be:

spec:
  foo1: "foo1"
  bars:
  - br1: "1_br1"
  - br1: "2_br1"
  barz:
    bz1: "bz1"

When to use cnrm.cloud.google.com/state-into-spec: absent

There are some common scenarios you may want to set cnrm.cloud.google.com/state-into-spec: absent.

Manage unspecified fields in a list externally

Config Connector treats all list fields in resource spec as atomic fields. As a result, by default, your change made to a subfield in the list from outside of Config Connector will be reverted by Config Connector. However, you can use this annotation to let Config Connector unmanage subfields in list. For more information, see Behavior for list fields in resource spec.

Resolve fighting between config management tools and Config Connector

If you are using config management tools like Config Sync or Argo CD, you may notice a fight between the config management tool and Config Connector. An example is the KNV2005 error explained in troubleshooting guide. The root cause of these types of issues are because:

  1. Config Connector will populate and default unspecified values in list in the spec, the spec.bars[0].br2 is an example.
  2. Both config management tools and Config Connector treat list fields as atomic, thus the added spec.bars[0].br2 is treated as a drift by config management tools and will be removed to correct the drift.

To resolve these issues, you can set cnrm.cloud.google.com/state-into-spec: absent so that Config Connector doesn't add unspecified field spec.bars[0].br2 into the spec.

Resolve GET/PUT symmetry issues

GET/PUT symmetry refers to a design principle in REST API. Specifically, it means when a GET response is sent as a PUT request to the same URL, the expected result is a HTTP 200 OK response with no change in the state of the underlying REST resource.

The unspecified fields populated by Config Connector in the resource spec are as a result of a GET request. This means in future reconciliations, Config Connector may send a PUT/PATCH request to the underlying Google Cloud API, with these unspecified field values learned from the GET request. This is usually not a problem, but it is possible some Google Cloud APIs will reject the PUT/PATCH request because of these unspecified field values. In the same example, the populated spec.barz.bz2 with value "bz2" may result an HTTP 400 client error or other unexpected responses if the API implementation violates the GET/PUT symmetry principle.

To avoid this category of issues, you can experiment setting cnrm.cloud.google.com/state-into-spec: absent and check if the errors during reconciliation will go away.

When to avoid cnrm.cloud.google.com/state-into-spec: absent

You should avoid setting cnrm.cloud.google.com/state-into-spec: absent if your solution depends on the populated values from unspecified fields. For example, if you are using a ComputeAddress resource and you need the server-generated spec.address value, which might be an unspecified field in your original YAML, then you should not use this annotation as it will skip populating the value of spec.address into the Kubernetes resource spec.

Observed State

If you need to set cnrm.cloud.google.com/state-into-spec: absent, but your solution depends on the populated values from unspecified fields, check if these fields exist under status.observedState in the CRD schema. If they're represented under status.observedState, then you can set cnrm.cloud.google.com/state-into-spec: absent and still access the values of the unspecified fields after a successful reconciliation.

The status.observedState field contains the live state of the selected, observed fields of the resource that Config Connector observed in the last successful reconciliation. The observed fields are selected if they are dependencies of common use cases, and are computed spec fields. You can find the observed fields in the CRD schemas.

If you can't find the observed fields you want, check for an existing issue or open a new issue in the public issue trackers .