@@ -19,6 +19,7 @@ package invoker
19
19
import (
20
20
"context"
21
21
"fmt"
22
+ "strings"
22
23
"time"
23
24
24
25
"stash.appscode.dev/apimachinery/apis/stash/v1beta1"
@@ -27,13 +28,16 @@ import (
27
28
v1beta1_util "stash.appscode.dev/apimachinery/client/clientset/versioned/typed/stash/v1beta1/util"
28
29
29
30
core "k8s.io/api/core/v1"
31
+ kerr "k8s.io/apimachinery/pkg/api/errors"
30
32
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31
33
"k8s.io/apimachinery/pkg/types"
32
34
"k8s.io/client-go/kubernetes"
33
35
"k8s.io/client-go/tools/reference"
34
36
kmapi "kmodules.xyz/client-go/api/v1"
35
37
core_util "kmodules.xyz/client-go/core/v1"
36
38
"kmodules.xyz/client-go/meta"
39
+ appcat "kmodules.xyz/custom-resources/apis/appcatalog/v1alpha1"
40
+ appcatalog_cs "kmodules.xyz/custom-resources/client/clientset/versioned"
37
41
ofst "kmodules.xyz/offshoot-api/api/v1"
38
42
)
39
43
@@ -59,26 +63,27 @@ type RestoreInvokerStatus struct {
59
63
}
60
64
61
65
type RestoreInvoker struct {
62
- TypeMeta metav1.TypeMeta
63
- ObjectMeta metav1.ObjectMeta
64
- Labels map [string ]string
65
- Hash string
66
- Driver v1beta1.Snapshotter
67
- Repository string
68
- TargetsInfo []RestoreTargetInfo
69
- ExecutionOrder v1beta1.ExecutionOrder
70
- Hooks * v1beta1.RestoreHooks
71
- ObjectRef * core.ObjectReference
72
- OwnerRef * metav1.OwnerReference
73
- Status RestoreInvokerStatus
74
- ObjectJson []byte
75
- AddFinalizer func () error
76
- RemoveFinalizer func () error
77
- HasCondition func (* v1beta1.TargetRef , string ) (bool , error )
78
- GetCondition func (* v1beta1.TargetRef , string ) (int , * kmapi.Condition , error )
79
- SetCondition func (* v1beta1.TargetRef , kmapi.Condition ) error
80
- IsConditionTrue func (* v1beta1.TargetRef , string ) (bool , error )
81
- NextInOrder func (v1beta1.TargetRef , []v1beta1.RestoreMemberStatus ) bool
66
+ TypeMeta metav1.TypeMeta
67
+ ObjectMeta metav1.ObjectMeta
68
+ Labels map [string ]string
69
+ Hash string
70
+ Driver v1beta1.Snapshotter
71
+ Repository string
72
+ TargetsInfo []RestoreTargetInfo
73
+ ExecutionOrder v1beta1.ExecutionOrder
74
+ Hooks * v1beta1.RestoreHooks
75
+ ObjectRef * core.ObjectReference
76
+ OwnerRef * metav1.OwnerReference
77
+ Status RestoreInvokerStatus
78
+ ObjectJson []byte
79
+ AddFinalizer func () error
80
+ RemoveFinalizer func () error
81
+ HasCondition func (* v1beta1.TargetRef , string ) (bool , error )
82
+ GetCondition func (* v1beta1.TargetRef , string ) (int , * kmapi.Condition , error )
83
+ SetCondition func (* v1beta1.TargetRef , kmapi.Condition ) error
84
+ IsConditionTrue func (* v1beta1.TargetRef , string ) (bool , error )
85
+ NextInOrder func (v1beta1.TargetRef , []v1beta1.RestoreMemberStatus ) bool
86
+ EnsureKubeDBIntegration func (appClient appcatalog_cs.Interface ) error
82
87
83
88
UpdateRestoreInvokerStatus func (status RestoreInvokerStatus ) (RestoreInvokerStatus , error )
84
89
CreateEvent func (eventType , source , reason , message string ) error
@@ -253,6 +258,41 @@ func ExtractRestoreInvokerInfo(kubeClient kubernetes.Interface, stashClient cs.I
253
258
}, metav1.CreateOptions {})
254
259
return err
255
260
}
261
+ invoker .EnsureKubeDBIntegration = func (appClient appcatalog_cs.Interface ) error {
262
+ for i := range restoreBatch .Spec .Members {
263
+ target := restoreBatch .Spec .Members [i ].Target
264
+ // Don't do anything if the target is not an AppBinding
265
+ if target == nil || ! TargetOfGroupKind (target .Ref , appcat .SchemeGroupVersion .Group , appcat .ResourceKindApp ) {
266
+ continue
267
+ }
268
+ // Get the respective AppBinding
269
+ appBinding , err := appClient .AppcatalogV1alpha1 ().AppBindings (restoreBatch .Namespace ).Get (context .TODO (), target .Ref .Name , metav1.GetOptions {})
270
+ if err != nil {
271
+ // If the AppBinding does not exist, then don't do anything.
272
+ if kerr .IsNotFound (err ) {
273
+ continue
274
+ }
275
+ return err
276
+ }
277
+ // If the AppBinding is not managed by KubeDB, then don't do anything
278
+ if manager , err := meta .GetStringValue (appBinding .Labels , meta .ManagedByLabelKey ); err != nil || manager != "kubedb.com" {
279
+ continue
280
+ }
281
+ // Extract the name, and managed-by labels. We are not passing "instance" label because there could be multiple AppBindings.
282
+ appLabels , err := extractLabels (appBinding .Labels , meta .ManagedByLabelKey , meta .NameLabelKey )
283
+ if err != nil {
284
+ return err
285
+ }
286
+
287
+ // Add the labels to the invoker
288
+ _ , _ , err = v1beta1_util .PatchRestoreBatch (context .TODO (), stashClient .StashV1beta1 (), restoreBatch , func (in * v1beta1.RestoreBatch ) * v1beta1.RestoreBatch {
289
+ in .Labels = meta .OverwriteKeys (in .Labels , appLabels )
290
+ return in
291
+ }, metav1.PatchOptions {})
292
+ return err
293
+ }
294
+ return nil
295
+ }
256
296
case v1beta1 .ResourceKindRestoreSession :
257
297
// get RestoreSession
258
298
restoreSession , err := stashClient .StashV1beta1 ().RestoreSessions (namespace ).Get (context .TODO (), invokerName , metav1.GetOptions {})
@@ -409,6 +449,37 @@ func ExtractRestoreInvokerInfo(kubeClient kubernetes.Interface, stashClient cs.I
409
449
}, metav1.CreateOptions {})
410
450
return err
411
451
}
452
+ invoker .EnsureKubeDBIntegration = func (appClient appcatalog_cs.Interface ) error {
453
+ // Don't do anything if the target is not an AppBinding
454
+ if restoreSession .Spec .Target == nil || ! TargetOfGroupKind (restoreSession .Spec .Target .Ref , appcat .SchemeGroupVersion .Group , appcat .ResourceKindApp ) {
455
+ return nil
456
+ }
457
+ // Get the AppBinding
458
+ appBinding , err := appClient .AppcatalogV1alpha1 ().AppBindings (restoreSession .Namespace ).Get (context .TODO (), restoreSession .Spec .Target .Ref .Name , metav1.GetOptions {})
459
+ if err != nil {
460
+ // If the AppBinding does not exist, then don't do anything.
461
+ if kerr .IsNotFound (err ) {
462
+ return nil
463
+ }
464
+ return err
465
+ }
466
+ // If the AppBinding is not managed by KubeDB, then don't do anything
467
+ if manager , err := meta .GetStringValue (appBinding .Labels , meta .ManagedByLabelKey ); err != nil || manager != "kubedb.com" {
468
+ return nil
469
+ }
470
+ // Extract the name, instance, and managed-by labels.
471
+ appLabels , err := extractLabels (appBinding .Labels , meta .InstanceLabelKey , meta .ManagedByLabelKey , meta .NameLabelKey )
472
+ if err != nil {
473
+ return err
474
+ }
475
+
476
+ // Add the labels to the invoker
477
+ _ , _ , err = v1beta1_util .PatchRestoreSession (context .TODO (), stashClient .StashV1beta1 (), restoreSession , func (in * v1beta1.RestoreSession ) * v1beta1.RestoreSession {
478
+ in .Labels = meta .OverwriteKeys (in .Labels , appLabels )
479
+ return in
480
+ }, metav1.PatchOptions {})
481
+ return err
482
+ }
412
483
default :
413
484
return invoker , fmt .Errorf ("failed to extract invoker info. Reason: unknown invoker" )
414
485
}
@@ -553,3 +624,23 @@ func TargetRestoreCompleted(ref v1beta1.TargetRef, targetStatus []v1beta1.Restor
553
624
}
554
625
return false
555
626
}
627
+
628
+ func extractLabels (in map [string ]string , keys ... string ) (map [string ]string , error ) {
629
+ out := make (map [string ]string , len (keys ))
630
+ for _ , k := range keys {
631
+ val , err := meta .GetStringValue (in , k )
632
+ if err != nil {
633
+ return nil , err
634
+ }
635
+ out [k ] = val
636
+ }
637
+ return out , nil
638
+ }
639
+
640
+ func TargetOfGroupKind (targetRef v1beta1.TargetRef , group , kind string ) bool {
641
+ gv := strings .Split (targetRef .APIVersion , "/" )
642
+ if len (gv ) > 0 && gv [0 ] == group && targetRef .Kind == kind {
643
+ return true
644
+ }
645
+ return false
646
+ }
0 commit comments