github.com/projecteru2/core@v0.0.0-20240321043226-06bcc1c23f58/cluster/calcium/replace_test.go (about)

     1  package calcium
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	enginemocks "github.com/projecteru2/core/engine/mocks"
     8  	enginetypes "github.com/projecteru2/core/engine/types"
     9  	lockmocks "github.com/projecteru2/core/lock/mocks"
    10  	resourcemocks "github.com/projecteru2/core/resource/mocks"
    11  	storemocks "github.com/projecteru2/core/store/mocks"
    12  	"github.com/projecteru2/core/types"
    13  
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/mock"
    16  )
    17  
    18  func TestReplaceWorkload(t *testing.T) {
    19  	c := NewTestCluster()
    20  	ctx := context.Background()
    21  	lock := &lockmocks.DistributedLock{}
    22  	lock.On("Lock", mock.Anything).Return(ctx, nil)
    23  	lock.On("Unlock", mock.Anything).Return(nil)
    24  	store := c.store.(*storemocks.Store)
    25  	rmgr := c.rmgr.(*resourcemocks.Manager)
    26  	rmgr.On("GetNodeResourceInfo", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, nil, nil, nil)
    27  
    28  	_, err := c.ReplaceWorkload(ctx, &types.ReplaceOptions{
    29  		DeployOptions: types.DeployOptions{
    30  			Entrypoint: &types.Entrypoint{
    31  				Name: "bad_entrypoint_name",
    32  			},
    33  		},
    34  	})
    35  	assert.Error(t, err)
    36  
    37  	opts := &types.ReplaceOptions{
    38  		DeployOptions: types.DeployOptions{
    39  			Name:  "appname",
    40  			Image: "image:latest",
    41  			Entrypoint: &types.Entrypoint{
    42  				Name: "nice-entry-name",
    43  			},
    44  			NodeFilter: &types.NodeFilter{},
    45  		},
    46  	}
    47  
    48  	workload := &types.Workload{
    49  		ID:       "xx",
    50  		Name:     "yy",
    51  		Nodename: "testnode",
    52  	}
    53  	// failed by ListWorkload
    54  	store.On("ListWorkloads", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, types.ErrMockError).Once()
    55  	_, err = c.ReplaceWorkload(ctx, opts)
    56  	assert.Error(t, err)
    57  	store.AssertExpectations(t)
    58  
    59  	store.On("ListWorkloads", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]*types.Workload{workload}, nil)
    60  	// failed by withWorkloadLocked
    61  	store.On("GetWorkloads", mock.Anything, mock.Anything).Return(nil, types.ErrMockError).Once()
    62  	ch, err := c.ReplaceWorkload(ctx, opts)
    63  	assert.NoError(t, err)
    64  	for r := range ch {
    65  		assert.Error(t, r.Error)
    66  	}
    67  	store.AssertExpectations(t)
    68  
    69  	store.On("GetWorkloads", mock.Anything, mock.Anything).Return([]*types.Workload{workload}, nil).Once()
    70  	store.On("CreateLock", mock.Anything, mock.Anything).Return(lock, nil)
    71  	// ignore because pod not fit
    72  	opts.Podname = "wtf"
    73  	ch, err = c.ReplaceWorkload(ctx, opts)
    74  	assert.NoError(t, err)
    75  	for range ch {
    76  	}
    77  	store.AssertExpectations(t)
    78  
    79  	workload.Podname = "wtf"
    80  	opts.NetworkInherit = true
    81  	store.On("GetWorkloads", mock.Anything, mock.Anything).Return([]*types.Workload{workload}, nil).Once()
    82  	// failed by inspect
    83  	ch, err = c.ReplaceWorkload(ctx, opts)
    84  	assert.NoError(t, err)
    85  	for r := range ch {
    86  		assert.Error(t, r.Error)
    87  	}
    88  	store.AssertExpectations(t)
    89  
    90  	engine := &enginemocks.API{}
    91  	workload.Engine = engine
    92  	store.On("GetWorkloads", mock.Anything, mock.Anything).Return([]*types.Workload{workload}, nil)
    93  	// failed by not running
    94  	engine.On("VirtualizationInspect", mock.Anything, mock.Anything).Return(&enginetypes.VirtualizationInfo{Running: false}, nil).Once()
    95  	ch, err = c.ReplaceWorkload(ctx, opts)
    96  	assert.NoError(t, err)
    97  	for r := range ch {
    98  		assert.Error(t, r.Error)
    99  	}
   100  	store.AssertExpectations(t)
   101  
   102  	engine.On("VirtualizationInspect", mock.Anything, mock.Anything).Return(&enginetypes.VirtualizationInfo{Running: true}, nil)
   103  	// failed by not fit
   104  	opts.FilterLabels = map[string]string{"x": "y"}
   105  	ch, err = c.ReplaceWorkload(ctx, opts)
   106  	assert.NoError(t, err)
   107  	for r := range ch {
   108  		assert.Error(t, r.Error)
   109  		assert.NotNil(t, r.Remove)
   110  		assert.False(t, r.Remove.Success)
   111  	}
   112  	store.AssertExpectations(t)
   113  
   114  	// failed by get node
   115  	opts.FilterLabels = map[string]string{}
   116  	store.On("GetNode", mock.Anything, mock.Anything).Return(nil, types.ErrMockError).Once()
   117  	ch, err = c.ReplaceWorkload(ctx, opts)
   118  	assert.NoError(t, err)
   119  	for r := range ch {
   120  		assert.Error(t, r.Error)
   121  		assert.NotNil(t, r.Remove)
   122  		assert.False(t, r.Remove.Success)
   123  	}
   124  	node := &types.Node{
   125  		NodeMeta: types.NodeMeta{
   126  			Name: "test",
   127  		},
   128  	}
   129  	store.On("GetNode", mock.Anything, mock.Anything).Return(node, nil).Once()
   130  	// failed by no image
   131  	opts.Image = ""
   132  	ch, err = c.ReplaceWorkload(ctx, opts)
   133  	assert.NoError(t, err)
   134  	for r := range ch {
   135  		assert.Error(t, r.Error)
   136  		assert.NotNil(t, r.Remove)
   137  		assert.False(t, r.Remove.Success)
   138  	}
   139  	opts.Image = "image:latest"
   140  	node.Engine = engine
   141  	engine.On("ImageLocalDigests", mock.Anything, mock.Anything).Return([]string{"id"}, nil)
   142  	engine.On("ImageRemoteDigest", mock.Anything, mock.Anything).Return("id", nil)
   143  	store.On("GetNode", mock.Anything, mock.Anything).Return(node, nil)
   144  	// failed by VirtualizationCopyFrom
   145  	opts.Copy = map[string]string{"src": "dst"}
   146  	engine.On("VirtualizationCopyFrom", mock.Anything, mock.Anything, mock.Anything).Return(nil, 0, 0, int64(0), types.ErrMockError).Once()
   147  	ch, err = c.ReplaceWorkload(ctx, opts)
   148  	assert.NoError(t, err)
   149  	for r := range ch {
   150  		assert.Error(t, r.Error)
   151  		assert.NotNil(t, r.Remove)
   152  		assert.False(t, r.Remove.Success)
   153  	}
   154  	store.AssertExpectations(t)
   155  	engine.AssertExpectations(t)
   156  
   157  	engine.On("VirtualizationCopyFrom", mock.Anything, mock.Anything, mock.Anything).Return([]byte{}, 0, 0, int64(0), nil)
   158  	// failed by Stop
   159  	engine.On("VirtualizationStop", mock.Anything, mock.Anything, mock.Anything).Return(types.ErrMockError).Once()
   160  	engine.On("VirtualizationStart", mock.Anything, mock.Anything).Return(types.ErrMockError).Once()
   161  	ch, err = c.ReplaceWorkload(ctx, opts)
   162  	assert.NoError(t, err)
   163  	for r := range ch {
   164  		assert.Error(t, r.Error)
   165  		assert.NotNil(t, r.Remove)
   166  		assert.False(t, r.Remove.Success)
   167  	}
   168  	store.AssertExpectations(t)
   169  	engine.AssertExpectations(t)
   170  
   171  	engine.On("VirtualizationStop", mock.Anything, mock.Anything, mock.Anything).Return(nil)
   172  	// failed by VirtualizationCreate
   173  	engine.On("VirtualizationCreate", mock.Anything, mock.Anything).Return(nil, types.ErrMockError).Once()
   174  	engine.On("VirtualizationStart", mock.Anything, mock.Anything).Return(types.ErrMockError).Once()
   175  	ch, err = c.ReplaceWorkload(ctx, opts)
   176  	assert.NoError(t, err)
   177  	for r := range ch {
   178  		assert.Error(t, r.Error)
   179  		assert.NotNil(t, r.Remove)
   180  		assert.False(t, r.Remove.Success)
   181  	}
   182  	store.AssertExpectations(t)
   183  	engine.AssertExpectations(t)
   184  
   185  	engine.On("VirtualizationCreate", mock.Anything, mock.Anything).Return(&enginetypes.VirtualizationCreated{ID: "new"}, nil)
   186  	engine.On("VirtualizationStart", mock.Anything, mock.Anything).Return(nil)
   187  	engine.On("VirtualizationCopyChunkTo", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
   188  	engine.On("VirtualizationInspect", mock.Anything, mock.Anything).Return(&enginetypes.VirtualizationInfo{User: "test"}, nil)
   189  	store.On("AddWorkload", mock.Anything, mock.Anything, mock.Anything).Return(nil)
   190  	// failed by remove workload
   191  	store.On("RemoveWorkload", mock.Anything, mock.Anything).Return(types.ErrMockError).Once()
   192  	ch, err = c.ReplaceWorkload(ctx, opts)
   193  	assert.NoError(t, err)
   194  	for r := range ch {
   195  		assert.Error(t, r.Error)
   196  		assert.NotNil(t, r.Remove)
   197  		assert.NotNil(t, r.Create)
   198  		assert.False(t, r.Remove.Success)
   199  		assert.Nil(t, r.Create.Error)
   200  	}
   201  	store.AssertExpectations(t)
   202  	engine.AssertExpectations(t)
   203  
   204  	engine.On("VirtualizationRemove", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
   205  	store.On("RemoveWorkload", mock.Anything, mock.Anything).Return(nil)
   206  	store.On("ListNodeWorkloads", mock.Anything, mock.Anything, mock.Anything).Return(nil, types.ErrMockError)
   207  	// succ
   208  	ch, err = c.ReplaceWorkload(ctx, opts)
   209  	assert.NoError(t, err)
   210  	for r := range ch {
   211  		assert.NoError(t, r.Error)
   212  		assert.NotNil(t, r.Remove)
   213  		assert.NotNil(t, r.Create)
   214  		assert.True(t, r.Remove.Success)
   215  		assert.Nil(t, r.Create.Error)
   216  	}
   217  }