Skip to content

Commit 34837c2

Browse files
authored
Merge pull request kubernetes-retired#197 from erikgb/refactor/conditions
Use in-tree metav1.Condition instead of custom copied type
2 parents 5e98248 + 8bddee6 commit 34837c2

File tree

9 files changed

+44
-126
lines changed

9 files changed

+44
-126
lines changed

api/v1alpha2/hierarchy_types.go

+1-91
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ limitations under the License.
1616
package v1alpha2
1717

1818
import (
19-
"fmt"
20-
2119
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2220
)
2321

@@ -152,7 +150,7 @@ type HierarchyConfigurationStatus struct {
152150
Children []string `json:"children,omitempty"`
153151

154152
// Conditions describes the errors, if any.
155-
Conditions []Condition `json:"conditions,omitempty"`
153+
Conditions []metav1.Condition `json:"conditions,omitempty"`
156154
}
157155

158156
// +kubebuilder:object:root=true
@@ -176,94 +174,6 @@ type MetaKVP struct {
176174
Value string `json:"value"`
177175
}
178176

179-
// metav1.Condition is introduced in k8s.io/apimachinery v0.20.0-alpha.1 and we
180-
// don't want to take a dependency on it yet, thus we copied the below struct from
181-
// https://github.com/kubernetes/apimachinery/blob/master/pkg/apis/meta/v1/types.go:
182-
183-
// Condition contains details for one aspect of the current state of this API Resource.
184-
// ---
185-
// This struct is intended for direct use as an array at the field path .status.conditions. For example,
186-
// type FooStatus struct{
187-
// // Represents the observations of a foo's current state.
188-
// // Known .status.conditions.type are: "Available", "Progressing", and "Degraded"
189-
// // +patchMergeKey=type
190-
// // +patchStrategy=merge
191-
// // +listType=map
192-
// // +listMapKey=type
193-
// Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
194-
//
195-
// // other fields
196-
// }
197-
type Condition struct {
198-
// type of condition in CamelCase or in foo.example.com/CamelCase.
199-
// ---
200-
// Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
201-
// useful (see .node.status.conditions), the ability to deconflict is important.
202-
// The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
203-
// +required
204-
// +kubebuilder:validation:Required
205-
// +kubebuilder:validation: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])$`
206-
// +kubebuilder:validation:MaxLength=316
207-
Type string `json:"type" protobuf:"bytes,1,opt,name=type"`
208-
// status of the condition, one of True, False, Unknown.
209-
// +required
210-
// +kubebuilder:validation:Required
211-
// +kubebuilder:validation:Enum=True;False;Unknown
212-
Status metav1.ConditionStatus `json:"status" protobuf:"bytes,2,opt,name=status"`
213-
// observedGeneration represents the .metadata.generation that the condition was set based upon.
214-
// For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
215-
// with respect to the current state of the instance.
216-
// +optional
217-
// +kubebuilder:validation:Minimum=0
218-
ObservedGeneration int64 `json:"observedGeneration,omitempty" protobuf:"varint,3,opt,name=observedGeneration"`
219-
// lastTransitionTime is the last time the condition transitioned from one status to another.
220-
// This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
221-
// +required
222-
// +kubebuilder:validation:Required
223-
// +kubebuilder:validation:Type=string
224-
// +kubebuilder:validation:Format=date-time
225-
LastTransitionTime metav1.Time `json:"lastTransitionTime" protobuf:"bytes,4,opt,name=lastTransitionTime"`
226-
// reason contains a programmatic identifier indicating the reason for the condition's last transition.
227-
// Producers of specific condition types may define expected values and meanings for this field,
228-
// and whether the values are considered a guaranteed API.
229-
// The value should be a CamelCase string.
230-
// This field may not be empty.
231-
// +required
232-
// +kubebuilder:validation:Required
233-
// +kubebuilder:validation:MaxLength=1024
234-
// +kubebuilder:validation:MinLength=1
235-
// +kubebuilder:validation:Pattern=`^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$`
236-
Reason string `json:"reason" protobuf:"bytes,5,opt,name=reason"`
237-
// message is a human readable message indicating details about the transition.
238-
// This may be an empty string.
239-
// +required
240-
// +kubebuilder:validation:Required
241-
// +kubebuilder:validation:MaxLength=32768
242-
Message string `json:"message" protobuf:"bytes,6,opt,name=message"`
243-
}
244-
245-
// NewCondition fills some required field with default values for schema
246-
// validation, e.g. Status and LastTransitionTime.
247-
func NewCondition(tp, reason, msg string) Condition {
248-
return Condition{
249-
Type: tp,
250-
Status: "True",
251-
// Set time as an obviously wrong value 1970-01-01T00:00:00Z since we
252-
// overwrite conditions every time.
253-
LastTransitionTime: metav1.Unix(0, 0),
254-
Reason: reason,
255-
Message: msg,
256-
}
257-
}
258-
259-
func (c Condition) String() string {
260-
msg := c.Message
261-
if len(msg) > 100 {
262-
msg = msg[:100] + "..."
263-
}
264-
return fmt.Sprintf("%s (%s): %s", c.Type, c.Reason, msg)
265-
}
266-
267177
func init() {
268178
SchemeBuilder.Register(&HierarchyConfiguration{}, &HierarchyConfigurationList{})
269179
}

