Skip to content

Commit 55f1b9d

Browse files
committed
ai: chore: Implement direct types for AgentRegistryBinding
Implementing the KRM types, CRD, and IdentityV2 for AgentRegistryBinding using the direct approach. Fix: 11271
1 parent 15c7729 commit 55f1b9d

302 files changed

Lines changed: 17410 additions & 73956 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gemini/journals/agentregistry.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
### [2026-07-06] AgentRegistry Google APIs Pin Update
2+
- **Context**: Implementing the initial KRM types and IdentityV2 for `AgentRegistryBinding`.
3+
- **Problem**: The original googleapis commit pin in `apis/git.versions` did not contain the `agentregistry` proto files, as the service was launched in 2026 whereas the old pin was from 2025.
4+
- **Solution**: Updated `apis/git.versions` to use `2b625c91510a2e8320a778bc88af8b65bc4a19a2` (the Google APIs commit from July 6, 2026) to pull in the `agentregistry` proto files, allowing the code generator to successfully run.
5+
- **Impact**: All future code generators and validation scripts will now have access to the `agentregistry` proto files.
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// Copyright 2026 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package v1alpha1
16+
17+
import (
18+
"context"
19+
"fmt"
20+
"strings"
21+
22+
"github.com/GoogleCloudPlatform/k8s-config-connector/apis/common"
23+
refsv1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
24+
"sigs.k8s.io/controller-runtime/pkg/client"
25+
)
26+
27+
// AgentRegistryBindingIdentity is the identity of an AgentRegistryBinding.
28+
type AgentRegistryBindingIdentity struct {
29+
parent *AgentRegistryBindingParent
30+
id string
31+
}
32+
33+
func (i *AgentRegistryBindingIdentity) String() string {
34+
return i.parent.String() + "/bindings/" + i.id
35+
}
36+
37+
func (i *AgentRegistryBindingIdentity) ID() string {
38+
return i.id
39+
}
40+
41+
func (i *AgentRegistryBindingIdentity) Parent() *AgentRegistryBindingParent {
42+
return i.parent
43+
}
44+
45+
type AgentRegistryBindingParent struct {
46+
ProjectID string
47+
Location string
48+
}
49+
50+
func (p *AgentRegistryBindingParent) String() string {
51+
return "projects/" + p.ProjectID + "/locations/" + p.Location
52+
}
53+
54+
// New builds an AgentRegistryBindingIdentity from the Config Connector AgentRegistryBinding object.
55+
func NewAgentRegistryBindingIdentity(ctx context.Context, reader client.Reader, obj *AgentRegistryBinding) (*AgentRegistryBindingIdentity, error) {
56+
57+
// Get Parent
58+
projectRef, err := refsv1beta1.ResolveProject(ctx, reader, obj.GetNamespace(), obj.Spec.ProjectRef)
59+
if err != nil {
60+
return nil, err
61+
}
62+
projectID := projectRef.ProjectID
63+
if projectID == "" {
64+
return nil, fmt.Errorf("cannot resolve project")
65+
}
66+
location := obj.Spec.Location
67+
68+
// Get desired ID
69+
resourceID := common.ValueOf(obj.Spec.ResourceID)
70+
if resourceID == "" {
71+
resourceID = obj.GetName()
72+
}
73+
if resourceID == "" {
74+
return nil, fmt.Errorf("cannot resolve resource ID")
75+
}
76+
77+
// Use approved External
78+
externalRef := common.ValueOf(obj.Status.ExternalRef)
79+
if externalRef != "" {
80+
// Validate desired with actual
81+
actualParent, actualResourceID, err := ParseAgentRegistryBindingExternal(externalRef)
82+
if err != nil {
83+
return nil, err
84+
}
85+
if actualParent.ProjectID != projectID {
86+
return nil, fmt.Errorf("spec.projectRef changed, expect %s, got %s", actualParent.ProjectID, projectID)
87+
}
88+
if actualParent.Location != location {
89+
return nil, fmt.Errorf("spec.location changed, expect %s, got %s", actualParent.Location, location)
90+
}
91+
if actualResourceID != resourceID {
92+
return nil, fmt.Errorf("cannot reset `metadata.name` or `spec.resourceID` to %s, since it has already assigned to %s",
93+
resourceID, actualResourceID)
94+
}
95+
}
96+
return &AgentRegistryBindingIdentity{
97+
parent: &AgentRegistryBindingParent{
98+
ProjectID: projectID,
99+
Location: location,
100+
},
101+
id: resourceID,
102+
}, nil
103+
}
104+
105+
func ParseAgentRegistryBindingExternal(external string) (parent *AgentRegistryBindingParent, resourceID string, err error) {
106+
tokens := strings.Split(external, "/")
107+
if len(tokens) != 6 || tokens[0] != "projects" || tokens[2] != "locations" || tokens[4] != "bindings" {
108+
return nil, "", fmt.Errorf("format of AgentRegistryBinding external=%q was not known (use projects/{{projectID}}/locations/{{location}}/bindings/{{bindingID}})", external)
109+
}
110+
parent = &AgentRegistryBindingParent{
111+
ProjectID: tokens[1],
112+
Location: tokens[3],
113+
}
114+
resourceID = tokens[5]
115+
return parent, resourceID, nil
116+
}
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
// Copyright 2026 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package v1alpha1
16+
17+
import (
18+
refsv1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
19+
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/k8s/v1alpha1"
20+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
)
22+
23+
var AgentRegistryBindingGVK = GroupVersion.WithKind("AgentRegistryBinding")
24+
25+
// AgentRegistryBindingSpec defines the desired state of AgentRegistryBinding
26+
// +kcc:spec:proto=google.cloud.agentregistry.v1.Binding
27+
type AgentRegistryBindingSpec struct {
28+
// The project that this resource belongs to.
29+
// +required
30+
ProjectRef *refsv1beta1.ProjectRef `json:"projectRef"`
31+
32+
// The location of this resource.
33+
// +required
34+
Location string `json:"location"`
35+
36+
// The AgentRegistryBinding name. If not given, the metadata.name will be used.
37+
// +optional
38+
ResourceID *string `json:"resourceID,omitempty"`
39+
40+
// Optional. User-defined display name for the Binding.
41+
// Can have a maximum length of 63 characters.
42+
// +optional
43+
// +kcc:proto:field=google.cloud.agentregistry.v1.Binding.display_name
44+
DisplayName *string `json:"displayName,omitempty"`
45+
46+
// Optional. User-defined description of a Binding.
47+
// Can have a maximum length of 2048 characters.
48+
// +optional
49+
// +kcc:proto:field=google.cloud.agentregistry.v1.Binding.description
50+
Description *string `json:"description,omitempty"`
51+
52+
// The binding for AuthProvider.
53+
// +optional
54+
// +kcc:proto:field=google.cloud.agentregistry.v1.Binding.auth_provider_binding
55+
AuthProviderBinding *AgentRegistryBindingAuthProviderBinding `json:"authProviderBinding,omitempty"`
56+
57+
// Required. The target Agent of the Binding.
58+
// +required
59+
// +kcc:proto:field=google.cloud.agentregistry.v1.Binding.source
60+
Source *AgentRegistryBindingSource `json:"source,omitempty"`
61+
62+
// Required. The target Agent Registry Resource of the Binding.
63+
// +required
64+
// +kcc:proto:field=google.cloud.agentregistry.v1.Binding.target
65+
Target *AgentRegistryBindingTarget `json:"target,omitempty"`
66+
}
67+
68+
// +kcc:proto=google.cloud.agentregistry.v1.Binding.AuthProviderBinding
69+
type AgentRegistryBindingAuthProviderBinding struct {
70+
// Required. The resource name of the target AuthProvider.
71+
// Format: `projects/{project}/locations/{location}/authProviders/{auth_provider}`
72+
// +kubebuilder:validation:Required
73+
// +kcc:proto:field=google.cloud.agentregistry.v1.Binding.AuthProviderBinding.auth_provider
74+
AuthProvider *string `json:"authProvider"`
75+
76+
// Optional. The list of OAuth2 scopes of the AuthProvider.
77+
// +kubebuilder:validation:Optional
78+
// +kcc:proto:field=google.cloud.agentregistry.v1.Binding.AuthProviderBinding.scopes
79+
Scopes []string `json:"scopes,omitempty"`
80+
81+
// Optional. The continue URI of the AuthProvider.
82+
// The URI is used to reauthenticate the user and finalize the managed OAuth
83+
// flow.
84+
// +kubebuilder:validation:Optional
85+
// +kcc:proto:field=google.cloud.agentregistry.v1.Binding.AuthProviderBinding.continue_uri
86+
ContinueURI *string `json:"continueURI,omitempty"`
87+
}
88+
89+
// +kcc:proto=google.cloud.agentregistry.v1.Binding.Source
90+
type AgentRegistryBindingSource struct {
91+
// The identifier of the source Agent.
92+
// Format: `urn:agent:{publisher}:{namespace}:{name}`
93+
// +kubebuilder:validation:Required
94+
// +kcc:proto:field=google.cloud.agentregistry.v1.Binding.Source.identifier
95+
Identifier *string `json:"identifier"`
96+
}
97+
98+
// +kcc:proto=google.cloud.agentregistry.v1.Binding.Target
99+
type AgentRegistryBindingTarget struct {
100+
// The identifier of the target Agent, MCP Server, or Endpoint.
101+
// Format:
102+
// * `urn:agent:{publisher}:{namespace}:{name}`
103+
// * `urn:mcp:{publisher}:{namespace}:{name}`
104+
// * `urn:endpoint:{publisher}:{namespace}:{name}`
105+
// +kubebuilder:validation:Required
106+
// +kcc:proto:field=google.cloud.agentregistry.v1.Binding.Target.identifier
107+
Identifier *string `json:"identifier"`
108+
}
109+
110+
// AgentRegistryBindingStatus defines the config connector machine state of AgentRegistryBinding
111+
type AgentRegistryBindingStatus struct {
112+
/* Conditions represent the latest available observations of the
113+
object's current state. */
114+
Conditions []v1alpha1.Condition `json:"conditions,omitempty"`
115+
116+
// 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.
117+
ObservedGeneration *int64 `json:"observedGeneration,omitempty"`
118+
119+
// A unique specifier for the AgentRegistryBinding resource in GCP.
120+
ExternalRef *string `json:"externalRef,omitempty"`
121+
122+
// ObservedState is the state of the resource as most recently observed in GCP.
123+
ObservedState *AgentRegistryBindingObservedState `json:"observedState,omitempty"`
124+
}
125+
126+
// AgentRegistryBindingObservedState is the state of the AgentRegistryBinding resource as most recently observed in GCP.
127+
// +kcc:observedstate:proto=google.cloud.agentregistry.v1.Binding
128+
type AgentRegistryBindingObservedState struct {
129+
// Output only. Timestamp when this binding was created.
130+
// +kcc:proto:field=google.cloud.agentregistry.v1.Binding.create_time
131+
CreateTime *string `json:"createTime,omitempty"`
132+
133+
// Output only. Timestamp when this binding was last updated.
134+
// +kcc:proto:field=google.cloud.agentregistry.v1.Binding.update_time
135+
UpdateTime *string `json:"updateTime,omitempty"`
136+
}
137+
138+
// +genclient
139+
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
140+
// +kubebuilder:resource:categories=gcp,shortName=gcpagentregistrybinding;gcpagentregistrybindings
141+
// +kubebuilder:subresource:status
142+
// +kubebuilder:metadata:labels="cnrm.cloud.google.com/managed-by-kcc=true"
143+
// +kubebuilder:metadata:labels="cnrm.cloud.google.com/system=true"
144+
// +kubebuilder:metadata:labels="cnrm.cloud.google.com/stability-level=alpha"
145+
// +kubebuilder:printcolumn:name="Age",JSONPath=".metadata.creationTimestamp",type="date"
146+
// +kubebuilder:printcolumn:name="Ready",JSONPath=".status.conditions[?(@.type=='Ready')].status",type="string",description="When 'True', the most recent reconcile of the resource succeeded"
147+
// +kubebuilder:printcolumn:name="Status",JSONPath=".status.conditions[?(@.type=='Ready')].reason",type="string",description="The reason for the value in 'Ready'"
148+
// +kubebuilder:printcolumn:name="Status Age",JSONPath=".status.conditions[?(@.type=='Ready')].lastTransitionTime",type="date",description="The last transition time for the value in 'Status'"
149+
150+
// AgentRegistryBinding is the Schema for the AgentRegistryBinding API
151+
// +k8s:openapi-gen=true
152+
type AgentRegistryBinding struct {
153+
metav1.TypeMeta `json:",inline"`
154+
metav1.ObjectMeta `json:"metadata,omitempty"`
155+
156+
// +required
157+
Spec AgentRegistryBindingSpec `json:"spec,omitempty"`
158+
Status AgentRegistryBindingStatus `json:"status,omitempty"`
159+
}
160+
161+
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
162+
// AgentRegistryBindingList contains a list of AgentRegistryBinding
163+
type AgentRegistryBindingList struct {
164+
metav1.TypeMeta `json:",inline"`
165+
metav1.ListMeta `json:"metadata,omitempty"`
166+
Items []AgentRegistryBinding `json:"items"`
167+
}
168+
169+
func init() {
170+
SchemeBuilder.Register(&AgentRegistryBinding{}, &AgentRegistryBindingList{})
171+
}

