Skip to content

Commit 2682c4f

Browse files
Merge pull request GoogleCloudPlatform#3790 from jasonvigil/apigeeenvgroupattachment
feat: Add ApigeeEnvgroupAttachment v1alpha1 reconciler
2 parents e433b2a + 66e3d3b commit 2682c4f

27 files changed

+1215
-329
lines changed

apis/apigee/v1alpha1/environmentgroup_identity.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ import (
2626
)
2727

2828
const (
29-
EnvgroupIDToken = "envgroups"
30-
EnvgroupIDFormat = apigeev1beta1.ApigeeOrganizationIDFormat + "/" + EnvgroupIDToken + "/{{envgroupID}}"
29+
ApigeeEnvgroupIDToken = "envgroups"
30+
ApigeeEnvgroupIDFormat = apigeev1beta1.ApigeeOrganizationIDFormat + "/" + ApigeeEnvgroupIDToken + "/{{envgroupID}}"
3131
)
3232

3333
var _ identity.Identity = &ApigeeEnvgroupIdentity{}
@@ -38,20 +38,20 @@ type ApigeeEnvgroupIdentity struct {
3838
}
3939

4040
func (i *ApigeeEnvgroupIdentity) String() string {
41-
return i.ParentID.String() + "/" + EnvgroupIDToken + "/" + i.ResourceID
41+
return i.ParentID.String() + "/" + ApigeeEnvgroupIDToken + "/" + i.ResourceID
4242
}
4343