api/v1alpha2/hnc_config.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ type HNCConfigurationStatus struct {
159159
// affected namespaces. The HierarchyConfiguration object in each of the
160160
// affected namespaces will have more information. To learn more about
161161
// conditions, see https://github.com/kubernetes-sigs/hierarchical-namespaces/blob/master/docs/user-guide/concepts.md#admin-conditions.
162-
Conditions []Condition `json:"conditions,omitempty"`
162+
Conditions []metav1.Condition `json:"conditions,omitempty"`
163163
}
164164

165165
// +kubebuilder:object:root=true

api/v1alpha2/zz_generated.deepcopy.go

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

internal/forest/namespace.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"strconv"
66
"strings"
77

8+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
89
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
910
"k8s.io/apimachinery/pkg/labels"
1011
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -46,7 +47,7 @@ type Namespace struct {
4647

4748
// conditions store conditions so that object propagation can be disabled if there's a problem
4849
// on this namespace.
49-
conditions []api.Condition
50+
conditions []metav1.Condition
5051

5152
// IsSub indicates that this namespace is being or was created solely to live as a
5253
// subnamespace of the specified parent.

internal/forest/namespaceconditions.go

+21-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ package forest
33
import (
44
"fmt"
55

6+
"k8s.io/apimachinery/pkg/api/meta"
7+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
8+
69
api "sigs.k8s.io/hierarchical-namespaces/api/v1alpha2"
710
)
811

@@ -41,7 +44,13 @@ func (ns *Namespace) SetCondition(tp, reason, msg string) {
4144
if reason == api.ReasonAncestor {
4245
return
4346
}
44-
ns.conditions = append(ns.conditions, api.NewCondition(tp, reason, msg))
47+
c := metav1.Condition{
48+
Type: tp,
49+
Status: metav1.ConditionTrue,
50+
Reason: reason,
51+
Message: msg,
52+
}
53+
meta.SetStatusCondition(&ns.conditions, c)
4554
}
4655

4756
// ClearConditions set conditions to nil.
@@ -50,12 +59,19 @@ func (ns *Namespace) ClearConditions() {
5059
}
5160

5261
// Conditions returns a full list of the conditions in the namespace.
53-
func (ns *Namespace) Conditions() []api.Condition {
62+
func (ns *Namespace) Conditions() []metav1.Condition {
5463
if root := ns.GetHaltedRoot(); root != "" && root != ns.name {
55-
msg := fmt.Sprintf("Propagation paused in %q and its descendants due to ActivitiesHalted condition on ancestor %q", ns.name, root)
56-
ret := []api.Condition{api.NewCondition(api.ConditionActivitiesHalted, api.ReasonAncestor, msg)}
64+
ret := []metav1.Condition{{
65+
Type: api.ConditionActivitiesHalted,
66+
Status: metav1.ConditionTrue,
67+
// TODO(adrianludwin) Review; Some callers require this field to be set - since it is mandatory in the API
68+
// Set time as an obviously wrong value 1970-01-01T00:00:00Z since we
69+
// overwrite conditions every time.
70+
LastTransitionTime: metav1.Unix(0, 0),
71+
Reason: api.ReasonAncestor,
72+
Message: fmt.Sprintf("Propagation paused in %q and its descendants due to ActivitiesHalted condition on ancestor %q", ns.name, root),
73+
}}
5774
return append(ret, ns.conditions...)
5875
}
59-
6076
return ns.conditions
6177
}

internal/hncconfig/reconciler.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
1212
"k8s.io/apimachinery/pkg/api/errors"
1313
"k8s.io/apimachinery/pkg/api/meta"
14+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1415
"k8s.io/apimachinery/pkg/runtime/schema"
1516
"k8s.io/apimachinery/pkg/types"
1617
ctrl "sigs.k8s.io/controller-runtime"
@@ -357,7 +358,13 @@ func (r *Reconciler) createObjectReconciler(gvk schema.GroupVersionKind, mode ap
357358
}
358359

359360
func (r *Reconciler) writeCondition(inst *api.HNCConfiguration, tp, reason, msg string) {
360-
inst.Status.Conditions = append(inst.Status.Conditions, api.NewCondition(tp, reason, msg))
361+
c := metav1.Condition{
362+
Type: tp,
363+
Status: metav1.ConditionTrue,
364+
Reason: reason,
365+
Message: msg,
366+
}
367+
meta.SetStatusCondition(&inst.Status.Conditions, c)
361368
}
362369

363370
// setTypeStatuses adds Status.Resources for types configured in the spec. Only the status of types

internal/kubectl/describe.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import (
2828
"k8s.io/api/core/v1"
2929
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3030
"k8s.io/apimachinery/pkg/util/duration"
31-
api "sigs.k8s.io/hierarchical-namespaces/api/v1alpha2"
3231
)
3332

3433
var describeCmd = &cobra.Command{
@@ -83,7 +82,7 @@ var describeCmd = &cobra.Command{
8382
},
8483
}
8584

86-
func describeConditions(cond []api.Condition) {
85+
func describeConditions(cond []metav1.Condition) {
8786
if len(cond) == 0 {
8887
fmt.Printf(" No conditions\n")
8988
return

internal/objects/reconciler.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424

2525
"github.com/go-logr/logr"
2626
"k8s.io/apimachinery/pkg/api/errors"
27-
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2828
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2929
"k8s.io/apimachinery/pkg/runtime/schema"
3030
"k8s.io/apimachinery/pkg/types"
@@ -310,7 +310,7 @@ func (r *Reconciler) skipNamespace(log logr.Logger, inst *unstructured.Unstructu
310310
// modify `inst`.
311311
func (r *Reconciler) syncMissingObject(log logr.Logger, inst *unstructured.Unstructured) syncAction {
312312
// If the object exists, skip.
313-
if inst.GetCreationTimestamp() != (v1.Time{}) {
313+
if inst.GetCreationTimestamp() != (metav1.Time{}) {
314314
return actionUnknown
315315
}
316316

@@ -435,7 +435,7 @@ func (r *Reconciler) syncPropagated(inst, srcInst *unstructured.Unstructured) (s
435435
}
436436

437437
// If an object doesn't exist, assume it's been deleted or not yet created.
438-
exists := inst.GetCreationTimestamp() != v1.Time{}
438+
exists := inst.GetCreationTimestamp() != metav1.Time{}
439439

440440
// If the copy does not exist, or is different from the source, return the write action and the
441441
// source instance. Note that DeepEqual could return `true` even if the object doesn't exist if
@@ -594,7 +594,7 @@ func (r *Reconciler) deleteObject(ctx context.Context, log logr.Logger, inst *un
594594

595595
func (r *Reconciler) writeObject(ctx context.Context, log logr.Logger, inst, srcInst *unstructured.Unstructured) error {
596596
// The object exists if CreationTimestamp is set. This flag enables us to have only 1 API call.
597-
exist := inst.GetCreationTimestamp() != v1.Time{}
597+
exist := inst.GetCreationTimestamp() != metav1.Time{}
598598
ns := inst.GetNamespace()
599599
// Get current ResourceVersion, required for updates for newer API objects (including custom resources).
600600
rv := inst.GetResourceVersion()

internal/selectors/selectors.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"strconv"
88
"strings"
99

10-
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1111
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1212
"k8s.io/apimachinery/pkg/labels"
1313
"k8s.io/apimachinery/pkg/util/validation"
@@ -126,11 +126,11 @@ func GetSelector(inst *unstructured.Unstructured) (labels.Selector, error) {
126126
// getSelectorFromString converts the given string to a selector
127127
// Note: any invalid Selector value will cause this object not propagating to any child namespace
128128
func getSelectorFromString(str string) (labels.Selector, error) {
129-
labelSelector, err := v1.ParseToLabelSelector(str)
129+
labelSelector, err := metav1.ParseToLabelSelector(str)
130130
if err != nil {
131131
return nil, err
132132
}
133-
selector, err := v1.LabelSelectorAsSelector(labelSelector)
133+
selector, err := metav1.LabelSelectorAsSelector(labelSelector)
134134
if err != nil {
135135
return nil, err
136136
}

0 commit comments

Comments
 (0)