Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions alpha/template/semver/semver.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package semver
import (
"cmp"
"context"
"encoding/json"
"fmt"
"io"
"slices"
Expand All @@ -16,6 +17,7 @@ import (
"github.com/operator-framework/operator-registry/alpha/declcfg"
"github.com/operator-framework/operator-registry/alpha/property"
"github.com/operator-framework/operator-registry/alpha/template/api"
"github.com/operator-framework/operator-registry/pkg/registry"
)

// Schema
Expand Down Expand Up @@ -115,6 +117,8 @@ func (t *semverTemplate) Render(ctx context.Context, reader io.Reader) (*declcfg
out.Channels = channels
out.Packages[0].DefaultChannel = sv.defaultChannel

sv.populatePackageMetadata(&out)

return &out, nil
}

Expand Down Expand Up @@ -428,6 +432,53 @@ func (sv *SemverTemplateData) generateChannels(semverChannels *bundleVersions) [
return outChannels
}

// populatePackageMetadata extracts icon and description from the head bundle of the default channel -- if present --
// and sets them on the package object
// this assumes that all schema have been validated as part of the declarative config aggregation
func (sv *SemverTemplateData) populatePackageMetadata(cfg *declcfg.DeclarativeConfig) {
if len(cfg.Packages) == 0 {
return
}

// Find the default channel
channelIdx := slices.IndexFunc(cfg.Channels, func(ch declcfg.Channel) bool {
return ch.Name == sv.defaultChannel
})
if channelIdx == -1 || len(cfg.Channels[channelIdx].Entries) == 0 {
return
}

// Find the head bundle (the bundle with the highest version, which is the last entry in the channel)
// Since bundles are processed in ascending version order, the last entry is the head
headBundleName := cfg.Channels[channelIdx].Entries[len(cfg.Channels[channelIdx].Entries)-1].Name

bundleIdx := slices.IndexFunc(cfg.Bundles, func(b declcfg.Bundle) bool {
return b.Name == headBundleName
})
if bundleIdx == -1 || cfg.Bundles[bundleIdx].CsvJSON == "" {
return
}

// Parse CSV JSON to extract metadata
var csv registry.ClusterServiceVersion
if err := json.Unmarshal([]byte(cfg.Bundles[bundleIdx].CsvJSON), &csv); err != nil {
return
}

// Extract and set description
if desc, err := csv.GetDescription(); err == nil && desc != "" {
cfg.Packages[0].Description = desc
}

// Extract and set icon
if icons, err := csv.GetIcons(); err == nil && len(icons) > 0 {
cfg.Packages[0].Icon = &declcfg.Icon{
Data: icons[0].Base64data,
MediaType: icons[0].MediaType,
}
}
}

func (sv *SemverTemplateData) linkChannels(unlinkedChannels map[string]*declcfg.Channel, entries []entryTuple) []declcfg.Channel {
channels := []declcfg.Channel{}

Expand Down
Loading
Loading