apis/agentregistry/v1alpha1/doc.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2026 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// +kcc:proto=google.cloud.agentregistry.v1
16+
package v1alpha1

pkg/test/resourcefixture/testdata/basic/dataplex/v1alpha1/dataplexmetadatajob/dataplexmetadatajob-minimal/create.yaml renamed to apis/agentregistry/v1alpha1/generate.sh

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#!/bin/bash
12
# Copyright 2026 Google LLC
23
#
34
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,16 +13,20 @@
1213
# See the License for the specific language governing permissions and
1314
# limitations under the License.
1415

15-
apiVersion: dataplex.cnrm.cloud.google.com/v1alpha1
16-
kind: DataplexMetadataJob
17-
metadata:
18-
name: dataplexmetadatajob-minimal-${uniqueId}
19-
spec:
20-
projectRef:
21-
external: ${projectId}
22-
location: us-central1
23-
type: EXPORT
24-
exportSpec:
25-
outputPath: gs://dataplex-metadatajob-bucket-${uniqueId}/export/
26-
scope:
27-
organizationLevel: false
16+
set -o errexit
17+
set -o nounset
18+
set -o pipefail
19+
20+
REPO_ROOT="$(git rev-parse --show-toplevel)"
21+
source "${REPO_ROOT}/dev/tools/goimports.sh"
22+
cd ${REPO_ROOT}/dev/tools/controllerbuilder
23+
24+
./generate-proto.sh
25+
26+
go run . generate-types \
27+
--service google.cloud.agentregistry.v1 \
28+
--api-version agentregistry.cnrm.cloud.google.com/v1alpha1 \
29+
--resource AgentRegistryBinding:Binding
30+
31+
cd ${REPO_ROOT}
32+
dev/tasks/generate-crds
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2026 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// +kubebuilder:object:generate=true
16+
// +groupName=agentregistry.cnrm.cloud.google.com
17+
package v1alpha1
18+
19+
import (
20+
"k8s.io/apimachinery/pkg/runtime/schema"
21+
"sigs.k8s.io/controller-runtime/pkg/scheme"
22+
)
23+
24+
var (
25+
// GroupVersion is group version used to register these objects
26+
GroupVersion = schema.GroupVersion{Group: "agentregistry.cnrm.cloud.google.com", Version: "v1alpha1"}
27+
28+
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
29+
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
30+
31+
// AddToScheme adds the types in this group-version to the given scheme.
32+
AddToScheme = SchemeBuilder.AddToScheme
33+
)

0 commit comments

Comments
 (0)