mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-15 17:51:20 +00:00
fix(globalcontext): old WaitGroup not stopping (#9813)
* fix(globalcontext): old waitgroup not stopping Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * chore(globalcontext): add AGE Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * feat(globalcontext): add lastRefreshTime Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * fix(globalcontext): unhandled intormer run exception Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * chore(globalcontext): comment wording Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * chore(globalcontext): codegen Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> * fix(globalcontext): linter Signed-off-by: Khaled Emara <khaled.emara@nirmata.com> --------- Signed-off-by: Khaled Emara <khaled.emara@nirmata.com>
This commit is contained in:
parent
0a5e47ba1e
commit
511df7a466
13 changed files with 127 additions and 8 deletions
|
@ -22,6 +22,9 @@ type GlobalContextEntryStatus struct {
|
|||
Ready bool `json:"ready" yaml:"ready"`
|
||||
// +optional
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty"`
|
||||
// Indicates the time when the globalcontextentry was last refreshed successfully for the API Call
|
||||
// +optional
|
||||
LastRefreshTime metav1.Time `json:"lastRefreshTime,omitempty"`
|
||||
}
|
||||
|
||||
func (status *GlobalContextEntryStatus) SetReady(ready bool, message string) {
|
||||
|
@ -40,6 +43,10 @@ func (status *GlobalContextEntryStatus) SetReady(ready bool, message string) {
|
|||
meta.SetStatusCondition(&status.Conditions, condition)
|
||||
}
|
||||
|
||||
func (status *GlobalContextEntryStatus) UpdateRefreshTime() {
|
||||
status.LastRefreshTime = metav1.Now()
|
||||
}
|
||||
|
||||
// IsReady indicates if the globalcontextentry has loaded
|
||||
func (status *GlobalContextEntryStatus) IsReady() bool {
|
||||
condition := meta.FindStatusCondition(status.Conditions, GlobalContextEntryConditionReady)
|
||||
|
|
|
@ -30,6 +30,8 @@ import (
|
|||
// +kubebuilder:resource:shortName=gctxentry,categories=kyverno,scope="Cluster"
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:printcolumn:name="READY",type=string,JSONPath=`.status.conditions[?(@.type == "Ready")].status`
|
||||
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
|
||||
// +kubebuilder:printcolumn:name="REFRESH",type="date",JSONPath=".status.lastRefreshTime"
|
||||
|
||||
// GlobalContextEntry declares resources to be cached.
|
||||
type GlobalContextEntry struct {
|
||||
|
@ -116,6 +118,7 @@ type KubernetesResource struct {
|
|||
Resource string `json:"resource,omitempty"`
|
||||
// Namespace defines the namespace of the resource. Leave empty for cluster scoped resources.
|
||||
// +kubebuilder:validation:Optional
|
||||
// +optional
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
}
|
||||
|
||||
|
|
|
@ -268,6 +268,7 @@ func (in *GlobalContextEntryStatus) DeepCopyInto(out *GlobalContextEntryStatus)
|
|||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
in.LastRefreshTime.DeepCopyInto(&out.LastRefreshTime)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,12 @@ spec:
|
|||
- jsonPath: .status.conditions[?(@.type == "Ready")].status
|
||||
name: READY
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: AGE
|
||||
type: date
|
||||
- jsonPath: .status.lastRefreshTime
|
||||
name: REFRESH
|
||||
type: date
|
||||
name: v2alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
|
@ -192,6 +198,11 @@ spec:
|
|||
- type
|
||||
type: object
|
||||
type: array
|
||||
lastRefreshTime:
|
||||
description: Indicates the time when the globalcontextentry was last
|
||||
refreshed successfully for the API Call
|
||||
format: date-time
|
||||
type: string
|
||||
ready:
|
||||
description: Deprecated in favor of Conditions
|
||||
type: boolean
|
||||
|
|
|
@ -22,6 +22,12 @@ spec:
|
|||
- jsonPath: .status.conditions[?(@.type == "Ready")].status
|
||||
name: READY
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: AGE
|
||||
type: date
|
||||
- jsonPath: .status.lastRefreshTime
|
||||
name: REFRESH
|
||||
type: date
|
||||
name: v2alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
|
@ -186,6 +192,11 @@ spec:
|
|||
- type
|
||||
type: object
|
||||
type: array
|
||||
lastRefreshTime:
|
||||
description: Indicates the time when the globalcontextentry was last
|
||||
refreshed successfully for the API Call
|
||||
format: date-time
|
||||
type: string
|
||||
ready:
|
||||
description: Deprecated in favor of Conditions
|
||||
type: boolean
|
||||
|
|
|
@ -28587,6 +28587,12 @@ spec:
|
|||
- jsonPath: .status.conditions[?(@.type == "Ready")].status
|
||||
name: READY
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: AGE
|
||||
type: date
|
||||
- jsonPath: .status.lastRefreshTime
|
||||
name: REFRESH
|
||||
type: date
|
||||
name: v2alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
|
@ -28751,6 +28757,11 @@ spec:
|
|||
- type
|
||||
type: object
|
||||
type: array
|
||||
lastRefreshTime:
|
||||
description: Indicates the time when the globalcontextentry was last
|
||||
refreshed successfully for the API Call
|
||||
format: date-time
|
||||
type: string
|
||||
ready:
|
||||
description: Deprecated in favor of Conditions
|
||||
type: boolean
|
||||
|
|
|
@ -8162,6 +8162,20 @@ bool
|
|||
<em>(Optional)</em>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>lastRefreshTime</code><br/>
|
||||
<em>
|
||||
<a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#time-v1-meta">
|
||||
Kubernetes meta/v1.Time
|
||||
</a>
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Indicates the time when the globalcontextentry was last refreshed successfully for the API Call</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr />
|
||||
|
@ -8223,6 +8237,7 @@ string
|
|||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>Namespace defines the namespace of the resource. Leave empty for cluster scoped resources.</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -1353,6 +1353,33 @@ Applicable only to policies that have validate.podSecurity subrule.</p>
|
|||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<td><code>lastRefreshTime</code>
|
||||
|
||||
</br>
|
||||
|
||||
|
||||
|
||||
|
||||
<span style="font-family: monospace">meta/v1.Time</span>
|
||||
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
|
||||
<p>Indicates the time when the globalcontextentry was last refreshed successfully for the API Call</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
@ -1485,8 +1512,6 @@ Applicable only to policies that have validate.podSecurity subrule.</p>
|
|||
<tr>
|
||||
<td><code>namespace</code>
|
||||
|
||||
<span style="color:blue;"> *</span>
|
||||
|
||||
</br>
|
||||
|
||||
|
||||
|
|
|
@ -25,8 +25,9 @@ import (
|
|||
// GlobalContextEntryStatusApplyConfiguration represents an declarative configuration of the GlobalContextEntryStatus type for use
|
||||
// with apply.
|
||||
type GlobalContextEntryStatusApplyConfiguration struct {
|
||||
Ready *bool `json:"ready,omitempty"`
|
||||
Conditions []v1.Condition `json:"conditions,omitempty"`
|
||||
Ready *bool `json:"ready,omitempty"`
|
||||
Conditions []v1.Condition `json:"conditions,omitempty"`
|
||||
LastRefreshTime *v1.Time `json:"lastRefreshTime,omitempty"`
|
||||
}
|
||||
|
||||
// GlobalContextEntryStatusApplyConfiguration constructs an declarative configuration of the GlobalContextEntryStatus type for use with
|
||||
|
@ -52,3 +53,11 @@ func (b *GlobalContextEntryStatusApplyConfiguration) WithConditions(values ...v1
|
|||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// WithLastRefreshTime sets the LastRefreshTime field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the LastRefreshTime field is set to the value of the last call.
|
||||
func (b *GlobalContextEntryStatusApplyConfiguration) WithLastRefreshTime(value v1.Time) *GlobalContextEntryStatusApplyConfiguration {
|
||||
b.LastRefreshTime = &value
|
||||
return b
|
||||
}
|
||||
|
|
|
@ -4,4 +4,5 @@ const (
|
|||
ReasonResourceListFailure = "FailedToList"
|
||||
ReasonAPICallFailure = "FailedToCallAPI"
|
||||
ReasonCacheSyncFailure = "FailedToWaitForCacheSync"
|
||||
ReasonInformerRunFailure = "ReasonInformerRunFailure"
|
||||
)
|
||||
|
|
|
@ -140,6 +140,9 @@ func updateStatus(ctx context.Context, gceName string, kyvernoClient versioned.I
|
|||
return fmt.Errorf("failed to update status: %s", latestGCE.Name)
|
||||
}
|
||||
latest.Status.SetReady(ready, reason)
|
||||
if ready {
|
||||
latest.Status.UpdateRefreshTime()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
"github.com/kyverno/kyverno/pkg/event"
|
||||
entryevent "github.com/kyverno/kyverno/pkg/globalcontext/event"
|
||||
"github.com/kyverno/kyverno/pkg/globalcontext/invalid"
|
||||
"github.com/kyverno/kyverno/pkg/globalcontext/store"
|
||||
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
@ -56,6 +55,29 @@ func New(
|
|||
// Wait for the group to terminate
|
||||
group.Wait()
|
||||
}
|
||||
err := informer.Informer().SetWatchErrorHandler(func(r *cache.Reflector, err error) {
|
||||
cancel()
|
||||
|
||||
if shouldUpdateStatus {
|
||||
if err := updateStatus(context.Background(), gce, kyvernoClient, false, "CacheSyncFailure"); err != nil {
|
||||
logger.Error(err, "failed to update status")
|
||||
}
|
||||
}
|
||||
|
||||
eventErr := fmt.Errorf("failed to run informer for %s", gvr)
|
||||
eventGen.Add(entryevent.NewErrorEvent(corev1.ObjectReference{
|
||||
APIVersion: gce.APIVersion,
|
||||
Kind: gce.Kind,
|
||||
Name: gce.Name,
|
||||
Namespace: gce.Namespace,
|
||||
UID: gce.UID,
|
||||
}, entryevent.ReasonInformerRunFailure, eventErr))
|
||||
})
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to set watch error handler")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
group.StartWithContext(ctx, func(ctx context.Context) {
|
||||
informer.Informer().Run(ctx.Done())
|
||||
})
|
||||
|
@ -77,7 +99,7 @@ func New(
|
|||
UID: gce.UID,
|
||||
}, entryevent.ReasonCacheSyncFailure, err))
|
||||
|
||||
return invalid.New(err), nil
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if shouldUpdateStatus {
|
||||
|
|
|
@ -25,9 +25,9 @@ func (l *store) Set(key string, val Entry) {
|
|||
l.Lock()
|
||||
defer l.Unlock()
|
||||
old := l.store[key]
|
||||
// If the key already exists, skip it before replacing it
|
||||
// If the key already exists, stop it before replacing it
|
||||
if old != nil {
|
||||
val.Stop()
|
||||
old.Stop()
|
||||
}
|
||||
l.store[key] = val
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue