@@ -24,10 +24,13 @@ import (
2424 "fmt"
2525 "net/http"
2626 "os"
27+ "path"
2728 "path/filepath"
2829 "strings"
2930 "time"
3031
32+ bsemver "github.com/blang/semver/v4"
33+ "github.com/distribution/reference"
3134 "github.com/spf13/cobra"
3235 "go.podman.io/image/v5/types"
3336 rbacv1 "k8s.io/api/rbac/v1"
@@ -58,6 +61,7 @@ import (
5861 "sigs.k8s.io/controller-runtime/pkg/metrics/server"
5962
6063 helmclient "github.com/operator-framework/helm-operator-plugins/pkg/client"
64+ "github.com/operator-framework/operator-registry/alpha/declcfg"
6165
6266 ocv1 "github.com/operator-framework/operator-controller/api/v1"
6367 "github.com/operator-framework/operator-controller/internal/operator-controller/action"
@@ -85,6 +89,11 @@ import (
8589 "github.com/operator-framework/operator-controller/internal/shared/version"
8690)
8791
92+ const (
93+ directBundleInstallImageAnnotation = "olm.operatorframework.io/bundle-image"
94+ directBundleInstallVersionAnnotation = "olm.operatorframework.io/bundle-version"
95+ )
96+
8897var (
8998 setupLog = ctrl .Log .WithName ("setup" )
9099 defaultSystemNamespace = "olmv1-system"
@@ -394,7 +403,7 @@ func run() error {
394403 return httputil .BuildHTTPClient (cpwCatalogd )
395404 })
396405
397- resolver := & resolve.CatalogResolver {
406+ catalogResolver := & resolve.CatalogResolver {
398407 WalkCatalogsFunc : resolve .CatalogWalker (
399408 func (ctx context.Context , option ... client.ListOption ) ([]ocv1.ClusterCatalog , error ) {
400409 var catalogs ocv1.ClusterCatalogList
@@ -410,6 +419,28 @@ func run() error {
410419 },
411420 }
412421
422+ var resolver resolve.Func = func (ctx context.Context , ext * ocv1.ClusterExtension , installedBundle * ocv1.BundleMetadata ) (* declcfg.Bundle , * bsemver.Version , * declcfg.Deprecation , error ) {
423+ if features .OperatorControllerFeatureGate .Enabled (features .DirectBundleInstall ) &&
424+ ext .Annotations != nil && ext .Annotations [directBundleInstallImageAnnotation ] != "" &&
425+ ext .Annotations [directBundleInstallVersionAnnotation ] != "" {
426+ bundleImageRef := ext .Annotations [directBundleInstallImageAnnotation ]
427+
428+ ref , err := reference .ParseNamed (bundleImageRef )
429+ if err != nil {
430+ return nil , nil , nil , err
431+ }
432+
433+ packageName := path .Base (ref .Name ())
434+ bundleVersion := bsemver .MustParse (ext .Annotations [directBundleInstallVersionAnnotation ])
435+ return & declcfg.Bundle {
436+ Package : packageName ,
437+ Image : bundleImageRef ,
438+ }, & bundleVersion , nil , nil
439+ } else {
440+ return catalogResolver .Resolve (ctx , ext , installedBundle )
441+ }
442+ }
443+
413444 aeClient , err := apiextensionsv1client .NewForConfig (mgr .GetConfig ())
414445 if err != nil {
415446 setupLog .Error (err , "unable to create apiextensions client" )
0 commit comments