github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/aggregator/tools/deploy/helper_test.go (about)

     1  // Copyright (c) 2017 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package deploy
    22  
    23  import (
    24  	"errors"
    25  	"fmt"
    26  	"strings"
    27  	"testing"
    28  	"time"
    29  
    30  	"github.com/m3db/m3/src/cluster/placement"
    31  	"github.com/m3db/m3/src/x/retry"
    32  
    33  	"github.com/golang/mock/gomock"
    34  	"github.com/stretchr/testify/require"
    35  )
    36  
    37  var (
    38  	testPlacement = placement.NewPlacement().SetInstances(
    39  		[]placement.Instance{
    40  			placement.NewInstance().
    41  				SetID("placement_instance1").
    42  				SetEndpoint("placement_instance1_endpoint").
    43  				SetShardSetID(0),
    44  			placement.NewInstance().
    45  				SetID("placement_instance2").
    46  				SetEndpoint("placement_instance2_endpoint").
    47  				SetShardSetID(0),
    48  			placement.NewInstance().
    49  				SetID("placement_instance3").
    50  				SetEndpoint("placement_instance3_endpoint").
    51  				SetShardSetID(1),
    52  			placement.NewInstance().
    53  				SetID("placement_instance4").
    54  				SetEndpoint("placement_instance4_endpoint").
    55  				SetShardSetID(1),
    56  		},
    57  	)
    58  	testInstanceMetadatas = instanceMetadatas{
    59  		{
    60  			PlacementInstanceID:  "placement_instance1",
    61  			DeploymentInstanceID: "deployment_instance1",
    62  			ShardSetID:           0,
    63  			APIEndpoint:          "placement_instance1_endpoint",
    64  			Revision:             "revision1",
    65  		},
    66  		{
    67  			PlacementInstanceID:  "placement_instance2",
    68  			DeploymentInstanceID: "deployment_instance2",
    69  			ShardSetID:           0,
    70  			APIEndpoint:          "placement_instance2_endpoint",
    71  			Revision:             "revision2",
    72  		},
    73  		{
    74  			PlacementInstanceID:  "placement_instance3",
    75  			DeploymentInstanceID: "deployment_instance3",
    76  			ShardSetID:           1,
    77  			APIEndpoint:          "placement_instance3_endpoint",
    78  			Revision:             "revision3",
    79  		},
    80  		{
    81  			PlacementInstanceID:  "placement_instance4",
    82  			DeploymentInstanceID: "deployment_instance4",
    83  			ShardSetID:           1,
    84  			APIEndpoint:          "placement_instance4_endpoint",
    85  			Revision:             "revision4",
    86  		},
    87  	}
    88  )
    89  
    90  func TestHelperDeployEmptyRevision(t *testing.T) {
    91  	helper := testHelper(t)
    92  	require.Equal(t, errInvalidRevision, helper.Deploy("", nil, DryRunMode))
    93  }
    94  
    95  func TestHelperGeneratePlanError(t *testing.T) {
    96  	ctrl := gomock.NewController(t)
    97  	defer ctrl.Finish()
    98  
    99  	instances := testMockInstances(ctrl)
   100  	mgr := NewMockManager(ctrl)
   101  	mgr.EXPECT().QueryAll().Return(instances, nil).AnyTimes()
   102  
   103  	errGeneratePlan := errors.New("error generating plan")
   104  	planner := NewMockplanner(ctrl)
   105  	planner.EXPECT().GeneratePlan(gomock.Any(), gomock.Any()).Return(emptyPlan, errGeneratePlan).AnyTimes()
   106  
   107  	helper := testHelper(t)
   108  	helper.mgr = mgr
   109  	helper.planner = planner
   110  	require.Error(t, helper.Deploy("revision4", testPlacement, DryRunMode))
   111  }
   112  
   113  func TestHelperGeneratePlanDryRunMode(t *testing.T) {
   114  	ctrl := gomock.NewController(t)
   115  	defer ctrl.Finish()
   116  
   117  	var (
   118  		filteredRes instanceMetadatas
   119  		allRes      instanceMetadatas
   120  	)
   121  
   122  	instances := testMockInstances(ctrl)
   123  	mgr := NewMockManager(ctrl)
   124  	mgr.EXPECT().QueryAll().Return(instances, nil).AnyTimes()
   125  
   126  	planner := NewMockplanner(ctrl)
   127  	planner.EXPECT().
   128  		GeneratePlan(gomock.Any(), gomock.Any()).
   129  		DoAndReturn(func(toDeploy, all instanceMetadatas) (deploymentPlan, error) {
   130  			filteredRes = toDeploy
   131  			allRes = all
   132  			return emptyPlan, nil
   133  		}).
   134  		AnyTimes()
   135  
   136  	helper := testHelper(t)
   137  	helper.mgr = mgr
   138  	helper.planner = planner
   139  	require.NoError(t, helper.Deploy("revision4", testPlacement, DryRunMode))
   140  	require.Equal(t, testInstanceMetadatas[:3], filteredRes)
   141  	require.Equal(t, testInstanceMetadatas, allRes)
   142  }
   143  
   144  func TestHelperWaitUntilSafeQueryError(t *testing.T) {
   145  	ctrl := gomock.NewController(t)
   146  	defer ctrl.Finish()
   147  
   148  	errQuery := errors.New("error querying instances")
   149  	mgr := NewMockManager(ctrl)
   150  	mgr.EXPECT().Query(gomock.Any()).Return(nil, errQuery).AnyTimes()
   151  
   152  	helper := testHelper(t)
   153  	retryOpts := retry.NewOptions().
   154  		SetMaxRetries(3).
   155  		SetInitialBackoff(10 * time.Millisecond).
   156  		SetBackoffFactor(1)
   157  	helper.foreverRetrier = retry.NewRetrier(retryOpts)
   158  	helper.mgr = mgr
   159  	require.Error(t, helper.waitUntilSafe(testInstanceMetadatas))
   160  }
   161  
   162  func TestHelperWaitUntilSafeInstanceUnhealthy(t *testing.T) {
   163  	ctrl := gomock.NewController(t)
   164  	defer ctrl.Finish()
   165  
   166  	var instances []Instance
   167  	instance1 := NewMockInstance(ctrl)
   168  	instance1.EXPECT().IsHealthy().Return(false).AnyTimes()
   169  	instance1.EXPECT().IsDeploying().Return(false).AnyTimes()
   170  	instances = append(instances, instance1)
   171  
   172  	instance2 := NewMockInstance(ctrl)
   173  	instance2.EXPECT().IsHealthy().Return(false).AnyTimes()
   174  	instance2.EXPECT().IsDeploying().Return(false).AnyTimes()
   175  	instances = append(instances, instance2)
   176  
   177  	mgr := NewMockManager(ctrl)
   178  	mgr.EXPECT().Query(gomock.Any()).Return(instances, nil).AnyTimes()
   179  
   180  	helper := testHelper(t)
   181  	retryOpts := retry.NewOptions().
   182  		SetMaxRetries(3).
   183  		SetInitialBackoff(10 * time.Millisecond).
   184  		SetBackoffFactor(1)
   185  	helper.foreverRetrier = retry.NewRetrier(retryOpts)
   186  	helper.mgr = mgr
   187  	require.Error(t, helper.waitUntilSafe(testInstanceMetadatas[:2]))
   188  }
   189  
   190  func TestHelperWaitUntilSafeInstanceIsDeploying(t *testing.T) {
   191  	ctrl := gomock.NewController(t)
   192  	defer ctrl.Finish()
   193  
   194  	var instances []Instance
   195  	instance1 := NewMockInstance(ctrl)
   196  	instance1.EXPECT().IsHealthy().Return(true).AnyTimes()
   197  	instance1.EXPECT().IsDeploying().Return(true).AnyTimes()
   198  	instances = append(instances, instance1)
   199  
   200  	instance2 := NewMockInstance(ctrl)
   201  	instance2.EXPECT().IsHealthy().Return(true).AnyTimes()
   202  	instance2.EXPECT().IsDeploying().Return(false).AnyTimes()
   203  	instances = append(instances, instance2)
   204  
   205  	mgr := NewMockManager(ctrl)
   206  	mgr.EXPECT().Query(gomock.Any()).Return(instances, nil).AnyTimes()
   207  
   208  	helper := testHelper(t)
   209  	retryOpts := retry.NewOptions().
   210  		SetMaxRetries(3).
   211  		SetInitialBackoff(10 * time.Millisecond).
   212  		SetBackoffFactor(1)
   213  	helper.foreverRetrier = retry.NewRetrier(retryOpts)
   214  	helper.mgr = mgr
   215  
   216  	client := NewMockAggregatorClient(ctrl)
   217  	client.EXPECT().IsHealthy(gomock.Any()).Return(nil).AnyTimes()
   218  	helper.client = client
   219  	require.Error(t, helper.waitUntilSafe(testInstanceMetadatas[:2]))
   220  }
   221  
   222  func TestHelperWaitUntilSafeInstanceUnhealthyFromAPI(t *testing.T) {
   223  	ctrl := gomock.NewController(t)
   224  	defer ctrl.Finish()
   225  
   226  	errInstanceUnhealthy := errors.New("instance is not healthy")
   227  	var instances []Instance
   228  	instance1 := NewMockInstance(ctrl)
   229  	instance1.EXPECT().IsHealthy().Return(true).AnyTimes()
   230  	instance1.EXPECT().IsDeploying().Return(false).AnyTimes()
   231  	instances = append(instances, instance1)
   232  
   233  	instance2 := NewMockInstance(ctrl)
   234  	instance2.EXPECT().IsHealthy().Return(true).AnyTimes()
   235  	instance2.EXPECT().IsDeploying().Return(false).AnyTimes()
   236  	instances = append(instances, instance2)
   237  
   238  	mgr := NewMockManager(ctrl)
   239  	mgr.EXPECT().Query(gomock.Any()).Return(instances, nil).AnyTimes()
   240  
   241  	helper := testHelper(t)
   242  	retryOpts := retry.NewOptions().
   243  		SetMaxRetries(3).
   244  		SetInitialBackoff(10 * time.Millisecond).
   245  		SetBackoffFactor(1)
   246  	helper.foreverRetrier = retry.NewRetrier(retryOpts)
   247  	helper.mgr = mgr
   248  
   249  	client := NewMockAggregatorClient(ctrl)
   250  	client.EXPECT().IsHealthy(gomock.Any()).Return(errInstanceUnhealthy).AnyTimes()
   251  	helper.client = client
   252  	require.Error(t, helper.waitUntilSafe(testInstanceMetadatas[:2]))
   253  }
   254  
   255  func TestHelperWaitUntilSafeSuccess(t *testing.T) {
   256  	ctrl := gomock.NewController(t)
   257  	defer ctrl.Finish()
   258  
   259  	var instances []Instance
   260  	instance1 := NewMockInstance(ctrl)
   261  	instance1.EXPECT().IsHealthy().Return(true).AnyTimes()
   262  	instance1.EXPECT().IsDeploying().Return(false).AnyTimes()
   263  	instances = append(instances, instance1)
   264  
   265  	instance2 := NewMockInstance(ctrl)
   266  	instance2.EXPECT().IsHealthy().Return(true).AnyTimes()
   267  	instance2.EXPECT().IsDeploying().Return(false).AnyTimes()
   268  	instances = append(instances, instance2)
   269  
   270  	mgr := NewMockManager(ctrl)
   271  	mgr.EXPECT().Query(gomock.Any()).Return(instances, nil).AnyTimes()
   272  
   273  	helper := testHelper(t)
   274  	helper.mgr = mgr
   275  
   276  	client := NewMockAggregatorClient(ctrl)
   277  	client.EXPECT().IsHealthy(gomock.Any()).Return(nil).AnyTimes()
   278  	helper.client = client
   279  	require.NoError(t, helper.waitUntilSafe(testInstanceMetadatas[:2]))
   280  }
   281  
   282  func TestHelperValidateError(t *testing.T) {
   283  	errValidate := errors.New("error validating")
   284  	targets := deploymentTargets{
   285  		{Validator: func() error { return errValidate }},
   286  		{Validator: func() error { return errValidate }},
   287  	}
   288  	helper := testHelper(t)
   289  	retryOpts := retry.NewOptions().
   290  		SetMaxRetries(3).
   291  		SetInitialBackoff(10 * time.Millisecond).
   292  		SetBackoffFactor(1)
   293  	helper.foreverRetrier = retry.NewRetrier(retryOpts)
   294  	require.Error(t, helper.validate(targets))
   295  }
   296  
   297  func TestHelperValidateSuccess(t *testing.T) {
   298  	targets := deploymentTargets{
   299  		{Validator: func() error { return nil }},
   300  		{Validator: func() error { return nil }},
   301  	}
   302  	helper := testHelper(t)
   303  	require.NoError(t, helper.validate(targets))
   304  }
   305  
   306  func TestHelperResignError(t *testing.T) {
   307  	ctrl := gomock.NewController(t)
   308  	defer ctrl.Finish()
   309  
   310  	errResign := errors.New("error resigning")
   311  	targets := deploymentTargets{
   312  		{Instance: testInstanceMetadatas[0]},
   313  		{Instance: testInstanceMetadatas[1]},
   314  	}
   315  	helper := testHelper(t)
   316  	retryOpts := retry.NewOptions().
   317  		SetMaxRetries(3).
   318  		SetInitialBackoff(10 * time.Millisecond).
   319  		SetBackoffFactor(1)
   320  	helper.retrier = retry.NewRetrier(retryOpts)
   321  
   322  	client := NewMockAggregatorClient(ctrl)
   323  	client.EXPECT().Resign(gomock.Any()).Return(errResign).AnyTimes()
   324  	helper.client = client
   325  	require.Error(t, helper.resign(targets))
   326  }
   327  
   328  func TestHelperResignSuccess(t *testing.T) {
   329  	ctrl := gomock.NewController(t)
   330  	defer ctrl.Finish()
   331  
   332  	targets := deploymentTargets{
   333  		{Instance: testInstanceMetadatas[0]},
   334  		{Instance: testInstanceMetadatas[1]},
   335  	}
   336  	helper := testHelper(t)
   337  	client := NewMockAggregatorClient(ctrl)
   338  	client.EXPECT().Resign(gomock.Any()).Return(nil).AnyTimes()
   339  	helper.client = client
   340  	require.NoError(t, helper.resign(targets))
   341  }
   342  
   343  func TestHelperWaitUntilProgressingQueryError(t *testing.T) {
   344  	ctrl := gomock.NewController(t)
   345  	defer ctrl.Finish()
   346  
   347  	targetIDs := []string{"instance1", "instance2"}
   348  	revision := "revision1"
   349  	helper := testHelper(t)
   350  	retryOpts := retry.NewOptions().
   351  		SetMaxRetries(3).
   352  		SetInitialBackoff(10 * time.Millisecond).
   353  		SetBackoffFactor(1)
   354  	helper.foreverRetrier = retry.NewRetrier(retryOpts)
   355  
   356  	errQuery := errors.New("error querying instances")
   357  	mgr := NewMockManager(ctrl)
   358  	mgr.EXPECT().Query(gomock.Any()).Return(nil, errQuery).AnyTimes()
   359  	helper.mgr = mgr
   360  	require.Error(t, helper.waitUntilProgressing(targetIDs, revision))
   361  }
   362  
   363  func TestHelperWaitUntilProgressingInstanceNotProgressing(t *testing.T) {
   364  	ctrl := gomock.NewController(t)
   365  	defer ctrl.Finish()
   366  
   367  	targetIDs := []string{"instance1", "instance2"}
   368  	revision := "revision2"
   369  
   370  	var instances []Instance
   371  	instance1 := NewMockInstance(ctrl)
   372  	instance1.EXPECT().IsDeploying().Return(false).AnyTimes()
   373  	instance1.EXPECT().Revision().Return("revision1").AnyTimes()
   374  	instances = append(instances, instance1)
   375  
   376  	instance2 := NewMockInstance(ctrl)
   377  	instance2.EXPECT().IsDeploying().Return(false).AnyTimes()
   378  	instance2.EXPECT().Revision().Return("revision1").AnyTimes()
   379  	instances = append(instances, instance2)
   380  
   381  	helper := testHelper(t)
   382  	retryOpts := retry.NewOptions().
   383  		SetMaxRetries(3).
   384  		SetInitialBackoff(10 * time.Millisecond).
   385  		SetBackoffFactor(1)
   386  	helper.foreverRetrier = retry.NewRetrier(retryOpts)
   387  
   388  	mgr := NewMockManager(ctrl)
   389  	mgr.EXPECT().Query(gomock.Any()).Return(instances, nil).AnyTimes()
   390  	helper.mgr = mgr
   391  	require.Error(t, helper.waitUntilProgressing(targetIDs, revision))
   392  }
   393  
   394  func TestHelperWaitUntilProgressingInstanceIsDeploying(t *testing.T) {
   395  	ctrl := gomock.NewController(t)
   396  	defer ctrl.Finish()
   397  
   398  	targetIDs := []string{"instance1", "instance2"}
   399  	revision := "revision2"
   400  
   401  	var instances []Instance
   402  	instance1 := NewMockInstance(ctrl)
   403  	instance1.EXPECT().IsDeploying().Return(true).AnyTimes()
   404  	instance1.EXPECT().Revision().Return("revision1").AnyTimes()
   405  	instances = append(instances, instance1)
   406  
   407  	instance2 := NewMockInstance(ctrl)
   408  	instance2.EXPECT().IsDeploying().Return(false).AnyTimes()
   409  	instance2.EXPECT().Revision().Return("revision1").AnyTimes()
   410  	instances = append(instances, instance2)
   411  
   412  	mgr := NewMockManager(ctrl)
   413  	mgr.EXPECT().Query(gomock.Any()).Return(instances, nil).AnyTimes()
   414  	helper := testHelper(t)
   415  	helper.mgr = mgr
   416  	require.NoError(t, helper.waitUntilProgressing(targetIDs, revision))
   417  }
   418  
   419  func TestHelperWaitUntilProgressingInstanceIsDeployed(t *testing.T) {
   420  	ctrl := gomock.NewController(t)
   421  	defer ctrl.Finish()
   422  
   423  	targetIDs := []string{"instance1", "instance2"}
   424  	revision := "revision2"
   425  
   426  	var instances []Instance
   427  	instance1 := NewMockInstance(ctrl)
   428  	instance1.EXPECT().IsDeploying().Return(false).AnyTimes()
   429  	instance1.EXPECT().Revision().Return("revision2").AnyTimes()
   430  	instances = append(instances, instance1)
   431  
   432  	instance2 := NewMockInstance(ctrl)
   433  	instance2.EXPECT().IsDeploying().Return(false).AnyTimes()
   434  	instance2.EXPECT().Revision().Return("revision1").AnyTimes()
   435  	instances = append(instances, instance2)
   436  
   437  	mgr := NewMockManager(ctrl)
   438  	mgr.EXPECT().Query(gomock.Any()).Return(instances, nil).AnyTimes()
   439  	helper := testHelper(t)
   440  	helper.mgr = mgr
   441  	require.NoError(t, helper.waitUntilProgressing(targetIDs, revision))
   442  }
   443  
   444  func TestHelperAllInstanceMetadatasManagerQueryAllError(t *testing.T) {
   445  	ctrl := gomock.NewController(t)
   446  	defer ctrl.Finish()
   447  
   448  	errQueryAll := errors.New("query all error")
   449  	mgr := NewMockManager(ctrl)
   450  	mgr.EXPECT().QueryAll().Return(nil, errQueryAll).AnyTimes()
   451  	helper := testHelper(t)
   452  	helper.mgr = mgr
   453  	_, err := helper.allInstanceMetadatas(testPlacement)
   454  	require.Error(t, err)
   455  }
   456  
   457  func TestHelperAllInstanceMetadatasNumInstancesMismatch(t *testing.T) {
   458  	ctrl := gomock.NewController(t)
   459  	defer ctrl.Finish()
   460  
   461  	var instances []Instance
   462  	instance1 := NewMockInstance(ctrl)
   463  	instance1.EXPECT().ID().Return("instance1").AnyTimes()
   464  	instances = append(instances, instance1)
   465  
   466  	mgr := NewMockManager(ctrl)
   467  	mgr.EXPECT().QueryAll().Return(instances, nil).AnyTimes()
   468  
   469  	helper := testHelper(t)
   470  	helper.mgr = mgr
   471  	_, err := helper.allInstanceMetadatas(testPlacement)
   472  	require.Error(t, err)
   473  }
   474  
   475  func TestHelperAllInstanceMetadatasToAPIEndpointFnError(t *testing.T) {
   476  	ctrl := gomock.NewController(t)
   477  	defer ctrl.Finish()
   478  
   479  	errToAPIEndpoint := errors.New("error converting to api endpoint")
   480  	instances := testMockInstances(ctrl)
   481  	mgr := NewMockManager(ctrl)
   482  	mgr.EXPECT().QueryAll().Return(instances, nil).AnyTimes()
   483  	helper := testHelper(t)
   484  	helper.mgr = mgr
   485  	helper.toAPIEndpointFn = func(string) (string, error) { return "", errToAPIEndpoint }
   486  	_, err := helper.allInstanceMetadatas(testPlacement)
   487  	require.Error(t, err)
   488  }
   489  
   490  func TestHelperAllInstanceMetadatasToPlacementInstanceIDFnError(t *testing.T) {
   491  	ctrl := gomock.NewController(t)
   492  	defer ctrl.Finish()
   493  
   494  	errToPlacementInstanceID := errors.New("error converting to placement instance id")
   495  	instances := testMockInstances(ctrl)
   496  	mgr := NewMockManager(ctrl)
   497  	mgr.EXPECT().QueryAll().Return(instances, nil).AnyTimes()
   498  	helper := testHelper(t)
   499  	helper.mgr = mgr
   500  	helper.toPlacementInstanceIDFn = func(string) (string, error) { return "", errToPlacementInstanceID }
   501  	_, err := helper.allInstanceMetadatas(testPlacement)
   502  	require.Error(t, err)
   503  }
   504  
   505  func TestHelperAllInstanceMetadatasDuplicateDeploymentInstance(t *testing.T) {
   506  	ctrl := gomock.NewController(t)
   507  	defer ctrl.Finish()
   508  
   509  	var instances []Instance
   510  	instances = append(instances, testMockInstances(ctrl)...)
   511  	instances[0] = instances[1]
   512  
   513  	mgr := NewMockManager(ctrl)
   514  	mgr.EXPECT().QueryAll().Return(instances, nil).AnyTimes()
   515  	helper := testHelper(t)
   516  	helper.mgr = mgr
   517  
   518  	_, err := helper.allInstanceMetadatas(testPlacement)
   519  	require.Error(t, err)
   520  }
   521  
   522  func TestHelperAllInstanceMetadatasDeploymentInstanceNotExist(t *testing.T) {
   523  	ctrl := gomock.NewController(t)
   524  	defer ctrl.Finish()
   525  
   526  	var instances []Instance
   527  	instances = append(instances, testMockInstances(ctrl)...)
   528  	instance := NewMockInstance(ctrl)
   529  	instance.EXPECT().ID().Return("deployment_instance5").AnyTimes()
   530  	instance.EXPECT().Revision().Return("revision5").AnyTimes()
   531  	instances[3] = instance
   532  
   533  	mgr := NewMockManager(ctrl)
   534  	mgr.EXPECT().QueryAll().Return(instances, nil).AnyTimes()
   535  	helper := testHelper(t)
   536  	helper.mgr = mgr
   537  
   538  	_, err := helper.allInstanceMetadatas(testPlacement)
   539  	require.Error(t, err)
   540  }
   541  
   542  func TestHelperAllInstanceMetadatasSuccess(t *testing.T) {
   543  	ctrl := gomock.NewController(t)
   544  	defer ctrl.Finish()
   545  
   546  	instances := testMockInstances(ctrl)
   547  	mgr := NewMockManager(ctrl)
   548  	mgr.EXPECT().QueryAll().Return(instances, nil).AnyTimes()
   549  	helper := testHelper(t)
   550  	helper.mgr = mgr
   551  
   552  	res, err := helper.allInstanceMetadatas(testPlacement)
   553  	require.NoError(t, err)
   554  	require.Equal(t, testInstanceMetadatas, res)
   555  }
   556  
   557  func TestInstanceMetadatasDeploymentInstanceIDs(t *testing.T) {
   558  	expectedIDs := []string{
   559  		"deployment_instance1",
   560  		"deployment_instance2",
   561  		"deployment_instance3",
   562  		"deployment_instance4",
   563  	}
   564  	require.Equal(t, expectedIDs, testInstanceMetadatas.DeploymentInstanceIDs())
   565  }
   566  
   567  func TestInstanceMetadatasFilter(t *testing.T) {
   568  	require.Equal(t, instanceMetadatas(testInstanceMetadatas[1:]), testInstanceMetadatas.WithoutRevision("revision1"))
   569  }
   570  
   571  func testMockInstances(ctrl *gomock.Controller) []Instance {
   572  	instances := make([]Instance, 4)
   573  	for i := 1; i <= 4; i++ {
   574  		instance := NewMockInstance(ctrl)
   575  		instance.EXPECT().ID().Return(fmt.Sprintf("deployment_instance%d", i)).AnyTimes()
   576  		instance.EXPECT().Revision().Return(fmt.Sprintf("revision%d", i)).AnyTimes()
   577  		instances[i-1] = instance
   578  	}
   579  	return instances
   580  }
   581  
   582  func testHelper(t *testing.T) helper {
   583  	toAPIEndpointFn := func(endpoint string) (string, error) { return endpoint, nil }
   584  	toPlacementInstanceIDFn := func(id string) (string, error) {
   585  		converted := strings.Replace(id, "deployment", "placement", -1)
   586  		return converted, nil
   587  	}
   588  	opts := NewHelperOptions().
   589  		SetPlannerOptions(NewPlannerOptions()).
   590  		SetToAPIEndpointFn(toAPIEndpointFn).
   591  		SetToPlacementInstanceIDFn(toPlacementInstanceIDFn)
   592  	res, err := NewHelper(opts)
   593  	require.NoError(t, err)
   594  	return res.(helper)
   595  }