Repository: GoogleCloudPlatform/k8s-config-connector
Pull request #4300: Add crd mapper fuzzer for private connection
Author: login: anhdle-sso
Labels: name: lgtm
name: approved
Created: 2025-04-08T00:01:24Z | Merged: 2025-04-17T23:57:24Z

### Change description

<!--
Describe what this pull request does.

* If your pull request is to address an open issue, indicate it by specifying the
issue number: 

For example: "Fixes #858"
-->
Fixes #

### Tests you have done

<!--

Make sure you have run "make ready-pr" to run required tests and ensure this PR is ready to review. 

Also if possible, share a bit more on the tests you have done. 

For example if you have updated the pubsubtopic sample, you can share the test logs from running the test case locally.

go test -v -tags=integration ./config/tests/samples/create -test.run TestAll -run-tests pubsubtopic

-->

- [ ] Run `make ready-pr` to ensure this PR is ready for review.
- [ ] Perform necessary E2E testing for changed resources.


Linked issue #858: BigtableInstance does not allow to switch back from autoscaling node allocation to manual node allocation 
### Checklist

- [X] I did not find a related open issue.
- [X] I did not find a solution in the troubleshooting guide: (https://cloud.google.com/config-connector/docs/troubleshooting)
- [X] If this issue is time-sensitive, I have submitted a corresponding issue with [GCP support](https://cloud.google.com/support-hub).

### Bug Description

BigtableInstance ConfigConnector resource does not allow a end-user to switch back from using `autoscalingConfig` to `numNodes`.
Switching from a `BigtableInstance` from `numNodes: 1` to `autoscalingConfig { cpuTarget: 10, minNodes: 1, maxNodes: 5 }` works as expected. But once we try to roll back the change, disabling autoscaling, the API returns an error. 
```
Error: API response status: Failure
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:     1: resource "kubernetes_manifest" "bigtable_instance_bigtable" {
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:  BigtableInstance.bigtable.cnrm.cloud.google.com "bigtable" is invalid:
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:  [spec.cluster[0].autoscalingConfig.cpuTarget: Required value,
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:  spec.cluster[0].autoscalingConfig.maxNodes: Required value,
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:  spec.cluster[0].autoscalingConfig.minNodes: Required value,
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:  spec.cluster[1].autoscalingConfig.cpuTarget: Required value,
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:  spec.cluster[1].autoscalingConfig.maxNodes: Required value,
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:  spec.cluster[1].autoscalingConfig.minNodes: Required value]
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:  Error: Kubernetes API Error: Invalid BigtableInstance.bigtable.cnrm.cloud.google.com [bigtable]
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:    with kubernetes_manifest.bigtable_instance_bigtable,
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:    on bigtable_bigtable.tf line 1, in resource "kubernetes_manifest" "bigtable_instance_bigtable":
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:     1: resource "kubernetes_manifest" "bigtable_instance_bigtable" {
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:  Error: spec.cluster[0].autoscalingConfig.cpuTarget
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:    with kubernetes_manifest.bigtable_instance_bigtable,
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:    on bigtable_bigtable.tf line 1, in resource "kubernetes_manifest" "bigtable_instance_bigtable":
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:     1: resource "kubernetes_manifest" "bigtable_instance_bigtable" {
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:  Required value
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:  Error: spec.cluster[0].autoscalingConfig.maxNodes
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:    with kubernetes_manifest.bigtable_instance_bigtable,
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:    on bigtable_bigtable.tf line 1, in resource "kubernetes_manifest" "bigtable_instance_bigtable":
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:     1: resource "kubernetes_manifest" "bigtable_instance_bigtable" {
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:
Tue 26 Sep 2023 12:46:22 [INFO    ] puppet: Gcp_project           Exec[run_terraform_for_project_resources]:  Required value
```

Doing the same change using Terraform `google_bigtable_instance` resource performs the change accordingly. 


### Additional Diagnostic Information

No info.

### Kubernetes Cluster Version

v1.25.10-gke.2700

### Config Connector Version

1.108.0

### Config Connector Mode

cluster mode

### Log Output

_No response_

### Steps to reproduce the issue

Create a BigtableInstance resource with ConfigConnector, specifying the numNodes to 1.
Once the resource is created, configure the `autoscalingConfig`. As an example:
```
  spec:
    cluster:
    - autoscalingConfig:
        cpuTarget: 10
        maxNodes: 5
        minNodes: 1
        storageTarget: 2560
      clusterId: bigtable-cluster
      numNodes: 1
      storageType: SSD
      zone: europe-west4-b
```
Then, once the second change is applied, try to disable the autoscaling configuration by removing it from the YAML.


### YAML snippets

_No response_
Linked issue comments: user: login: diviner524
created_at: 2023-09-26T17:03:43Z
body: This could be related to a feature gap in Config Connector, which is how the current controller interpret "removal".

https://cloud.google.com/config-connector/docs/troubleshooting#unable_to_remove_fields_from_resource_spec

Since `autoscalingConfig` is an object field, we may need to introduce a proper feature or syntax to indicate the field needs to be set to NULL/empty.
author_association: CONTRIBUTOR
user: login: diogomvsantos
created_at: 2023-12-13T11:08:51Z
body: A public tracker has been created for this bug.
https://issuetracker.google.com/issues/315988174
author_association: NONE

Diff:
diff --git a/apis/clouddms/v1alpha1/privateconnection_identity.go b/apis/clouddms/v1alpha1/privateconnection_identity.go
new file mode 100644
index 00000000000..854354fd725
--- /dev/null
+++ b/apis/clouddms/v1alpha1/privateconnection_identity.go
@@ -0,0 +1,117 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package v1alpha1
+
+import (
+	"context"
+	"fmt"
+	"strings"
+
+	"github.com/GoogleCloudPlatform/k8s-config-connector/apis/common"
+	refsv1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+)
+
+// PrivateConnectionIdentity defines the resource reference to CloudDMSPrivateConnection, which "External" field
+// holds the GCP identifier for the KRM object.
+type PrivateConnectionIdentity struct {
+	parent *PrivateConnectionParent
+	id     string
+}
+
+func (i *PrivateConnectionIdentity) String() string {
+	return i.parent.String() + "/privateConnections/" + i.id
+}
+
+func (i *PrivateConnectionIdentity) ID() string {
+	return i.id
+}
+
+func (i *PrivateConnectionIdentity) Parent() *PrivateConnectionParent {
+	return i.parent
+}
+
+type PrivateConnectionParent struct {
+	ProjectID string
+	Location  string
+}
+
+func (p *PrivateConnectionParent) String() string {
+	return "projects/" + p.ProjectID + "/locations/" + p.Location
+}
+
+// New builds a PrivateConnectionIdentity from the Config Connector PrivateConnection object.
+func NewPrivateConnectionIdentity(ctx context.Context, reader client.Reader, obj *CloudDMSPrivateConnection) (*PrivateConnectionIdentity, error) {
+
+	// Get Parent
+	projectRef, err := refsv1beta1.ResolveProject(ctx, reader, obj.GetNamespace(), obj.Spec.ProjectRef)
+	if err != nil {
+		return nil, err
+	}
+	projectID := projectRef.ProjectID
+	if projectID == "" {
+		return nil, fmt.Errorf("cannot resolve project")
+	}
+	location := obj.Spec.Location
+
+	// Get desired ID
+	resourceID := common.ValueOf(obj.Spec.ResourceID)
+	if resourceID == "" {
+		resourceID = obj.GetName()
+	}
+	if resourceID == "" {
+		return nil, fmt.Errorf("cannot resolve resource ID")
+	}
+
+	// Use approved External
+	externalRef := common.ValueOf(obj.Status.ExternalRef)
+	if externalRef != "" {
+		// Validate desired with actual
+		actualParent, actualResourceID, err := ParsePrivateConnectionExternal(externalRef)
+		if err != nil {
+			return nil, err
+		}
+		if actualParent.ProjectID != projectID {
+			return nil, fmt.Errorf("spec.projectRef changed, expect %s, got %s", actualParent.ProjectID, projectID)
+		}
+		if actualParent.Location != location {
+			return nil, fmt.Errorf("spec.location changed, expect %s, got %s", actualParent.Location, location)
+		}
+		if actualResourceID != resourceID {
+			return nil, fmt.Errorf("cannot reset `metadata.name` or `spec.resourceID` to %s, since it has already assigned to %s",
+				resourceID, actualResourceID)
+		}
+	}
+	return &PrivateConnectionIdentity{
+		parent: &PrivateConnectionParent{
+			ProjectID: projectID,
+			Location:  location,
+		},
+		id: resourceID,
+	}, nil
+}
+
+func ParsePrivateConnectionExternal(external string) (parent *PrivateConnectionParent, resourceID string, err error) {
+	tokens := strings.Split(external, "/")
+	if len(tokens) != 6 || tokens[0] != "projects" || tokens[2] != "locations" || tokens[4] != "privateConnections" {
+		return nil, "", fmt.Errorf("format of CloudDMSPrivateConnection external=%q was not known (use projects/{{projectID}}/locations/{{location}}/privateConnections/{{privateconnectionID}})", external)
+	}
+	parent = &PrivateConnectionParent{
+		ProjectID: tokens[1],
+		Location:  tokens[3],
+	}
+	resourceID = tokens[5]
+	return parent, resourceID, nil
+}
diff --git a/apis/clouddms/v1alpha1/privateconnection_reference.go b/apis/clouddms/v1alpha1/privateconnection_reference.go
new file mode 100644
index 00000000000..bbd9b3dd4ea
--- /dev/null
+++ b/apis/clouddms/v1alpha1/privateconnection_reference.go
@@ -0,0 +1,83 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package v1alpha1
+
+import (
+	"context"
+	"fmt"
+
+	refsv1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
+	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s"
+	apierrors "k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/apimachinery/pkg/types"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+)
+
+var _ refsv1beta1.ExternalNormalizer = &PrivateConnectionRef{}
+
+// PrivateConnectionRef defines the resource reference to CloudDMSPrivateConnection, which "External" field
+// holds the GCP identifier for the KRM object.
+type PrivateConnectionRef struct {
+	// A reference to an externally managed CloudDMSPrivateConnection resource.
+	// Should be in the format "projects/{{projectID}}/locations/{{location}}/privateconnections/{{privateconnectionID}}".
+	External string `json:"external,omitempty"`
+
+	// The name of a CloudDMSPrivateConnection resource.
+	Name string `json:"name,omitempty"`
+
+	// The namespace of a CloudDMSPrivateConnection resource.
+	Namespace string `json:"namespace,omitempty"`
+}
+
+// NormalizedExternal provision the "External" value for other resource that depends on CloudDMSPrivateConnection.
+// If the "External" is given in the other resource's spec.CloudDMSPrivateConnectionRef, the given value will be used.
+// Otherwise, the "Name" and "Namespace" will be used to query the actual CloudDMSPrivateConnection object from the cluster.
+func (r *PrivateConnectionRef) NormalizedExternal(ctx context.Context, reader client.Reader, otherNamespace string) (string, error) {
+	if r.External != "" && r.Name != "" {
+		return "", fmt.Errorf("cannot specify both name and external on %s reference", CloudDMSPrivateConnectionGVK.Kind)
+	}
+	// From given External
+	if r.External != "" {
+		if _, _, err := ParsePrivateConnectionExternal(r.External); err != nil {
+			return "", err
+		}
+		return r.External, nil
+	}
+
+	// From the Config Connector object
+	if r.Namespace == "" {
+		r.Namespace = otherNamespace
+	}
+	key := types.NamespacedName{Name: r.Name, Namespace: r.Namespace}
+	u := &unstructured.Unstructured{}
+	u.SetGroupVersionKind(CloudDMSPrivateConnectionGVK)
+	if err := reader.Get(ctx, key, u); err != nil {
+		if apierrors.IsNotFound(err) {
+			return "", k8s.NewReferenceNotFoundError(u.GroupVersionKind(), key)
+		}
+		return "", fmt.Errorf("reading referenced %s %s: %w", CloudDMSPrivateConnectionGVK, key, err)
+	}
+	// Get external from status.externalRef. This is the most trustworthy place.
+	actualExternalRef, _, err := unstructured.NestedString(u.Object, "status", "externalRef")
+	if err != nil {
+		return "", fmt.Errorf("reading status.externalRef: %w", err)
+	}
+	if actualExternalRef == "" {
+		return "", k8s.NewReferenceNotReadyError(u.GroupVersionKind(), key)
+	}
+	r.External = actualExternalRef
+	return r.External, nil
+}
diff --git a/apis/clouddms/v1alpha1/privateconnection_types.go b/apis/clouddms/v1alpha1/privateconnection_types.go
new file mode 100644
index 00000000000..b70ad81a60c
--- /dev/null
+++ b/apis/clouddms/v1alpha1/privateconnection_types.go
@@ -0,0 +1,196 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package v1alpha1
+
+import (
+	refs "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
+	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/k8s/v1alpha1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+var CloudDMSPrivateConnectionGVK = GroupVersion.WithKind("CloudDMSPrivateConnection")
+
+type Parent struct {
+	// Required. The location of the application.
+	Location string `json:"location,omitempty"`
+
+	// Required. The host project of the application.
+	ProjectRef *refs.ProjectRef `json:"projectRef,omitempty"`
+}
+
+// +kcc:proto=google.protobuf.Any
+type Any struct {
+	// A URL/resource name that uniquely identifies the type of the serialized
+	//  protocol buffer message. This string must contain at least
+	//  one "/" character. The last segment of the URL's path must represent
+	//  the fully qualified name of the type (as in
+	//  `path/google.protobuf.Duration`). The name should be in a canonical form
+	//  (e.g., leading "." is not accepted).
+	//
+	//  In practice, teams usually precompile into the binary all types that they
+	//  expect it to use in the context of Any. However, for URLs which use the
+	//  scheme `http`, `https`, or no scheme, one can optionally set up a type
+	//  server that maps type URLs to message definitions as follows:
+	//
+	//  * If no scheme is provided, `https` is assumed.
+	//  * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+	//    value in binary format, or produce an error.
+	//  * Applications are allowed to cache lookup results based on the
+	//    URL, or have them precompiled into a binary to avoid any
+	//    lookup. Therefore, binary compatibility needs to be preserved
+	//    on changes to types. (Use versioned type names to manage
+	//    breaking changes.)
+	//
+	//  Note: this functionality is not currently available in the official
+	//  protobuf release, and it is not used for type URLs beginning with
+	//  type.googleapis.com.
+	//
+	//  Schemes other than `http`, `https` (or the empty scheme) might be
+	//  used with implementation specific semantics.
+	// +kcc:proto:field=google.protobuf.Any.type_url
+	TypeURL *string `json:"typeURL,omitempty"`
+
+	// Must be a valid serialized protocol buffer of the above specified type.
+	// +kcc:proto:field=google.protobuf.Any.value
+	Value []byte `json:"value,omitempty"`
+}
+
+// +kcc:proto=google.rpc.Status
+type Status struct {
+	// The status code, which should be an enum value of
+	//  [google.rpc.Code][google.rpc.Code].
+	// +kcc:proto:field=google.rpc.Status.code
+	Code *int32 `json:"code,omitempty"`
+
+	// A developer-facing error message, which should be in English. Any
+	//  user-facing error message should be localized and sent in the
+	//  [google.rpc.Status.details][google.rpc.Status.details] field, or localized
+	//  by the client.
+	// +kcc:proto:field=google.rpc.Status.message
+	Message *string `json:"message,omitempty"`
+
+	// NOT YET
+	// A list of messages that carry the error details.  There is a common set of
+	//  message types for APIs to use.
+	// +kcc:proto:field=google.rpc.Status.details
+	// Details []Any `json:"details,omitempty"`
+}
+
+// +kcc:proto=google.cloud.clouddms.v1.VpcPeeringConfig
+type VpcPeeringConfig struct {
+	// Required. Fully qualified name of the VPC that Database Migration Service
+	//  will peer to.
+	// +kcc:proto:field=google.cloud.clouddms.v1.VpcPeeringConfig.vpc_name
+	VpcNameRef *refs.ComputeNetworkRef `json:"vpcNameRef,omitempty"`
+
+	// Required. A free subnet for peering. (CIDR of /29)
+	// +kcc:proto:field=google.cloud.clouddms.v1.VpcPeeringConfig.subnet
+	Subnet *string `json:"subnet,omitempty"`
+}
+
+// CloudDMSPrivateConnectionStatus defines the config connector machine state of CloudDMSPrivateConnection
+type CloudDMSPrivateConnectionStatus struct {
+	/* Conditions represent the latest available observations of the
+	   object's current state. */
+	Conditions []v1alpha1.Condition `json:"conditions,omitempty"`
+
+	// ObservedGeneration is the generation of the resource that was most recently observed by the Config Connector controller. If this is equal to metadata.generation, then that means that the current reported status reflects the most recent desired state of the resource.
+	ObservedGeneration *int64 `json:"observedGeneration,omitempty"`
+
+	// A unique specifier for the CloudDMSPrivateConnection resource in GCP.
+	ExternalRef *string `json:"externalRef,omitempty"`
+
+	// ObservedState is the state of the resource as most recently observed in GCP.
+	ObservedState *CloudDMSPrivateConnectionObservedState `json:"observedState,omitempty"`
+}
+
+// CloudDMSPrivateConnectionSpec defines the desired state of CloudDMSPrivateConnection
+// +kcc:proto=google.cloud.clouddms.v1.PrivateConnection
+type CloudDMSPrivateConnectionSpec struct {
+	// The CloudDMSPrivateConnection name. If not given, the metadata.name will be used.
+	ResourceID *string `json:"resourceID,omitempty"`
+
+	// Required. Defines the parent path of the resource.
+	*Parent `json:",inline"`
+
+	// The resource labels for private connections to use to annotate any related
+	//  underlying resources such as Compute Engine VMs. An object containing a
+	//  list of "key": "value" pairs.
+	//
+	//  Example: `{ "name": "wrench", "mass": "1.3kg", "count": "3" }`.
+	// +kcc:proto:field=google.cloud.clouddms.v1.PrivateConnection.labels
+	Labels map[string]string `json:"labels,omitempty"`
+
+	// The private connection display name.
+	// +kcc:proto:field=google.cloud.clouddms.v1.PrivateConnection.display_name
+	DisplayName *string `json:"displayName,omitempty"`
+
+	// VPC peering configuration.
+	// +kcc:proto:field=google.cloud.clouddms.v1.PrivateConnection.vpc_peering_config
+	VpcPeeringConfig *VpcPeeringConfig `json:"vpcPeeringConfig,omitempty"`
+}
+
+// CloudDMSPrivateConnectionObservedState is the state of the CloudDMSPrivateConnection resource as most recently observed in GCP.
+// +kcc:proto=google.cloud.clouddms.v1.PrivateConnection
+type CloudDMSPrivateConnectionObservedState struct {
+	// Output only. The create time of the resource.
+	// +kcc:proto:field=google.cloud.clouddms.v1.PrivateConnection.create_time
+	CreateTime *string `json:"createTime,omitempty"`
+
+	// Output only. The last update time of the resource.
+	// +kcc:proto:field=google.cloud.clouddms.v1.PrivateConnection.update_time
+	UpdateTime *string `json:"updateTime,omitempty"`
+
+	// Output only. The state of the private connection.
+	// +kcc:proto:field=google.cloud.clouddms.v1.PrivateConnection.state
+	State *string `json:"state,omitempty"`
+
+	// Output only. The error details in case of state FAILED.
+	// +kcc:proto:field=google.cloud.clouddms.v1.PrivateConnection.error
+	Error *Status `json:"error,omitempty"`
+}
+
+// +genclient
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// +kubebuilder:resource:categories=gcp,shortName=gcpclouddmsprivateconnection;gcpclouddmsprivateconnections
+// +kubebuilder:subresource:status
+// +kubebuilder:metadata:labels="cnrm.cloud.google.com/managed-by-kcc=true";"cnrm.cloud.google.com/system=true"
+// +kubebuilder:printcolumn:name="Age",JSONPath=".metadata.creationTimestamp",type="date"
+// +kubebuilder:printcolumn:name="Ready",JSONPath=".status.conditions[?(@.type=='Ready')].status",type="string",description="When 'True', the most recent reconcile of the resource succeeded"
+// +kubebuilder:printcolumn:name="Status",JSONPath=".status.conditions[?(@.type=='Ready')].reason",type="string",description="The reason for the value in 'Ready'"
+// +kubebuilder:printcolumn:name="Status Age",JSONPath=".status.conditions[?(@.type=='Ready')].lastTransitionTime",type="date",description="The last transition time for the value in 'Status'"
+
+// CloudDMSPrivateConnection is the Schema for the CloudDMSPrivateConnection API
+// +k8s:openapi-gen=true
+type CloudDMSPrivateConnection struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+
+	// +required
+	Spec   CloudDMSPrivateConnectionSpec   `json:"spec,omitempty"`
+	Status CloudDMSPrivateConnectionStatus `json:"status,omitempty"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// CloudDMSPrivateConnectionList contains a list of CloudDMSPrivateConnection
+type CloudDMSPrivateConnectionList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+	Items           []CloudDMSPrivateConnection `json:"items"`
+}
+
+func init() {
+	SchemeBuilder.Register(&CloudDMSPrivateConnection{}, &CloudDMSPrivateConnectionList{})
+}
diff --git a/apis/clouddms/v1alpha1/zz_generated.deepcopy.go b/apis/clouddms/v1alpha1/zz_generated.deepcopy.go
index 361e199bbd2..7b795186f20 100644
--- a/apis/clouddms/v1alpha1/zz_generated.deepcopy.go
+++ b/apis/clouddms/v1alpha1/zz_generated.deepcopy.go
@@ -24,6 +24,31 @@ import (
 	runtime "k8s.io/apimachinery/pkg/runtime"
 )
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Any) DeepCopyInto(out *Any) {
+	*out = *in
+	if in.TypeURL != nil {
+		in, out := &in.TypeURL, &out.TypeURL
+		*out = new(string)
+		**out = **in
+	}
+	if in.Value != nil {
+		in, out := &in.Value, &out.Value
+		*out = make([]byte, len(*in))
+		copy(*out, *in)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Any.
+func (in *Any) DeepCopy() *Any {
+	if in == nil {
+		return nil
+	}
+	out := new(Any)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *CloudDMSConversionWorkspace) DeepCopyInto(out *CloudDMSConversionWorkspace) {
 	*out = *in
@@ -205,6 +230,177 @@ func (in *CloudDMSConversionWorkspaceStatus) DeepCopy() *CloudDMSConversionWorks
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *CloudDMSPrivateConnection) DeepCopyInto(out *CloudDMSPrivateConnection) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	in.Status.DeepCopyInto(&out.Status)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CloudDMSPrivateConnection.
+func (in *CloudDMSPrivateConnection) DeepCopy() *CloudDMSPrivateConnection {
+	if in == nil {
+		return nil
+	}
+	out := new(CloudDMSPrivateConnection)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *CloudDMSPrivateConnection) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *CloudDMSPrivateConnectionList) DeepCopyInto(out *CloudDMSPrivateConnectionList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]CloudDMSPrivateConnection, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CloudDMSPrivateConnectionList.
+func (in *CloudDMSPrivateConnectionList) DeepCopy() *CloudDMSPrivateConnectionList {
+	if in == nil {
+		return nil
+	}
+	out := new(CloudDMSPrivateConnectionList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *CloudDMSPrivateConnectionList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *CloudDMSPrivateConnectionObservedState) DeepCopyInto(out *CloudDMSPrivateConnectionObservedState) {
+	*out = *in
+	if in.CreateTime != nil {
+		in, out := &in.CreateTime, &out.CreateTime
+		*out = new(string)
+		**out = **in
+	}
+	if in.UpdateTime != nil {
+		in, out := &in.UpdateTime, &out.UpdateTime
+		*out = new(string)
+		**out = **in
+	}
+	if in.State != nil {
+		in, out := &in.State, &out.State
+		*out = new(string)
+		**out = **in
+	}
+	if in.Error != nil {
+		in, out := &in.Error, &out.Error
+		*out = new(Status)
+		(*in).DeepCopyInto(*out)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CloudDMSPrivateConnectionObservedState.
+func (in *CloudDMSPrivateConnectionObservedState) DeepCopy() *CloudDMSPrivateConnectionObservedState {
+	if in == nil {
+		return nil
+	}
+	out := new(CloudDMSPrivateConnectionObservedState)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *CloudDMSPrivateConnectionSpec) DeepCopyInto(out *CloudDMSPrivateConnectionSpec) {
+	*out = *in
+	if in.ResourceID != nil {
+		in, out := &in.ResourceID, &out.ResourceID
+		*out = new(string)
+		**out = **in
+	}
+	if in.Parent != nil {
+		in, out := &in.Parent, &out.Parent
+		*out = new(Parent)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Labels != nil {
+		in, out := &in.Labels, &out.Labels
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+	if in.DisplayName != nil {
+		in, out := &in.DisplayName, &out.DisplayName
+		*out = new(string)
+		**out = **in
+	}
+	if in.VpcPeeringConfig != nil {
+		in, out := &in.VpcPeeringConfig, &out.VpcPeeringConfig
+		*out = new(VpcPeeringConfig)
+		(*in).DeepCopyInto(*out)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CloudDMSPrivateConnectionSpec.
+func (in *CloudDMSPrivateConnectionSpec) DeepCopy() *CloudDMSPrivateConnectionSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(CloudDMSPrivateConnectionSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *CloudDMSPrivateConnectionStatus) DeepCopyInto(out *CloudDMSPrivateConnectionStatus) {
+	*out = *in
+	if in.Conditions != nil {
+		in, out := &in.Conditions, &out.Conditions
+		*out = make([]k8sv1alpha1.Condition, len(*in))
+		copy(*out, *in)
+	}
+	if in.ObservedGeneration != nil {
+		in, out := &in.ObservedGeneration, &out.ObservedGeneration
+		*out = new(int64)
+		**out = **in
+	}
+	if in.ExternalRef != nil {
+		in, out := &in.ExternalRef, &out.ExternalRef
+		*out = new(string)
+		**out = **in
+	}
+	if in.ObservedState != nil {
+		in, out := &in.ObservedState, &out.ObservedState
+		*out = new(CloudDMSPrivateConnectionObservedState)
+		(*in).DeepCopyInto(*out)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CloudDMSPrivateConnectionStatus.
+func (in *CloudDMSPrivateConnectionStatus) DeepCopy() *CloudDMSPrivateConnectionStatus {
+	if in == nil {
+		return nil
+	}
+	out := new(CloudDMSPrivateConnectionStatus)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *ConversionWorkspaceIdentity) DeepCopyInto(out *ConversionWorkspaceIdentity) {
 	*out = *in
@@ -279,3 +475,123 @@ func (in *DatabaseEngineInfo) DeepCopy() *DatabaseEngineInfo {
 	in.DeepCopyInto(out)
 	return out
 }
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Parent) DeepCopyInto(out *Parent) {
+	*out = *in
+	if in.ProjectRef != nil {
+		in, out := &in.ProjectRef, &out.ProjectRef
+		*out = new(v1beta1.ProjectRef)
+		**out = **in
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Parent.
+func (in *Parent) DeepCopy() *Parent {
+	if in == nil {
+		return nil
+	}
+	out := new(Parent)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PrivateConnectionIdentity) DeepCopyInto(out *PrivateConnectionIdentity) {
+	*out = *in
+	if in.parent != nil {
+		in, out := &in.parent, &out.parent
+		*out = new(PrivateConnectionParent)
+		**out = **in
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateConnectionIdentity.
+func (in *PrivateConnectionIdentity) DeepCopy() *PrivateConnectionIdentity {
+	if in == nil {
+		return nil
+	}
+	out := new(PrivateConnectionIdentity)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PrivateConnectionParent) DeepCopyInto(out *PrivateConnectionParent) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateConnectionParent.
+func (in *PrivateConnectionParent) DeepCopy() *PrivateConnectionParent {
+	if in == nil {
+		return nil
+	}
+	out := new(PrivateConnectionParent)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PrivateConnectionRef) DeepCopyInto(out *PrivateConnectionRef) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateConnectionRef.
+func (in *PrivateConnectionRef) DeepCopy() *PrivateConnectionRef {
+	if in == nil {
+		return nil
+	}
+	out := new(PrivateConnectionRef)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Status) DeepCopyInto(out *Status) {
+	*out = *in
+	if in.Code != nil {
+		in, out := &in.Code, &out.Code
+		*out = new(int32)
+		**out = **in
+	}
+	if in.Message != nil {
+		in, out := &in.Message, &out.Message
+		*out = new(string)
+		**out = **in
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Status.
+func (in *Status) DeepCopy() *Status {
+	if in == nil {
+		return nil
+	}
+	out := new(Status)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *VpcPeeringConfig) DeepCopyInto(out *VpcPeeringConfig) {
+	*out = *in
+	if in.VpcNameRef != nil {
+		in, out := &in.VpcNameRef, &out.VpcNameRef
+		*out = new(v1beta1.ComputeNetworkRef)
+		**out = **in
+	}
+	if in.Subnet != nil {
+		in, out := &in.Subnet, &out.Subnet
+		*out = new(string)
+		**out = **in
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VpcPeeringConfig.
+func (in *VpcPeeringConfig) DeepCopy() *VpcPeeringConfig {
+	if in == nil {
+		return nil
+	}
+	out := new(VpcPeeringConfig)
+	in.DeepCopyInto(out)
+	return out
+}
diff --git a/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_clouddmsprivateconnections.clouddms.cnrm.cloud.google.com.yaml b/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_clouddmsprivateconnections.clouddms.cnrm.cloud.google.com.yaml
new file mode 100644
index 00000000000..f6a05ee3639
--- /dev/null
+++ b/config/crds/resources/apiextensions.k8s.io_v1_customresourcedefinition_clouddmsprivateconnections.clouddms.cnrm.cloud.google.com.yaml
@@ -0,0 +1,231 @@
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  annotations:
+    cnrm.cloud.google.com/version: 0.0.0-dev
+  creationTimestamp: null
+  labels:
+    cnrm.cloud.google.com/managed-by-kcc: "true"
+    cnrm.cloud.google.com/system: "true"
+  name: clouddmsprivateconnections.clouddms.cnrm.cloud.google.com
+spec:
+  group: clouddms.cnrm.cloud.google.com
+  names:
+    categories:
+    - gcp
+    kind: CloudDMSPrivateConnection
+    listKind: CloudDMSPrivateConnectionList
+    plural: clouddmsprivateconnections
+    shortNames:
+    - gcpclouddmsprivateconnection
+    - gcpclouddmsprivateconnections
+    singular: clouddmsprivateconnection
+  preserveUnknownFields: false
+  scope: Namespaced
+  versions:
+  - additionalPrinterColumns:
+    - jsonPath: .metadata.creationTimestamp
+      name: Age
+      type: date
+    - description: When 'True', the most recent reconcile of the resource succeeded
+      jsonPath: .status.conditions[?(@.type=='Ready')].status
+      name: Ready
+      type: string
+    - description: The reason for the value in 'Ready'
+      jsonPath: .status.conditions[?(@.type=='Ready')].reason
+      name: Status
+      type: string
+    - description: The last transition time for the value in 'Status'
+      jsonPath: .status.conditions[?(@.type=='Ready')].lastTransitionTime
+      name: Status Age
+      type: date
+    name: v1alpha1
+    schema:
+      openAPIV3Schema:
+        description: CloudDMSPrivateConnection is the Schema for the CloudDMSPrivateConnection
+          API
+        properties:
+          apiVersion:
+            description: 'APIVersion defines the versioned schema of this representation
+              of an object. Servers should convert recognized schemas to the latest
+              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            type: string
+          kind:
+            description: 'Kind is a string value representing the REST resource this
+              object represents. Servers may infer this from the endpoint the client
+              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            type: string
+          metadata:
+            type: object
+          spec:
+            description: CloudDMSPrivateConnectionSpec defines the desired state of
+              CloudDMSPrivateConnection
+            properties:
+              displayName:
+                description: The private connection display name.
+                type: string
+              labels:
+                additionalProperties:
+                  type: string
+                description: |-
+                  The resource labels for private connections to use to annotate any related
+                   underlying resources such as Compute Engine VMs. An object containing a
+                   list of "key": "value" pairs.
+
+                   Example: `{ "name": "wrench", "mass": "1.3kg", "count": "3" }`.
+                type: object
+              location:
+                description: Required. The location of the application.
+                type: string
+              projectRef:
+                description: Required. The host project of the application.
+                oneOf:
+                - not:
+                    required:
+                    - external
+                  required:
+                  - name
+                - not:
+                    anyOf:
+                    - required:
+                      - name
+                    - required:
+                      - namespace
+                  required:
+                  - external
+                properties:
+                  external:
+                    description: The `projectID` field of a project, when not managed
+                      by Config Connector.
+                    type: string
+                  kind:
+                    description: The kind of the Project resource; optional but must
+                      be `Project` if provided.
+                    type: string
+                  name:
+                    description: The `name` field of a `Project` resource.
+                    type: string
+                  namespace:
+                    description: The `namespace` field of a `Project` resource.
+                    type: string
+                type: object
+              resourceID:
+                description: The CloudDMSPrivateConnection name. If not given, the
+                  metadata.name will be used.
+                type: string
+              vpcPeeringConfig:
+                description: VPC peering configuration.
+                properties:
+                  subnet:
+                    description: Required. A free subnet for peering. (CIDR of /29)
+                    type: string
+                  vpcNameRef:
+                    description: Required. Fully qualified name of the VPC that Database
+                      Migration Service will peer to.
+                    oneOf:
+                    - not:
+                        required:
+                        - external
+                      required:
+                      - name
+                    - not:
+                        anyOf:
+                        - required:
+                          - name
+                        - required:
+                          - namespace
+                      required:
+                      - external
+                    properties:
+                      external:
+                        description: A reference to an externally managed Compute
+                          Network resource. Should be in the format `projects/{{projectID}}/global/networks/{{network}}`.
+                        type: string
+                      name:
+                        description: The `name` field of a `ComputeNetwork` resource.
+                        type: string
+                      namespace:
+                        description: The `namespace` field of a `ComputeNetwork` resource.
+                        type: string
+                    type: object
+                type: object
+            type: object
+          status:
+            description: CloudDMSPrivateConnectionStatus defines the config connector
+              machine state of CloudDMSPrivateConnection
+            properties:
+              conditions:
+                description: Conditions represent the latest available observations
+                  of the object's current state.
+                items:
+                  properties:
+                    lastTransitionTime:
+                      description: Last time the condition transitioned from one status
+                        to another.
+                      type: string
+                    message:
+                      description: Human-readable message indicating details about
+                        last transition.
+                      type: string
+                    reason:
+                      description: Unique, one-word, CamelCase reason for the condition's
+                        last transition.
+                      type: string
+                    status:
+                      description: Status is the status of the condition. Can be True,
+                        False, Unknown.
+                      type: string
+                    type:
+                      description: Type is the type of the condition.
+                      type: string
+                  type: object
+                type: array
+              externalRef:
+                description: A unique specifier for the CloudDMSPrivateConnection
+                  resource in GCP.
+                type: string
+              observedGeneration:
+                description: ObservedGeneration is the generation of the resource
+                  that was most recently observed by the Config Connector controller.
+                  If this is equal to metadata.generation, then that means that the
+                  current reported status reflects the most recent desired state of
+                  the resource.
+                format: int64
+                type: integer
+              observedState:
+                description: ObservedState is the state of the resource as most recently
+                  observed in GCP.
+                properties:
+                  createTime:
+                    description: Output only. The create time of the resource.
+                    type: string
+                  error:
+                    description: Output only. The error details in case of state FAILED.
+                    properties:
+                      code:
+                        description: The status code, which should be an enum value
+                          of [google.rpc.Code][google.rpc.Code].
+                        format: int32
+                        type: integer
+                      message:
+                        description: A developer-facing error message, which should
+                          be in English. Any user-facing error message should be localized
+                          and sent in the [google.rpc.Status.details][google.rpc.Status.details]
+                          field, or localized by the client.
+                        type: string
+                    type: object
+                  state:
+                    description: Output only. The state of the private connection.
+                    type: string
+                  updateTime:
+                    description: Output only. The last update time of the resource.
+                    type: string
+                type: object
+            type: object
+        required:
+        - spec
+        type: object
+    served: true
+    storage: true
+    subresources:
+      status: {}
diff --git a/pkg/controller/direct/clouddms/privateconnection_fuzzer.go b/pkg/controller/direct/clouddms/privateconnection_fuzzer.go
new file mode 100644
index 00000000000..352c4039df4
--- /dev/null
+++ b/pkg/controller/direct/clouddms/privateconnection_fuzzer.go
@@ -0,0 +1,49 @@
+// Copyright 2024 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +tool:fuzz-gen
+// proto.message: google.cloud.clouddms.v1.PrivateConnection
+// api.group: clouddms.cnrm.cloud.google.com
+
+package clouddms
+
+import (
+	pb "cloud.google.com/go/clouddms/apiv1/clouddmspb"
+	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/fuzztesting"
+)
+
+func init() {
+	fuzztesting.RegisterKRMFuzzer(cloudDMSPrivateConnectionFuzzer())
+}
+
+func cloudDMSPrivateConnectionFuzzer() fuzztesting.KRMFuzzer {
+	f := fuzztesting.NewKRMTypedFuzzer(&pb.PrivateConnection{},
+		CloudDMSPrivateConnectionSpec_FromProto, CloudDMSPrivateConnectionSpec_ToProto,
+		CloudDMSPrivateConnectionObservedState_FromProto, CloudDMSPrivateConnectionObservedState_ToProto,
+	)
+
+	f.SpecFields.Insert(".labels")
+	f.SpecFields.Insert(".display_name")
+	f.SpecFields.Insert(".vpc_peering_config")
+
+	f.StatusFields.Insert(".create_time")
+	f.StatusFields.Insert(".update_time")
+	f.StatusFields.Insert(".state")
+	f.StatusFields.Insert(".error")
+
+	f.UnimplementedFields.Insert(".name")          // special field
+	f.UnimplementedFields.Insert(".error.details") // NOTYET
+
+	return f
+}
diff --git a/pkg/controller/direct/clouddms/privateconnection_mapper.go b/pkg/controller/direct/clouddms/privateconnection_mapper.go
new file mode 100644
index 00000000000..9c45e49c6b3
--- /dev/null
+++ b/pkg/controller/direct/clouddms/privateconnection_mapper.go
@@ -0,0 +1,120 @@
+// Copyright 2025 Google LLC
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +generated:mapper
+// krm.group: clouddms.cnrm.cloud.google.com
+// krm.version: v1alpha1
+// proto.service: google.cloud.clouddms.v1
+
+package clouddms
+
+import (
+	pb "cloud.google.com/go/clouddms/apiv1/clouddmspb"
+	krm "github.com/GoogleCloudPlatform/k8s-config-connector/apis/clouddms/v1alpha1"
+	refsv1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
+	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct"
+	status "google.golang.org/genproto/googleapis/rpc/status"
+)
+
+func CloudDMSPrivateConnectionObservedState_FromProto(mapCtx *direct.MapContext, in *pb.PrivateConnection) *krm.CloudDMSPrivateConnectionObservedState {
+	if in == nil {
+		return nil
+	}
+	out := &krm.CloudDMSPrivateConnectionObservedState{}
+	// MISSING: Name
+	out.CreateTime = direct.StringTimestamp_FromProto(mapCtx, in.GetCreateTime())
+	out.UpdateTime = direct.StringTimestamp_FromProto(mapCtx, in.GetUpdateTime())
+	out.State = direct.Enum_FromProto(mapCtx, in.GetState())
+	out.Error = CloudDMSPrivateConnectionStatus_FromProto(mapCtx, in.Error)
+	return out
+}
+func CloudDMSPrivateConnectionObservedState_ToProto(mapCtx *direct.MapContext, in *krm.CloudDMSPrivateConnectionObservedState) *pb.PrivateConnection {
+	if in == nil {
+		return nil
+	}
+	out := &pb.PrivateConnection{}
+	// MISSING: Name
+	out.CreateTime = direct.StringTimestamp_ToProto(mapCtx, in.CreateTime)
+	out.UpdateTime = direct.StringTimestamp_ToProto(mapCtx, in.UpdateTime)
+	out.State = direct.Enum_ToProto[pb.PrivateConnection_State](mapCtx, in.State)
+	out.Error = CloudDMSPrivateConnectionStatus_ToProto(mapCtx, in.Error)
+	return out
+}
+func CloudDMSPrivateConnectionSpec_FromProto(mapCtx *direct.MapContext, in *pb.PrivateConnection) *krm.CloudDMSPrivateConnectionSpec {
+	if in == nil {
+		return nil
+	}
+	out := &krm.CloudDMSPrivateConnectionSpec{}
+	// MISSING: Name
+	out.Labels = in.Labels
+	out.DisplayName = direct.LazyPtr(in.GetDisplayName())
+	out.VpcPeeringConfig = VpcPeeringConfig_FromProto(mapCtx, in.GetVpcPeeringConfig())
+	return out
+}
+func CloudDMSPrivateConnectionSpec_ToProto(mapCtx *direct.MapContext, in *krm.CloudDMSPrivateConnectionSpec) *pb.PrivateConnection {
+	if in == nil {
+		return nil
+	}
+	out := &pb.PrivateConnection{}
+	// MISSING: Name
+	out.Labels = in.Labels
+	out.DisplayName = direct.ValueOf(in.DisplayName)
+	if oneof := VpcPeeringConfig_ToProto(mapCtx, in.VpcPeeringConfig); oneof != nil {
+		out.Connectivity = &pb.PrivateConnection_VpcPeeringConfig{VpcPeeringConfig: oneof}
+	}
+	return out
+}
+func VpcPeeringConfig_FromProto(mapCtx *direct.MapContext, in *pb.VpcPeeringConfig) *krm.VpcPeeringConfig {
+	if in == nil {
+		return nil
+	}
+	out := &krm.VpcPeeringConfig{}
+	if in.GetVpcName() != "" {
+		out.VpcNameRef = &refsv1beta1.ComputeNetworkRef{External: in.GetVpcName()}
+	}
+	out.Subnet = direct.LazyPtr(in.GetSubnet())
+	return out
+}
+func VpcPeeringConfig_ToProto(mapCtx *direct.MapContext, in *krm.VpcPeeringConfig) *pb.VpcPeeringConfig {
+	if in == nil {
+		return nil
+	}
+	out := &pb.VpcPeeringConfig{}
+	if in.VpcNameRef != nil {
+		out.VpcName = in.VpcNameRef.External
+	}
+	out.Subnet = direct.ValueOf(in.Subnet)
+	return out
+}
+
+func CloudDMSPrivateConnectionStatus_ToProto(mapCtx *direct.MapContext, in *krm.Status) *status.Status {
+	if in == nil {
+		return nil
+	}
+	out := &status.Status{}
+	out.Code = direct.ValueOf(in.Code)
+	out.Message = direct.ValueOf(in.Message)
+	return out
+}
+
+func CloudDMSPrivateConnectionStatus_FromProto(mapCtx *direct.MapContext, in *status.Status) *krm.Status {
+	if in == nil {
+		return nil
+	}
+	out := &krm.Status{}
+	out.Code = direct.LazyPtr(in.Code)
+	out.Message = direct.LazyPtr(in.Message)
+	return out
+}
diff --git a/pkg/gvks/supportedgvks/gvks_generated.go b/pkg/gvks/supportedgvks/gvks_generated.go
index 8dcd0d87f96..1cb84189257 100644
--- a/pkg/gvks/supportedgvks/gvks_generated.go
+++ b/pkg/gvks/supportedgvks/gvks_generated.go
@@ -1164,6 +1164,16 @@ var SupportedGVKs = map[schema.GroupVersionKind]GVKMetadata{
 			"cnrm.cloud.google.com/system":         "true",
 		},
 	},
+	{
+		Group:   "clouddms.cnrm.cloud.google.com",
+		Version: "v1alpha1",
+		Kind:    "CloudDMSPrivateConnection",
+	}: {
+		Labels: map[string]string{
+			"cnrm.cloud.google.com/managed-by-kcc": "true",
+			"cnrm.cloud.google.com/system":         "true",
+		},
+	},
 	{
 		Group:   "cloudfunctions2.cnrm.cloud.google.com",
 		Version: "v1alpha1",


Reviews:
user: login: yuwenma
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T02:55:07Z
user: login: anhdle-sso
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T05:25:01Z
user: login: anhdle-sso
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-11T05:26:43Z
user: login: jingyih
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T09:11:05Z
user: login: anhdle-sso
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-17T21:40:18Z
user: login: justinsb
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-17T21:59:24Z

Review comments:
diff_hunk: @@ -0,0 +1,196 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package v1alpha1
+
+import (
+	refs "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
+	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/k8s/v1alpha1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+var CloudDMSPrivateConnectionGVK = GroupVersion.WithKind("CloudDMSPrivateConnection")
+
+type Parent struct {
+	// Required. The location of the application.
+	Location string `json:"location,omitempty"`
+
+	// Required. The host project of the application.
+	ProjectRef *refs.ProjectRef `json:"projectRef,omitempty"`
+}
+
+// +kcc:proto=google.protobuf.Any
+type Any struct {
+	// A URL/resource name that uniquely identifies the type of the serialized
+	//  protocol buffer message. This string must contain at least
+	//  one "/" character. The last segment of the URL's path must represent
+	//  the fully qualified name of the type (as in
+	//  `path/google.protobuf.Duration`). The name should be in a canonical form
+	//  (e.g., leading "." is not accepted).
+	//
+	//  In practice, teams usually precompile into the binary all types that they
+	//  expect it to use in the context of Any. However, for URLs which use the
+	//  scheme `http`, `https`, or no scheme, one can optionally set up a type
+	//  server that maps type URLs to message definitions as follows:
+	//
+	//  * If no scheme is provided, `https` is assumed.
+	//  * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+	//    value in binary format, or produce an error.
+	//  * Applications are allowed to cache lookup results based on the
+	//    URL, or have them precompiled into a binary to avoid any
+	//    lookup. Therefore, binary compatibility needs to be preserved
+	//    on changes to types. (Use versioned type names to manage
+	//    breaking changes.)
+	//
+	//  Note: this functionality is not currently available in the official
+	//  protobuf release, and it is not used for type URLs beginning with
+	//  type.googleapis.com.
+	//
+	//  Schemes other than `http`, `https` (or the empty scheme) might be
+	//  used with implementation specific semantics.
+	// +kcc:proto:field=google.protobuf.Any.type_url
+	TypeURL *string `json:"typeURL,omitempty"`
+
+	// Must be a valid serialized protocol buffer of the above specified type.
+	// +kcc:proto:field=google.protobuf.Any.value
+	Value []byte `json:"value,omitempty"`
+}
+
+// +kcc:proto=google.rpc.Status
+type Status struct {
+	// The status code, which should be an enum value of
+	//  [google.rpc.Code][google.rpc.Code].
+	// +kcc:proto:field=google.rpc.Status.code
+	Code *int32 `json:"code,omitempty"`
+
+	// A developer-facing error message, which should be in English. Any
+	//  user-facing error message should be localized and sent in the
+	//  [google.rpc.Status.details][google.rpc.Status.details] field, or localized
+	//  by the client.
+	// +kcc:proto:field=google.rpc.Status.message
+	Message *string `json:"message,omitempty"`
+
+	// NOT YET
+	// A list of messages that carry the error details.  There is a common set of
+	//  message types for APIs to use.
+	// +kcc:proto:field=google.rpc.Status.details
+	// Details []Any `json:"details,omitempty"`
+}
+
+// +kcc:proto=google.cloud.clouddms.v1.VpcPeeringConfig
+type VpcPeeringConfig struct {
+	// Required. Fully qualified name of the VPC that Database Migration Service
+	//  will peer to.
+	// +kcc:proto:field=google.cloud.clouddms.v1.VpcPeeringConfig.vpc_name
+	VpcName *refs.ComputeNetworkRef `json:"vpcName,omitempty"`
+
+	// Required. A free subnet for peering. (CIDR of /29)
+	// +kcc:proto:field=google.cloud.clouddms.v1.VpcPeeringConfig.subnet
+	Subnet *string `json:"subnet,omitempty"`
path: apis/clouddms/v1alpha1/privateconnection_types.go
user: login: yuwenma
body: suggest changing this to a reference of Subnetwork  
created_at: 2025-04-11T02:54:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -19,6 +19,7 @@
 [refs] crd=billingbudgetsbudgets.billingbudgets.cnrm.cloud.google.com version=v1beta1: field ".spec.budgetFilter.projects[].external" should be a reference
 [refs] crd=binaryauthorizationpolicies.binaryauthorization.cnrm.cloud.google.com version=v1beta1: field ".spec.defaultAdmissionRule.requireAttestationsBy[].external" should be a reference
 [refs] crd=cloudbuildtriggers.cloudbuild.cnrm.cloud.google.com version=v1beta1: field ".spec.build.options.workerPool" should be a reference
+[refs] crd=clouddmsprivateconnections.clouddms.cnrm.cloud.google.com version=v1alpha1: field ".spec.vpcPeeringConfig.vpcName.external" should be a reference
path: tests/apichecks/testdata/exceptions/missingrefs.txt
user: login: yuwenma
body: please fix this
created_at: 2025-04-11T02:55:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,196 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package v1alpha1
+
+import (
+	refs "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
+	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/k8s/v1alpha1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+var CloudDMSPrivateConnectionGVK = GroupVersion.WithKind("CloudDMSPrivateConnection")
+
+type Parent struct {
+	// Required. The location of the application.
+	Location string `json:"location,omitempty"`
+
+	// Required. The host project of the application.
+	ProjectRef *refs.ProjectRef `json:"projectRef,omitempty"`
+}
+
+// +kcc:proto=google.protobuf.Any
+type Any struct {
+	// A URL/resource name that uniquely identifies the type of the serialized
+	//  protocol buffer message. This string must contain at least
+	//  one "/" character. The last segment of the URL's path must represent
+	//  the fully qualified name of the type (as in
+	//  `path/google.protobuf.Duration`). The name should be in a canonical form
+	//  (e.g., leading "." is not accepted).
+	//
+	//  In practice, teams usually precompile into the binary all types that they
+	//  expect it to use in the context of Any. However, for URLs which use the
+	//  scheme `http`, `https`, or no scheme, one can optionally set up a type
+	//  server that maps type URLs to message definitions as follows:
+	//
+	//  * If no scheme is provided, `https` is assumed.
+	//  * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+	//    value in binary format, or produce an error.
+	//  * Applications are allowed to cache lookup results based on the
+	//    URL, or have them precompiled into a binary to avoid any
+	//    lookup. Therefore, binary compatibility needs to be preserved
+	//    on changes to types. (Use versioned type names to manage
+	//    breaking changes.)
+	//
+	//  Note: this functionality is not currently available in the official
+	//  protobuf release, and it is not used for type URLs beginning with
+	//  type.googleapis.com.
+	//
+	//  Schemes other than `http`, `https` (or the empty scheme) might be
+	//  used with implementation specific semantics.
+	// +kcc:proto:field=google.protobuf.Any.type_url
+	TypeURL *string `json:"typeURL,omitempty"`
+
+	// Must be a valid serialized protocol buffer of the above specified type.
+	// +kcc:proto:field=google.protobuf.Any.value
+	Value []byte `json:"value,omitempty"`
+}
+
+// +kcc:proto=google.rpc.Status
+type Status struct {
+	// The status code, which should be an enum value of
+	//  [google.rpc.Code][google.rpc.Code].
+	// +kcc:proto:field=google.rpc.Status.code
+	Code *int32 `json:"code,omitempty"`
+
+	// A developer-facing error message, which should be in English. Any
+	//  user-facing error message should be localized and sent in the
+	//  [google.rpc.Status.details][google.rpc.Status.details] field, or localized
+	//  by the client.
+	// +kcc:proto:field=google.rpc.Status.message
+	Message *string `json:"message,omitempty"`
+
+	// NOT YET
+	// A list of messages that carry the error details.  There is a common set of
+	//  message types for APIs to use.
+	// +kcc:proto:field=google.rpc.Status.details
+	// Details []Any `json:"details,omitempty"`
+}
+
+// +kcc:proto=google.cloud.clouddms.v1.VpcPeeringConfig
+type VpcPeeringConfig struct {
+	// Required. Fully qualified name of the VPC that Database Migration Service
+	//  will peer to.
+	// +kcc:proto:field=google.cloud.clouddms.v1.VpcPeeringConfig.vpc_name
+	VpcName *refs.ComputeNetworkRef `json:"vpcName,omitempty"`
+
+	// Required. A free subnet for peering. (CIDR of /29)
+	// +kcc:proto:field=google.cloud.clouddms.v1.VpcPeeringConfig.subnet
+	Subnet *string `json:"subnet,omitempty"`
path: apis/clouddms/v1alpha1/privateconnection_types.go
user: login: anhdle-sso
body: This is not a compute subnetwork. Example value is `"10.2.0.0/16"`
created_at: 2025-04-11T05:25:01Z
author_association: COLLABORATOR
diff_hunk: @@ -19,6 +19,7 @@
 [refs] crd=billingbudgetsbudgets.billingbudgets.cnrm.cloud.google.com version=v1beta1: field ".spec.budgetFilter.projects[].external" should be a reference
 [refs] crd=binaryauthorizationpolicies.binaryauthorization.cnrm.cloud.google.com version=v1beta1: field ".spec.defaultAdmissionRule.requireAttestationsBy[].external" should be a reference
 [refs] crd=cloudbuildtriggers.cloudbuild.cnrm.cloud.google.com version=v1beta1: field ".spec.build.options.workerPool" should be a reference
+[refs] crd=clouddmsprivateconnections.clouddms.cnrm.cloud.google.com version=v1alpha1: field ".spec.vpcPeeringConfig.vpcName.external" should be a reference
path: tests/apichecks/testdata/exceptions/missingrefs.txt
user: login: anhdle-sso
body: I already make this field `.spec.vpcPeeringConfig.vpcName` a reference to ComputeNetwork. This unit test somehow think the external resource string should be a ref; since I modify this file
created_at: 2025-04-11T05:26:43Z
author_association: COLLABORATOR
diff_hunk: @@ -19,6 +19,7 @@
 [refs] crd=billingbudgetsbudgets.billingbudgets.cnrm.cloud.google.com version=v1beta1: field ".spec.budgetFilter.projects[].external" should be a reference
 [refs] crd=binaryauthorizationpolicies.binaryauthorization.cnrm.cloud.google.com version=v1beta1: field ".spec.defaultAdmissionRule.requireAttestationsBy[].external" should be a reference
 [refs] crd=cloudbuildtriggers.cloudbuild.cnrm.cloud.google.com version=v1beta1: field ".spec.build.options.workerPool" should be a reference
+[refs] crd=clouddmsprivateconnections.clouddms.cnrm.cloud.google.com version=v1alpha1: field ".spec.vpcPeeringConfig.vpcName.external" should be a reference
path: tests/apichecks/testdata/exceptions/missingrefs.txt
user: login: jingyih
body: I think it is complaining because the field name does not end with "Ref".
created_at: 2025-04-11T09:11:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -19,6 +19,7 @@
 [refs] crd=billingbudgetsbudgets.billingbudgets.cnrm.cloud.google.com version=v1beta1: field ".spec.budgetFilter.projects[].external" should be a reference
 [refs] crd=binaryauthorizationpolicies.binaryauthorization.cnrm.cloud.google.com version=v1beta1: field ".spec.defaultAdmissionRule.requireAttestationsBy[].external" should be a reference
 [refs] crd=cloudbuildtriggers.cloudbuild.cnrm.cloud.google.com version=v1beta1: field ".spec.build.options.workerPool" should be a reference
+[refs] crd=clouddmsprivateconnections.clouddms.cnrm.cloud.google.com version=v1alpha1: field ".spec.vpcPeeringConfig.vpcName.external" should be a reference
path: tests/apichecks/testdata/exceptions/missingrefs.txt
user: login: anhdle-sso
body: added the ref to the field name
created_at: 2025-04-17T21:40:18Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,196 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package v1alpha1
+
+import (
+	refs "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
+	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/k8s/v1alpha1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+var CloudDMSPrivateConnectionGVK = GroupVersion.WithKind("CloudDMSPrivateConnection")
+
+type Parent struct {
+	// Required. The location of the application.
+	Location string `json:"location,omitempty"`
+
+	// Required. The host project of the application.
+	ProjectRef *refs.ProjectRef `json:"projectRef,omitempty"`
+}
+
+// +kcc:proto=google.protobuf.Any
+type Any struct {
+	// A URL/resource name that uniquely identifies the type of the serialized
+	//  protocol buffer message. This string must contain at least
+	//  one "/" character. The last segment of the URL's path must represent
+	//  the fully qualified name of the type (as in
+	//  `path/google.protobuf.Duration`). The name should be in a canonical form
+	//  (e.g., leading "." is not accepted).
+	//
+	//  In practice, teams usually precompile into the binary all types that they
+	//  expect it to use in the context of Any. However, for URLs which use the
+	//  scheme `http`, `https`, or no scheme, one can optionally set up a type
+	//  server that maps type URLs to message definitions as follows:
+	//
+	//  * If no scheme is provided, `https` is assumed.
+	//  * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+	//    value in binary format, or produce an error.
+	//  * Applications are allowed to cache lookup results based on the
+	//    URL, or have them precompiled into a binary to avoid any
+	//    lookup. Therefore, binary compatibility needs to be preserved
+	//    on changes to types. (Use versioned type names to manage
+	//    breaking changes.)
+	//
+	//  Note: this functionality is not currently available in the official
+	//  protobuf release, and it is not used for type URLs beginning with
+	//  type.googleapis.com.
+	//
+	//  Schemes other than `http`, `https` (or the empty scheme) might be
+	//  used with implementation specific semantics.
+	// +kcc:proto:field=google.protobuf.Any.type_url
+	TypeURL *string `json:"typeURL,omitempty"`
+
+	// Must be a valid serialized protocol buffer of the above specified type.
+	// +kcc:proto:field=google.protobuf.Any.value
+	Value []byte `json:"value,omitempty"`
path: apis/clouddms/v1alpha1/privateconnection_types.go
user: login: justinsb
body: I feel this is going to be unusable in KRM, easier to just omit it?  (Mark it NOTYET)
created_at: 2025-04-17T21:55:02Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,196 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package v1alpha1
+
+import (
+	refs "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
+	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/k8s/v1alpha1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+var CloudDMSPrivateConnectionGVK = GroupVersion.WithKind("CloudDMSPrivateConnection")
+
+type Parent struct {
+	// Required. The location of the application.
+	Location string `json:"location,omitempty"`
+
+	// Required. The host project of the application.
+	ProjectRef *refs.ProjectRef `json:"projectRef,omitempty"`
+}
+
+// +kcc:proto=google.protobuf.Any
+type Any struct {
+	// A URL/resource name that uniquely identifies the type of the serialized
+	//  protocol buffer message. This string must contain at least
+	//  one "/" character. The last segment of the URL's path must represent
+	//  the fully qualified name of the type (as in
+	//  `path/google.protobuf.Duration`). The name should be in a canonical form
+	//  (e.g., leading "." is not accepted).
+	//
+	//  In practice, teams usually precompile into the binary all types that they
+	//  expect it to use in the context of Any. However, for URLs which use the
+	//  scheme `http`, `https`, or no scheme, one can optionally set up a type
+	//  server that maps type URLs to message definitions as follows:
+	//
+	//  * If no scheme is provided, `https` is assumed.
+	//  * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+	//    value in binary format, or produce an error.
+	//  * Applications are allowed to cache lookup results based on the
+	//    URL, or have them precompiled into a binary to avoid any
+	//    lookup. Therefore, binary compatibility needs to be preserved
+	//    on changes to types. (Use versioned type names to manage
+	//    breaking changes.)
+	//
+	//  Note: this functionality is not currently available in the official
+	//  protobuf release, and it is not used for type URLs beginning with
+	//  type.googleapis.com.
+	//
+	//  Schemes other than `http`, `https` (or the empty scheme) might be
+	//  used with implementation specific semantics.
+	// +kcc:proto:field=google.protobuf.Any.type_url
+	TypeURL *string `json:"typeURL,omitempty"`
+
+	// Must be a valid serialized protocol buffer of the above specified type.
+	// +kcc:proto:field=google.protobuf.Any.value
+	Value []byte `json:"value,omitempty"`
+}
+
+// +kcc:proto=google.rpc.Status
+type Status struct {
+	// The status code, which should be an enum value of
+	//  [google.rpc.Code][google.rpc.Code].
+	// +kcc:proto:field=google.rpc.Status.code
+	Code *int32 `json:"code,omitempty"`
+
+	// A developer-facing error message, which should be in English. Any
+	//  user-facing error message should be localized and sent in the
+	//  [google.rpc.Status.details][google.rpc.Status.details] field, or localized
+	//  by the client.
+	// +kcc:proto:field=google.rpc.Status.message
+	Message *string `json:"message,omitempty"`
+
+	// NOT YET
+	// A list of messages that carry the error details.  There is a common set of
+	//  message types for APIs to use.
+	// +kcc:proto:field=google.rpc.Status.details
+	// Details []Any `json:"details,omitempty"`
+}
+
+// +kcc:proto=google.cloud.clouddms.v1.VpcPeeringConfig
+type VpcPeeringConfig struct {
+	// Required. Fully qualified name of the VPC that Database Migration Service
+	//  will peer to.
+	// +kcc:proto:field=google.cloud.clouddms.v1.VpcPeeringConfig.vpc_name
+	VpcNameRef *refs.ComputeNetworkRef `json:"vpcNameRef,omitempty"`
+
+	// Required. A free subnet for peering. (CIDR of /29)
+	// +kcc:proto:field=google.cloud.clouddms.v1.VpcPeeringConfig.subnet
+	Subnet *string `json:"subnet,omitempty"`
+}
+
+// CloudDMSPrivateConnectionStatus defines the config connector machine state of CloudDMSPrivateConnection
+type CloudDMSPrivateConnectionStatus struct {
+	/* Conditions represent the latest available observations of the
+	   object's current state. */
+	Conditions []v1alpha1.Condition `json:"conditions,omitempty"`
+
+	// ObservedGeneration is the generation of the resource that was most recently observed by the Config Connector controller. If this is equal to metadata.generation, then that means that the current reported status reflects the most recent desired state of the resource.
+	ObservedGeneration *int64 `json:"observedGeneration,omitempty"`
+
+	// A unique specifier for the CloudDMSPrivateConnection resource in GCP.
+	ExternalRef *string `json:"externalRef,omitempty"`
+
+	// ObservedState is the state of the resource as most recently observed in GCP.
+	ObservedState *CloudDMSPrivateConnectionObservedState `json:"observedState,omitempty"`
+}
+
+// CloudDMSPrivateConnectionSpec defines the desired state of CloudDMSPrivateConnection
+// +kcc:proto=google.cloud.clouddms.v1.PrivateConnection
+type CloudDMSPrivateConnectionSpec struct {
+	// The CloudDMSPrivateConnection name. If not given, the metadata.name will be used.
+	ResourceID *string `json:"resourceID,omitempty"`
+
+	// Required. Defines the parent path of the resource.
+	*Parent `json:",inline"`
path: apis/clouddms/v1alpha1/privateconnection_types.go
user: login: justinsb
body: Probably `Parent` rather than `*Parent`?
created_at: 2025-04-17T21:55:58Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,196 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package v1alpha1
+
+import (
+	refs "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
+	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/k8s/v1alpha1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+var CloudDMSPrivateConnectionGVK = GroupVersion.WithKind("CloudDMSPrivateConnection")
+
+type Parent struct {
+	// Required. The location of the application.
+	Location string `json:"location,omitempty"`
+
+	// Required. The host project of the application.
+	ProjectRef *refs.ProjectRef `json:"projectRef,omitempty"`
+}
+
+// +kcc:proto=google.protobuf.Any
+type Any struct {
+	// A URL/resource name that uniquely identifies the type of the serialized
+	//  protocol buffer message. This string must contain at least
+	//  one "/" character. The last segment of the URL's path must represent
+	//  the fully qualified name of the type (as in
+	//  `path/google.protobuf.Duration`). The name should be in a canonical form
+	//  (e.g., leading "." is not accepted).
+	//
+	//  In practice, teams usually precompile into the binary all types that they
+	//  expect it to use in the context of Any. However, for URLs which use the
+	//  scheme `http`, `https`, or no scheme, one can optionally set up a type
+	//  server that maps type URLs to message definitions as follows:
+	//
+	//  * If no scheme is provided, `https` is assumed.
+	//  * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+	//    value in binary format, or produce an error.
+	//  * Applications are allowed to cache lookup results based on the
+	//    URL, or have them precompiled into a binary to avoid any
+	//    lookup. Therefore, binary compatibility needs to be preserved
+	//    on changes to types. (Use versioned type names to manage
+	//    breaking changes.)
+	//
+	//  Note: this functionality is not currently available in the official
+	//  protobuf release, and it is not used for type URLs beginning with
+	//  type.googleapis.com.
+	//
+	//  Schemes other than `http`, `https` (or the empty scheme) might be
+	//  used with implementation specific semantics.
+	// +kcc:proto:field=google.protobuf.Any.type_url
+	TypeURL *string `json:"typeURL,omitempty"`
+
+	// Must be a valid serialized protocol buffer of the above specified type.
+	// +kcc:proto:field=google.protobuf.Any.value
+	Value []byte `json:"value,omitempty"`
+}
+
+// +kcc:proto=google.rpc.Status
+type Status struct {
+	// The status code, which should be an enum value of
+	//  [google.rpc.Code][google.rpc.Code].
+	// +kcc:proto:field=google.rpc.Status.code
+	Code *int32 `json:"code,omitempty"`
+
+	// A developer-facing error message, which should be in English. Any
+	//  user-facing error message should be localized and sent in the
+	//  [google.rpc.Status.details][google.rpc.Status.details] field, or localized
+	//  by the client.
+	// +kcc:proto:field=google.rpc.Status.message
+	Message *string `json:"message,omitempty"`
+
+	// NOT YET
+	// A list of messages that carry the error details.  There is a common set of
+	//  message types for APIs to use.
+	// +kcc:proto:field=google.rpc.Status.details
+	// Details []Any `json:"details,omitempty"`
+}
+
+// +kcc:proto=google.cloud.clouddms.v1.VpcPeeringConfig
+type VpcPeeringConfig struct {
+	// Required. Fully qualified name of the VPC that Database Migration Service
+	//  will peer to.
+	// +kcc:proto:field=google.cloud.clouddms.v1.VpcPeeringConfig.vpc_name
+	VpcNameRef *refs.ComputeNetworkRef `json:"vpcNameRef,omitempty"`
+
+	// Required. A free subnet for peering. (CIDR of /29)
+	// +kcc:proto:field=google.cloud.clouddms.v1.VpcPeeringConfig.subnet
+	Subnet *string `json:"subnet,omitempty"`
+}
+
+// CloudDMSPrivateConnectionStatus defines the config connector machine state of CloudDMSPrivateConnection
+type CloudDMSPrivateConnectionStatus struct {
+	/* Conditions represent the latest available observations of the
+	   object's current state. */
+	Conditions []v1alpha1.Condition `json:"conditions,omitempty"`
+
+	// ObservedGeneration is the generation of the resource that was most recently observed by the Config Connector controller. If this is equal to metadata.generation, then that means that the current reported status reflects the most recent desired state of the resource.
+	ObservedGeneration *int64 `json:"observedGeneration,omitempty"`
+
+	// A unique specifier for the CloudDMSPrivateConnection resource in GCP.
+	ExternalRef *string `json:"externalRef,omitempty"`
+
+	// ObservedState is the state of the resource as most recently observed in GCP.
+	ObservedState *CloudDMSPrivateConnectionObservedState `json:"observedState,omitempty"`
+}
+
+// CloudDMSPrivateConnectionSpec defines the desired state of CloudDMSPrivateConnection
+// +kcc:proto=google.cloud.clouddms.v1.PrivateConnection
+type CloudDMSPrivateConnectionSpec struct {
+	// The CloudDMSPrivateConnection name. If not given, the metadata.name will be used.
+	ResourceID *string `json:"resourceID,omitempty"`
+
+	// Required. Defines the parent path of the resource.
+	*Parent `json:",inline"`
+
+	// The resource labels for private connections to use to annotate any related
+	//  underlying resources such as Compute Engine VMs. An object containing a
+	//  list of "key": "value" pairs.
+	//
+	//  Example: `{ "name": "wrench", "mass": "1.3kg", "count": "3" }`.
+	// +kcc:proto:field=google.cloud.clouddms.v1.PrivateConnection.labels
+	Labels map[string]string `json:"labels,omitempty"`
path: apis/clouddms/v1alpha1/privateconnection_types.go
user: login: justinsb
body: I think this needs to be NOTYET, because we haven't tackled metadata.labels
created_at: 2025-04-17T21:56:22Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,196 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package v1alpha1
+
+import (
+	refs "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
+	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/k8s/v1alpha1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+var CloudDMSPrivateConnectionGVK = GroupVersion.WithKind("CloudDMSPrivateConnection")
+
+type Parent struct {
+	// Required. The location of the application.
+	Location string `json:"location,omitempty"`
+
+	// Required. The host project of the application.
+	ProjectRef *refs.ProjectRef `json:"projectRef,omitempty"`
+}
+
+// +kcc:proto=google.protobuf.Any
+type Any struct {
+	// A URL/resource name that uniquely identifies the type of the serialized
+	//  protocol buffer message. This string must contain at least
+	//  one "/" character. The last segment of the URL's path must represent
+	//  the fully qualified name of the type (as in
+	//  `path/google.protobuf.Duration`). The name should be in a canonical form
+	//  (e.g., leading "." is not accepted).
+	//
+	//  In practice, teams usually precompile into the binary all types that they
+	//  expect it to use in the context of Any. However, for URLs which use the
+	//  scheme `http`, `https`, or no scheme, one can optionally set up a type
+	//  server that maps type URLs to message definitions as follows:
+	//
+	//  * If no scheme is provided, `https` is assumed.
+	//  * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+	//    value in binary format, or produce an error.
+	//  * Applications are allowed to cache lookup results based on the
+	//    URL, or have them precompiled into a binary to avoid any
+	//    lookup. Therefore, binary compatibility needs to be preserved
+	//    on changes to types. (Use versioned type names to manage
+	//    breaking changes.)
+	//
+	//  Note: this functionality is not currently available in the official
+	//  protobuf release, and it is not used for type URLs beginning with
+	//  type.googleapis.com.
+	//
+	//  Schemes other than `http`, `https` (or the empty scheme) might be
+	//  used with implementation specific semantics.
+	// +kcc:proto:field=google.protobuf.Any.type_url
+	TypeURL *string `json:"typeURL,omitempty"`
+
+	// Must be a valid serialized protocol buffer of the above specified type.
+	// +kcc:proto:field=google.protobuf.Any.value
+	Value []byte `json:"value,omitempty"`
+}
+
+// +kcc:proto=google.rpc.Status
+type Status struct {
+	// The status code, which should be an enum value of
+	//  [google.rpc.Code][google.rpc.Code].
+	// +kcc:proto:field=google.rpc.Status.code
+	Code *int32 `json:"code,omitempty"`
+
+	// A developer-facing error message, which should be in English. Any
+	//  user-facing error message should be localized and sent in the
+	//  [google.rpc.Status.details][google.rpc.Status.details] field, or localized
+	//  by the client.
+	// +kcc:proto:field=google.rpc.Status.message
+	Message *string `json:"message,omitempty"`
+
+	// NOT YET
+	// A list of messages that carry the error details.  There is a common set of
+	//  message types for APIs to use.
+	// +kcc:proto:field=google.rpc.Status.details
+	// Details []Any `json:"details,omitempty"`
+}
+
+// +kcc:proto=google.cloud.clouddms.v1.VpcPeeringConfig
+type VpcPeeringConfig struct {
+	// Required. Fully qualified name of the VPC that Database Migration Service
+	//  will peer to.
+	// +kcc:proto:field=google.cloud.clouddms.v1.VpcPeeringConfig.vpc_name
+	VpcNameRef *refs.ComputeNetworkRef `json:"vpcNameRef,omitempty"`
+
+	// Required. A free subnet for peering. (CIDR of /29)
+	// +kcc:proto:field=google.cloud.clouddms.v1.VpcPeeringConfig.subnet
+	Subnet *string `json:"subnet,omitempty"`
+}
+
+// CloudDMSPrivateConnectionStatus defines the config connector machine state of CloudDMSPrivateConnection
+type CloudDMSPrivateConnectionStatus struct {
+	/* Conditions represent the latest available observations of the
+	   object's current state. */
+	Conditions []v1alpha1.Condition `json:"conditions,omitempty"`
+
+	// ObservedGeneration is the generation of the resource that was most recently observed by the Config Connector controller. If this is equal to metadata.generation, then that means that the current reported status reflects the most recent desired state of the resource.
+	ObservedGeneration *int64 `json:"observedGeneration,omitempty"`
+
+	// A unique specifier for the CloudDMSPrivateConnection resource in GCP.
+	ExternalRef *string `json:"externalRef,omitempty"`
+
+	// ObservedState is the state of the resource as most recently observed in GCP.
+	ObservedState *CloudDMSPrivateConnectionObservedState `json:"observedState,omitempty"`
+}
+
+// CloudDMSPrivateConnectionSpec defines the desired state of CloudDMSPrivateConnection
+// +kcc:proto=google.cloud.clouddms.v1.PrivateConnection
+type CloudDMSPrivateConnectionSpec struct {
+	// The CloudDMSPrivateConnection name. If not given, the metadata.name will be used.
+	ResourceID *string `json:"resourceID,omitempty"`
+
+	// Required. Defines the parent path of the resource.
+	*Parent `json:",inline"`
+
+	// The resource labels for private connections to use to annotate any related
+	//  underlying resources such as Compute Engine VMs. An object containing a
+	//  list of "key": "value" pairs.
+	//
+	//  Example: `{ "name": "wrench", "mass": "1.3kg", "count": "3" }`.
+	// +kcc:proto:field=google.cloud.clouddms.v1.PrivateConnection.labels
+	Labels map[string]string `json:"labels,omitempty"`
+
+	// The private connection display name.
+	// +kcc:proto:field=google.cloud.clouddms.v1.PrivateConnection.display_name
+	DisplayName *string `json:"displayName,omitempty"`
+
+	// VPC peering configuration.
+	// +kcc:proto:field=google.cloud.clouddms.v1.PrivateConnection.vpc_peering_config
+	VpcPeeringConfig *VpcPeeringConfig `json:"vpcPeeringConfig,omitempty"`
+}
+
+// CloudDMSPrivateConnectionObservedState is the state of the CloudDMSPrivateConnection resource as most recently observed in GCP.
+// +kcc:proto=google.cloud.clouddms.v1.PrivateConnection
+type CloudDMSPrivateConnectionObservedState struct {
+	// Output only. The create time of the resource.
+	// +kcc:proto:field=google.cloud.clouddms.v1.PrivateConnection.create_time
+	CreateTime *string `json:"createTime,omitempty"`
+
+	// Output only. The last update time of the resource.
+	// +kcc:proto:field=google.cloud.clouddms.v1.PrivateConnection.update_time
+	UpdateTime *string `json:"updateTime,omitempty"`
+
+	// Output only. The state of the private connection.
+	// +kcc:proto:field=google.cloud.clouddms.v1.PrivateConnection.state
+	State *string `json:"state,omitempty"`
+
+	// Output only. The error details in case of state FAILED.
+	// +kcc:proto:field=google.cloud.clouddms.v1.PrivateConnection.error
+	Error *Status `json:"error,omitempty"`
path: apis/clouddms/v1alpha1/privateconnection_types.go
user: login: justinsb
body: Less critical that the others, but I might mark this one NOTYET also
created_at: 2025-04-17T21:56:54Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,196 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package v1alpha1
+
+import (
+	refs "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
+	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/k8s/v1alpha1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+var CloudDMSPrivateConnectionGVK = GroupVersion.WithKind("CloudDMSPrivateConnection")
+
+type Parent struct {
+	// Required. The location of the application.
+	Location string `json:"location,omitempty"`
+
+	// Required. The host project of the application.
+	ProjectRef *refs.ProjectRef `json:"projectRef,omitempty"`
+}
+
+// +kcc:proto=google.protobuf.Any
+type Any struct {
+	// A URL/resource name that uniquely identifies the type of the serialized
+	//  protocol buffer message. This string must contain at least
+	//  one "/" character. The last segment of the URL's path must represent
+	//  the fully qualified name of the type (as in
+	//  `path/google.protobuf.Duration`). The name should be in a canonical form
+	//  (e.g., leading "." is not accepted).
+	//
+	//  In practice, teams usually precompile into the binary all types that they
+	//  expect it to use in the context of Any. However, for URLs which use the
+	//  scheme `http`, `https`, or no scheme, one can optionally set up a type
+	//  server that maps type URLs to message definitions as follows:
+	//
+	//  * If no scheme is provided, `https` is assumed.
+	//  * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+	//    value in binary format, or produce an error.
+	//  * Applications are allowed to cache lookup results based on the
+	//    URL, or have them precompiled into a binary to avoid any
+	//    lookup. Therefore, binary compatibility needs to be preserved
+	//    on changes to types. (Use versioned type names to manage
+	//    breaking changes.)
+	//
+	//  Note: this functionality is not currently available in the official
+	//  protobuf release, and it is not used for type URLs beginning with
+	//  type.googleapis.com.
+	//
+	//  Schemes other than `http`, `https` (or the empty scheme) might be
+	//  used with implementation specific semantics.
+	// +kcc:proto:field=google.protobuf.Any.type_url
+	TypeURL *string `json:"typeURL,omitempty"`
+
+	// Must be a valid serialized protocol buffer of the above specified type.
+	// +kcc:proto:field=google.protobuf.Any.value
+	Value []byte `json:"value,omitempty"`
+}
+
+// +kcc:proto=google.rpc.Status
+type Status struct {
+	// The status code, which should be an enum value of
+	//  [google.rpc.Code][google.rpc.Code].
+	// +kcc:proto:field=google.rpc.Status.code
+	Code *int32 `json:"code,omitempty"`
+
+	// A developer-facing error message, which should be in English. Any
+	//  user-facing error message should be localized and sent in the
+	//  [google.rpc.Status.details][google.rpc.Status.details] field, or localized
+	//  by the client.
+	// +kcc:proto:field=google.rpc.Status.message
+	Message *string `json:"message,omitempty"`
+
+	// NOT YET
+	// A list of messages that carry the error details.  There is a common set of
+	//  message types for APIs to use.
+	// +kcc:proto:field=google.rpc.Status.details
+	// Details []Any `json:"details,omitempty"`
+}
+
+// +kcc:proto=google.cloud.clouddms.v1.VpcPeeringConfig
+type VpcPeeringConfig struct {
+	// Required. Fully qualified name of the VPC that Database Migration Service
+	//  will peer to.
+	// +kcc:proto:field=google.cloud.clouddms.v1.VpcPeeringConfig.vpc_name
+	VpcNameRef *refs.ComputeNetworkRef `json:"vpcNameRef,omitempty"`
path: apis/clouddms/v1alpha1/privateconnection_types.go
user: login: justinsb
body: I wonder if this should be `vpcRef` (or `networkRef`).  Name is the "type" and is confusing here...
created_at: 2025-04-17T21:58:52Z
author_association: COLLABORATOR

PR comments:
user: login: justinsb
created_at: 2025-04-17T21:59:50Z
body: A few comments but I don't think any of them are blocking for an alpha resource.

/approve
/lgtm

/hold for consideration of the points
author_association: COLLABORATOR
user: login: google-oss-prow[bot]
created_at: 2025-04-17T22:00:12Z
body: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/GoogleCloudPlatform/k8s-config-connector/pull/4300#issuecomment-2814101034" title="LGTM">justinsb</a>*

The full list of commands accepted by this bot can be found [here](https://oss.gprow.dev/command-help?repo=GoogleCloudPlatform%2Fk8s-config-connector).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/GoogleCloudPlatform/k8s-config-connector/blob/master/OWNERS)~~ [justinsb]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
author_association: CONTRIBUTOR
user: login: anhdle-sso
created_at: 2025-04-17T23:56:38Z
body: /unhold 

I already have a working controller PR done in the pipeline. I will merge this as is for alpha resource.
author_association: COLLABORATOR