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

Add conditions and patch helpers, and docs to runtime #101

Merged
merged 28 commits into from
Jul 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6df6c0e
Add `conditions` helper to `runtime`
hiddeco May 14, 2021
1cf6ea6
Add support for negative polarity conditions
hiddeco May 14, 2021
45d6bb8
Prio Stalled and Reconciling in lexico cond order
hiddeco May 14, 2021
e1d94e5
Always update ObservedGeneration on condition Set
hiddeco May 14, 2021
308c5d6
Support summarizing to condition other than Ready
hiddeco May 14, 2021
723c6bd
Add `patch` helper to `runtime`
hiddeco May 14, 2021
84a9050
Allow subset message match in MatchConditions
hiddeco May 21, 2021
4bae447
Expand `SetAggregate` API and features
hiddeco May 21, 2021
4a7e889
Further tidying of runtime and meta elements
hiddeco Jun 23, 2021
16fa76c
Document Kustomize API package
hiddeco Jul 2, 2021
ab78173
Document meta API package
hiddeco Jul 2, 2021
94067b9
Document runtime client package
hiddeco Jul 2, 2021
702679a
Document runtime conditions package
hiddeco Jul 2, 2021
7c2b0b8
Document runtime controller package
hiddeco Jul 2, 2021
bac7da8
Make runtime dependency package to use meta API
hiddeco Jul 2, 2021
0db78f1
Make runtime errors package errors more generic
hiddeco Jul 2, 2021
0e9caec
Document runtime leaderelection package
hiddeco Jul 5, 2021
2d67687
Document runtime testenv package
hiddeco Jul 5, 2021
4ee6f3b
Document runtime probes package
hiddeco Jul 5, 2021
95d5db3
Document runtime transform package
hiddeco Jul 5, 2021
f248cff
Document runtime events package
hiddeco Jul 5, 2021
ac747c7
Document runtime logger package
hiddeco Jul 5, 2021
7b2d1e9
Document and extend runtime pprof package
hiddeco Jul 5, 2021
65de24f
Align Go modules with all recent changes
hiddeco Jul 5, 2021
7ec4df6
Document runtime metrics package
hiddeco Jul 5, 2021
06cface
Document runtime predicates package
hiddeco Jul 5, 2021
25fb8b6
Document runtime patch package
hiddeco Jul 5, 2021
b7eec63
Fixup: indents in-comment code blocks and wordings
hiddeco Jul 6, 2021
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
3 changes: 1 addition & 2 deletions apis/kustomize/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

// Package kustomize contains a selective set of Kustomize APIs for use by
// toolkit components.
// Package kustomize contains a selective set of Kustomize API types for use by GitOps Toolkit components.
// +kubebuilder:object:generate=true
package kustomize
46 changes: 25 additions & 21 deletions apis/kustomize/kustomize_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ import (
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
)

