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

[release-4.4] Bug 1806687: Image pruner updates: Controller / Prune Registry #468

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
10 changes: 9 additions & 1 deletion cmd/cluster-image-registry-operator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,20 @@ func runOperator(cmd *cobra.Command, args []string) {
// set up signals so we handle the first shutdown signal gracefully
stopCh := signals.SetupSignalHandler()

go metrics.RunServer(metricsPort, stopCh)

imagePrunerController, err := operator.NewImagePrunerController(cfg)
if err != nil {
klog.Fatal(err)
}

go imagePrunerController.Run(stopCh)

controller, err := operator.NewController(cfg)
if err != nil {
klog.Fatal(err)
}

go metrics.RunServer(metricsPort, stopCh)
err = controller.Run(stopCh)
if err != nil {
klog.Fatal(err)
Expand Down
10 changes: 10 additions & 0 deletions pkg/client/listers.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,13 @@ type Listers struct {
ProxyConfigs configlisters.ProxyLister
Infrastructures configlisters.InfrastructureLister
}

type ImagePrunerControllerListers struct {
Jobs kjoblisters.JobNamespaceLister
CronJobs kbatchlisters.CronJobNamespaceLister
ServiceAccounts kcorelisters.ServiceAccountNamespaceLister
ClusterRoles krbaclisters.ClusterRoleLister
ClusterRoleBindings krbaclisters.ClusterRoleBindingLister
RegistryConfigs regoplisters.ConfigLister
ImagePrunerConfigs regoplisters.ImagePrunerLister
}
143 changes: 21 additions & 122 deletions pkg/operator/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,11 @@ package operator
import (
"fmt"
"reflect"
"sort"
"time"

regopclient "github.com/openshift/cluster-image-registry-operator/pkg/client"
"github.com/openshift/cluster-image-registry-operator/pkg/parameters"
"github.com/openshift/cluster-image-registry-operator/pkg/resource"
"github.com/openshift/cluster-image-registry-operator/pkg/resource/object"
"github.com/openshift/cluster-image-registry-operator/pkg/resource/strategy"
"github.com/openshift/cluster-image-registry-operator/pkg/storage"

configapiv1 "github.com/openshift/api/config/v1"
imageregistryv1 "github.com/openshift/api/imageregistry/v1"
operatorapi "github.com/openshift/api/operator/v1"
configset "github.com/openshift/client-go/config/clientset/versioned"
configsetv1 "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1"
configinformers "github.com/openshift/client-go/config/informers/externalversions"
regopset "github.com/openshift/client-go/imageregistry/clientset/versioned"
regopinformers "github.com/openshift/client-go/imageregistry/informers/externalversions"
routeset "github.com/openshift/client-go/route/clientset/versioned"
routesetv1 "github.com/openshift/client-go/route/clientset/versioned/typed/route/v1"
routeinformers "github.com/openshift/client-go/route/informers/externalversions"
"github.com/openshift/cluster-image-registry-operator/defaults"

batchv1 "k8s.io/api/batch/v1"
"k8s.io/apimachinery/pkg/api/errors"
kmeta "k8s.io/apimachinery/pkg/api/meta"
metaapi "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/selection"
"k8s.io/apimachinery/pkg/util/wait"
kubeinformers "k8s.io/client-go/informers"
kubeset "k8s.io/client-go/kubernetes"
Expand All @@ -43,6 +19,26 @@ import (
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/workqueue"
"k8s.io/klog"

configapiv1 "github.com/openshift/api/config/v1"
imageregistryv1 "github.com/openshift/api/imageregistry/v1"
operatorapi "github.com/openshift/api/operator/v1"
configset "github.com/openshift/client-go/config/clientset/versioned"
configsetv1 "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1"
configinformers "github.com/openshift/client-go/config/informers/externalversions"
regopset "github.com/openshift/client-go/imageregistry/clientset/versioned"
regopinformers "github.com/openshift/client-go/imageregistry/informers/externalversions"
routeset "github.com/openshift/client-go/route/clientset/versioned"
routesetv1 "github.com/openshift/client-go/route/clientset/versioned/typed/route/v1"
routeinformers "github.com/openshift/client-go/route/informers/externalversions"

"github.com/openshift/cluster-image-registry-operator/defaults"
regopclient "github.com/openshift/cluster-image-registry-operator/pkg/client"
"github.com/openshift/cluster-image-registry-operator/pkg/parameters"
"github.com/openshift/cluster-image-registry-operator/pkg/resource"
"github.com/openshift/cluster-image-registry-operator/pkg/resource/object"
"github.com/openshift/cluster-image-registry-operator/pkg/resource/strategy"
"github.com/openshift/cluster-image-registry-operator/pkg/storage"
)

const (
Expand Down Expand Up @@ -146,104 +142,7 @@ func (c *Controller) createOrUpdateResources(cr *imageregistryv1.Config) error {
return nil
}

type ByCreationTimestamp []*batchv1.Job

func (b ByCreationTimestamp) Len() int {
return len(b)
}

func (b ByCreationTimestamp) Swap(i, j int) {
b[i], b[j] = b[j], b[i]
}

func (b ByCreationTimestamp) Less(i, j int) bool {
return !b[j].CreationTimestamp.Time.After(b[i].CreationTimestamp.Time)
}

func (c *Controller) sync() error {
prunerResourceFound := true
pcr, err := c.listers.ImagePrunerConfigs.Get(defaults.ImageRegistryImagePrunerResourceName)
if err != nil {
if errors.IsNotFound(err) {
prunerResourceFound = false
} else {
return fmt.Errorf("failed to get %q image registry pruner resource: %s", defaults.ImageRegistryImagePrunerResourceName, err)
}
}
if prunerResourceFound {
pcr = pcr.DeepCopy() // we don't want to change the cached version
prevPCR := pcr.DeepCopy()
prunerCronJob, err := c.listers.CronJobs.Get("image-pruner")
if errors.IsNotFound(err) {
prunerCronJob = nil
} else if err != nil {
return fmt.Errorf("failed to get image-pruner pruner job: %s", err)
} else {
prunerCronJob = prunerCronJob.DeepCopy()
}

jobSelector := labels.NewSelector()
requirement, err := labels.NewRequirement("created-by", selection.Equals, []string{"image-pruner"})
if err != nil {
return err
}
jobSelector.Add(*requirement)
prunerJobs, err := c.listers.Jobs.List(jobSelector)
if err != nil {
return fmt.Errorf("failed to get pruner jobs: %s", err)
}

lastPrunerJobConditions := []batchv1.JobCondition{}
if len(prunerJobs) > 0 {
sort.Sort(ByCreationTimestamp(prunerJobs))
lastPrunerJobConditions = prunerJobs[len(prunerJobs)-1].Status.Conditions
}

c.syncPrunerStatus(pcr, prunerCronJob, lastPrunerJobConditions)

metadataChanged := strategy.Metadata(&prevPCR.ObjectMeta, &pcr.ObjectMeta)
specChanged := !reflect.DeepEqual(prevPCR.Spec, pcr.Spec)
if metadataChanged || specChanged {
klog.Infof("Updating pruner cr")
difference, err := object.DiffString(prevPCR, pcr)
if err != nil {
klog.Errorf("unable to calculate difference in %s: %s", utilObjectInfo(pcr), err)
}
klog.Infof("object changed: %s (metadata=%t, spec=%t): %s", utilObjectInfo(pcr), metadataChanged, specChanged, difference)

updatedPCR, err := c.clients.RegOp.ImageregistryV1().ImagePruners().Update(pcr)
if err != nil {
if !errors.IsConflict(err) {
klog.Errorf("unable to update %s: %s", utilObjectInfo(pcr), err)
}
return err
}

// If we updated the Status field too, we'll make one more call and we
// want it to succeed.
pcr.ResourceVersion = updatedPCR.ResourceVersion

}

pcr.Status.ObservedGeneration = pcr.Generation
statusChanged := !reflect.DeepEqual(prevPCR.Status, pcr.Status)
if statusChanged {
difference, err := object.DiffString(prevPCR, pcr)
if err != nil {
klog.Errorf("unable to calculate difference in %s: %s", utilObjectInfo(pcr), err)
}
klog.Infof("object changed: %s (status=%t): %s", utilObjectInfo(pcr), statusChanged, difference)

_, err = c.clients.RegOp.ImageregistryV1().ImagePruners().UpdateStatus(pcr)
if err != nil {
if !errors.IsConflict(err) {
klog.Errorf("unable to update status %s: %s", utilObjectInfo(pcr), err)
}
return err
}
}
}

cr, err := c.listers.RegistryConfigs.Get(defaults.ImageRegistryResourceName)
if err != nil {
if errors.IsNotFound(err) {
Expand Down Expand Up @@ -601,7 +500,7 @@ func (c *Controller) Run(stopCh <-chan struct{}) error {
regopInformerFactory.Start(stopCh)
routeInformerFactory.Start(stopCh)

// TODO(dmage): This controller should be started from main.
// TODO(dmage):This controller should be started from main.
go clusterOperatorStatusController.Run(stopCh)

klog.Info("waiting for informer caches to sync")
Expand Down