Skip to content

Commit

Permalink
Adding a commandline graph pruner
Browse files Browse the repository at this point in the history
Extracting the load/save logic into their own functions

Updating commandline options for pruning graph

Code review changes

Adding items that are in both the To and From lists

Go formatting

Performing prune inside method with defer

Returning error from saveUpgradeGraph()

Post-rebase updates

Small refactoring

Fix klog version

Convert to using set
  • Loading branch information
bradmwilliams committed Mar 4, 2022
1 parent c2894de commit 7012ece
Show file tree
Hide file tree
Showing 3 changed files with 211 additions and 63 deletions.
20 changes: 17 additions & 3 deletions cmd/release-controller/main.go
Expand Up @@ -95,6 +95,10 @@ type options struct {
ClusterGroups []string

ARTSuffix string

PruneGraph bool
PrintPrunedGraph string
ConfirmPruneGraph bool
}

// Add metrics for bugzilla verifier errors
Expand Down Expand Up @@ -122,7 +126,10 @@ func main() {
opt := &options{
ListenAddr: ":8080",
ToolsImageStreamTag: ":tests",
Registry: "registry.ci.openshift.org",

Registry: "registry.ci.openshift.org",

PrintPrunedGraph: releasecontroller.PruneGraphPrintSecret,
}
cmd := &cobra.Command{
Run: func(cmd *cobra.Command, arguments []string) {
Expand Down Expand Up @@ -190,6 +197,10 @@ func main() {
// configurations can be distributed properly on the environment that they require.
flagset.StringArrayVar(&opt.ClusterGroups, "cluster-group", opt.ClusterGroups, "A comma seperated list of build cluster names to evenly distribute jobs to. May be specified multiple times to account for different configurations of build clusters.")

flagset.BoolVar(&opt.PruneGraph, "prune-graph", opt.PruneGraph, "Reads the upgrade graph, prunes edges, and prints the result")
flagset.StringVar(&opt.PrintPrunedGraph, "print-pruned-graph", opt.PrintPrunedGraph, "Print the result of pruning the graph. Valid options are: <|secret|debug>. The default, 'secret', is the base64 encoded secret payload. The 'debug' option will pretty print the json payload")
flagset.BoolVar(&opt.ConfirmPruneGraph, "confirm-prune-graph", opt.ConfirmPruneGraph, "Persist the pruned graph")

goFlagSet := flag.NewFlagSet("prowflags", flag.ContinueOnError)
opt.github.AddFlags(goFlagSet)
opt.bugzilla.AddFlags(goFlagSet)
Expand All @@ -212,7 +223,6 @@ func (o *options) Run() error {
if o.validateConfigs != "" {
return validateConfigs(o.validateConfigs)
}

tagParts := strings.Split(o.ToolsImageStreamTag, ":")
if len(tagParts) != 2 || len(tagParts[1]) == 0 {
return fmt.Errorf("--tools-image-stream-tag must be STREAM:TAG or :TAG (default STREAM is the oldest release stream)")
Expand All @@ -233,7 +243,9 @@ func (o *options) Run() error {
if len(o.ReleaseArchitecture) > 0 {
architecture = o.ReleaseArchitecture
}

if len(o.PrintPrunedGraph) > 0 && o.PrintPrunedGraph != releasecontroller.PruneGraphPrintSecret && o.PrintPrunedGraph != releasecontroller.PruneGraphPrintDebug {
return fmt.Errorf("--print-prune-graph must be \"%s\" or \"%s\"", releasecontroller.PruneGraphPrintSecret, releasecontroller.PruneGraphPrintDebug)
}
inClusterCfg, err := loadClusterConfig()
if err != nil {
return fmt.Errorf("failed to load incluster config: %w", err)
Expand Down Expand Up @@ -527,6 +539,8 @@ func (o *options) Run() error {
health.ServeReady(func() bool { return true })

switch {
case o.PruneGraph:
return c.PruneGraph(releasesClient.CoreV1().Secrets(releaseNamespace), o.ReleaseNamespaces[0], "release-upgrade-graph", o.PrintPrunedGraph, o.ConfirmPruneGraph)
case o.DryRun:
klog.Infof("Dry run mode (no changes will be made)")

Expand Down
75 changes: 75 additions & 0 deletions cmd/release-controller/prune_graph.go
@@ -0,0 +1,75 @@
package main

import (
"bytes"
releasecontroller "github.com/openshift/release-controller/pkg/release-controller"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait"
kv1core "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/klog"
)

func (c *Controller) PruneGraph(secretClient kv1core.SecretInterface, ns, name string, printOption string, confirm bool) error {
stopCh := wait.NeverStop

releasecontroller.LoadUpgradeGraph(c.graph, secretClient, ns, name, stopCh)

imageStreams, err := c.releaseLister.ImageStreams(ns).List(labels.Everything())
if err != nil {
return err
}

var stableTagList []string

for _, imageStream := range imageStreams {
r, ok, err := releasecontroller.ReleaseDefinition(imageStream, c.parsedReleaseConfigCache, c.eventRecorder, *c.releaseLister)
if err != nil || !ok {
continue
}
if r.Config.As == releasecontroller.ReleaseConfigModeStable {
for _, tag := range imageStream.Spec.Tags {
stableTagList = append(stableTagList, tag.Name)
}
}
}

// To tags that are not present in the stable tags
toMissingList := make([]string, 0, len(c.graph.To))
for tag := range c.graph.To {
if !releasecontroller.StringSliceContains(stableTagList, tag) {
toMissingList = append(toMissingList, tag)
}
}

// From tags that are not present in the stable tags
fromMissingList := make([]string, 0, len(c.graph.From))
for tag := range c.graph.From {
if !releasecontroller.StringSliceContains(stableTagList, tag) {
fromMissingList = append(fromMissingList, tag)
}
}

// Combine the 2 lists into a set to eliminate duplicates
pruneTagList := sets.NewString(append(toMissingList, fromMissingList...)...).UnsortedList()
klog.V(2).Infof("Pruning %d/%d tags from release controller graph\n", len(pruneTagList), len(c.graph.To))

c.graph.PruneTags(pruneTagList)

if confirm {
buf := &bytes.Buffer{}
err = releasecontroller.SaveUpgradeGraph(buf, c.graph, secretClient, ns, name)
if err != nil {
return err
}
} else {
switch printOption {
case releasecontroller.PruneGraphPrintDebug:
c.graph.PrettyPrint()
case releasecontroller.PruneGraphPrintSecret:
c.graph.PrintSecretPayload()
}
}

return nil
}

0 comments on commit 7012ece

Please sign in to comment.