Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ ifeq (,$(shell which opm 2>/dev/null))
set -e ;\
mkdir -p $(dir $(OPM)) ;\
OS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \
curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.23.0/$${OS}-$${ARCH}-opm ;\
curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.55.0/$${OS}-$${ARCH}-opm ;\
chmod +x $(OPM) ;\
}
else
Expand Down
93 changes: 69 additions & 24 deletions api/v1alpha1/power_monitor_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package v1alpha1

import (
"context"
"fmt"

apierrors "k8s.io/apimachinery/pkg/api/errors"
Expand All @@ -30,55 +31,99 @@ var DefaultSecurityConfig = SecurityConfig{

var pmonLog = logf.Log.WithName("power-monitor-resource")

func (r *PowerMonitor) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
// SetupWebhookWithManager registers the webhook for PowerMonitor in the manager.
func SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).For(&PowerMonitor{}).
WithValidator(&PowerMonitorCustomValidator{}).
WithDefaulter(&PowerMonitorCustomDefaulter{}).
Complete()
}

// +kubebuilder:webhook:path=/mutate-kepler-system-sustainable-computing-io-v1alpha1-powermonitor,mutating=true,failurePolicy=fail,sideEffects=None,groups=kepler.system.sustainable.computing.io,resources=powermonitors,verbs=create;update,versions=v1alpha1,name=mpowermonitor.kb.io,admissionReviewVersions=v1

var _ webhook.Defaulter = &PowerMonitor{}
// PowerMonitorCustomDefaulter struct is responsible for setting default values on the custom resource of the
// Kind PowerMonitor when those are created or updated.
//
// NOTE: The +kubebuilder:object:generate=false marker prevents controller-gen from generating DeepCopy methods,
// as it is used only for temporary operations and does not need to be deeply copied.
type PowerMonitorCustomDefaulter struct {
// TODO(user): Add more fields as needed for defaulting
}

var _ webhook.CustomDefaulter = &PowerMonitorCustomDefaulter{}