4444
func (i *ApigeeEnvgroupIdentity) FromExternal(ref string) error {
45-
requiredTokens := len(strings.Split(EnvgroupIDFormat, "/"))
45+
requiredTokens := len(strings.Split(ApigeeEnvgroupIDFormat, "/"))
4646

4747
tokens := strings.Split(ref, "/")
48-
if len(tokens) != requiredTokens || tokens[len(tokens)-2] != EnvgroupIDToken {
49-
return fmt.Errorf("format of ApigeeEnvgroup ref=%q was not known (use %q)", ref, EnvgroupIDFormat)
48+
if len(tokens) != requiredTokens || tokens[len(tokens)-2] != ApigeeEnvgroupIDToken {
49+
return fmt.Errorf("format of ApigeeEnvgroup ref=%q was not known (use %q)", ref, ApigeeEnvgroupIDFormat)
5050
}
5151

5252
parentID := &apigeev1beta1.ApigeeOrganizationIdentity{}
5353
if err := parentID.FromExternal(strings.Join(tokens[:len(tokens)-2], "/")); err != nil {
54-
return fmt.Errorf("format of ApigeeEnvgroup ref=%q was not known (use %q)", ref, EnvgroupIDFormat)
54+
return fmt.Errorf("format of ApigeeEnvgroup ref=%q was not known (use %q)", ref, ApigeeEnvgroupIDFormat)
5555
}
5656

5757
resourceID := tokens[len(tokens)-1]

apis/apigee/v1alpha1/envgroupattachment_identity.go apis/apigee/v1alpha1/environmentgroupattachment_identity.go

+20-16
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,14 @@ import (
1919
"fmt"
2020
"strings"
2121

22-
apigeev1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/apis/apigee/v1beta1"
2322
"github.com/GoogleCloudPlatform/k8s-config-connector/apis/common"
2423
"github.com/GoogleCloudPlatform/k8s-config-connector/apis/common/identity"
25-
2624
"sigs.k8s.io/controller-runtime/pkg/client"
2725
)
2826

2927
const (
30-
EnvgroupAttachmentIDToken = "attachments"
31-
EnvgroupAttachmentIDFormat = apigeev1beta1.EnvgroupIDFormat + "/" + EnvgroupAttachmentIDToken + "/{{attachmentID}}"
28+
ApigeeEnvgroupAttachmentIDToken = "attachments"
29+
ApigeeEnvgroupAttachmentIDFormat = ApigeeEnvgroupIDFormat + "/" + ApigeeEnvgroupAttachmentIDToken + "/{{attachmentID}}"
3230
)
3331

3432
var _ identity.Identity = &ApigeeEnvgroupAttachmentIdentity{}
@@ -39,20 +37,25 @@ type ApigeeEnvgroupAttachmentIdentity struct {
3937
}
4038

4139
func (i *ApigeeEnvgroupAttachmentIdentity) String() string {
42-
return i.ParentID.String() + "/" + EnvgroupAttachmentIDToken + "/" + i.ResourceID
40+
if i.ResourceID == "" {
41+
// Initially, the identity of the ApigeeEnvgroupAttachment is unknown, until it is acquired or created.
42+
// This is because the resource uses a service-generated ID.
43+
return ""
44+
}
45+
return i.ParentID.String() + "/" + ApigeeEnvgroupAttachmentIDToken + "/" + i.ResourceID
4346
}
4447

4548
func (i *ApigeeEnvgroupAttachmentIdentity) FromExternal(ref string) error {
46-
requiredTokens := len(strings.Split(EnvgroupAttachmentIDFormat, "/"))
49+
requiredTokens := len(strings.Split(ApigeeEnvgroupAttachmentIDFormat, "/"))
4750

4851
tokens := strings.Split(ref, "/")
49-
if len(tokens) != requiredTokens || tokens[len(tokens)-2] != EnvgroupAttachmentIDToken {
50-
return fmt.Errorf("format of ApigeeEnvgroupAttachment ref=%q was not known (use %q)", ref, EnvgroupAttachmentIDFormat)
52+
if len(tokens) != requiredTokens || tokens[len(tokens)-2] != ApigeeEnvgroupAttachmentIDToken {
53+
return fmt.Errorf("format of ApigeeEnvgroupAttachment ref=%q was not known (use %q)", ref, ApigeeEnvgroupAttachmentIDFormat)
5154
}
5255

5356
parentID := &ApigeeEnvgroupIdentity{}
5457
if err := parentID.FromExternal(strings.Join(tokens[:len(tokens)-2], "/")); err != nil {
55-
return fmt.Errorf("format of ApigeeEnvgroupAttachment ref=%q was not known (use %q)", ref, EnvgroupAttachmentIDFormat)
58+
return fmt.Errorf("format of ApigeeEnvgroupAttachment ref=%q was not known (use %q)", ref, ApigeeEnvgroupAttachmentIDFormat)
5659
}
5760

5861
resourceID := tokens[len(tokens)-1]
@@ -72,13 +75,14 @@ func (obj *ApigeeEnvgroupAttachment) GetIdentity(ctx context.Context, reader cli
7275
return nil, err
7376
}
7477

75-
// Get desired ID
78+
// Get service-generated resource ID
7679
resourceID := common.ValueOf(obj.Spec.ResourceID)
77-
if resourceID == "" {
78-
resourceID = obj.GetName()
79-
}
80-
if resourceID == "" {
81-
return nil, fmt.Errorf("cannot resolve resource ID")
80+
if resourceID == "" && obj.Status.ExternalRef != nil {
81+
savedID := &ApigeeEnvgroupAttachmentIdentity{}
82+
if err := savedID.FromExternal(common.ValueOf(obj.Status.ExternalRef)); err != nil {
83+
return nil, err
84+
}
85+
resourceID = savedID.ResourceID
8286
}
8387

8488
id := &ApigeeEnvgroupAttachmentIdentity{
@@ -89,7 +93,7 @@ func (obj *ApigeeEnvgroupAttachment) GetIdentity(ctx context.Context, reader cli
8993
// Attempt to ensure ID is immutable, by verifying against previously-set `status.externalRef`.
9094
externalRef := common.ValueOf(obj.Status.ExternalRef)
9195
if externalRef != "" {
92-
previousID := &ApigeeEnvgroupIdentity{}
96+
previousID := &ApigeeEnvgroupAttachmentIdentity{}
9397
if err := previousID.FromExternal(externalRef); err != nil {
9498
return nil, err
9599
}

apis/apigee/v1alpha1/envgroupattachment_reference.go apis/apigee/v1alpha1/environmentgroupattachment_reference.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,24 @@ import (
1818
"context"
1919

2020
refsv1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
21+
2122
"k8s.io/apimachinery/pkg/runtime/schema"
2223
"k8s.io/apimachinery/pkg/types"
2324
"sigs.k8s.io/controller-runtime/pkg/client"
2425
)
2526

2627
var _ refsv1beta1.Ref = &ApigeeEnvgroupAttachmentRef{}
2728

28-
// ApigeeEnvgroupAttachmentRef is a reference to a ApigeeEnvgroup resource.
29+
// ApigeeEnvgroupAttachmentRef is a reference to a ApigeeEnvgroupAttachment resource.
2930
type ApigeeEnvgroupAttachmentRef struct {
30-
// A reference to an externally managed EnvgroupAttachment resource.
31+
// A reference to an externally managed ApigeeEnvgroupAttachment resource.
3132
// Should be in the format "organizations/{{organizationID}}/envgroups/{{envgroupID}}/attachments/{{attachmentID}}".
3233
External string `json:"external,omitempty"`
3334

34-
// The name of a EnvgroupAttachment resource.
35+
// The name of a ApigeeEnvgroupAttachment resource.
3536
Name string `json:"name,omitempty"`
3637

37-
// The namespace of a EnvgroupAttachment resource.
38+
// The namespace of a ApigeeEnvgroupAttachment resource.
3839
Namespace string `json:"namespace,omitempty"`
3940
}
4041

apis/apigee/v1alpha1/envgroupattachment_types.go apis/apigee/v1alpha1/environmentgroupattachment_types.go

+31-31
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
// Copyright 2025 Google LLC.
2-
1+
// Copyright 2025 Google LLC
2+
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
55
// You may obtain a copy of the License at
6-
6+
//
77
// http://www.apache.org/licenses/LICENSE-2.0
8-
8+
//
99
// Unless required by applicable law or agreed to in writing, software
1010
// distributed under the License is distributed on an "AS IS" BASIS,
1111
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -23,69 +23,69 @@ import (
2323

2424
var ApigeeEnvgroupAttachmentGVK = GroupVersion.WithKind("ApigeeEnvgroupAttachment")
2525

26-
// ApigeeEnvgroupAttachmentSpec defines the desired state of EnvgroupAttachment
26+
// ApigeeEnvgroupAttachmentSpec defines the desired state of ApigeeEnvgroupAttachment
27+
// +kcc:proto=mockgcp.cloud.apigee.v1.GoogleCloudApigeeV1EnvironmentGroupAttachment
2728
type ApigeeEnvgroupAttachmentSpec struct {
28-
// Reference to parent ApigeeEnvgroup.
29+
// Reference to parent Environment Group
2930
// +required
30-
EnvgroupRef *ApigeeEnvgroupRef `json:"envgroupRef"`
31+
EnvgroupRef *ApigeeEnvgroupRef `json:"envgroupRef,omitempty"`
3132

32-
// The Apigee environment to attach to.
33-
// +required
34-
EnvironmentRef *apigeev1beta1.ApigeeEnvironmentRef `json:"environmentRef"`
33+
// Required. ID of the attached environment.
34+
// +kcc:proto:field=mockgcp.cloud.apigee.v1.GoogleCloudApigeeV1EnvironmentGroupAttachment.environment
35+
EnvironmentRef *apigeev1beta1.ApigeeEnvironmentRef `json:"environmentRef,omitempty"`
3536

36-
// The EnvgroupAttachment name. If not given, the metadata.name will be used.
37+
// The ApigeeEnvgroupAttachment name. If not given, the metadata.name will be used.
3738
ResourceID *string `json:"resourceID,omitempty"`
3839
}
3940

40-
// ApigeeEnvgroupAttachmentStatus defines the observed state of EnvgroupAttachment
41+
// ApigeeEnvgroupAttachmentStatus defines the config connector machine state of ApigeeEnvgroupAttachment
4142
type ApigeeEnvgroupAttachmentStatus struct {
42-
// Conditions represent the latest available observations of the
43-
// EnvgroupAttachment's current state.
43+
/* Conditions represent the latest available observations of the
44+
object's current state. */
4445
Conditions []v1alpha1.Condition `json:"conditions,omitempty"`
4546

46-
// ObservedGeneration is the generation of the resource that was most recently observed by the Config Connector controller.
47-
// If this is equal to metadata.generation, then that means that the current reported status reflects the most recent desired state of the resource.
48-
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
47+
// 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.
48+
ObservedGeneration *int64 `json:"observedGeneration,omitempty"`
4949

50-
// A unique specifier for the EnvgroupAttachment resource.
51-
// +optional
50+
// A unique specifier for the ApigeeEnvgroupAttachment resource in GCP.
5251
ExternalRef *string `json:"externalRef,omitempty"`
5352

5453
// ObservedState is the state of the resource as most recently observed in GCP.
55-
ObservedState *EnvgroupAttachmentObservedState `json:"observedState,omitempty"`
54+
ObservedState *ApigeeEnvgroupAttachmentObservedState `json:"observedState,omitempty"`
5655
}
5756

58-
// EnvgroupAttachmentObservedState defines the desired state of ApigeeEnvgroupAttachment
59-
type EnvgroupAttachmentObservedState struct {
60-
// Output only. The time at which the environment group attachment
61-
// was created as milliseconds since epoch.
57+
// ApigeeEnvgroupAttachmentObservedState is the state of the ApigeeEnvgroupAttachment resource as most recently observed in GCP.
58+
// +kcc:proto=mockgcp.cloud.apigee.v1.GoogleCloudApigeeV1EnvironmentGroupAttachment
59+
type ApigeeEnvgroupAttachmentObservedState struct {
60+
// Output only. The time at which the environment group attachment was created as milliseconds since epoch.
61+
// +kcc:proto:field=mockgcp.cloud.apigee.v1.GoogleCloudApigeeV1EnvironmentGroupAttachment.created_at
6262
CreatedAt *string `json:"createdAt,omitempty"`
6363
}
6464

6565
// +genclient
6666
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
67-
68-
// ApigeeEnvgroupAttachment is the Schema for the EnvgroupAttachments API
69-
// +genclient
70-
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
67+
// TODO(user): make sure the pluralizaiton below is correct
7168
// +kubebuilder:resource:categories=gcp,shortName=gcpapigeeenvgroupattachment;gcpapigeeenvgroupattachments
7269
// +kubebuilder:subresource:status
73-
// +kubebuilder:metadata:labels="cnrm.cloud.google.com/managed-by-kcc=true";"cnrm.cloud.google.com/system=true";"cnrm.cloud.google.com/stability-level=alpha"
70+
// +kubebuilder:metadata:labels="cnrm.cloud.google.com/managed-by-kcc=true";"cnrm.cloud.google.com/system=true"
7471
// +kubebuilder:printcolumn:name="Age",JSONPath=".metadata.creationTimestamp",type="date"
7572
// +kubebuilder:printcolumn:name="Ready",JSONPath=".status.conditions[?(@.type=='Ready')].status",type="string",description="When 'True', the most recent reconcile of the resource succeeded"
7673
// +kubebuilder:printcolumn:name="Status",JSONPath=".status.conditions[?(@.type=='Ready')].reason",type="string",description="The reason for the value in 'Ready'"
7774
// +kubebuilder:printcolumn:name="Status Age",JSONPath=".status.conditions[?(@.type=='Ready')].lastTransitionTime",type="date",description="The last transition time for the value in 'Status'"
75+
76+
// ApigeeEnvgroupAttachment is the Schema for the ApigeeEnvgroupAttachment API
77+
// +k8s:openapi-gen=true
7878
type ApigeeEnvgroupAttachment struct {
7979
metav1.TypeMeta `json:",inline"`
8080
metav1.ObjectMeta `json:"metadata,omitempty"`
8181

82+
// +required
8283
Spec ApigeeEnvgroupAttachmentSpec `json:"spec,omitempty"`
8384
Status ApigeeEnvgroupAttachmentStatus `json:"status,omitempty"`
8485
}
8586

8687
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
87-
88-
// ApigeeEnvgroupAttachmentList contains a list of EnvgroupAttachment
88+
// ApigeeEnvgroupAttachmentList contains a list of ApigeeEnvgroupAttachment
8989
type ApigeeEnvgroupAttachmentList struct {
9090
metav1.TypeMeta `json:",inline"`
9191
metav1.ListMeta `json:"metadata,omitempty"`

apis/apigee/v1alpha1/zz_generated.deepcopy.go

+26-21
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apis/apigee/v1beta1/environment_identity.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ import (
2525
)
2626

2727
const (
28-
EnvironmentIDToken = "environments"
29-
EnvironmentIDFormat = ApigeeOrganizationIDFormat + "/" + EnvironmentIDToken + "/{{environmentID}}"
28+
ApigeeEnvironmentIDToken = "environments"
29+
ApigeeEnvironmentIDFormat = ApigeeOrganizationIDFormat + "/" + ApigeeEnvironmentIDToken + "/{{environmentID}}"
3030
)
3131

3232
var _ identity.Identity = &ApigeeEnvironmentIdentity{}
@@ -37,20 +37,20 @@ type ApigeeEnvironmentIdentity struct {
3737
}
3838

3939
func (i *ApigeeEnvironmentIdentity) String() string {
40-
return i.ParentID.String() + "/" + EnvironmentIDToken + "/" + i.ResourceID
40+
return i.ParentID.String() + "/" + ApigeeEnvironmentIDToken + "/" + i.ResourceID
4141
}
4242

4343
func (i *ApigeeEnvironmentIdentity) FromExternal(ref string) error {
44-
requiredTokens := len(strings.Split(EnvironmentIDFormat, "/"))
44+
requiredTokens := len(strings.Split(ApigeeEnvironmentIDFormat, "/"))
4545

4646
tokens := strings.Split(ref, "/")
47-
if len(tokens) != requiredTokens || tokens[len(tokens)-2] != EnvironmentIDToken {
48-
return fmt.Errorf("format of ApigeeEnvironment ref=%q was not known (use %q)", ref, EnvironmentIDFormat)
47+
if len(tokens) != requiredTokens || tokens[len(tokens)-2] != ApigeeEnvironmentIDToken {
48+
return fmt.Errorf("format of ApigeeEnvironment ref=%q was not known (use %q)", ref, ApigeeEnvironmentIDFormat)
4949
}
5050

5151
parentID := &ApigeeOrganizationIdentity{}
5252
if err := parentID.FromExternal(strings.Join(tokens[:len(tokens)-2], "/")); err != nil {
53-
return fmt.Errorf("format of ApigeeEnvironment ref=%q was not known (use %q)", ref, EnvironmentIDFormat)
53+
return fmt.Errorf("format of ApigeeEnvironment ref=%q was not known (use %q)", ref, ApigeeEnvironmentIDFormat)
5454
}
5555

5656
resourceID := tokens[len(tokens)-1]

apis/apigee/v1beta1/environment_reference.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ func (r *ApigeeEnvironmentRef) Normalize(ctx context.Context, reader client.Read
126126
if envID == "" {
127127
return k8s.NewReferenceNotReadyError(u.GroupVersionKind(), key)
128128
}
129-
r.SetExternal(orgRef.External + "/" + EnvironmentIDToken + "/" + envID)
129+
r.SetExternal(orgRef.External + "/" + ApigeeEnvironmentIDToken + "/" + envID)
130130
}
131131

132132
id := &ApigeeEnvironmentIdentity{}

0 commit comments

Comments
 (0)