diff --git a/internal/cmd/operator-sdk/generate/bundle/bundle.go b/internal/cmd/operator-sdk/generate/bundle/bundle.go index cd772f25bae..5b5e636610a 100644 --- a/internal/cmd/operator-sdk/generate/bundle/bundle.go +++ b/internal/cmd/operator-sdk/generate/bundle/bundle.go @@ -286,7 +286,7 @@ func (c bundleCmd) runMetadata() error { if !errors.As(err, &merr) { return err } - } else if !c.overwrite { + } else if !c.overwrite && !c.overwriteAnnotations { return nil } } @@ -302,6 +302,11 @@ func (c bundleCmd) runMetadata() error { IsScoreConfigPresent: genutil.IsExist(scorecardConfigPath), } + if c.overwriteAnnotations { + return bundleMetadata.GenerateAnnotations() // Overwrite only annotations.yaml + } + + // If overwrite or metadata is generated for the first time, all files will be overwritten. return bundleMetadata.GenerateMetadata() } diff --git a/internal/cmd/operator-sdk/generate/bundle/cmd.go b/internal/cmd/operator-sdk/generate/bundle/cmd.go index e4803a962b5..5737836dc94 100644 --- a/internal/cmd/operator-sdk/generate/bundle/cmd.go +++ b/internal/cmd/operator-sdk/generate/bundle/cmd.go @@ -42,9 +42,10 @@ type bundleCmd struct { extraServiceAccounts []string // Metadata options. - channels string - defaultChannel string - overwrite bool + channels string + defaultChannel string + overwrite bool + overwriteAnnotations bool // These are set if a PROJECT config is not present. layout string @@ -63,6 +64,11 @@ func NewCmd() *cobra.Command { Long: longHelp, Example: examples, RunE: func(cmd *cobra.Command, args []string) error { + if c.overwriteAnnotations { + // Priority control, when checking --overwrite-annotations, set --overwrite to false + c.overwrite = false + } + if len(args) != 0 { return fmt.Errorf("command %s doesn't accept any arguments", cmd.CommandPath()) } @@ -138,6 +144,7 @@ func (c *bundleCmd) addFlagsTo(fs *pflag.FlagSet) { "Names of service accounts, outside of the operator's Deployment account, "+ "that have bindings to {Cluster}Roles that should be added to the CSV") fs.BoolVar(&c.overwrite, "overwrite", true, "Overwrite the bundle's metadata and Dockerfile if they exist") + fs.BoolVar(&c.overwriteAnnotations, "overwrite-annotations", false, "Only overwrite annotations.yaml without modifying bundle.Dockerfile") fs.BoolVarP(&c.quiet, "quiet", "q", false, "Run in quiet mode") fs.BoolVar(&c.stdout, "stdout", false, "Write bundle manifest to stdout") diff --git a/internal/util/bundleutil/bundleutil.go b/internal/util/bundleutil/bundleutil.go index 7a30dce03a9..2e34a51fc58 100644 --- a/internal/util/bundleutil/bundleutil.go +++ b/internal/util/bundleutil/bundleutil.go @@ -140,6 +140,54 @@ func (meta *BundleMetaData) GenerateMetadata() error { return nil } +// GenerateAnnotations generates the annotations.yaml file using the provided +// annotation values for the Operator Bundle. +func (meta *BundleMetaData) GenerateAnnotations() error { + // Ensure the output directory exists + metadataDir := filepath.Join(meta.BundleDir, defaultMetadataDir) + if err := os.MkdirAll(metadataDir, projutil.DirMode); err != nil { + return err + } + + // Prepare annotation values + values := annotationsValues{ + BundleDir: meta.BundleDir, + PackageName: meta.PackageName, + Channels: meta.Channels, + DefaultChannel: meta.DefaultChannel, + IsScorecardConfigPresent: meta.IsScoreConfigPresent, + } + + // Add any other labels to the values + for k, v := range meta.OtherLabels { + values.OtherLabels = append(values.OtherLabels, fmt.Sprintf("%s=%s", k, v)) + } + sort.Strings(values.OtherLabels) + + // Define the path to annotations.yaml + annotationsPath := filepath.Join(metadataDir, "annotations.yaml") + + // Open (or create) the annotations.yaml file + f, err := os.OpenFile(annotationsPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) + if err != nil { + return err + } + defer func() { + if err := f.Close(); err != nil { + log.Error(err) + } + }() + + // Create and execute the annotations template + err = annotationsTemplate.Execute(f, values) + if err != nil { + return err + } + + log.Infof("Annotations generated successfully at %s", annotationsPath) + return nil +} + // CopyOperatorManifests copies packagemanifestsDir/manifests to bundleDir/manifests. func (meta *BundleMetaData) CopyOperatorManifests() error { return copyOperatorManifests(meta.PkgmanifestPath, filepath.Join(meta.BundleDir, defaultManifestDir)) diff --git a/website/content/en/docs/cli/operator-sdk_generate_bundle.md b/website/content/en/docs/cli/operator-sdk_generate_bundle.md index 84aa231d861..afd52e54558 100644 --- a/website/content/en/docs/cli/operator-sdk_generate_bundle.md +++ b/website/content/en/docs/cli/operator-sdk_generate_bundle.md @@ -100,6 +100,7 @@ operator-sdk generate bundle [flags] --metadata Generate bundle metadata and Dockerfile --output-dir string Directory to write the bundle to --overwrite Overwrite the bundle's metadata and Dockerfile if they exist (default true) + --overwrite-annotations Only overwrite annotations.yaml without modifying bundle.Dockerfile --package string Bundle's package name -q, --quiet Run in quiet mode --stdout Write bundle manifest to stdout