Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Jul 11, 2023. It is now read-only.

Commit cf607ad

Browse files
committed
Use informer implementation for MRCClientImpl
Signed-off-by: Keith Mattix II <[email protected]>
1 parent 7831a73 commit cf607ad

File tree

11 files changed

+167
-59
lines changed

11 files changed

+167
-59
lines changed

cmd/osm-bootstrap/osm-bootstrap.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ func main() {
213213
log.Fatal().Err(err).Msg("Error getting certificate options")
214214
}
215215

216-
certManager, err := providers.NewCertificateManager(ctx, kubeClient, kubeConfig, cfg, osmNamespace, certOpts, msgBroker)
216+
certManager, err := providers.NewCertificateManager(ctx, kubeClient, kubeConfig, cfg, osmNamespace, certOpts, msgBroker, informerCollection)
217217
if err != nil {
218218
events.GenericEventRecorder().FatalEvent(err, events.InvalidCertificateManager,
219219
"Error initializing certificate manager of kind %s", certProviderKind)

cmd/osm-controller/osm-controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ func main() {
208208

209209
// Intitialize certificate manager/provider
210210
certManager, err := providers.NewCertificateManager(ctx, kubeClient, kubeConfig, cfg, osmNamespace,
211-
certOpts, msgBroker)
211+
certOpts, msgBroker, informerCollection)
212212

213213
if err != nil {
214214
events.GenericEventRecorder().FatalEvent(err, events.InvalidCertificateManager,

cmd/osm-injector/osm-injector.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ func main() {
203203
}
204204
// Intitialize certificate manager/provider
205205
certManager, err := providers.NewCertificateManager(ctx, kubeClient, kubeConfig, cfg, osmNamespace,
206-
certOpts, msgBroker)
206+
certOpts, msgBroker, informerCollection)
207207
if err != nil {
208208
events.GenericEventRecorder().FatalEvent(err, events.InvalidCertificateManager,
209209
"Error initializing certificate manager of kind %s", certProviderKind)

pkg/certificate/errors.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ var ErrInvalidCertSecret = errors.New("invalid secret for certificate")
2020

2121
// ErrSecretNotFound should be returned if the secret isn't present in the underlying infra, on a Get
2222
var ErrSecretNotFound = errors.New("secret not found")
23+
24+
// ErrNoValidMeshRootCertificates should be returned if no valid MeshRootCertificates are detected in the cluster
25+
var ErrNoValidMeshRootCertificates = errors.New("no valid mesh root certificates could be found")

pkg/certificate/manager.go

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"github.com/rs/zerolog/log"
88

99
"github.com/openservicemesh/osm/pkg/announcements"
10+
"github.com/openservicemesh/osm/pkg/apis/config/v1alpha2"
11+
"github.com/openservicemesh/osm/pkg/constants"
1012
"github.com/openservicemesh/osm/pkg/errcode"
1113
"github.com/openservicemesh/osm/pkg/k8s/events"
1214
"github.com/openservicemesh/osm/pkg/messaging"
@@ -20,29 +22,22 @@ func NewManager(ctx context.Context, mrcClient MRCClient, serviceCertValidityDur
2022
return nil, err
2123
}
2224

23-
mrcs, err := mrcClient.List()
24-
if err != nil {
25-
return nil, err
25+
m := &Manager{
26+
serviceCertValidityDuration: serviceCertValidityDuration,
27+
msgBroker: msgBroker,
2628
}
27-
28-
client, ca, clientID, err := mrcClient.GetCertIssuerForMRC(mrcs[0])
29+
// We need an MRC in order to get the correct issuers, so handle initial MRC List now
30+
mrcs, err := mrcClient.List()
2931
if err != nil {
3032
return nil, err
3133
}
3234

33-
c := &issuer{Issuer: client, ID: clientID, CertificateAuthority: ca}
35+
m.init(mrcs, mrcClient)
3436

35-
m := &Manager{
36-
// The signingIssuer is responsible for signing all newly issued certificates
37-
// The validatingIssuer is the issuer that issued existing certificates.
38-
// its underlying cert is still in the validating trust store
39-
signingIssuer: c,
40-
validatingIssuer: c,
41-
serviceCertValidityDuration: serviceCertValidityDuration,
42-
msgBroker: msgBroker,
43-
}
44-
45-
// start a watch
37+
// now that the manager is initialized, start a watch
38+
// we wait until the manager is initialized so that there's
39+
// no lock contention between the event handler and the initial
40+
// state of the manager.
4641
go func() {
4742
for {
4843
select {
@@ -62,6 +57,38 @@ func NewManager(ctx context.Context, mrcClient MRCClient, serviceCertValidityDur
6257
return m, nil
6358
}
6459

60+
// init initializes the Manager receiver based on the observed state of the cluster at this
61+
// instant in time. This is why we pass in a slice of MRCs; we know our Watch call will make us initially
62+
// consistent, we just need a valid state of the world at this instant to kick things off.
63+
// This method is meant to be called at initialization time, so we don't grab the lock
64+
func (m *Manager) init(mrcs []*v1alpha2.MeshRootCertificate, mrcClient MRCClient) error {
65+
for _, mrc := range mrcs {
66+
client, ca, clientID, err := mrcClient.GetCertIssuerForMRC(mrc)
67+
if err != nil {
68+
return err
69+
}
70+
71+
c := &issuer{Issuer: client, ID: clientID, CertificateAuthority: ca}
72+
switch {
73+
case mrc.Status.State == "errored":
74+
continue
75+
case mrc.Status.State == constants.MRCStateComplete && mrc.Status.RotationStage == constants.MRCStageIssuing:
76+
m.signingIssuer = c
77+
m.validatingIssuer = c
78+
case mrc.Status.RotationStage == constants.MRCStageIssuing:
79+
m.signingIssuer = c
80+
case mrc.Status.RotationStage == constants.MRCStageValidating:
81+
m.validatingIssuer = c
82+
}
83+
}
84+
85+
if m.signingIssuer == nil || m.validatingIssuer == nil {
86+
return ErrNoValidMeshRootCertificates
87+
}
88+
89+
return nil
90+
}
91+
6592
func (m *Manager) handleMRCEvent(event MRCEvent) {
6693
switch event.Type {
6794
case MRCEventAdded:

pkg/certificate/providers/config.go

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/openservicemesh/osm/pkg/certificate/providers/vault"
2222
"github.com/openservicemesh/osm/pkg/configurator"
2323
"github.com/openservicemesh/osm/pkg/constants"
24+
"github.com/openservicemesh/osm/pkg/k8s/informers"
2425
"github.com/openservicemesh/osm/pkg/messaging"
2526
)
2627

@@ -43,42 +44,60 @@ var getCA func(certificate.Issuer) (pem.RootCertificate, error) = func(i certifi
4344
// NewCertificateManager returns a new certificate manager, with an MRC compat client.
4445
// TODO(4713): Use an informer behind a feature flag.
4546
func NewCertificateManager(ctx context.Context, kubeClient kubernetes.Interface, kubeConfig *rest.Config, cfg configurator.Configurator,
46-
providerNamespace string, options Options, msgBroker *messaging.Broker) (*certificate.Manager, error) {
47+
providerNamespace string, options Options, msgBroker *messaging.Broker, informers *informers.InformerCollection) (*certificate.Manager, error) {
4748
if err := options.Validate(); err != nil {
4849
return nil, err
4950
}
5051

51-
// TODO(4713): Switch the compat client to an informer. Might need another struct to compose the informer and
52-
// provider generator.
53-
mrcClient := &MRCCompatClient{
54-
MRCProviderGenerator: MRCProviderGenerator{
55-
kubeClient: kubeClient,
56-
kubeConfig: kubeConfig,
57-
KeyBitSize: cfg.GetCertKeyBitSize(),
58-
caExtractorFunc: getCA,
59-
},
60-
mrc: &v1alpha2.MeshRootCertificate{
61-
ObjectMeta: metav1.ObjectMeta{
62-
Name: "legacy-compat",
63-
Namespace: providerNamespace,
64-
Annotations: map[string]string{
65-
constants.MRCVersionAnnotation: "legacy-compat",
66-
},
52+
var mrcClient certificate.MRCClient
53+
// TODO(4713): Switch out with feature flag or some other mechanism
54+
if true {
55+
c := &MRCCompatClient{
56+
MRCProviderGenerator: MRCProviderGenerator{
57+
kubeClient: kubeClient,
58+
kubeConfig: kubeConfig,
59+
KeyBitSize: cfg.GetCertKeyBitSize(),
60+
caExtractorFunc: getCA,
6761
},
68-
Spec: v1alpha2.MeshRootCertificateSpec{
69-
Provider: options.AsProviderSpec(),
62+
mrc: &v1alpha2.MeshRootCertificate{
63+
ObjectMeta: metav1.ObjectMeta{
64+
Name: "legacy-compat",
65+
Namespace: providerNamespace,
66+
Annotations: map[string]string{
67+
constants.MRCVersionAnnotation: "legacy-compat",
68+
},
69+
},
70+
Spec: v1alpha2.MeshRootCertificateSpec{
71+
Provider: options.AsProviderSpec(),
72+
},
73+
// TODO(#4713): Detect if an actual MRC exists, and set the status accordingly.
74+
Status: v1alpha2.MeshRootCertificateStatus{
75+
State: constants.MRCStateComplete,
76+
RotationStage: constants.MRCStageIssuing,
77+
},
7078
},
71-
// TODO(#4713): Detect if an actual MRC exists, and set the status accordingly.
72-
Status: v1alpha2.MeshRootCertificateStatus{
73-
State: constants.MRCStateComplete,
74-
RotationStage: constants.MRCStageIssuing,
79+
}
80+
// TODO(#4745): Remove after deprecating the osm.vault.token option.
81+
if vaultOption, ok := options.(VaultOptions); ok {
82+
c.MRCProviderGenerator.DefaultVaultToken = vaultOption.VaultToken
83+
}
84+
mrcClient = c
85+
} else {
86+
c := &MRCClientImpl{
87+
MRCProviderGenerator: MRCProviderGenerator{
88+
kubeClient: kubeClient,
89+
kubeConfig: kubeConfig,
90+
KeyBitSize: cfg.GetCertKeyBitSize(),
91+
caExtractorFunc: getCA,
7592
},
76-
},
77-
}
93+
informerCollection: informers,
94+
}
95+
96+
if vaultOption, ok := options.(VaultOptions); ok {
97+
c.MRCProviderGenerator.DefaultVaultToken = vaultOption.VaultToken
98+
}
7899

79-
// TODO(#4745): Remove after deprecating the osm.vault.token option.
80-
if vaultOption, ok := options.(VaultOptions); ok {
81-
mrcClient.MRCProviderGenerator.DefaultVaultToken = vaultOption.VaultToken
100+
mrcClient = c
82101
}
83102

84103
return certificate.NewManager(ctx, mrcClient, cfg.GetServiceCertValidityPeriod(), msgBroker)

pkg/certificate/providers/config_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func TestGetCertificateManager(t *testing.T) {
116116
getCA = oldCA
117117
}()
118118

119-
manager, err := NewCertificateManager(context.Background(), tc.kubeClient, tc.restConfig, tc.cfg, tc.providerNamespace, tc.options, tc.msgBroker)
119+
manager, err := NewCertificateManager(context.Background(), tc.kubeClient, tc.restConfig, tc.cfg, tc.providerNamespace, tc.options, tc.msgBroker, nil)
120120
if tc.expectError {
121121
assert.Empty(manager)
122122
assert.Error(err)

pkg/certificate/providers/mrcclient.go

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,73 @@ import (
55

66
"github.com/openservicemesh/osm/pkg/apis/config/v1alpha2"
77
"github.com/openservicemesh/osm/pkg/certificate"
8-
"github.com/openservicemesh/osm/pkg/configurator"
8+
"github.com/openservicemesh/osm/pkg/k8s/informers"
9+
"github.com/pkg/errors"
10+
"k8s.io/client-go/tools/cache"
911
)
1012

13+
var (
14+
errNilInformerCollection = errors.New("informer collection is nil")
15+
)
16+
17+
// TODO: Rename (keithmattix)
1118
type MRCClientImpl struct {
12-
configurator configurator.Configurator
13-
certificate.MRCEventBroker
19+
informerCollection *informers.InformerCollection
1420
MRCProviderGenerator
1521
}
1622

17-
func (m *MRCClientImpl) List() ([]v1alpha2.MeshRootCertificate, error) {
18-
return m.configurator.GetMeshRootCertificates()
23+
func (m *MRCClientImpl) List() ([]*v1alpha2.MeshRootCertificate, error) {
24+
if m.informerCollection == nil {
25+
return nil, errNilInformerCollection
26+
}
27+
// informers return slice of pointers so we'll convert them to value types before returning
28+
mrcPtrs := m.informerCollection.List(informers.InformerKeyMeshRootCertificate)
29+
var mrcs []*v1alpha2.MeshRootCertificate
30+
for _, mrcPtr := range mrcPtrs {
31+
if mrcPtr == nil {
32+
continue
33+
}
34+
mrc, ok := mrcPtr.(*v1alpha2.MeshRootCertificate)
35+
if !ok {
36+
continue
37+
}
38+
mrcs = append(mrcs, mrc)
39+
}
40+
41+
return mrcs, nil
1942
}
2043

2144
func (m *MRCClientImpl) Watch(ctx context.Context) (<-chan certificate.MRCEvent, error) {
45+
if m.informerCollection == nil {
46+
return nil, errNilInformerCollection
47+
}
48+
49+
eventChan := make(chan certificate.MRCEvent)
50+
m.informerCollection.AddEventHandler(informers.InformerKeyMeshRootCertificate, cache.ResourceEventHandlerFuncs{
51+
AddFunc: func(obj interface{}) {
52+
mrc := obj.(*v1alpha2.MeshRootCertificate)
53+
eventChan <- certificate.MRCEvent{
54+
Type: certificate.MRCEventAdded,
55+
MRC: mrc,
56+
}
57+
},
58+
UpdateFunc: func(oldObj, newObj interface{}) {
59+
oldMRC := oldObj.(*v1alpha2.MeshRootCertificate)
60+
mrc := newObj.(*v1alpha2.MeshRootCertificate)
61+
eventChan <- certificate.MRCEvent{
62+
Type: certificate.MRCEventUpdated,
63+
MRC: mrc,
64+
OldMRC: oldMRC,
65+
}
66+
},
67+
DeleteFunc: func(obj interface{}) {
68+
mrc := obj.(*v1alpha2.MeshRootCertificate)
69+
eventChan <- certificate.MRCEvent{
70+
Type: certificate.MRCEventUpdated,
71+
MRC: mrc,
72+
}
73+
},
74+
})
2275

76+
return eventChan, nil
2377
}

pkg/certificate/types.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,11 @@ type MRCClient interface {
106106
type MRCEventType string
107107
type MRCEvent struct {
108108
Type MRCEventType
109-
MRC *v1alpha2.MeshRootCertificate
109+
// The last observed version of the MRC as of the time of this event
110+
MRC *v1alpha2.MeshRootCertificate
111+
// The previous version of the MRC. Only populated during updates
112+
// +optional
113+
OldMRC *v1alpha2.MeshRootCertificate
110114
}
111115

112116
var (

pkg/configurator/client.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package configurator
22

33
import (
4+
"errors"
45
"fmt"
56
"reflect"
67

@@ -68,10 +69,10 @@ func (c *Client) getMeshConfig() configv1alpha2.MeshConfig {
6869
return meshConfig
6970
}
7071

71-
func (c *client) getMeshRootCertificates() ([]configv1alpha2.MeshRootCertificate, error) {
72+
func (c *Client) getMeshRootCertificates() ([]configv1alpha2.MeshRootCertificate, error) {
7273
var mrcs []configv1alpha2.MeshRootCertificate
7374

74-
for _, item := range c.caches.meshRootCertificate.List() {
75+
for _, item := range c.informers.List(informers.InformerKeyMeshRootCertificate) {
7576
mrc, ok := item.(*configv1alpha2.MeshRootCertificate)
7677
if !ok {
7778
return nil, errors.New("error casting cache entry to *MeshRootCertificate")
@@ -82,7 +83,7 @@ func (c *client) getMeshRootCertificates() ([]configv1alpha2.MeshRootCertificate
8283
return mrcs, nil
8384
}
8485

85-
func (c *client) metricsHandler() cache.ResourceEventHandlerFuncs {
86+
func (c *Client) metricsHandler() cache.ResourceEventHandlerFuncs {
8687
handleMetrics := func(obj interface{}) {
8788
config := obj.(*configv1alpha2.MeshConfig)
8889

0 commit comments

Comments
 (0)