@@ -3,6 +3,7 @@ package cincinnati
33import (
44 "context"
55 "encoding/json"
6+ "errors"
67 "fmt"
78 "io"
89 "net/http"
@@ -289,9 +290,9 @@ type graph struct {
289290}
290291
291292type node struct {
292- Version semver.Version `json:"version"`
293- Image string `json:"payload"`
294- Metadata map [string ]string `json:"metadata,omitempty"`
293+ Version semver.Version `json:"version"`
294+ Image string `json:"payload"`
295+ Metadata map [string ]interface {} `json:"metadata,omitempty"`
295296}
296297
297298type edge struct {
@@ -329,28 +330,65 @@ func (e *edge) UnmarshalJSON(data []byte) error {
329330}
330331
331332func convertRetrievedUpdateToRelease (update node ) (configv1.Release , error ) {
332- cvoUpdate := configv1.Release {
333- Version : update .Version .String (),
334- Image : update .Image ,
335- }
336- if urlString , ok := update .Metadata ["url" ]; ok {
337- _ , err := url .Parse (urlString )
338- if err != nil {
339- return cvoUpdate , fmt .Errorf ("invalid URL for %s: %s" , cvoUpdate .Version , err )
333+ release , err := ParseMetadata (update .Metadata )
334+ release .Version = update .Version .String ()
335+ release .Image = update .Image
336+ return release , err
337+ }
338+
339+ // ParseMetadata parses release metadata (URL, channels, etc.). It does not populate the version or image properties.
340+ func ParseMetadata (metadata map [string ]interface {}) (configv1.Release , error ) {
341+ release := configv1.Release {}
342+ errs := []error {}
343+ if urlInterface , hasURL := metadata ["url" ]; hasURL {
344+ if urlString , isString := urlInterface .(string ); isString {
345+ if _ , err := url .Parse (urlString ); err == nil {
346+ release .URL = configv1 .URL (urlString )
347+ } else {
348+ errs = append (errs , fmt .Errorf ("invalid release URL: %s" , err ))
349+ }
350+ } else {
351+ errs = append (errs , fmt .Errorf ("URL is not a string: %v" , urlInterface ))
340352 }
341- cvoUpdate .URL = configv1 .URL (urlString )
342353 }
343- if arch , ok := update .Metadata ["release.openshift.io/architecture" ]; ok {
344- switch arch {
345- case "multi" :
346- cvoUpdate .Architecture = configv1 .ClusterVersionArchitectureMulti
347- default :
348- klog .Warningf ("Unrecognized release.openshift.io/architecture value %q" , arch )
354+ if archInterface , hasArch := metadata ["release.openshift.io/architecture" ]; hasArch {
355+ if arch , isString := archInterface .(string ); isString {
356+ if arch == "multi" {
357+ release .Architecture = configv1 .ClusterVersionArchitectureMulti
358+ } else {
359+ errs = append (errs , fmt .Errorf ("unrecognized release.openshift.io/architecture value %q" , arch ))
360+ }
361+ } else {
362+ errs = append (errs , fmt .Errorf ("release.openshift.io/architecture is not a string: %v" , archInterface ))
349363 }
350364 }
351- if channels , ok := update .Metadata ["io.openshift.upgrades.graph.release.channels" ]; ok {
352- cvoUpdate .Channels = strings .Split (channels , "," )
353- sort .Strings (cvoUpdate .Channels )
365+ if channelsInterface , hasChannels := metadata ["io.openshift.upgrades.graph.release.channels" ]; hasChannels {
366+ if channelsString , isString := channelsInterface .(string ); isString {
367+ if len (channelsString ) == 0 {
368+ errs = append (errs , fmt .Errorf ("io.openshift.upgrades.graph.release.channels is an empty string" ))
369+ } else {
370+ channels := strings .Split (channelsString , "," )
371+ if len (channels ) == 0 {
372+ errs = append (errs , fmt .Errorf ("no comma-delimited channels in io.openshift.upgrades.graph.release.channels %q" , channelsString ))
373+ } else {
374+ for i := len (channels ) - 1 ; i >= 0 ; i -- {
375+ if len (channels [i ]) == 0 {
376+ errs = append (errs , fmt .Errorf ("io.openshift.upgrades.graph.release.channels entry %d is an empty string: %q" , i , channelsString ))
377+ channels = append (channels [:i ], channels [i + 1 :]... )
378+ }
379+ }
380+ if len (channels ) == 0 {
381+ errs = append (errs , fmt .Errorf ("no non-empty channels in io.openshift.upgrades.graph.release.channels %q" , channels ))
382+ } else {
383+ sort .Strings (channels )
384+ release .Channels = channels
385+ }
386+ }
387+ }
388+ } else {
389+ errs = append (errs , fmt .Errorf ("io.openshift.upgrades.graph.release.channels is not a string: %v" , channelsInterface ))
390+ }
354391 }
355- return cvoUpdate , nil
392+ klog .V (2 ).Infof ("parsed metadata: URL %q, architecture %q, channels %v, errors %v" , release .URL , release .Architecture , release .Channels , errs )
393+ return release , errors .Join (errs ... )
356394}
0 commit comments