// Image contains an image name, a new name, a new tag or digest,
// which will replace the original name and tag.
// Image contains an image name, a new name, a new tag or digest, which will replace the original name and tag.
type Image struct {
// Name is a tag-less image name.
// +required
Expand All @@ -41,19 +40,17 @@ type Image struct {
Digest string `json:"digest,omitempty"`
}

// Selector specifies a set of resources.
// Any resource that matches intersection of all conditions is included in this set.
// Selector specifies a set of resources. Any resource that matches intersection of all conditions is included in this
// set.
type Selector struct {
// Group is the API group to select resources from.
// Together with Version and Kind it is capable of unambiguously
// identifying and/or selecting resources.
// Together with Version and Kind it is capable of unambiguously identifying and/or selecting resources.
// https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md
// +optional
Group string `json:"group,omitempty"`

// Version of the API Group to select resources from.
// Together with Group and Kind it is capable of unambiguously
// identifying and/or selecting resources.
// Together with Group and Kind it is capable of unambiguously identifying and/or selecting resources.
// https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md
// +optional
Version string `json:"version,omitempty"`
Expand Down Expand Up @@ -86,44 +83,51 @@ type Selector struct {
LabelSelector string `json:"labelSelector,omitempty"`
}

// Patch contains either a StrategicMerge or a JSON6902 patch, either a file or inline,
// and the target the patch should be applied to.
// Patch contains either a StrategicMerge or a JSON6902 patch, either a file or inline, and the target the patch should
// be applied to.
type Patch struct {
// Patch contains the JSON6902 patch document with an array of
// operation objects.
// Patch contains the JSON6902 patch document with an array of operation objects.
// +required
Patch string `json:"patch,omitempty"`

// Target points to the resources that the patch document should
// be applied to.
// Target points to the resources that the patch document should be applied to.
// +optional
Target Selector `json:"target,omitempty"`
}

// JSON6902 is a JSON6902 operation object.
// https://tools.ietf.org/html/rfc6902#section-4
// https://datatracker.ietf.org/doc/html/rfc6902#section-4
type JSON6902 struct {
// Op indicates the operation to perform. Its value MUST be one of "add", "remove", "replace", "move", "copy", or
// "test".
// https://datatracker.ietf.org/doc/html/rfc6902#section-4
// +kubebuilder:validation:Enum=test;remove;add;replace;move;copy
// +required
Op string `json:"op"`

// Path contains the JSON-pointer value that references a location within the target document where the operation
// is performed. The meaning of the value depends on the value of Op.
// +required
Path string `json:"path"`

// From contains a JSON-pointer value that references a location within the target document where the operation is
// performed. The meaning of the value depends on the value of Op, and is NOT taken into account by all operations.
// +optional
From string `json:"from,omitempty"`

// Value contains a valid JSON structure. The meaning of the value depends on the value of Op, and is NOT taken into
// account by all operations.
// +optional
Value *apiextensionsv1.JSON `json:"value,omitempty"`
}

// JSON6902Patch contains a JSON6902 patch and the target the patch
// should be applied to.
// JSON6902Patch contains a JSON6902 patch and the target the patch should be applied to.
type JSON6902Patch struct {
// Patch contains the JSON6902 patch document with an array of
// operation objects.
// Patch contains the JSON6902 patch document with an array of operation objects.
// +required
Patch []JSON6902 `json:"patch"`

// Target points to the resources that the patch document should
// be applied to.
// Target points to the resources that the patch document should be applied to.
// +required
Target Selector `json:"target"`
}
57 changes: 35 additions & 22 deletions apis/meta/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ const (
// outside of the defined schedule. Despite the name, the value is not
// interpreted as a timestamp, and any change in value shall trigger a
// reconciliation.
// DEPRECATED: has been replaced by ReconcileRequestAnnotation.
// DEPRECATED: has been replaced by ReconcileRequestAnnotation. For
Copy link
Member

Choose a reason for hiding this comment

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

I think it's time to remove this, we've switched all controllers to ReconcileRequestAnnotation in 2020.

Copy link
Member Author

Choose a reason for hiding this comment

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

I would probably do this in a separate PR to not incorporate more "hidden" breaking changes in this one.

// backward-compatibility, use ReconcileAnnotationValue, which will account for
// both annotations.
ReconcileAtAnnotation string = "fluxcd.io/reconcileAt"

// ReconcileRequestAnnotation is the new ReconcileAtAnnotation,
// with a better name. For backward-compatibility, use
// ReconcileAnnotationValue, which will account for both
// annotations.
// ReconcileRequestAnnotation is the annotation used for triggering a reconciliation
// outside of a defined schedule. The value is interpreted as a token, and any change
// in value SHOULD trigger a reconciliation.
ReconcileRequestAnnotation string = "reconcile.fluxcd.io/requestedAt"
)

// ReconcileAnnotationValue returns a value for the reconciliation
// request annotations, which can be used to detect changes; and, a
// boolean indicating whether either annotation was set.
// ReconcileAnnotationValue returns a value for the reconciliation request annotations, which can be used to detect
// changes; and, a boolean indicating whether either annotation was set.
func ReconcileAnnotationValue(annotations map[string]string) (string, bool) {
reconcileAt, ok1 := annotations[ReconcileAtAnnotation]
requestedAt, ok2 := annotations[ReconcileRequestAnnotation]
Expand All @@ -49,27 +49,40 @@ func ReconcileAnnotationValue(annotations map[string]string) (string, bool) {
return reconcileAt + requestedAt, ok1 || ok2
}

// ReconcileRequestStatus is a struct to embed in the status type, so
// that all types using the mechanism have the same field. Use it like
// this:
// ReconcileRequestStatus is a struct to embed in a status type, so that all types using the mechanism have the same
// field. Use it like this:
//
// ```
// type WhateverStatus struct {
// meta.ReconcileRequestStatus `json:",inline"`
// // other status fields...
// }
// ```
// type FooStatus struct {
// meta.ReconcileRequestStatus `json:",inline"`
// // other status fields...
// }
type ReconcileRequestStatus struct {
// LastHandledReconcileAt holds the value of the most recent
// reconcile request value, so a change can be detected.
// reconcile request value, so a change of the annotation value
// can be detected.
// +optional
LastHandledReconcileAt string `json:"lastHandledReconcileAt,omitempty"`
}

func (rs ReconcileRequestStatus) GetLastHandledReconcileRequest() string {
return rs.LastHandledReconcileAt
// GetLastHandledReconcileRequest returns the most recent reconcile request value from the ReconcileRequestStatus.
func (in ReconcileRequestStatus) GetLastHandledReconcileRequest() string {
return in.LastHandledReconcileAt
}

func (rs *ReconcileRequestStatus) SetLastHandledReconcileRequest(token string) {
rs.LastHandledReconcileAt = token
// SetLastHandledReconcileRequest sets the most recent reconcile request value in the ReconcileRequestStatus.
func (in *ReconcileRequestStatus) SetLastHandledReconcileRequest(token string) {
in.LastHandledReconcileAt = token
}

// StatusWithHandledReconcileRequest describes a status type which holds the value of the most recent
// ReconcileAnnotationValue.
// +k8s:deepcopy-gen=false
type StatusWithHandledReconcileRequest interface {
GetLastHandledReconcileRequest() string
}

// StatusWithHandledReconcileRequestSetter describes a status with a setter for the most ReconcileAnnotationValue.
// +k8s:deepcopy-gen=false
type StatusWithHandledReconcileRequestSetter interface {
SetLastHandledReconcileRequest(token string)
}
113 changes: 75 additions & 38 deletions apis/meta/conditions.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,62 +17,99 @@ limitations under the License.
package meta

import (
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// These constants define generic Condition types to be used by GitOps Toolkit components.
//
// The ReadyCondition SHOULD be implemented by all components' Kubernetes resources to indicate they have been fully
// reconciled by their respective reconciler. This MAY suffice for simple resources, e.g. a resource that just declares
// state once and is not expected to receive any updates afterwards.
//
// For Kubernetes resources that are expected to receive spec updates over time, take a longer time to reconcile, or
// deal with more complex logic in which for example a finite error state can be observed, it is RECOMMENDED to
// implement the StalledCondition and ReconcilingCondition.
//
// By doing this, observers making use of kstatus to determine the current state of the resource will have a better
Copy link
Member

Choose a reason for hiding this comment

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

<3 this explanation

// experience while they are e.g. waiting for a change to be reconciled, and will be able to stop waiting for a change
// if a StalledCondition is observed, without having to rely on a timeout.
//
// For more information on kstatus, see:
// https://github.com/kubernetes-sigs/cli-utils/blob/v0.25.0/pkg/kstatus/README.md
const (
// ReadyCondition is the name of the Ready condition implemented by all toolkit
// resources.
// ReadyCondition indicates the resource is ready and fully reconciled.
// If the Condition is False, the resource SHOULD be considered to be in the process of reconciling and not a
// representation of actual state.
ReadyCondition string = "Ready"

// StalledCondition is the name of the Stalled kstatus condition
// StalledCondition indicates the reconciliation of the resource has stalled, e.g. because the controller has
// encountered an error during the reconcile process or it has made insufficient progress (timeout).
// The Condition adheres to an "abnormal-true" polarity pattern, and MUST only be present on the resource if the
hiddeco marked this conversation as resolved.
Show resolved Hide resolved
// Condition is True.
// For more information about polarity patterns, see:
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties
StalledCondition string = "Stalled"

// ReconcilingCondition is the name of the Reconciling kstatus condition
// ReconcilingCondition indicates the controller is currently working on reconciling the latest changes. This MAY be
// True for multiple reconciliation attempts, e.g. when an transient error occurred.
// The Condition adheres to an "abnormal-true" polarity pattern, and MUST only be present on the resource if the
// Condition is True.
// For more information about polarity patterns, see:
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties
ReconcilingCondition string = "Reconciling"
)

// These constants define generic Condition reasons to be used by GitOps Toolkit components.
//
// Making use of a generic Reason is RECOMMENDED whenever it can be applied to a Condition in which it provides
// sufficient context together with the type to summarize the meaning of the Condition cause.
//
// Where any of the generic Condition reasons does not suffice, GitOps Toolkit components can introduce new reasons to
// their API specification, or use an arbitrary PascalCase string when setting the Condition.
// Declaration of domain common Condition reasons in the API specification is RECOMMENDED, as it eases observations
// for user and computer.
//
// For more information on Condition reason conventions, see:
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties
const (
// ReconciliationSucceededReason represents the fact that the reconciliation of
// a toolkit resource has succeeded.
ReconciliationSucceededReason string = "ReconciliationSucceeded"

// ReconciliationFailedReason represents the fact that the reconciliation of a
// toolkit resource has failed.
ReconciliationFailedReason string = "ReconciliationFailed"

// ProgressingReason represents the fact that the reconciliation of a toolkit
// resource is underway.
// SucceededReason indicates a condition or event observed a success, for example when declared desired state
// matches actual state, or a performed action succeeded.
//
// More information about the reason of success MAY be available as additional metadata in an attached message.
SucceededReason string = "Succeeded"

// FailedReason indicates a condition or event observed a failure, for example when declared state does not match
// actual state, or a performed action failed.
//
// More information about the reason of failure MAY be available as additional metadata in an attached message.
FailedReason string = "Failed"

// ProgressingReason indicates a condition or event observed progression, for example when the reconciliation of a
// resource or an action has started.
//
// When this reason is given, other conditions and types MAY no longer be considered as an up-to-date observation.
// Producers of the specific condition type or event SHOULD provide more information about the expectations and
// precise meaning in their API specification.
//
// More information about the reason or the current state of the progression MAY be available as additional metadata
// in an attached message.
ProgressingReason string = "Progressing"

// DependencyNotReadyReason represents the fact that one of the toolkit resource
// dependencies is not ready.
DependencyNotReadyReason string = "DependencyNotReady"

// SuspendedReason represents the fact that the reconciliation of a toolkit
// resource is suspended.
// SuspendedReason indicates a condition or event has observed a suspension, for
// example because a resource has been suspended, or a dependency is.
SuspendedReason string = "Suspended"
)

// ObjectWithStatusConditions is an interface that describes kubernetes resource
// type structs with Status Conditions
// ObjectWithConditions describes a Kubernetes resource object with status conditions.
// +k8s:deepcopy-gen=false
type ObjectWithStatusConditions interface {
GetStatusConditions() *[]metav1.Condition
type ObjectWithConditions interface {
// GetConditions returns a slice of metav1.Condition
GetConditions() []metav1.Condition
}

// SetResourceCondition sets the given condition with the given status,
// reason and message on a resource.
func SetResourceCondition(obj ObjectWithStatusConditions, condition string, status metav1.ConditionStatus, reason, message string) {
conditions := obj.GetStatusConditions()

newCondition := metav1.Condition{
Type: condition,
Status: status,
Reason: reason,
Message: message,
}

apimeta.SetStatusCondition(conditions, newCondition)
// ObjectWithConditionsSetter describes a Kubernetes resource object with a status conditions setter.
// +k8s:deepcopy-gen=false
type ObjectWithConditionsSetter interface {
// SetConditions sets the status conditions on the object
SetConditions([]metav1.Condition)
}
24 changes: 24 additions & 0 deletions apis/meta/dependencies.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
Copyright 2021 The Flux authors

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 meta

// ObjectWithDependencies describes a Kubernetes resource object with dependencies.
// +k8s:deepcopy-gen=false
type ObjectWithDependencies interface {
// GetDependsOn returns a NamespacedObjectReference list the object depends on.
GetDependsOn() []NamespacedObjectReference
}
7 changes: 5 additions & 2 deletions apis/meta/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

// Package meta contains the generic metadata APIs for use by
// toolkit components.
// Package meta contains the generic metadata APIs for use by GitOps Toolkit components.
//
// It is intended only to help adhere to Kubernetes API conventions, utility integrations, and Flux project considered
// best practices. It may therefore be suitable for usage by Kubernetes resources with no relationship to the GitOps
// Toolkit.
// +kubebuilder:object:generate=true
package meta
Loading