Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding a commandline graph pruner #253

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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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")
bradmwilliams marked this conversation as resolved.
Show resolved Hide resolved
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
}