// Default implements webhook.Defaulter so a webhook will be registered for the type
func (r *PowerMonitor) Default() {
pmonLog.Info("default", "name", r.Name)
if r.Spec.Kepler.Deployment.Security.Mode == "" {
// Default implements webhook.CustomDefaulter so a webhook will be registered for the Kind PowerMonitor.
func (d *PowerMonitorCustomDefaulter) Default(_ context.Context, obj runtime.Object) error {
powerMonitor, ok := obj.(*PowerMonitor)

if !ok {
return fmt.Errorf("expected a PowerMonitor object but got %T", obj)
}
pmonLog.Info("Defaulting for PowerMonitor", "name", powerMonitor.GetName())

if powerMonitor.Spec.Kepler.Deployment.Security.Mode == "" {
pmonLog.Info("default", "mode", DefaultSecurityConfig.Mode)
r.Spec.Kepler.Deployment.Security.Mode = DefaultSecurityConfig.Mode
powerMonitor.Spec.Kepler.Deployment.Security.Mode = DefaultSecurityConfig.Mode
}
if r.Spec.Kepler.Deployment.Security.AllowedSANames == nil {
if powerMonitor.Spec.Kepler.Deployment.Security.AllowedSANames == nil {
pmonLog.Info("default", "allowed sa", DefaultSecurityConfig.AllowedSANames)
r.Spec.Kepler.Deployment.Security.AllowedSANames = DefaultSecurityConfig.AllowedSANames
powerMonitor.Spec.Kepler.Deployment.Security.AllowedSANames = DefaultSecurityConfig.AllowedSANames
}

return nil
}

// +kubebuilder:webhook:path=/validate-kepler-system-sustainable-computing-io-v1alpha1-powermonitor,mutating=false,failurePolicy=fail,sideEffects=None,groups=kepler.system.sustainable.computing.io,resources=powermonitors,verbs=create;update;delete,versions=v1alpha1,name=vpowermonitor.kb.io,admissionReviewVersions=v1

var _ webhook.Validator = &PowerMonitor{}
// PowerMonitorCustomValidator struct is responsible for validating the PowerMonitor resource
// when it is created, updated, or deleted.
//
// NOTE: The +kubebuilder:object:generate=false marker prevents controller-gen from generating DeepCopy methods,
// as this struct is used only for temporary operations and does not need to be deeply copied.
type PowerMonitorCustomValidator struct {
// TODO(user): Add more fields as needed for validation
}

// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (r *PowerMonitor) ValidateCreate() (admission.Warnings, error) {
pmonLog.Info("validate create", "name", r.Name)
var _ webhook.CustomValidator = &PowerMonitorCustomValidator{}

// Example: Enforce a specific name if needed
if r.Name != PowerMonitorInstanceName {
return nil, apierrors.NewBadRequest(fmt.Sprintf("invalid name %q; name must be %q", r.Name, PowerMonitorInstanceName))
// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type PowerMonitor.
func (v *PowerMonitorCustomValidator) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
powerMonitor, ok := obj.(*PowerMonitor)
if !ok {
return nil, fmt.Errorf("expected a PowerMonitor object but got %T", obj)
}
pmonLog.Info("Validation for PowerMonitor upon creation", "name", powerMonitor.GetName())

// Enforce a specific name if needed
if powerMonitor.Name != PowerMonitorInstanceName {
return nil, apierrors.NewBadRequest(fmt.Sprintf("invalid name %q; name must be %q", powerMonitor.Name, PowerMonitorInstanceName))
}

return nil, nil
}

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (r *PowerMonitor) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
pmonLog.Info("validate update", "name", r.Name)
// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type PowerMonitor.
func (v *PowerMonitorCustomValidator) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
powerMonitor, ok := newObj.(*PowerMonitor)
if !ok {
return nil, fmt.Errorf("expected a PowerMonitor object for the newObj but got %T", newObj)
}
pmonLog.Info("Validation for PowerMonitor upon update", "name", powerMonitor.GetName())

// TODO(user): fill in your validation logic upon object update.

return nil, nil
}

// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (r *PowerMonitor) ValidateDelete() (admission.Warnings, error) {
pmonLog.Info("validate delete", "name", r.Name)
// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type PowerMonitor.
func (v *PowerMonitorCustomValidator) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
powerMonitor, ok := obj.(*PowerMonitor)
if !ok {
return nil, fmt.Errorf("expected a PowerMonitor object but got %T", obj)
}
pmonLog.Info("Validation for PowerMonitor upon deletion", "name", powerMonitor.GetName())

// TODO(user): fill in your validation logic upon object deletion.

return nil, nil
}
30 changes: 30 additions & 0 deletions api/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 bundle.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ LABEL operators.operatorframework.io.bundle.metadata.v1=metadata/
LABEL operators.operatorframework.io.bundle.package.v1=kepler-operator
LABEL operators.operatorframework.io.bundle.channels.v1=alpha
LABEL operators.operatorframework.io.bundle.channel.default.v1=alpha
LABEL operators.operatorframework.io.metrics.builder=operator-sdk-v1.39.1
LABEL operators.operatorframework.io.metrics.builder=operator-sdk-v1.41.1
LABEL operators.operatorframework.io.metrics.mediatype.v1=metrics+v1
LABEL operators.operatorframework.io.metrics.project_layout=go.kubebuilder.io/v4

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
creationTimestamp: null
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: kepler-operator
name: kepler-operator-kepler-admin-role
rules:
- apiGroups:
- kepler.system.sustainable.computing.io
resources:
- keplers
verbs:
- '*'
- apiGroups:
- kepler.system.sustainable.computing.io
resources:
- keplers/status
verbs:
- get
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
creationTimestamp: null
labels:
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: kepler-operator
app.kubernetes.io/instance: kepler-editor-role
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: clusterrole
app.kubernetes.io/part-of: kepler-operator
name: kepler-operator-kepler-editor-role
rules:
- apiGroups:
- kepler.system.sustainable.computing.io
resources:
- keplers
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- kepler.system.sustainable.computing.io
resources:
- keplers/status
verbs:
- get
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
creationTimestamp: null
labels:
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: kepler-operator
app.kubernetes.io/instance: kepler-viewer-role
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: clusterrole
app.kubernetes.io/part-of: kepler-operator
name: kepler-operator-kepler-viewer-role
rules:
- apiGroups:
- kepler.system.sustainable.computing.io
resources:
- keplers
verbs:
- get
- list
- watch
- apiGroups:
- kepler.system.sustainable.computing.io
resources:
- keplers/status
verbs:
- get
10 changes: 5 additions & 5 deletions bundle/manifests/kepler-operator.clusterserviceversion.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ metadata:
capabilities: Seamless Upgrades
categories: Monitoring
containerImage: quay.io/sustainable_computing_io/kepler-operator:0.22.3
createdAt: "2025-10-09T13:54:51Z"
createdAt: "2025-11-13T06:04:17Z"
description: Deploys and Manages Kepler on Kubernetes
operators.operatorframework.io/builder: operator-sdk-v1.39.1
operators.operatorframework.io/builder: operator-sdk-v1.41.1
operators.operatorframework.io/internal-objects: |-
[
"powermonitorinternals.kepler.system.sustainable.computing.io"
Expand Down Expand Up @@ -243,12 +243,12 @@ spec:
periodSeconds: 20
name: manager
ports:
- containerPort: 9443
name: webhook-server
protocol: TCP
- containerPort: 8080
name: metrics
protocol: TCP
- containerPort: 9443
name: webhook-server
protocol: TCP
readinessProbe:
httpGet:
path: /readyz
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.17.2
controller-gen.kubebuilder.io/version: v0.19.0
creationTimestamp: null
name: powermonitorinternals.kepler.system.sustainable.computing.io
spec:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.17.2
controller-gen.kubebuilder.io/version: v0.19.0
creationTimestamp: null
name: powermonitors.kepler.system.sustainable.computing.io
spec:
Expand Down
2 changes: 1 addition & 1 deletion bundle/metadata/annotations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ annotations:
operators.operatorframework.io.bundle.package.v1: kepler-operator
operators.operatorframework.io.bundle.channels.v1: alpha
operators.operatorframework.io.bundle.channel.default.v1: alpha
operators.operatorframework.io.metrics.builder: operator-sdk-v1.39.1
operators.operatorframework.io.metrics.builder: operator-sdk-v1.41.1
operators.operatorframework.io.metrics.mediatype.v1: metrics+v1
operators.operatorframework.io.metrics.project_layout: go.kubebuilder.io/v4

Expand Down
12 changes: 6 additions & 6 deletions bundle/tests/scorecard/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ stages:
- entrypoint:
- scorecard-test
- basic-check-spec
image: quay.io/operator-framework/scorecard-test:v1.35.0
image: quay.io/operator-framework/scorecard-test:v1.41.1
labels:
suite: basic
test: basic-check-spec-test
Expand All @@ -18,7 +18,7 @@ stages:
- entrypoint:
- scorecard-test
- olm-bundle-validation
image: quay.io/operator-framework/scorecard-test:v1.35.0
image: quay.io/operator-framework/scorecard-test:v1.41.1
labels:
suite: olm
test: olm-bundle-validation-test
Expand All @@ -28,7 +28,7 @@ stages:
- entrypoint:
- scorecard-test
- olm-crds-have-validation
image: quay.io/operator-framework/scorecard-test:v1.35.0
image: quay.io/operator-framework/scorecard-test:v1.41.1
labels:
suite: olm
test: olm-crds-have-validation-test
Expand All @@ -38,7 +38,7 @@ stages:
- entrypoint:
- scorecard-test
- olm-crds-have-resources
image: quay.io/operator-framework/scorecard-test:v1.35.0
image: quay.io/operator-framework/scorecard-test:v1.41.1
labels:
suite: olm
test: olm-crds-have-resources-test
Expand All @@ -48,7 +48,7 @@ stages:
- entrypoint:
- scorecard-test
- olm-spec-descriptors
image: quay.io/operator-framework/scorecard-test:v1.35.0
image: quay.io/operator-framework/scorecard-test:v1.41.1
labels:
suite: olm
test: olm-spec-descriptors-test
Expand All @@ -58,7 +58,7 @@ stages:
- entrypoint:
- scorecard-test
- olm-status-descriptors
image: quay.io/operator-framework/scorecard-test:v1.35.0
image: quay.io/operator-framework/scorecard-test:v1.41.1
labels:
suite: olm
test: olm-status-descriptors-test
Expand Down
Loading
Loading