···11+/*
22+Copyright 2025.
33+44+Licensed under the Apache License, Version 2.0 (the "License");
55+you may not use this file except in compliance with the License.
66+You may obtain a copy of the License at
77+88+ http://www.apache.org/licenses/LICENSE-2.0
99+1010+Unless required by applicable law or agreed to in writing, software
1111+distributed under the License is distributed on an "AS IS" BASIS,
1212+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313+See the License for the specific language governing permissions and
1414+limitations under the License.
1515+*/
1616+1717+package controller
1818+1919+import (
2020+ "context"
2121+ "os"
2222+2323+ appsv1 "k8s.io/api/apps/v1"
2424+ "sigs.k8s.io/controller-runtime/pkg/client"
2525+ "sigs.k8s.io/controller-runtime/pkg/log"
2626+)
2727+2828+const defaultImage = "ghcr.io/evanjarrett/hsm-secrets-operator:latest"
2929+3030+// ImageResolver provides functionality to resolve container images
3131+type ImageResolver struct {
3232+ Client client.Client
3333+}
3434+3535+// NewImageResolver creates a new ImageResolver
3636+func NewImageResolver(k8sClient client.Client) *ImageResolver {
3737+ return &ImageResolver{
3838+ Client: k8sClient,
3939+ }
4040+}
4141+4242+// GetManagerImage attempts to detect the manager's running image by looking for manager deployments
4343+func (r *ImageResolver) GetManagerImage(ctx context.Context) string {
4444+ logger := log.FromContext(ctx)
4545+4646+ // Get manager deployment by looking for deployments with manager labels
4747+ deployments := &appsv1.DeploymentList{}
4848+ listOpts := []client.ListOption{
4949+ client.MatchingLabels{
5050+ "app.kubernetes.io/name": "hsm-secrets-operator",
5151+ "app.kubernetes.io/component": "manager",
5252+ },
5353+ }
5454+5555+ if err := r.Client.List(ctx, deployments, listOpts...); err != nil {
5656+ logger.V(1).Info("Failed to list manager deployments for image detection", "error", err)
5757+ return ""
5858+ }
5959+6060+ // Find the manager container and extract its image
6161+ for _, deployment := range deployments.Items {
6262+ for _, container := range deployment.Spec.Template.Spec.Containers {
6363+ if container.Name == "manager" {
6464+ logger.V(1).Info("Detected manager image", "image", container.Image)
6565+ return container.Image
6666+ }
6767+ }
6868+ }
6969+7070+ logger.V(1).Info("Could not detect manager image")
7171+ return ""
7272+}
7373+7474+func (r *ImageResolver) GetImage(ctx context.Context, env string) string {
7575+ // Try environment variable first
7676+ if discoveryImage := os.Getenv(env); discoveryImage != "" {
7777+ return discoveryImage
7878+ }
7979+8080+ // Try to detect the manager's running image as fallback
8181+ if managerImage := r.GetManagerImage(ctx); managerImage != "" {
8282+ return managerImage
8383+ }
8484+8585+ // last resort
8686+ return defaultImage
8787+}