-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Justin Kulikauskas <[email protected]>
- Loading branch information
1 parent
7ea4fed
commit 1ecbc80
Showing
10 changed files
with
273 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
// Copyright Contributors to the Open Cluster Management project | ||
|
||
package compliance | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"time" | ||
|
||
corev1 "k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
|
||
nucleusv1beta1 "open-cluster-management.io/governance-policy-nucleus/api/v1beta1" | ||
) | ||
|
||
// Can't be an interface because then Emit couldn't be a method | ||
type K8sEmitter struct { | ||
Client client.Client // required | ||
Source corev1.EventSource // optional? | ||
|
||
// debatable for inclusion; allows tweaks of the event like adding/removing labels | ||
// if not included, we could skip creating the event, just build it for the user to send | ||
// but if it is included, we can build bigger things on top of this, and still have extensibility | ||
Mutators []func(corev1.Event) (corev1.Event, error) | ||
} | ||
|
||
func (e K8sEmitter) Emit(ctx context.Context, pl nucleusv1beta1.PolicyLike) (*corev1.Event, error) { | ||
plGVK := pl.GetObjectKind().GroupVersionKind() | ||
time := time.Now() | ||
|
||
// This event name matches the convention of recorders from client-go | ||
name := fmt.Sprintf("%v.%x", pl.Parent().Name, time.UnixNano()) | ||
|
||
// The reason must match a pattern looked for by the policy framework | ||
var reason string | ||
if ns := pl.GetNamespace(); ns != "" { | ||
reason = "policy: " + ns + "/" + pl.GetName() | ||
} else { | ||
reason = "policy: " + pl.GetName() | ||
} | ||
|
||
// The message must begin with the compliance, then go into the descriptive message. | ||
message := string(pl.ComplianceState()) + "; " + pl.ComplianceMessage() | ||
|
||
evType := "Normal" | ||
if pl.ComplianceState() != nucleusv1beta1.Compliant { | ||
evType = "Warning" | ||
} | ||
|
||
event := corev1.Event{ | ||
TypeMeta: metav1.TypeMeta{ | ||
Kind: "Event", | ||
APIVersion: "v1", | ||
}, | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: name, | ||
Namespace: pl.ParentNamespace(), | ||
Labels: pl.GetLabels(), | ||
Annotations: pl.GetAnnotations(), | ||
}, | ||
InvolvedObject: corev1.ObjectReference{ | ||
Kind: pl.Parent().Kind, | ||
Namespace: pl.ParentNamespace(), | ||
Name: pl.Parent().Name, | ||
UID: pl.Parent().UID, | ||
APIVersion: pl.Parent().APIVersion, | ||
}, | ||
Reason: reason, | ||
Message: message, | ||
Source: e.Source, | ||
FirstTimestamp: metav1.NewTime(time), | ||
LastTimestamp: metav1.NewTime(time), | ||
Count: 1, | ||
Type: evType, | ||
EventTime: metav1.NewMicroTime(time), // does this break anything? | ||
Series: nil, | ||
Action: "ComplianceStateUpdate", | ||
Related: &corev1.ObjectReference{ | ||
Kind: plGVK.Kind, | ||
Namespace: pl.GetNamespace(), | ||
Name: pl.GetName(), | ||
UID: pl.GetUID(), | ||
APIVersion: plGVK.GroupVersion().String(), | ||
ResourceVersion: pl.GetResourceVersion(), | ||
}, | ||
ReportingController: e.Source.Component, | ||
ReportingInstance: e.Source.Host, | ||
} | ||
|
||
for _, mutatorFunc := range e.Mutators { | ||
var err error | ||
|
||
event, err = mutatorFunc(event) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
err := e.Client.Create(ctx, &event) | ||
|
||
return &event, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// Copyright Contributors to the Open Cluster Management project | ||
|
||
package testutils | ||
|
||
import ( | ||
"context" | ||
"regexp" | ||
"sort" | ||
|
||
corev1 "k8s.io/api/core/v1" | ||
"k8s.io/apimachinery/pkg/types" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
) | ||
|
||
type Toolkit struct { | ||
client.Client | ||
} | ||
|
||
// This regular expression is copied from | ||
// https://github.com/open-cluster-management-io/governance-policy-framework-addon/blob/v0.13.0/controllers/statussync/policy_status_sync.go#L220 | ||
var compEventRegex = regexp.MustCompile(`(?i)^policy:\s*(?:([a-z0-9.-]+)\s*\/)?(.+)`) | ||
|
||
// GetComplianceEvents queries the cluster and returns a sorted list of the kubernetes compliance | ||
// events for the given policy. | ||
func (tk Toolkit) GetComplianceEvents( | ||
ctx context.Context, ns string, parentUID types.UID, templateName string, | ||
) ([]corev1.Event, error) { | ||
list := &corev1.EventList{} | ||
|
||
err := tk.List(ctx, list, client.InNamespace(ns)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
events := make([]corev1.Event, 0) | ||
|
||
for _, event := range list.Items { | ||
event := event | ||
|
||
if event.InvolvedObject.UID != parentUID { | ||
continue | ||
} | ||
|
||
submatch := compEventRegex.FindStringSubmatch(event.Reason) | ||
if submatch != nil && submatch[2] == templateName { | ||
events = append(events, event) | ||
} | ||
} | ||
|
||
sort.SliceStable(events, func(i, j int) bool { | ||
return events[i].Name < events[j].Name | ||
}) | ||
|
||
return events, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// Copyright Contributors to the Open Cluster Management project | ||
|
||
package test |
Oops, something went wrong.