Skip to content

Commit

Permalink
feat: implement expansion template pod status (#2598)
Browse files Browse the repository at this point in the history
Signed-off-by: Davis Haba <52938648+davis-haba@users.noreply.github.com>
Co-authored-by: Rita Zhang <rita.z.zhang@gmail.com>
  • Loading branch information
davis-haba and ritazh committed Apr 5, 2023
1 parent 143e8cf commit 7c519b4
Show file tree
Hide file tree
Showing 49 changed files with 1,753 additions and 437 deletions.
9 changes: 8 additions & 1 deletion apis/expansion/unversioned/expansiontemplate_types.go
Expand Up @@ -16,6 +16,7 @@ limitations under the License.
package unversioned

import (
statusv1alpha1 "github.com/open-policy-agent/gatekeeper/apis/status/v1beta1"
"github.com/open-policy-agent/gatekeeper/pkg/mutation/match"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
Expand Down Expand Up @@ -63,7 +64,13 @@ type ExpansionTemplate struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec ExpansionTemplateSpec `json:"spec,omitempty"`
Spec ExpansionTemplateSpec `json:"spec,omitempty"`
Status ExpansionTemplateStatus `json:"status,omitempty"`
}

// ExpansionTemplateStatus defines the observed state of ExpansionTemplate.
type ExpansionTemplateStatus struct {
ByPod []statusv1alpha1.ExpansionTemplatePodStatusStatus `json:"byPod,omitempty"`
}

// +kubebuilder:object:root=true
Expand Down
24 changes: 24 additions & 0 deletions apis/expansion/unversioned/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Expand Up @@ -16,6 +16,7 @@ limitations under the License.
package v1alpha1

import (
status "github.com/open-policy-agent/gatekeeper/apis/status/v1beta1"
"github.com/open-policy-agent/gatekeeper/pkg/mutation/match"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
Expand Down Expand Up @@ -56,13 +57,21 @@ type GeneratedGVK struct {
// +kubebuilder:object:root=true
// +kubebuilder:resource:path="expansiontemplate"
// +kubebuilder:resource:scope="Cluster"
// +kubebuilder:subresource:status
// +kubebuilder:storageversion

// ExpansionTemplate is the Schema for the ExpansionTemplate API.
type ExpansionTemplate struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec ExpansionTemplateSpec `json:"spec,omitempty"`
Spec ExpansionTemplateSpec `json:"spec,omitempty"`
Status ExpansionTemplateStatus `json:"status,omitempty"`
}

// ExpansionTemplateStatus defines the observed state of ExpansionTemplate.
type ExpansionTemplateStatus struct {
ByPod []status.ExpansionTemplatePodStatusStatus `json:"byPod,omitempty"`
}

// +kubebuilder:object:root=true
Expand Down
37 changes: 37 additions & 0 deletions apis/expansion/v1alpha1/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions apis/expansion/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apis/status/v1beta1/constraintpodstatus_types.go
Expand Up @@ -113,5 +113,5 @@ func KeyForConstraint(id string, constraint *unstructured.Unstructured) (string,
// because K8s requires all lowercase letters for resource names
kind := strings.ToLower(constraint.GetObjectKind().GroupVersionKind().Kind)
name := constraint.GetName()
return dashPacker(id, kind, name)
return DashPacker(id, kind, name)
}
2 changes: 1 addition & 1 deletion apis/status/v1beta1/constrainttemplatepodstatus_types.go
Expand Up @@ -88,5 +88,5 @@ func NewConstraintTemplateStatusForPod(pod *corev1.Pod, templateName string, sch
// KeyForConstraintTemplate returns a unique status object name given the Pod ID and
// a template object.
func KeyForConstraintTemplate(id string, templateName string) (string, error) {
return dashPacker(id, templateName)
return DashPacker(id, templateName)
}
83 changes: 83 additions & 0 deletions apis/status/v1beta1/expansiontemplatepodstatus_types.go
@@ -0,0 +1,83 @@
package v1beta1

import (
"github.com/open-policy-agent/gatekeeper/pkg/operations"
"github.com/open-policy-agent/gatekeeper/pkg/util"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)

// ExpansionTemplatePodStatusStatus defines the observed state of ExpansionTemplatePodStatus.
type ExpansionTemplatePodStatusStatus struct {
// Important: Run "make" to regenerate code after modifying this file
ID string `json:"id,omitempty"`
TemplateUID types.UID `json:"templateUID,omitempty"`
Operations []string `json:"operations,omitempty"`
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
Errors []*ExpansionTemplateError `json:"errors,omitempty"`
}

// +kubebuilder:object:generate=true

type ExpansionTemplateError struct {
Type string `json:"type,omitempty"`
Message string `json:"message"`
}

// +kubebuilder:object:root=true
// +kubebuilder:resource:scope=Namespaced

// ExpansionTemplatePodStatus is the Schema for the expansiontemplatepodstatuses API.
type ExpansionTemplatePodStatus struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Status ExpansionTemplatePodStatusStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

// ExpansionTemplatePodStatusList contains a list of ExpansionTemplatePodStatus.
type ExpansionTemplatePodStatusList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ExpansionTemplatePodStatus `json:"items"`
}

func init() {
SchemeBuilder.Register(&ExpansionTemplatePodStatus{}, &ExpansionTemplatePodStatusList{})
}

// NewExpansionTemplateStatusForPod returns an expansion template status object
// that has been initialized with the bare minimum of fields to make it functional
// with the expansion template status controller.
func NewExpansionTemplateStatusForPod(pod *corev1.Pod, templateName string, scheme *runtime.Scheme) (*ExpansionTemplatePodStatus, error) {
obj := &ExpansionTemplatePodStatus{}
name, err := KeyForExpansionTemplate(pod.Name, templateName)
if err != nil {
return nil, err
}
obj.SetName(name)
obj.SetNamespace(util.GetNamespace())
obj.Status.ID = pod.Name
obj.Status.Operations = operations.AssignedStringList()
obj.SetLabels(map[string]string{
ExpansionTemplateNameLabel: templateName,
PodLabel: pod.Name,
})

if err := controllerutil.SetOwnerReference(pod, obj, scheme); err != nil {
return nil, err
}

return obj, nil
}

// KeyForExpansionTemplate returns a unique status object name given the Pod ID and
// a template object.
func KeyForExpansionTemplate(id string, templateName string) (string, error) {
return DashPacker(id, templateName)
}
1 change: 1 addition & 0 deletions apis/status/v1beta1/labels.go
Expand Up @@ -2,6 +2,7 @@ package v1beta1

// Label keys used for internal gatekeeper operations.
const (
ExpansionTemplateNameLabel = "internal.gatekeeper.sh/expansiontemplate-name"
ConstraintNameLabel = "internal.gatekeeper.sh/constraint-name"
ConstraintKindLabel = "internal.gatekeeper.sh/constraint-kind"
ConstraintTemplateNameLabel = "internal.gatekeeper.sh/constrainttemplate-name"
Expand Down
2 changes: 1 addition & 1 deletion apis/status/v1beta1/mutatorpodstatus_types.go
Expand Up @@ -113,5 +113,5 @@ func KeyForMutatorID(id string, mID mtypes.ID) (string, error) {
// We must do this because K8s requires all lowercase letters for resource names
kind := strings.ToLower(mID.Kind)
name := mID.Name
return dashPacker(id, kind, name)
return DashPacker(id, kind, name)
}
10 changes: 5 additions & 5 deletions apis/status/v1beta1/util.go
Expand Up @@ -32,7 +32,7 @@ func dashExtractor(val string) []string {
return tokens
}

// dashPacker puts a list of strings into a dash-separated format. Note that
// DashPacker puts a list of strings into a dash-separated format. Note that
// it cannot handle empty strings, as that makes the dash separator for the empty
// string reduce to an escaped dash. This is fine because none of the packed strings
// are allowed to be empty. If this changes in the future, we could create a placeholder
Expand All @@ -43,17 +43,17 @@ func dashExtractor(val string) []string {
// which is also disallowed by the schema (and would require an additional placeholder
// character to fix). Finally, note that it is impossible to distinguish between
// a nil list of strings and a list of one empty string.
func dashPacker(vals ...string) (string, error) {
func DashPacker(vals ...string) (string, error) {
if len(vals) == 0 {
return "", fmt.Errorf("dashPacker cannot pack an empty list of strings")
return "", fmt.Errorf("DashPacker cannot pack an empty list of strings")
}
b := strings.Builder{}
for i, val := range vals {
if strings.HasPrefix(val, "-") || strings.HasSuffix(val, "-") {
return "", fmt.Errorf("dashPacker cannot pack strings that begin or end with a dash: %+v", vals)
return "", fmt.Errorf("DashPacker cannot pack strings that begin or end with a dash: %+v", vals)
}
if len(val) == 0 {
return "", fmt.Errorf("dashPacker cannot pack empty strings: %v", vals)
return "", fmt.Errorf("DashPacker cannot pack empty strings: %v", vals)
}
if i != 0 {
b.WriteString("-")
Expand Down
4 changes: 2 additions & 2 deletions apis/status/v1beta1/util_test.go
Expand Up @@ -91,12 +91,12 @@ var dashingTestCases = []struct {
func TestDashPacker(t *testing.T) {
for _, tc := range dashingTestCases {
t.Run(tc.name, func(t *testing.T) {
gotPacked, err := dashPacker(tc.extracted...)
gotPacked, err := DashPacker(tc.extracted...)
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(tc.packed, gotPacked); diff != "" {
t.Fatal("got dashPacker(tc.extracted...) != tc.packed, want equal")
t.Fatal("got DashPacker(tc.extracted...) != tc.packed, want equal")
}
})
}
Expand Down

0 comments on commit 7c519b4

Please sign in to comment.