-
Notifications
You must be signed in to change notification settings - Fork 19
/
named_peerref_with_data.go
135 lines (122 loc) · 4.57 KB
/
named_peerref_with_data.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package controllers
import (
"context"
"errors"
"reflect"
multiclusterv1alpha1 "github.com/red-hat-storage/odf-multicluster-orchestrator/api/v1alpha1"
"github.com/red-hat-storage/odf-multicluster-orchestrator/controllers/utils"
corev1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)
// NamedPeerRefWithSecretData is an intermediate data structure,
// when converting a source secret to corresponding peer destination secret
type NamedPeerRefWithSecretData struct {
multiclusterv1alpha1.PeerRef
Name string
Data []byte
SecretOrigin string
}
// NewNamedPeerRefWithSecretData creates a new PeerRef instance which has the source Name and Data details
// attached to it.
// Make sure we give a source secret and it's (one of the) connected PeerRef as arguments.
func NewNamedPeerRefWithSecretData(secret *corev1.Secret, peerRef multiclusterv1alpha1.PeerRef) *NamedPeerRefWithSecretData {
var nPeerRef NamedPeerRefWithSecretData = NamedPeerRefWithSecretData{
Name: secret.Name,
Data: secret.Data[utils.SecretDataKey],
PeerRef: peerRef,
SecretOrigin: string(secret.Data[utils.SecretOriginKey]),
}
return &nPeerRef
}
// GenerateSecret will generate a secret of provided type.
// nPeerRef object contains TWO parts,
//
// a. details of the secret, like name,namespace etc; that is to be generated
// b. data part that is to be passed on to the newly created secret
//
// The type of secret (ie; source or destination) is passed as the argument
func (nPR *NamedPeerRefWithSecretData) GenerateSecret(secretLabelType utils.SecretLabelType) *corev1.Secret {
if nPR == nil {
return nil
}
secretNamespacedName := types.NamespacedName{
Name: nPR.Name,
Namespace: nPR.PeerRef.ClusterName,
}
storageClusterNamespacedName := types.NamespacedName{
Name: nPR.PeerRef.StorageClusterRef.Name,
Namespace: nPR.PeerRef.StorageClusterRef.Namespace,
}
var retSecret *corev1.Secret
if secretLabelType == utils.DestinationLabel {
retSecret = utils.CreateDestinationSecret(secretNamespacedName, storageClusterNamespacedName, nPR.Data, nPR.SecretOrigin)
} else if secretLabelType == utils.SourceLabel {
retSecret = utils.CreateSourceSecret(secretNamespacedName, storageClusterNamespacedName, nPR.Data, nPR.SecretOrigin)
}
return retSecret
}
func (nPR *NamedPeerRefWithSecretData) Request() (req reconcile.Request) {
if nPR == nil {
return
}
req.NamespacedName = types.NamespacedName{
Name: nPR.Name,
Namespace: nPR.PeerRef.ClusterName,
}
return
}
func (nPR *NamedPeerRefWithSecretData) ErrorOnNilReceiver() (err error) {
if nPR == nil {
err = errors.New("'nil' receiver detected")
}
return err
}
// GetAssociatedSecret returns a secret in the cluster, which has the
// same 'Name' and 'Namespace' matching the PeerRef's name and clustername
func (nPR *NamedPeerRefWithSecretData) GetAssociatedSecret(ctx context.Context, rc client.Client, holdSecret *corev1.Secret) error {
if err := nPR.ErrorOnNilReceiver(); err != nil {
return err
}
var err error
localSecret := corev1.Secret{}
req := nPR.Request()
err = rc.Get(ctx, req.NamespacedName, &localSecret)
if err == nil && holdSecret != nil {
localSecret.DeepCopyInto(holdSecret)
}
return err
}
// CreateOrUpdateDestinationSecret creates/updates the destination secret from NamedPeerRefWithSecretData object
func (nPR *NamedPeerRefWithSecretData) CreateOrUpdateDestinationSecret(ctx context.Context, rc client.Client) error {
err := nPR.ErrorOnNilReceiver()
if err != nil {
return err
}
logger := log.FromContext(ctx)
expectedDest := nPR.GenerateSecret(utils.DestinationLabel)
var currentDest corev1.Secret
err = nPR.GetAssociatedSecret(ctx, rc, ¤tDest)
if err != nil {
if k8serrors.IsNotFound(err) {
logger.Info("Creating destination secret", "secret", expectedDest.Name, "namespace", expectedDest.Namespace)
return rc.Create(ctx, expectedDest)
}
logger.Error(err, "Unable to get the destination secret", "destination-ref", nPR.PeerRef)
return err
}
// recieved a destination secret, now compare
if !reflect.DeepEqual(expectedDest.Data, currentDest.Data) {
logger.Info("Updating the destination secret", "secret", currentDest.Name, "namespace", currentDest.Namespace)
_, err := controllerutil.CreateOrUpdate(ctx, rc, ¤tDest, func() error {
currentDest.Data = expectedDest.Data
return nil
})
return err
}
return nil
}