github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/controller/model/graph_client_test.go (about) 1 /* 2 Copyright (C) 2022-2023 ApeCloud Co., Ltd 3 4 This file is part of KubeBlocks project 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU Affero General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU Affero General Public License for more details. 15 16 You should have received a copy of the GNU Affero General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 package model 21 22 import ( 23 "slices" 24 25 . "github.com/onsi/ginkgo/v2" 26 . "github.com/onsi/gomega" 27 28 appsv1 "k8s.io/api/apps/v1" 29 corev1 "k8s.io/api/core/v1" 30 "sigs.k8s.io/controller-runtime/pkg/client" 31 32 "github.com/1aal/kubeblocks/pkg/controller/builder" 33 "github.com/1aal/kubeblocks/pkg/controller/graph" 34 ) 35 36 var _ = Describe("graph client test.", func() { 37 const ( 38 namespace = "foo" 39 name = "bar" 40 ) 41 42 Context("GraphWriter", func() { 43 It("should work well", func() { 44 graphCli := NewGraphClient(nil) 45 dag := graph.NewDAG() 46 dagExpected := graph.NewDAG() 47 root := builder.NewStatefulSetBuilder(namespace, name).GetObject() 48 49 By("init root vertex") 50 graphCli.Root(dag, root.DeepCopy(), root, ActionStatusPtr()) 51 dagExpected.AddVertex(&ObjectVertex{Obj: root, OriObj: root, Action: ActionStatusPtr()}) 52 Expect(dag.Equals(dagExpected, DefaultLess)).Should(BeTrue()) 53 54 By("create object") 55 obj0 := builder.NewPodBuilder(namespace, name+"0").GetObject() 56 obj1 := builder.NewPodBuilder(namespace, name+"1").GetObject() 57 obj2 := builder.NewPodBuilder(namespace, name+"2").GetObject() 58 graphCli.Create(dag, obj0) 59 graphCli.Create(dag, obj1) 60 graphCli.Create(dag, obj2) 61 graphCli.DependOn(dag, obj1, obj2) 62 v0 := &ObjectVertex{Obj: obj0, Action: ActionCreatePtr()} 63 v1 := &ObjectVertex{Obj: obj1, Action: ActionCreatePtr()} 64 v2 := &ObjectVertex{Obj: obj2, Action: ActionCreatePtr()} 65 dagExpected.AddConnectRoot(v0) 66 dagExpected.AddConnectRoot(v1) 67 dagExpected.AddConnectRoot(v2) 68 dagExpected.Connect(v1, v2) 69 Expect(dag.Equals(dagExpected, DefaultLess)).Should(BeTrue()) 70 71 By("update&delete&status object") 72 graphCli.Status(dag, obj0, obj0.DeepCopy()) 73 graphCli.Update(dag, obj1, obj1.DeepCopy()) 74 graphCli.Delete(dag, obj2) 75 v0.Action = ActionStatusPtr() 76 v1.Action = ActionUpdatePtr() 77 v2.Action = ActionDeletePtr() 78 Expect(dag.Equals(dagExpected, DefaultLess)).Should(BeTrue()) 79 80 By("replace an existing object") 81 newObj1 := builder.NewPodBuilder(namespace, name+"1").GetObject() 82 graphCli.Update(dag, nil, newObj1, ReplaceIfExistingOption) 83 Expect(dag.Equals(dagExpected, DefaultLess)).Should(BeTrue()) 84 podList := graphCli.FindAll(dag, &corev1.Pod{}) 85 Expect(podList).Should(HaveLen(3)) 86 Expect(slices.IndexFunc(podList, func(obj client.Object) bool { 87 return obj == newObj1 88 })).Should(BeNumerically(">=", 0)) 89 90 By("noop") 91 graphCli.Noop(dag, obj0) 92 Expect(dag.Equals(dagExpected, DefaultLess)).Should(BeFalse()) 93 v0.Action = ActionNoopPtr() 94 Expect(dag.Equals(dagExpected, DefaultLess)).Should(BeTrue()) 95 96 By("patch") 97 graphCli.Patch(dag, obj0.DeepCopy(), obj0) 98 Expect(dag.Equals(dagExpected, DefaultLess)).Should(BeFalse()) 99 v0.Action = ActionPatchPtr() 100 Expect(dag.Equals(dagExpected, DefaultLess)).Should(BeTrue()) 101 102 By("find objects exist") 103 podList = graphCli.FindAll(dag, &corev1.Pod{}) 104 Expect(podList).Should(HaveLen(3)) 105 for _, object := range []client.Object{obj0, newObj1, obj2} { 106 Expect(slices.IndexFunc(podList, func(obj client.Object) bool { 107 return obj == object 108 })).Should(BeNumerically(">=", 0)) 109 } 110 Expect(slices.IndexFunc(podList, func(obj client.Object) bool { 111 return obj == obj1 112 })).Should(BeNumerically("<", 0)) 113 114 By("find objects not existing") 115 Expect(graphCli.FindAll(dag, &appsv1.Deployment{})).Should(HaveLen(0)) 116 117 By("find objects different with the given type") 118 newPodList := graphCli.FindAll(dag, &appsv1.StatefulSet{}, HaveDifferentTypeWithOption) 119 Expect(newPodList).Should(HaveLen(3)) 120 // should have same result as podList 121 for _, object := range podList { 122 Expect(slices.IndexFunc(newPodList, func(obj client.Object) bool { 123 return obj == object 124 })).Should(BeNumerically(">=", 0)) 125 } 126 127 By("find nil should return empty list") 128 Expect(graphCli.FindAll(dag, nil)).Should(HaveLen(0)) 129 130 By("find all objects") 131 objectList := graphCli.FindAll(dag, nil, HaveDifferentTypeWithOption) 132 Expect(objectList).Should(HaveLen(4)) 133 allObjects := podList 134 allObjects = append(allObjects, root) 135 for _, object := range allObjects { 136 Expect(slices.IndexFunc(objectList, func(obj client.Object) bool { 137 return obj == object 138 })).Should(BeNumerically(">=", 0)) 139 } 140 141 }) 142 143 It("post init root vertex", func() { 144 graphCli := NewGraphClient(nil) 145 dag := graph.NewDAG() 146 dagExpected := graph.NewDAG() 147 148 By("create none root vertex first") 149 obj := builder.NewPodBuilder(namespace, name+"0").GetObject() 150 graphCli.Root(dag, obj, obj, ActionCreatePtr()) 151 v := &ObjectVertex{OriObj: obj, Obj: obj, Action: ActionCreatePtr()} 152 dagExpected.AddVertex(v) 153 Expect(dag.Equals(dagExpected, DefaultLess)).Should(BeTrue()) 154 155 By("post create root vertex") 156 root := builder.NewStatefulSetBuilder(namespace, name).GetObject() 157 graphCli.Root(dag, root.DeepCopy(), root, ActionStatusPtr()) 158 rootVertex := &ObjectVertex{Obj: root, OriObj: root, Action: ActionStatusPtr()} 159 dagExpected.AddVertex(rootVertex) 160 dagExpected.Connect(rootVertex, v) 161 Expect(dag.Equals(dagExpected, DefaultLess)).Should(BeTrue()) 162 }) 163 164 It("IsAction should work", func() { 165 graphCli := NewGraphClient(nil) 166 dag := graph.NewDAG() 167 168 By("create root vertex") 169 obj := builder.NewPodBuilder(namespace, name+"0").GetObject() 170 graphCli.Root(dag, obj, obj, ActionStatusPtr()) 171 Expect(graphCli.IsAction(dag, obj, ActionStatusPtr())).Should(BeTrue()) 172 Expect(graphCli.IsAction(dag, obj, ActionCreatePtr())).Should(BeFalse()) 173 174 By("vertex not existing") 175 Expect(graphCli.IsAction(dag, &corev1.Pod{}, ActionStatusPtr())).Should(BeFalse()) 176 Expect(graphCli.IsAction(dag, &corev1.Pod{}, ActionCreatePtr())).Should(BeFalse()) 177 178 By("nil action") 179 graphCli.Root(dag, obj, obj, nil) 180 Expect(graphCli.IsAction(dag, obj, nil)).Should(BeTrue()) 181 Expect(graphCli.IsAction(dag, obj, ActionCreatePtr())).Should(BeFalse()) 182 }) 183 }) 184 })