diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 6187064a..27f7c84e 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -9,7 +9,6 @@ rules: resources: - daemonsets - deployments - - secrets verbs: - create - delete @@ -17,6 +16,13 @@ rules: - patch - update - watch +- apiGroups: + - apps + resources: + - secrets + verbs: + - list + - watch - apiGroups: - "" resources: @@ -48,7 +54,6 @@ rules: - nodes/metrics - nodes/proxy - nodes/stats - - secrets verbs: - get - list diff --git a/pkg/components/exporter/exporter.go b/pkg/components/exporter/exporter.go index 89fa4525..47f0c5a5 100644 --- a/pkg/components/exporter/exporter.go +++ b/pkg/components/exporter/exporter.go @@ -36,20 +36,22 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" - "k8s.io/utils/pointer" + "k8s.io/utils/ptr" ) const ( ServicePortName = "http" - overviewDashboardName = "power-monitoring-overview" - nsInfoDashboardName = "power-monitoring-by-ns" - DashboardNs = "openshift-config-managed" - REDFISH_ARGS = "-redfish-cred-file-path=/etc/redfish/redfish.csv" - REDFISH_CSV = "redfish.csv" - REDFISH_ANNOTATION = "kepler.system.sustainable.computing.io/redfish-secret-ref" + overviewDashboardName = "power-monitoring-overview" + nsInfoDashboardName = "power-monitoring-by-ns" + DashboardNs = "openshift-config-managed" + RedfishArgs = "-redfish-cred-file-path=/etc/redfish/redfish.csv" + RedfishCSV = "redfish.csv" + RedfishSecretAnnotation = "kepler.system.sustainable.computing.io/redfish-secret-ref" +) - IdxKeplerContainer = 0 +const ( + KeplerContainerIndex k8s.ContainerIndex = 0 ) var ( @@ -138,15 +140,19 @@ func NewDaemonSet(detail components.Detail, k *v1alpha1.KeplerInternal) *appsv1. } func MountRedfishSecretToDaemonSet(ds *appsv1.DaemonSet, secret *corev1.Secret) { - spec := ds.Spec.Template.Spec - spec.Containers[IdxKeplerContainer].Command = append(spec.Containers[IdxKeplerContainer].Command, REDFISH_ARGS) - spec.Containers[IdxKeplerContainer].VolumeMounts = append(spec.Containers[IdxKeplerContainer].VolumeMounts, - corev1.VolumeMount{Name: "redfish-cred", MountPath: "/etc/redfish", ReadOnly: true}) + spec := &ds.Spec.Template.Spec + keplerContainer := &spec.Containers[KeplerContainerIndex] + keplerContainer.Command = append(keplerContainer.Command, RedfishArgs) + keplerContainer.VolumeMounts = append(keplerContainer.VolumeMounts, + corev1.VolumeMount{Name: "redfish-cred", MountPath: "/etc/redfish", ReadOnly: true}, + ) spec.Volumes = append(spec.Volumes, k8s.VolumeFromSecret("redfish-cred", secret.ObjectMeta.Name)) - ds.Spec.Template.Spec = spec + + // NOTE: annotating the Pods with the secret's resource version + // forces pods to be reployed if the secret chanage ds.Spec.Template.Annotations = map[string]string{ - REDFISH_ANNOTATION: secret.ResourceVersion, + RedfishSecretAnnotation: secret.ResourceVersion, } } @@ -606,7 +612,7 @@ func newExporterContainer(kiName, dsName string, deployment v1alpha1.InternalExp bindAddress := "0.0.0.0:" + strconv.Itoa(int(deployment.Port)) return corev1.Container{ Name: dsName, - SecurityContext: &corev1.SecurityContext{Privileged: pointer.Bool(true)}, + SecurityContext: &corev1.SecurityContext{Privileged: ptr.To(true)}, Image: deployment.Image, Command: []string{ "/usr/bin/kepler", diff --git a/pkg/components/exporter/exporter_test.go b/pkg/components/exporter/exporter_test.go index b0295357..a37e326a 100644 --- a/pkg/components/exporter/exporter_test.go +++ b/pkg/components/exporter/exporter_test.go @@ -208,10 +208,10 @@ func TestDaemonSet(t *testing.T) { actual_hostPID := k8s.HostPIDFromDS(ds) assert.Equal(t, actual_hostPID, tc.hostPID) - actual_exporterCommand := k8s.CommandFromDS(ds, IdxKeplerContainer) + actual_exporterCommand := k8s.CommandFromDS(ds, KeplerContainerIndex) assert.Equal(t, actual_exporterCommand, tc.exporterCommand) - actual_volumeMounts := k8s.VolumeMountsFromDS(ds, IdxKeplerContainer) + actual_volumeMounts := k8s.VolumeMountsFromDS(ds, KeplerContainerIndex) assert.Equal(t, actual_volumeMounts, tc.volumeMounts) actual_Volumes := k8s.VolumesFromDS(ds) diff --git a/pkg/controllers/kepler_internal.go b/pkg/controllers/kepler_internal.go index b8371c3d..565d4ed5 100644 --- a/pkg/controllers/kepler_internal.go +++ b/pkg/controllers/kepler_internal.go @@ -48,12 +48,13 @@ type KeplerInternalReconciler struct { //+kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=*,verbs=* // RBAC for running Kepler exporter -//+kubebuilder:rbac:groups=apps,resources=daemonsets;deployments;secrets,verbs=list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=apps,resources=daemonsets;deployments,verbs=list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=apps,resources=secrets,verbs=list;watch //+kubebuilder:rbac:groups=security.openshift.io,resources=securitycontextconstraints,verbs=list;watch;create;update;patch;delete;use //+kubebuilder:rbac:groups=monitoring.coreos.com,resources=servicemonitors;prometheusrules,verbs=list;watch;create;update;patch;delete // RBAC required by Kepler exporter -//+kubebuilder:rbac:groups=core,resources=nodes/metrics;nodes/proxy;nodes/stats;secrets,verbs=get;list;watch +//+kubebuilder:rbac:groups=core,resources=nodes/metrics;nodes/proxy;nodes/stats,verbs=get;list;watch // SetupWithManager sets up the controller with the Manager. func (r *KeplerInternalReconciler) SetupWithManager(mgr ctrl.Manager) error { diff --git a/pkg/reconciler/reconciler.go b/pkg/reconciler/reconciler.go index 8622bd21..9513684c 100644 --- a/pkg/reconciler/reconciler.go +++ b/pkg/reconciler/reconciler.go @@ -69,7 +69,7 @@ func (r KeplerDaemonSetReconciler) Reconcile(ctx context.Context, cli client.Cli if secret == nil { return Result{Action: Stop, Error: fmt.Errorf("Redfish secret configured, but secret %q not found", secretRef)} } - if _, ok := secret.Data[exporter.REDFISH_CSV]; !ok { + if _, ok := secret.Data[exporter.RedfishCSV]; !ok { return Result{Action: Stop, Error: fmt.Errorf("Redfish secret does not contain \"redfish.csv\"")} } diff --git a/pkg/utils/k8s/k8s.go b/pkg/utils/k8s/k8s.go index 5160f6c8..96e7d5d1 100644 --- a/pkg/utils/k8s/k8s.go +++ b/pkg/utils/k8s/k8s.go @@ -34,6 +34,9 @@ const ( OpenShift ) +// ContainerIndex type represents the hard-coded index of Containers in a PodSpec +type ContainerIndex int + type StringMap map[string]string type SCCAllows struct { @@ -158,7 +161,7 @@ func HostPIDFromDS(ds *appsv1.DaemonSet) bool { return ds.Spec.Template.Spec.HostPID } -func CommandFromDS(ds *appsv1.DaemonSet, index int) []string { +func CommandFromDS(ds *appsv1.DaemonSet, index ContainerIndex) []string { return ds.Spec.Template.Spec.Containers[index].Command } @@ -166,7 +169,7 @@ func AnnotationFromDS(ds *appsv1.DaemonSet) map[string]string { return ds.Spec.Template.Annotations } -func VolumeMountsFromDS(ds *appsv1.DaemonSet, index int) []corev1.VolumeMount { +func VolumeMountsFromDS(ds *appsv1.DaemonSet, index ContainerIndex) []corev1.VolumeMount { return ds.Spec.Template.Spec.Containers[index].VolumeMounts } diff --git a/tests/e2e/kepler_internal_test.go b/tests/e2e/kepler_internal_test.go index 63f6c08e..4fd91493 100644 --- a/tests/e2e/kepler_internal_test.go +++ b/tests/e2e/kepler_internal_test.go @@ -121,13 +121,13 @@ func TestKeplerInternal_ReconciliationWithRedfish(t *testing.T) { containers := ds.Spec.Template.Spec.Containers assert.Equal(t, 1, len(containers)) - exp := containers[exporter.IdxKeplerContainer] - assert.Contains(t, exp.Command, exporter.REDFISH_ARGS) + exp := containers[exporter.KeplerContainerIndex] + assert.Contains(t, exp.Command, exporter.RedfishArgs) assert.Contains(t, exp.VolumeMounts, corev1.VolumeMount{Name: "redfish-cred", MountPath: "/etc/redfish", ReadOnly: true}) assert.Contains(t, ds.Spec.Template.Spec.Volumes, k8s.VolumeFromSecret("redfish-cred", redfishSecret.Name)) - assert.Contains(t, ds.Spec.Template.Annotations, exporter.REDFISH_ANNOTATION) + assert.Contains(t, ds.Spec.Template.Annotations, exporter.RedfishSecretAnnotation) og := ds.Status.ObservedGeneration assert.Equal(t, og, int64(1))