This file provides guidance on the Konflux Image Controller operator.
The operator is a part of Konflux project and is responsible for management of OCI image repositories based on ImageRepository objects in cluster.
Currently it supports only Quay compatible OCI registries: quay.io and self-hosted instances.
cmd/main.gooperator entrypoint, contains startup logic and global settings.internal/controllercontrollers, main reconcile logic.pkg/quayquay API client implementation.pkg/metricsmetrics and availability probes.apiowned CRDs definitions.*_unit_test.gounit tests.internal/controller/suite_util_test.gocommon utilities used in integration tests (envtest).e2e-testse2e tests, separate go project, require a cluster with installed Konflux to run. Agents shouldn't run those.
The main controller of the operator.
Reconciles ImageRepository objects and manages image repository and its lifecycle:
- Creation and removal of actual OCI image repository in the remote registry.
- The image repository settings (public / private, etc.)
- Management of push / pull k8s secrets (per repository and namespace wide), including credentials rotation on demand.
- If marked for Component via
appstudio.redhat.com/componentlabel andimage-controller.appstudio.redhat.com/update-component-imageannotation, updatesComponentresource by setting itsspec.containerImagebased on the provisioned image repository. - Notifications management (Quay specific).
Watches Component resources and checks for image.redhat.com/generate annotation.
If it is present, creates ImageRepository resource for the Component.
It's done for backward compatibility as currently recommended way is to define ImageRepository resource in GitOps or Konflux UI would do it automatically.
Manages k8s secret per Konflux Application that has pull access to all image repositories within the Konflux Application.
The per Application approach pull secret is replaced with per namespace pull secret named components-namespace-pull.
The operator owns ImageRepository CRD which is defined in api/vialpha1/imagerepository_types.go.
Typical ImageRepository in k8s or Openshift cluster:
apiVersion: appstudio.redhat.com/v1alpha1
kind: ImageRepository
metadata:
labels:
appstudio.redhat.com/application: image-controller
appstudio.redhat.com/component: image-controller
spec:
image:
name: image-controller-tenant/image-controller
visibility: public
status:
credentials:
generationTimestamp: '2026-02-13T19:30:22Z'
pull-robot-account: image_controller_tenant_image_controller_ddffda7318_pull
pull-secret: imagerepository-for-image-controller-image-pull
push-robot-account: image_controller_tenant_image_controller_56f4bae305
push-secret: imagerepository-for-image-controller-image-push
image:
url: quay.io/quay-organization/image-controller-tenant/image-controller
visibility: public
state: readyNote, spec.name should always have tenant (user namespace in cluster) prefix.
That is done to prevent accessing different tenants from current one.
After making code changes, always make sure that:
- unit and integration tests (envtest) pass (run with
make testafter all changes made). - all linters pass (run with
make lint).
If linters are not installed, install them:
make golangci-lintto install golangci-lint.make envtestto install envtest binaries needed for integration tests.
To verify single file, run:
./bin/golangci-lint run path/to/file.goAfter changing any reconciler permissions, update the operator role by running make manifests.
Check README.md for installation and usage details.