Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add member conditions in status of KonnectGatewayControlPlane #138

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions api/konnect/v1alpha1/konnect_gateway_controlplane_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func init() {
// +kubebuilder:printcolumn:name="OrgID",description="Konnect Organization ID this resource belongs to.",type=string,JSONPath=`.status.organizationID`
// +kubebuilder:validation:XValidation:message="spec.konnect.authRef is immutable when an entity is already Programmed", rule="!self.status.conditions.exists(c, c.type == 'Programmed' && c.status == 'True') ? true : self.spec.konnect.authRef == oldSelf.spec.konnect.authRef"
// +kubebuilder:validation:XValidation:message="spec.konnect.authRef is immutable when an entity refers to a Valid API Auth Configuration", rule="!self.status.conditions.exists(c, c.type == 'APIAuthValid' && c.status == 'True') ? true : self.spec.konnect.authRef == oldSelf.spec.konnect.authRef"
// +kubebuilder:validation:XValidation:message="status.members is only applicable for ControlPlanes that are created as groups", rule="(has(self.spec.cluster_type) && self.spec.cluster_type != 'CLUSTER_TYPE_CONTROL_PLANE_GROUP') ? (!has(self.status) || !has(self.status.members)) : true"
// +apireference:kgo:include
type KonnectGatewayControlPlane struct {
metav1.TypeMeta `json:",inline"`
Expand Down Expand Up @@ -71,6 +72,10 @@ type KonnectGatewayControlPlaneStatus struct {
// +kubebuilder:validation:MaxItems=8
// +kubebuilder:default={{type: "Programmed", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}
Conditions []metav1.Condition `json:"conditions,omitempty"`

// MemberStatus is the status of each member in the control plane group.
// This field is only applicable for control planes with spec.cluster_type = CLUSTER_TYPE_CONTROL_PLANE_GROUP.
MemberStatus map[string][]metav1.Condition `json:"members,omitempty"`
Comment on lines +76 to +78
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to allow an extension of this field in the future, I suggest to put the conditions in a struct, which could then have other fields added in the future.

Suggested change
// MemberStatus is the status of each member in the control plane group.
// This field is only applicable for control planes with spec.cluster_type = CLUSTER_TYPE_CONTROL_PLANE_GROUP.
MemberStatus map[string][]metav1.Condition `json:"members,omitempty"`
// MembersStatus is the status of each member in the control plane group.
// This field is only applicable for control planes with spec.cluster_type = CLUSTER_TYPE_CONTROL_PLANE_GROUP.
MembersStatus map[string][]metav1.Condition `json:"members,omitempty"`

}

// GetKonnectLabels gets the Konnect Labels from object's spec.
Expand All @@ -88,6 +93,18 @@ func (c *KonnectGatewayControlPlane) GetKonnectAPIAuthConfigurationRef() Konnect
return c.Spec.KonnectConfiguration.APIAuthConfigurationRef
}

// SetMemberStatus sets conditions of a member of the control plane group in status.
// REVIEW: is it better to replace it with `SetMemberCondition` to set a single condition of a member?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we see a use case for setting more than 1 condition for a member?

I believe at this stage we're OK with setting just 1 (e.g. Programmed). Changing this API in the future will be simple so accommodate for in consumers (KGO) so I'm OK with allowing a single condition in the declaration here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about not adding another field and having it granular per member, but only populating a MembersReferencesResolved condition in the CP's conditions? That would be True if all are valid, and False if any are invalid (with a message indicating which ones).

When creating Kong/gateway-operator#797 I didn't take that into account, but I think that might be easier to implement and cleaner.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 This would already be a nice improvement and as you've mentioned: will be easier, less error prone and more efficient to implement.

WDYT @randmonkey ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It sounds good to add a specific condition type in the CP representing the CP group. For further details, we can add fields map[string]MemeberStatus for status of each member. The detail part could be in the next release. How about this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's focus on the CP group condition like suggested by @czeslavo - MembersReferencesResolved. At this point, I'd treat adding status conditions for each members as a nice to have, until requested by a user.

func (c *KonnectGatewayControlPlane) SetMemberStatus(name string, conditions []metav1.Condition) {
if c.Status.MemberStatus == nil {
c.Status.MemberStatus = map[string][]metav1.Condition{
name: conditions,
}
}

c.Status.MemberStatus[name] = conditions
}

// KonnectGatewayControlPlaneList contains a list of KonnectGatewayControlPlane.
// +kubebuilder:object:root=true
// +apireference:kgo:include
Expand Down
18 changes: 18 additions & 0 deletions api/konnect/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,68 @@ spec:
ID is the unique identifier of the Konnect entity as assigned by Konnect API.
If it's unset (empty string), it means the Konnect entity hasn't been created yet.
type: string
members:
additionalProperties:
items:
description: Condition contains details for one aspect of the
current state of this API Resource.
properties:
lastTransitionTime:
description: |-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: |-
message is a human readable message indicating details about the transition.
This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: |-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: |-
reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False,
Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
description: |-
MemberStatus is the status of each member in the control plane group.
This field is only applicable for control planes with spec.cluster_type = CLUSTER_TYPE_CONTROL_PLANE_GROUP.
type: object
organizationID:
description: OrgID is ID of Konnect Org that this entity has been
created in.
Expand All @@ -273,6 +335,10 @@ spec:
API Auth Configuration
rule: '!self.status.conditions.exists(c, c.type == ''APIAuthValid'' && c.status
== ''True'') ? true : self.spec.konnect.authRef == oldSelf.spec.konnect.authRef'
- message: status.members is only applicable for ControlPlanes that are created
as groups
rule: '(has(self.spec.cluster_type) && self.spec.cluster_type != ''CLUSTER_TYPE_CONTROL_PLANE_GROUP'')
? (!has(self.status) || !has(self.status.members)) : true'
served: true
storage: true
subresources:
Expand Down
1 change: 0 additions & 1 deletion test/crdsvalidation/konnectgatewaycontrolplane_test.go
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add tests here for the added field?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried but it requires "error happens in updating status". This requires more changes in the testing framework.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this change introduces CEL validation, I'd halt merging this until we can figure out what is the cause of this error. We don't want to merge a change that would break updating the CP CRD for any supported use case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if we should validate status fields with CEL rules 🤔 It will only be populated by the controller - that's where we should ensure it's generated valid.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point @czeslavo. This makes a lot of sense. 👍

Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,6 @@ func TestKonnectGatewayControlPlane(t *testing.T) {
},
ExpectedErrorMessage: lo.ToPtr("spec.labels keys must be of length 1-63 characters"),
},
//
{
Name: "spec.labels values' length must not be greater than 63",
TestObject: &konnectv1alpha1.KonnectGatewayControlPlane{
Expand Down