@@ -20,9 +20,11 @@ import (
2020 "io/ioutil"
2121 "os"
2222 "path/filepath"
23+ "strings"
2324
2425 "github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3"
2526 "github.com/operator-framework/operator-registry/pkg/lib/bundle"
27+ corev1 "k8s.io/api/core/v1"
2628 "sigs.k8s.io/yaml"
2729
2830 metricsannotations "github.com/operator-framework/operator-sdk/internal/annotations/metrics"
@@ -188,6 +190,11 @@ func (c bundleCmd) runManifests() (err error) {
188190 c .println ("Building a ClusterServiceVersion without an existing base" )
189191 }
190192
193+ relatedImages , err := c .findRelatedImages (col )
194+ if err != nil {
195+ return err
196+ }
197+
191198 var opts []gencsv.Option
192199 stdout := genutil .NewMultiManifestWriter (os .Stdout )
193200 if c .stdout {
@@ -202,6 +209,7 @@ func (c bundleCmd) runManifests() (err error) {
202209 Collector : col ,
203210 Annotations : metricsannotations .MakeBundleObjectAnnotations (c .layout ),
204211 ExtraServiceAccounts : c .extraServiceAccounts ,
212+ RelatedImages : relatedImages ,
205213 }
206214 if err := csvGen .Generate (opts ... ); err != nil {
207215 return fmt .Errorf ("error generating ClusterServiceVersion: %v" , err )
@@ -287,3 +295,51 @@ func (c bundleCmd) runMetadata() error {
287295
288296 return bundleMetadata .GenerateMetadata ()
289297}
298+
299+ // findRelatedImages looks in the controller manager's environment for images used by the operator.
300+ func (c bundleCmd ) findRelatedImages (col * collector.Manifests ) (map [string ]string , error ) {
301+ const relatedImagePrefix = "RELATED_IMAGE_"
302+ env , err := c .findManagerEnvironment (col )
303+ if err != nil {
304+ return nil , err
305+ }
306+ imageNames := make (map [string ]string , len (env ))
307+ for _ , envVar := range env {
308+ if strings .HasPrefix (envVar .Name , relatedImagePrefix ) {
309+ if envVar .ValueFrom != nil {
310+ return nil , fmt .Errorf ("related images with valueFrom field unsupported, found in %s`" , envVar .Name )
311+ }
312+
313+ // transforms RELATED_IMAGE_This_IS_a_cool_image to this-is-a-cool-image
314+ name := strings .ToLower (strings .Replace (strings .TrimPrefix (envVar .Name , relatedImagePrefix ), "_" , "-" , - 1 ))
315+ imageNames [name ] = envVar .Value
316+ }
317+ }
318+
319+ return imageNames , nil
320+ }
321+
322+ // findManagerEnvironment returns the environment passed to the controller manager container.
323+ func (c bundleCmd ) findManagerEnvironment (col * collector.Manifests ) ([]corev1.EnvVar , error ) {
324+ const (
325+ managerLabel = "control-plane"
326+ managerLabelValue = "controller-manager"
327+ managerContainerName = "manager"
328+ )
329+
330+ for _ , deployment := range col .Deployments {
331+ if val , ok := deployment .GetLabels ()[managerLabel ]; ok && val == managerLabelValue {
332+ for _ , container := range deployment .Spec .Template .Spec .Containers {
333+ if container .Name == managerContainerName {
334+ return container .Env , nil
335+ }
336+ }
337+
338+ return nil , fmt .Errorf ("manager deployment does not have container named %q" , managerContainerName )
339+ }
340+ }
341+
342+ return nil , fmt .Errorf (
343+ "could not find manager deployment, should have label %s=%s" , managerLabel , managerLabelValue ,
344+ )
345+ }
0 commit comments