github.com/projecteru2/core@v0.0.0-20240321043226-06bcc1c23f58/cluster/calcium/node_test.go (about) 1 package calcium 2 3 import ( 4 "context" 5 "fmt" 6 "testing" 7 "time" 8 9 "github.com/projecteru2/core/engine/factory" 10 enginemocks "github.com/projecteru2/core/engine/mocks" 11 enginetypes "github.com/projecteru2/core/engine/types" 12 lockmocks "github.com/projecteru2/core/lock/mocks" 13 resourcemocks "github.com/projecteru2/core/resource/mocks" 14 plugintypes "github.com/projecteru2/core/resource/plugins/types" 15 resourcetypes "github.com/projecteru2/core/resource/types" 16 storemocks "github.com/projecteru2/core/store/mocks" 17 "github.com/projecteru2/core/types" 18 19 "github.com/stretchr/testify/assert" 20 "github.com/stretchr/testify/mock" 21 ) 22 23 func TestAddNode(t *testing.T) { 24 c := NewTestCluster() 25 ctx := context.Background() 26 factory.InitEngineCache(ctx, c.config, nil) 27 28 opts := &types.AddNodeOptions{} 29 // failed by validating 30 _, err := c.AddNode(ctx, opts) 31 assert.Error(t, err) 32 33 nodename := "nodename" 34 podname := "podname" 35 opts.Nodename = nodename 36 opts.Podname = podname 37 opts.Endpoint = fmt.Sprintf("mock://%s", nodename) 38 39 // failed by rmgr.AddNode 40 rmgr := c.rmgr.(*resourcemocks.Manager) 41 rmgr.On("AddNode", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, types.ErrMockError).Once() 42 _, err = c.AddNode(ctx, opts) 43 assert.Error(t, err) 44 rmgr.AssertExpectations(t) 45 rmgr.On("AddNode", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( 46 resourcetypes.Resources{}, nil) 47 rmgr.On("RemoveNode", mock.Anything, mock.Anything).Return(nil) 48 49 // failed by store.AddNode 50 store := c.store.(*storemocks.Store) 51 store.On("AddNode", mock.Anything, mock.Anything).Return(nil, types.ErrMockError).Once() 52 _, err = c.AddNode(ctx, opts) 53 assert.Error(t, err) 54 store.AssertExpectations(t) 55 name := "test" 56 node := &types.Node{ 57 NodeMeta: types.NodeMeta{ 58 Name: name, 59 Endpoint: "endpoint", 60 }, 61 } 62 store.On("AddNode", mock.Anything, mock.Anything).Return(node, nil) 63 rmgr.On("GetNodeMetrics", mock.Anything, mock.Anything).Return([]*plugintypes.Metrics{}, nil) 64 n, err := c.AddNode(ctx, opts) 65 assert.NoError(t, err) 66 assert.Equal(t, n.Name, name) 67 } 68 69 func TestRemoveNode(t *testing.T) { 70 c := NewTestCluster() 71 ctx := context.Background() 72 store := c.store.(*storemocks.Store) 73 74 lock := &lockmocks.DistributedLock{} 75 lock.On("Lock", mock.Anything).Return(ctx, nil) 76 lock.On("Unlock", mock.Anything).Return(nil) 77 store.On("CreateLock", mock.Anything, mock.Anything).Return(lock, nil) 78 name := "test" 79 node := &types.Node{NodeMeta: types.NodeMeta{Name: name}} 80 store.On("GetNode", mock.Anything, mock.Anything).Return(node, nil) 81 82 // fail, ListNodeWorkloads fail 83 store.On("ListNodeWorkloads", mock.Anything, mock.Anything, mock.Anything).Return([]*types.Workload{}, types.ErrMockError).Once() 84 assert.Error(t, c.RemoveNode(ctx, name)) 85 86 // fail, node still has associated workloads 87 store.On("ListNodeWorkloads", mock.Anything, mock.Anything, mock.Anything).Return([]*types.Workload{{}}, nil).Once() 88 assert.Error(t, c.RemoveNode(ctx, name)) 89 store.AssertExpectations(t) 90 91 // fail by store.RemoveNode 92 store.On("ListNodeWorkloads", mock.Anything, mock.Anything, mock.Anything).Return([]*types.Workload{}, nil) 93 store.On("RemoveNode", mock.Anything, mock.Anything).Return(types.ErrMockError).Once() 94 assert.Error(t, c.RemoveNode(ctx, name)) 95 96 // success 97 store.On("RemoveNode", mock.Anything, mock.Anything).Return(nil) 98 rmgr := c.rmgr.(*resourcemocks.Manager) 99 rmgr.On("RemoveNode", mock.Anything, mock.Anything).Return(nil) 100 assert.NoError(t, c.RemoveNode(ctx, name)) 101 store.AssertExpectations(t) 102 rmgr.AssertExpectations(t) 103 } 104 105 func TestListPodNodes(t *testing.T) { 106 c := NewTestCluster() 107 ctx := context.Background() 108 109 opts := &types.ListNodesOptions{} 110 store := c.store.(*storemocks.Store) 111 // failed by GetNodesByPod 112 store.On("GetNodesByPod", mock.Anything, mock.Anything, mock.Anything).Return(nil, types.ErrMockError).Once() 113 _, err := c.ListPodNodes(ctx, opts) 114 assert.Error(t, err) 115 store.AssertExpectations(t) 116 117 // success 118 engine := &enginemocks.API{} 119 engine.On("Info", mock.Anything).Return(nil, types.ErrMockError) 120 name1 := "test1" 121 name2 := "test2" 122 nodes := []*types.Node{ 123 {NodeMeta: types.NodeMeta{Name: name1}, Engine: engine, Available: true}, 124 {NodeMeta: types.NodeMeta{Name: name2}, Engine: engine, Available: false}, 125 } 126 store.On("GetNodesByPod", mock.Anything, mock.Anything, mock.Anything).Return(nodes, nil) 127 rmgr := c.rmgr.(*resourcemocks.Manager) 128 rmgr.On("GetNodeResourceInfo", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, nil, nil, types.ErrMockError) 129 opts.CallInfo = true 130 131 ns, err := c.ListPodNodes(ctx, &types.ListNodesOptions{}) 132 assert.NoError(t, err) 133 cnt := 0 134 for range ns { 135 cnt++ 136 } 137 assert.Equal(t, cnt, 2) 138 rmgr.AssertExpectations(t) 139 store.AssertExpectations(t) 140 } 141 142 func TestGetNode(t *testing.T) { 143 c := NewTestCluster() 144 ctx := context.Background() 145 // fail by validating 146 _, err := c.GetNode(ctx, "") 147 assert.Error(t, err) 148 nodename := "test" 149 150 // failed by store.GetNode 151 store := c.store.(*storemocks.Store) 152 store.On("GetNode", mock.Anything, mock.Anything).Return(nil, types.ErrMockError).Once() 153 _, err = c.GetNode(ctx, nodename) 154 assert.Error(t, err) 155 156 node := &types.Node{ 157 NodeMeta: types.NodeMeta{Name: nodename}, 158 } 159 store.On("GetNode", mock.Anything, mock.Anything).Return(node, nil) 160 161 // failed by GetNodeResourceInfo 162 rmgr := c.rmgr.(*resourcemocks.Manager) 163 rmgr.On("GetNodeResourceInfo", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, nil, nil, types.ErrMockError).Once() 164 _, err = c.GetNode(ctx, nodename) 165 assert.Error(t, err) 166 167 rmgr.On("GetNodeResourceInfo", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, nil, nil, nil) 168 169 // success 170 node, err = c.GetNode(ctx, nodename) 171 assert.NoError(t, err) 172 assert.Equal(t, node.Name, nodename) 173 174 rmgr.AssertExpectations(t) 175 store.AssertExpectations(t) 176 } 177 178 func TestGetNodeEngine(t *testing.T) { 179 c := NewTestCluster() 180 ctx := context.Background() 181 182 // fail by validating 183 _, err := c.GetNodeEngineInfo(ctx, "") 184 assert.Error(t, err) 185 nodename := "test" 186 187 // fail by store.GetNode 188 store := c.store.(*storemocks.Store) 189 store.On("GetNode", mock.Anything, mock.Anything).Return(nil, types.ErrMockError).Once() 190 _, err = c.GetNode(ctx, nodename) 191 assert.Error(t, err) 192 193 // success 194 engine := &enginemocks.API{} 195 engine.On("Info", mock.Anything).Return(&enginetypes.Info{Type: "fake"}, nil) 196 node := &types.Node{ 197 NodeMeta: types.NodeMeta{Name: nodename}, 198 Engine: engine, 199 } 200 store.On("GetNode", mock.Anything, mock.Anything).Return(node, nil) 201 202 e, err := c.GetNodeEngineInfo(ctx, nodename) 203 assert.NoError(t, err) 204 assert.Equal(t, e.Type, "fake") 205 store.AssertExpectations(t) 206 } 207 208 func TestSetNode(t *testing.T) { 209 c := NewTestCluster() 210 ctx := context.Background() 211 212 opts := &types.SetNodeOptions{} 213 214 // failed by validating 215 _, err := c.SetNode(ctx, opts) 216 assert.Error(t, err) 217 218 store := c.store.(*storemocks.Store) 219 lock := &lockmocks.DistributedLock{} 220 lock.On("Lock", mock.Anything).Return(ctx, nil) 221 lock.On("Unlock", mock.Anything).Return(nil) 222 store.On("CreateLock", mock.Anything, mock.Anything).Return(lock, nil) 223 name := "test" 224 opts.Nodename = name 225 node := &types.Node{NodeMeta: types.NodeMeta{Name: name}} 226 store.On("GetNode", mock.Anything, mock.Anything).Return(node, nil) 227 228 // failed by GetNodeResourceInfo 229 rmgr := c.rmgr.(*resourcemocks.Manager) 230 rmgr.On("GetNodeResourceInfo", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, nil, nil, types.ErrMockError).Once() 231 _, err = c.SetNode(ctx, opts) 232 assert.Error(t, err) 233 rmgr.On("GetNodeResourceInfo", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, nil, nil, nil) 234 235 // for bypass 236 opts.Bypass = types.TriTrue 237 opts.WorkloadsDown = true 238 // for setAllWorkloadsOnNodeDown 239 workloads := []*types.Workload{{ID: "1", Name: "wrong_name"}, {ID: "2", Name: "a_b_c"}} 240 store.On("ListNodeWorkloads", mock.Anything, mock.Anything, mock.Anything).Return(workloads, nil) 241 store.On("SetWorkloadStatus", mock.Anything, mock.Anything, mock.Anything).Return(nil) 242 243 // for set endpoint 244 endpoint := "mock://test2" 245 opts.Endpoint = endpoint 246 247 // for labels update 248 labels := map[string]string{"a": "1", "b": "2"} 249 opts.Labels = labels 250 251 // failed by SetNodeResourceCapacity 252 opts.Resources = resourcetypes.Resources{"a": {"a": 1}} 253 rmgr.On("SetNodeResourceCapacity", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( 254 nil, nil, types.ErrMockError, 255 ).Once() 256 _, err = c.SetNode(ctx, opts) 257 assert.Error(t, err) 258 rmgr.On("SetNodeResourceCapacity", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( 259 nil, nil, nil, 260 ) 261 262 // rollback 263 store.On("UpdateNodes", mock.Anything, mock.Anything).Return(types.ErrMockError).Once() 264 _, err = c.SetNode(ctx, opts) 265 assert.Error(t, err) 266 store.On("UpdateNodes", mock.Anything, mock.Anything).Return(nil) 267 rmgr.On("GetNodeMetrics", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]*plugintypes.Metrics{}, nil) 268 269 // done 270 node, err = c.SetNode(ctx, opts) 271 assert.NoError(t, err) 272 assert.Equal(t, node.Endpoint, endpoint) 273 assert.Equal(t, labels["a"], node.Labels["a"]) 274 store.AssertExpectations(t) 275 time.Sleep(100 * time.Millisecond) // for send metrics testing 276 rmgr.AssertExpectations(t) 277 } 278 279 func TestFilterNodes(t *testing.T) { 280 c := NewTestCluster() 281 ctx := context.Background() 282 store := c.store.(*storemocks.Store) 283 284 // failed by GetNode 285 nf := &types.NodeFilter{Includes: []string{"test"}} 286 store.On("GetNode", mock.Anything, mock.Anything).Return(nil, types.ErrMockError).Once() 287 _, err := c.filterNodes(ctx, nf) 288 assert.Error(t, err) 289 290 // succ by GetNode 291 node1 := &types.Node{NodeMeta: types.NodeMeta{Name: "0"}} 292 store.On("GetNode", mock.Anything, mock.Anything).Return(node1, nil) 293 ns, err := c.filterNodes(ctx, nf) 294 assert.NoError(t, err) 295 assert.Len(t, ns, 1) 296 297 // failed by GetNodesByPod 298 nf.Includes = []string{} 299 store.On("GetNodesByPod", mock.Anything, mock.Anything).Return(nil, types.ErrMockError).Once() 300 _, err = c.filterNodes(ctx, nf) 301 assert.Error(t, err) 302 303 nodes := []*types.Node{ 304 { 305 NodeMeta: types.NodeMeta{Name: "A"}, 306 }, 307 { 308 NodeMeta: types.NodeMeta{Name: "B"}, 309 }, 310 { 311 NodeMeta: types.NodeMeta{Name: "C"}, 312 }, 313 { 314 NodeMeta: types.NodeMeta{Name: "D"}, 315 }, 316 } 317 store.On("GetNodesByPod", mock.Anything, mock.Anything).Return(nodes, nil) 318 319 // no excludes 320 ns, err = c.filterNodes(ctx, nf) 321 assert.NoError(t, err) 322 assert.Len(t, ns, 4) 323 324 // excludes 325 nf.Excludes = []string{"A", "C"} 326 ns, err = c.filterNodes(ctx, nf) 327 assert.NoError(t, err) 328 assert.Len(t, ns, 2) 329 }