Config Connector requires the Beta resource to be backward compatible. Thus, we have a higher bar on migrating the Beta resource compared to migrating an Alpha resource.
- In the MockGCP step, we require the Mock GCP to reflect the real GCP cases where the current Terraform or DCL based approach uses or depend on to make sure the migration is backward compatible (i.e. assigning defaulting value to a field, same HTTP errors for matching, etc)
- In the API and mapper step, we require the migration to happen in two stages: the first stage is to make sure all APIs and their behavior are exactly the same after migration (verifying via the golden logs). The second stage is to add new fields to make the resource up-to-date with what the current GCP service supports.
- In the controller step, we do not require the direct controller and the Terraform/DCL based controller to behave exactly the same, but fixing the legacy or non Kubernetes-native problems like merging config back to
spec
(state-into-spec:merge
), setting defaulting on-behalf of users.
To help the developer better manage the migration, we design the following steps to be self-validating and not restricted by the Config Connector release cycles. In other words, it is safe for a migration to happen across multiple Config Connector releases.
Follow deep-dives Step 1. We use the Terraform or DCL based controller to help develop the Mock GCP.
-
The 1st git-commit shall contain
create.yaml
andupdate.yaml
files with exactly the same config. -
The 2nd git-commit shall have
update.yaml
changing all the mutable fields, reflected in the git-diff based on the first commit. -
The 3rd git-commit (or N-th git-commit) shall run against real GCP. The generated
_generated_object_<resource>.golden.yaml
and_http.log
is the golden log reflecting the real GCP. The_generated_obeject_<resource>.golden.yaml
matches thespec
inupdate.yaml
-
The 4rd git-commit (or N+1-th git-commit) shall run against the Mock GCP. The git-diff shows
_generated_object_<resource>.golden.yaml
is unchanged, and the_http.log
is as much like the real GCP as possible. -
If the resource has dependencies (
dependencies.yaml
), we should cover all the referenced fields. If the dependency resource does not have mockGCP, you need to implement those dependencies' MockGCP methods as well.
If the test suite has been added, make sure all field behaviors (OPTIONAL, REQUIRED, (IM)MUTABLE) are covered in the basic and full test suites create.yaml
and update.yaml
.
- We require basic test suites and full test suites.
- We require two contiguous git-commits reflecting the real GCP and Mock GCP logs. The Mock log should be as much like the real GCP log as possible.
- We require two contiguous git-commits reflecting the mutable fields for
update.yaml
and matching changes in the generated_generated_object_<resource>.golden.yaml
and_http.log
- We require the
dependencies.yaml
to cover all referenced fields, and the_http.log
showing the Cloud requests. You need to implement those dependencies' MockGCP methods as well.
Follow deep-dives Step 2. We use the Mock GCP and Terraform or DCL based controller to verify the API migration is backward compatible.
The PR shall contain the types and deepcopy codes. It shall make modifications to make sure the CRDs are the same, because Beta resource has to be backward compatible.
-
You may need to modify the auto-generated
types.go
to keep the existing fields the same (even if it is not following the recommended styles and conventions). You can rundev/tasks/generate-crds
(repeatedly) to make sure the CRD are the same (comment changes are acceptable). -
Add
cnrm.cloud.google.com/dcl2crd: "true"
orcnrm.cloud.google.com/tf2crd: "true"
to the API tag example, to continue using DCL-based or Terraform-based controllers. -
You may see some new fields added to the CRD. These are expected since the Terraform/DCL based resources could be out of date (and users are looking forward to these new fields!). You shall comment out those new fields using
/*NOTYET ..*/
in this PR if they are not supported in the Terraform-based controller yet (we will add them later).
Note: Do not use excluded_resources
, we want the presubmit to validate the existing APIs are unchanged and the behaviors are the same.
- We require the
_http.log
,_generated_object_<resource>.golden.yaml
,create.yaml
andupdate.yaml
unchanged.
Follow deep-dives Step 3
The PR adds the direct mapper. You can do this together with the previous step or the next step if no additional manual changes are needed. Using /*NOTYET .. */
to comment out new functions, same as the last step.
Follow deep-dives Step 4.
- Use the
KCC_USE_DIRECT_RECONCILERS
flag example.
Tips The KCC_USE_DIRECT_RECONCILERS
will override the tf2crd
and dcl2crd
label to force using the direct controller, but it will not affect the releases which will still use the Terraform/DCL based controllers until the Direct controller is fully ready. This allows developing the API and controller in different Config Connector releases without code freeze.
- We require the roundtrip fuzz tests to cover all the fields in
spec
andstatus.observedState
fields Example - We require the MockGCP pass without any change to the
create.yaml
,update.yaml
and_generated_object_<resource>.golden.yaml
files.
Once the direct controller is fully implemented, you can swith to the direct controller.
-
Remove the
cnrm.cloud.google.com/dcl2crd: "true"
orcnrm.cloud.google.com/tf2crd: "true"
API tag example. Rundev/tasks/generate-crds
to update the CRDs, now all the API and controller have been migration to the direct approach. -
Remove the
KCC_USE_DIRECT_RECONCILERS
flag.
- We require the MockGCP unchange and pass.
The PR shall add back those fields that commented out in Step 3.
You need to update both types.go
and mapping.go
, and may need to adjust the direct controller as well to support those new fields.
- The MockGCP test shall reflect the new fields in
create.yaml
,update.yaml
(if mutable),_generated_object_<resource>.golden.yaml
, and_http.log
. - We require the roundtrip fuzz tests to cover the new fields in
spec
or/andstatus.observedState
fields example (For mapper) - We require no /*NOTYET .. */ in the API and Mapper code.