Skip to content

Commit c63c1bc

Browse files
Ankita ThomasAnkita Thomas
authored andcommitted
Move server side apply patch code to library, use ssa to update catalog source pods
1 parent d1ebc80 commit c63c1bc

File tree

99 files changed

+18074
-135
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+18074
-135
lines changed

cmd/catalog/main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/prometheus/client_golang/prometheus/promhttp"
1414
log "github.com/sirupsen/logrus"
1515
utilclock "k8s.io/apimachinery/pkg/util/clock"
16+
k8sscheme "k8s.io/client-go/kubernetes/scheme"
1617
"k8s.io/client-go/tools/clientcmd"
1718

1819
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/client"
@@ -172,7 +173,7 @@ func main() {
172173
}
173174

174175
// Create a new instance of the operator.
175-
op, err := catalog.NewOperator(ctx, *kubeConfigPath, utilclock.RealClock{}, logger, *wakeupInterval, *configmapServerImage, *utilImage, *catalogNamespace)
176+
op, err := catalog.NewOperator(ctx, *kubeConfigPath, utilclock.RealClock{}, logger, *wakeupInterval, *configmapServerImage, *utilImage, *catalogNamespace, k8sscheme.Scheme)
176177
if err != nil {
177178
log.Panicf("error configuring operator: %s", err.Error())
178179
}

