1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-14 11:57:48 +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:
Khaled Emara 2024-02-27 20:24:39 +02:00 committed by GitHub
parent 0a5e47ba1e
commit 511df7a466
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 127 additions and 8 deletions

View file

@ -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)

View file

@ -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"`
}

View file

@ -268,6 +268,7 @@ func (in *GlobalContextEntryStatus) DeepCopyInto(out *GlobalContextEntryStatus)
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
in.LastRefreshTime.DeepCopyInto(&out.LastRefreshTime)
return
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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>

View file

@ -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>

View file

@ -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
}

View file

@ -4,4 +4,5 @@ const (
ReasonResourceListFailure = "FailedToList"
ReasonAPICallFailure = "FailedToCallAPI"
ReasonCacheSyncFailure = "FailedToWaitForCacheSync"
ReasonInformerRunFailure = "ReasonInformerRunFailure"
)

View file

@ -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
})

View file

@ -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 {

View file

@ -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
}