go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@ require (
1818
github.com/otiai10/copy v1.0.1
1919
github.com/pkg/errors v0.8.1
2020
github.com/prometheus/client_golang v1.2.1
21+
github.com/prometheus/client_model v0.2.0 // indirect
2122
github.com/sirupsen/logrus v1.4.2
2223
github.com/spf13/cobra v0.0.5
2324
github.com/stretchr/testify v1.4.0
2425
golang.org/x/sys v0.0.0-20191210023423-ac6580df4449 // indirect
2526
golang.org/x/time v0.0.0-20191024005414-555d28b269f0
27+
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
2628
google.golang.org/grpc v1.24.0
2729
gopkg.in/yaml.v2 v2.2.4
2830
helm.sh/helm/v3 v3.0.1
@@ -37,7 +39,10 @@ require (
3739
k8s.io/kube-aggregator v0.0.0
3840
k8s.io/kube-openapi v0.0.0-20190918143330-0270cf2f1c1d
3941
k8s.io/kubernetes v1.16.0
42+
sigs.k8s.io/controller-runtime v0.5.1 // indirect
4043
sigs.k8s.io/controller-tools v0.2.4
44+
sigs.k8s.io/testing_frameworks v0.1.2 // indirect
45+
sigs.k8s.io/yaml v1.1.0 // indirect
4146
)
4247

4348
replace (

go.sum

Lines changed: 42 additions & 0 deletions
Large diffs are not rendered by default.

pkg/controller/operators/catalog/operator.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
"sync"
1212
"time"
1313

14+
"k8s.io/apimachinery/pkg/runtime"
15+
1416
errorwrap "github.com/pkg/errors"
1517
"github.com/sirupsen/logrus"
1618
"google.golang.org/grpc/connectivity"
@@ -47,6 +49,7 @@ import (
4749
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/grpc"
4850
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/reconciler"
4951
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver"
52+
controllerclient "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/controller-runtime/client"
5053
index "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/index"
5154
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
5255
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister"
@@ -70,6 +73,7 @@ const (
7073
generatedByKey = "olm.generated-by"
7174
maxInstallPlanCount = 5
7275
maxDeletesPerSweep = 5
76+
RegistryFieldManager = "olm.registry"
7377
)
7478

7579
// Operator represents a Kubernetes operator that executes InstallPlans by
@@ -102,7 +106,7 @@ type Operator struct {
102106
type CatalogSourceSyncFunc func(logger *logrus.Entry, in *v1alpha1.CatalogSource) (out *v1alpha1.CatalogSource, continueSync bool, syncError error)
103107

104108
// NewOperator creates a new Catalog Operator.
105-
func NewOperator(ctx context.Context, kubeconfigPath string, clock utilclock.Clock, logger *logrus.Logger, resync time.Duration, configmapRegistryImage, utilImage string, operatorNamespace string) (*Operator, error) {
109+
func NewOperator(ctx context.Context, kubeconfigPath string, clock utilclock.Clock, logger *logrus.Logger, resync time.Duration, configmapRegistryImage, utilImage string, operatorNamespace string, scheme *runtime.Scheme) (*Operator, error) {
106110
resyncPeriod := queueinformer.ResyncWithJitter(resync, 0.2)
107111
config, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath)
108112
if err != nil {
@@ -131,6 +135,10 @@ func NewOperator(ctx context.Context, kubeconfigPath string, clock utilclock.Clo
131135
// Create an OperatorLister
132136
lister := operatorlister.NewLister()
133137

138+
ssaClient, err := controllerclient.NewForConfig(config, scheme, RegistryFieldManager)
139+
if err != nil {
140+
return nil, err
141+
}
134142
// Allocate the new instance of an Operator.
135143
op := &Operator{
136144
Operator: queueOperator,
@@ -151,7 +159,7 @@ func NewOperator(ctx context.Context, kubeconfigPath string, clock utilclock.Clo
151159
clientAttenuator: scoped.NewClientAttenuator(logger, config, opClient, crClient, dynamicClient),
152160
}
153161
op.sources = grpc.NewSourceStore(logger, 10*time.Second, 10*time.Minute, op.syncSourceState)
154-
op.reconciler = reconciler.NewRegistryReconcilerFactory(lister, opClient, configmapRegistryImage, op.now)
162+
op.reconciler = reconciler.NewRegistryReconcilerFactory(lister, opClient, configmapRegistryImage, op.now, ssaClient)
155163

156164
// Wire OLM CR sharedIndexInformers
157165
crInformerFactory := externalversions.NewSharedInformerFactoryWithOptions(op.client, resyncPeriod())

pkg/controller/operators/catalog/operator_test.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import (
4949
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver"
5050
"github.com/operator-framework/operator-lifecycle-manager/pkg/fakes"
5151
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/clientfake"
52+
controllerclient "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/controller-runtime/client"
5253
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
5354
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister"
5455
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
@@ -1301,7 +1302,14 @@ func NewFakeOperator(ctx context.Context, namespace string, namespaces []string,
13011302
}
13021303
op.sources = grpc.NewSourceStore(config.logger, 1*time.Second, 5*time.Second, op.syncSourceState)
13031304
if op.reconciler == nil {
1304-
op.reconciler = reconciler.NewRegistryReconcilerFactory(lister, op.opClient, "test:pod", op.now)
1305+
s := runtime.NewScheme()
1306+
err := k8sfake.AddToScheme(s)
1307+
if err != nil {
1308+
return nil, err
1309+
}
1310+
applier := controllerclient.NewFakeApplier(s, "testowner")
1311+
1312+
op.reconciler = reconciler.NewRegistryReconcilerFactory(lister, op.opClient, "test:pod", op.now, applier)
13051313
}
13061314

13071315
op.RunInformers(ctx)

pkg/controller/registry/reconciler/grpc.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package reconciler
22

33
import (
4+
"context"
45
"fmt"
56

67
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
8+
controllerclient "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/controller-runtime/client"
79
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
810
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister"
911
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
@@ -69,9 +71,10 @@ func (s *grpcCatalogSourceDecorator) Pod() *v1.Pod {
6971
}
7072

7173
type GrpcRegistryReconciler struct {
72-
now nowFunc
73-
Lister operatorlister.OperatorLister
74-
OpClient operatorclient.ClientInterface
74+
now nowFunc
75+
Lister operatorlister.OperatorLister
76+
OpClient operatorclient.ClientInterface
77+
SSAClient *controllerclient.ServerSideApplier
7578
}
7679

7780
var _ RegistryReconciler = &GrpcRegistryReconciler{}
@@ -193,16 +196,16 @@ func (c *GrpcRegistryReconciler) ensureUpdatePod(source grpcCatalogSourceDecorat
193196
logrus.WithField("CatalogSource", source.GetName()).Info("detect image update for catalogsource pod")
194197

195198
updateFlag = true
196-
updatePod.Labels[CatalogSourceLabelKey] = source.GetName()
197-
updatePod.Labels[CatalogSourceUpdateKey] = ""
198199

199200
// Update the update pod to promote it to serving pod
200-
_, err := c.OpClient.KubernetesInterface().CoreV1().Pods(source.GetNamespace()).Update(updatePod)
201+
err := c.SSAClient.Apply(context.TODO(), updatePod, func(p *v1.Pod) error {
202+
p.Labels[CatalogSourceLabelKey] = source.GetName()
203+
p.Labels[CatalogSourceUpdateKey] = ""
204+
return nil
205+
})()
201206
if err != nil {
202-
return errors.Wrapf(err, "error creating new pod: %s", source.Pod().GetName())
207+
return errors.Wrapf(err, "error updating catalog source pod: %s", source.Pod().GetName())
203208
}
204-
205-
break
206209
}
207210
}
208211

pkg/controller/registry/reconciler/reconciler.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package reconciler
33

44
import (
55
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
6+
controllerclient "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/controller-runtime/client"
67
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
78
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister"
89
v1 "k8s.io/api/core/v1"
@@ -46,6 +47,7 @@ type registryReconcilerFactory struct {
4647
Lister operatorlister.OperatorLister
4748
OpClient operatorclient.ClientInterface
4849
ConfigMapServerImage string
50+
SSAClient *controllerclient.ServerSideApplier
4951
}
5052

5153
// ReconcilerForSource returns a RegistryReconciler based on the configuration of the given CatalogSource.
@@ -62,9 +64,10 @@ func (r *registryReconcilerFactory) ReconcilerForSource(source *v1alpha1.Catalog
6264
case v1alpha1.SourceTypeGrpc:
6365
if source.Spec.Image != "" {
6466
return &GrpcRegistryReconciler{
65-
now: r.now,
66-
Lister: r.Lister,
67-
OpClient: r.OpClient,
67+
now: r.now,
68+
Lister: r.Lister,
69+
OpClient: r.OpClient,
70+
SSAClient: r.SSAClient,
6871
}
6972
} else if source.Spec.Address != "" {
7073
return &GrpcAddressRegistryReconciler{
@@ -76,12 +79,13 @@ func (r *registryReconcilerFactory) ReconcilerForSource(source *v1alpha1.Catalog
7679
}
7780

7881
// NewRegistryReconcilerFactory returns an initialized RegistryReconcilerFactory.
79-
func NewRegistryReconcilerFactory(lister operatorlister.OperatorLister, opClient operatorclient.ClientInterface, configMapServerImage string, now nowFunc) RegistryReconcilerFactory {
82+
func NewRegistryReconcilerFactory(lister operatorlister.OperatorLister, opClient operatorclient.ClientInterface, configMapServerImage string, now nowFunc, ssaClient *controllerclient.ServerSideApplier) RegistryReconcilerFactory {
8083
return &registryReconcilerFactory{
8184
now: now,
8285
Lister: lister,
8386
OpClient: opClient,
8487
ConfigMapServerImage: configMapServerImage,
88+
SSAClient: ssaClient,
8589
}
8690
}
8791

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package client
2+
3+
import (
4+
"context"
5+
"k8s.io/apimachinery/pkg/runtime"
6+
"k8s.io/apimachinery/pkg/types"
7+
k8scontrollerclient "sigs.k8s.io/controller-runtime/pkg/client"
8+
fakecontrollerclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
9+
)
10+
11+
// FakeApplier provides a wrapper around the fake k8s controller client to convert the unsupported apply-type patches to merge patches.
12+
func NewFakeApplier(scheme *runtime.Scheme, owner string, objs ...runtime.Object) *ServerSideApplier {
13+
return &ServerSideApplier{
14+
client: &fakeApplier{fakecontrollerclient.NewFakeClientWithScheme(scheme, objs...)},
15+
Scheme: scheme,
16+
Owner: k8scontrollerclient.FieldOwner(owner),
17+
}
18+
}
19+
20+
type fakeApplier struct {
21+
k8scontrollerclient.Client
22+
}
23+
24+
func (c *fakeApplier) Patch(ctx context.Context, obj runtime.Object, patch k8scontrollerclient.Patch, opts ...k8scontrollerclient.PatchOption) error {
25+
patch, opts = convertApplyToMergePatch(patch, opts...)
26+
return c.Client.Patch(ctx, obj, patch, opts...)
27+
}
28+
29+
func (c *fakeApplier) Status() k8scontrollerclient.StatusWriter {
30+
return fakeStatusWriter{c.Client.Status()}
31+
}
32+
33+
type fakeStatusWriter struct {
34+
k8scontrollerclient.StatusWriter
35+
}
36+
37+
func (c fakeStatusWriter) Patch(ctx context.Context, obj runtime.Object, patch k8scontrollerclient.Patch, opts ...k8scontrollerclient.PatchOption) error {
38+
patch, opts = convertApplyToMergePatch(patch, opts...)
39+
return c.StatusWriter.Patch(ctx, obj, patch, opts...)
40+
}
41+
42+
func convertApplyToMergePatch(patch k8scontrollerclient.Patch, opts ...k8scontrollerclient.PatchOption) (k8scontrollerclient.Patch, []k8scontrollerclient.PatchOption) {
43+
// Apply patch type is not supported on the fake controller
44+
if patch.Type() == types.ApplyPatchType {
45+
patch = k8scontrollerclient.Merge
46+
patchOptions := make([]k8scontrollerclient.PatchOption, 0, len(opts))
47+
for _, opt := range opts {
48+
if opt == k8scontrollerclient.ForceOwnership {
49+
continue
50+
}
51+
patchOptions = append(patchOptions, opt)
52+
}
53+
opts = patchOptions
54+
}
55+
return patch, opts
56+
}

0 commit comments

Comments
 (0)