github.com/kubeshop/testkube@v1.17.23/pkg/executor/containerexecutor/containerexecutor_test.go (about)

     1  package containerexecutor
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/golang/mock/gomock"
     9  	"github.com/stretchr/testify/assert"
    10  	"go.uber.org/zap"
    11  	corev1 "k8s.io/api/core/v1"
    12  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    13  	"k8s.io/apimachinery/pkg/runtime"
    14  	"k8s.io/client-go/kubernetes/fake"
    15  
    16  	executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1"
    17  	testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3"
    18  	templatesclientv1 "github.com/kubeshop/testkube-operator/pkg/client/templates/v1"
    19  	v3 "github.com/kubeshop/testkube-operator/pkg/client/tests/v3"
    20  	"github.com/kubeshop/testkube/pkg/api/v1/testkube"
    21  	"github.com/kubeshop/testkube/pkg/executor"
    22  	"github.com/kubeshop/testkube/pkg/executor/client"
    23  	"github.com/kubeshop/testkube/pkg/featureflags"
    24  	"github.com/kubeshop/testkube/pkg/imageinspector"
    25  	"github.com/kubeshop/testkube/pkg/repository/result"
    26  )
    27  
    28  var ctx = context.Background()
    29  
    30  func TestExecuteAsync(t *testing.T) {
    31  	t.Parallel()
    32  
    33  	ce := ContainerExecutor{
    34  		clientSet:           getFakeClient("1"),
    35  		log:                 logger(),
    36  		repository:          FakeResultRepository{},
    37  		metrics:             FakeExecutionMetric{},
    38  		emitter:             FakeEmitter{},
    39  		configMap:           FakeConfigRepository{},
    40  		testsClient:         FakeTestsClient{},
    41  		executorsClient:     FakeExecutorsClient{},
    42  		serviceAccountNames: map[string]string{"": ""},
    43  	}
    44  
    45  	execution := &testkube.Execution{Id: "1"}
    46  	options := client.ExecuteOptions{}
    47  	res, err := ce.Execute(ctx, execution, options)
    48  	assert.NoError(t, err)
    49  
    50  	// Status is either running or passed, depends if async goroutine managed to finish
    51  	assert.Contains(t,
    52  		[]testkube.ExecutionStatus{testkube.RUNNING_ExecutionStatus, testkube.PASSED_ExecutionStatus},
    53  		*res.Status)
    54  }
    55  
    56  func TestExecuteSync(t *testing.T) {
    57  	t.Parallel()
    58  
    59  	ce := ContainerExecutor{
    60  		clientSet:           getFakeClient("1"),
    61  		log:                 logger(),
    62  		repository:          FakeResultRepository{},
    63  		metrics:             FakeExecutionMetric{},
    64  		emitter:             FakeEmitter{},
    65  		configMap:           FakeConfigRepository{},
    66  		testsClient:         FakeTestsClient{},
    67  		executorsClient:     FakeExecutorsClient{},
    68  		serviceAccountNames: map[string]string{"default": ""},
    69  	}
    70  
    71  	execution := &testkube.Execution{Id: "1", TestNamespace: "default"}
    72  	options := client.ExecuteOptions{
    73  		ImagePullSecretNames: []string{"secret-name1"},
    74  		Sync:                 true,
    75  	}
    76  	res, err := ce.Execute(ctx, execution, options)
    77  	assert.NoError(t, err)
    78  	assert.Equal(t, testkube.PASSED_ExecutionStatus, *res.Status)
    79  }
    80  
    81  func TestNewExecutorJobSpecEmptyArgs(t *testing.T) {
    82  	t.Parallel()
    83  
    84  	jobOptions := &JobOptions{
    85  		Name:                      "name",
    86  		Namespace:                 "namespace",
    87  		InitImage:                 "kubeshop/testkube-init-executor:0.7.10",
    88  		Image:                     "ubuntu",
    89  		JobTemplate:               defaultJobTemplate,
    90  		ScraperTemplate:           "",
    91  		PvcTemplate:               "",
    92  		JobTemplateExtensions:     "",
    93  		ScraperTemplateExtensions: "",
    94  		PvcTemplateExtensions:     "",
    95  		Command:                   []string{},
    96  		Args:                      []string{},
    97  		Features:                  featureflags.FeatureFlags{},
    98  	}
    99  	spec, err := NewExecutorJobSpec(logger(), jobOptions)
   100  	assert.NoError(t, err)
   101  	assert.NotNil(t, spec)
   102  }
   103  
   104  func TestNewExecutorJobSpecWithArgs(t *testing.T) {
   105  	t.Parallel()
   106  
   107  	jobOptions := &JobOptions{
   108  		Name:                      "name",
   109  		Namespace:                 "namespace",
   110  		InitImage:                 "kubeshop/testkube-init-executor:0.7.10",
   111  		Image:                     "curl",
   112  		JobTemplate:               defaultJobTemplate,
   113  		ScraperTemplate:           "",
   114  		PvcTemplate:               "",
   115  		JobTemplateExtensions:     "",
   116  		ScraperTemplateExtensions: "",
   117  		PvcTemplateExtensions:     "",
   118  		ImagePullSecrets:          []string{"secret-name"},
   119  		Command:                   []string{"/bin/curl"},
   120  		Args:                      []string{"-v", "https://testkube.kubeshop.io"},
   121  		ActiveDeadlineSeconds:     100,
   122  		Envs:                      map[string]string{"key": "value"},
   123  		Variables:                 map[string]testkube.Variable{"aa": {Name: "aa", Value: "bb", Type_: testkube.VariableTypeBasic}},
   124  		Features:                  featureflags.FeatureFlags{},
   125  	}
   126  	spec, err := NewExecutorJobSpec(logger(), jobOptions)
   127  
   128  	assert.NotEmpty(t, defaultJobTemplate)
   129  	assert.NoError(t, err)
   130  	assert.NotNil(t, spec)
   131  
   132  	wantEnvs := []corev1.EnvVar{
   133  		{Name: "DEBUG", Value: "false"},
   134  		{Name: "RUNNER_ENDPOINT", Value: ""},
   135  		{Name: "RUNNER_ACCESSKEYID", Value: ""},
   136  		{Name: "RUNNER_SECRETACCESSKEY", Value: ""},
   137  		{Name: "RUNNER_REGION", Value: ""},
   138  		{Name: "RUNNER_TOKEN", Value: ""},
   139  		{Name: "RUNNER_BUCKET", Value: ""},
   140  		{Name: "RUNNER_SSL", Value: "false"},
   141  		{Name: "RUNNER_SKIP_VERIFY", Value: "false"},
   142  		{Name: "RUNNER_CERT_FILE", Value: ""},
   143  		{Name: "RUNNER_KEY_FILE", Value: ""},
   144  		{Name: "RUNNER_CA_FILE", Value: ""},
   145  		{Name: "RUNNER_SCRAPPERENABLED", Value: "false"},
   146  		{Name: "RUNNER_DATADIR", Value: "/data"},
   147  		{Name: "RUNNER_CDEVENTS_TARGET", Value: ""},
   148  		{Name: "RUNNER_DASHBOARD_URI", Value: ""},
   149  		{Name: "RUNNER_COMPRESSARTIFACTS", Value: "false"},
   150  		{Name: "RUNNER_WORKINGDIR", Value: ""},
   151  		{Name: "RUNNER_EXECUTIONID", Value: "name"},
   152  		{Name: "RUNNER_TESTNAME", Value: ""},
   153  		{Name: "RUNNER_EXECUTIONNUMBER", Value: "0"},
   154  		{Name: "RUNNER_CONTEXTTYPE", Value: ""},
   155  		{Name: "RUNNER_CONTEXTDATA", Value: ""},
   156  		{Name: "RUNNER_APIURI", Value: ""},
   157  		{Name: "RUNNER_PRO_MODE", Value: "false"},
   158  		{Name: "RUNNER_PRO_API_KEY", Value: ""},
   159  		{Name: "RUNNER_PRO_API_URL", Value: ""},
   160  		{Name: "RUNNER_PRO_API_TLS_INSECURE", Value: "false"},
   161  		{Name: "RUNNER_PRO_API_SKIP_VERIFY", Value: "false"},
   162  		{Name: "RUNNER_PRO_CONNECTION_TIMEOUT", Value: "10"},
   163  		{Name: "RUNNER_CLOUD_MODE", Value: "false"},             // DEPRECATED
   164  		{Name: "RUNNER_CLOUD_API_KEY", Value: ""},               // DEPRECATED
   165  		{Name: "RUNNER_CLOUD_API_URL", Value: ""},               // DEPRECATED
   166  		{Name: "RUNNER_CLOUD_API_TLS_INSECURE", Value: "false"}, // DEPRECATED
   167  		{Name: "RUNNER_CLOUD_API_SKIP_VERIFY", Value: "false"},  // DEPRECATED
   168  		{Name: "RUNNER_CLUSTERID", Value: ""},
   169  		{Name: "RUNNER_PRO_API_CERT_FILE", Value: ""},
   170  		{Name: "RUNNER_PRO_API_KEY_FILE", Value: ""},
   171  		{Name: "RUNNER_PRO_API_CA_FILE", Value: ""},
   172  		{Name: "CI", Value: "1"},
   173  		{Name: "key", Value: "value"},
   174  		{Name: "aa", Value: "bb"},
   175  	}
   176  
   177  	assert.ElementsMatch(t, wantEnvs, spec.Spec.Template.Spec.Containers[0].Env)
   178  }
   179  
   180  func TestNewExecutorJobSpecWithoutInitImage(t *testing.T) {
   181  	t.Parallel()
   182  
   183  	jobOptions := &JobOptions{
   184  		Name:                      "name",
   185  		Namespace:                 "namespace",
   186  		InitImage:                 "",
   187  		Image:                     "ubuntu",
   188  		JobTemplate:               defaultJobTemplate,
   189  		ScraperTemplate:           "",
   190  		PvcTemplate:               "",
   191  		JobTemplateExtensions:     "",
   192  		ScraperTemplateExtensions: "",
   193  		PvcTemplateExtensions:     "",
   194  		Command:                   []string{},
   195  		Args:                      []string{},
   196  		Features:                  featureflags.FeatureFlags{},
   197  	}
   198  	spec, err := NewExecutorJobSpec(logger(), jobOptions)
   199  	assert.NoError(t, err)
   200  	assert.NotNil(t, spec)
   201  }
   202  
   203  func TestNewExecutorJobSpecWithWorkingDirRelative(t *testing.T) {
   204  	t.Parallel()
   205  
   206  	mockCtrl := gomock.NewController(t)
   207  	defer mockCtrl.Finish()
   208  
   209  	mockTemplatesClient := templatesclientv1.NewMockInterface(mockCtrl)
   210  	mockInspector := imageinspector.NewMockInspector(mockCtrl)
   211  
   212  	jobOptions, _ := NewJobOptions(
   213  		logger(),
   214  		mockTemplatesClient,
   215  		executor.Images{},
   216  		executor.Templates{},
   217  		mockInspector,
   218  		map[string]string{},
   219  		"",
   220  		"",
   221  		"",
   222  		testkube.Execution{
   223  			Id:            "name",
   224  			TestName:      "name-test-1",
   225  			TestNamespace: "namespace",
   226  		},
   227  		client.ExecuteOptions{
   228  			TestSpec: testsv3.TestSpec{
   229  				ExecutionRequest: &testsv3.ExecutionRequest{
   230  					Image: "ubuntu",
   231  				},
   232  				Content: &testsv3.TestContent{
   233  					Repository: &testsv3.Repository{
   234  						WorkingDir: "relative/path",
   235  					},
   236  				},
   237  			},
   238  		},
   239  		"",
   240  		false,
   241  	)
   242  
   243  	spec, err := NewExecutorJobSpec(logger(), jobOptions)
   244  	assert.NoError(t, err)
   245  	assert.NotNil(t, spec)
   246  
   247  	assert.Equal(t, repoPath+"/relative/path", spec.Spec.Template.Spec.Containers[0].WorkingDir)
   248  }
   249  
   250  func TestNewExecutorJobSpecWithWorkingDirAbsolute(t *testing.T) {
   251  	t.Parallel()
   252  
   253  	mockCtrl := gomock.NewController(t)
   254  	defer mockCtrl.Finish()
   255  
   256  	mockTemplatesClient := templatesclientv1.NewMockInterface(mockCtrl)
   257  	mockInspector := imageinspector.NewMockInspector(mockCtrl)
   258  
   259  	jobOptions, _ := NewJobOptions(
   260  		logger(),
   261  		mockTemplatesClient,
   262  		executor.Images{},
   263  		executor.Templates{},
   264  		mockInspector,
   265  		map[string]string{},
   266  		"",
   267  		"",
   268  		"",
   269  		testkube.Execution{
   270  			Id:            "name",
   271  			TestName:      "name-test-1",
   272  			TestNamespace: "namespace",
   273  		},
   274  		client.ExecuteOptions{
   275  			TestSpec: testsv3.TestSpec{
   276  				ExecutionRequest: &testsv3.ExecutionRequest{
   277  					Image: "ubuntu",
   278  				},
   279  				Content: &testsv3.TestContent{
   280  					Repository: &testsv3.Repository{
   281  						WorkingDir: "/absolute/path",
   282  					},
   283  				},
   284  			},
   285  		},
   286  		"",
   287  		false,
   288  	)
   289  	spec, err := NewExecutorJobSpec(logger(), jobOptions)
   290  	assert.NoError(t, err)
   291  	assert.NotNil(t, spec)
   292  
   293  	assert.Equal(t, "/absolute/path", spec.Spec.Template.Spec.Containers[0].WorkingDir)
   294  }
   295  
   296  func TestNewExecutorJobSpecWithoutWorkingDir(t *testing.T) {
   297  	t.Parallel()
   298  
   299  	mockCtrl := gomock.NewController(t)
   300  	defer mockCtrl.Finish()
   301  
   302  	mockTemplatesClient := templatesclientv1.NewMockInterface(mockCtrl)
   303  	mockInspector := imageinspector.NewMockInspector(mockCtrl)
   304  
   305  	jobOptions, _ := NewJobOptions(
   306  		logger(),
   307  		mockTemplatesClient,
   308  		executor.Images{},
   309  		executor.Templates{},
   310  		mockInspector,
   311  		map[string]string{},
   312  		"",
   313  		"",
   314  		"",
   315  		testkube.Execution{
   316  			Id:            "name",
   317  			TestName:      "name-test-1",
   318  			TestNamespace: "namespace",
   319  		},
   320  		client.ExecuteOptions{
   321  			Namespace: "namespace",
   322  			TestSpec: testsv3.TestSpec{
   323  				ExecutionRequest: &testsv3.ExecutionRequest{
   324  					Image: "ubuntu",
   325  				},
   326  				Content: &testsv3.TestContent{
   327  					Repository: &testsv3.Repository{},
   328  				},
   329  			},
   330  		},
   331  		"",
   332  		false,
   333  	)
   334  	spec, err := NewExecutorJobSpec(logger(), jobOptions)
   335  	assert.NoError(t, err)
   336  	assert.NotNil(t, spec)
   337  
   338  	assert.Empty(t, spec.Spec.Template.Spec.Containers[0].WorkingDir)
   339  }
   340  
   341  func logger() *zap.SugaredLogger {
   342  	atomicLevel := zap.NewAtomicLevel()
   343  	atomicLevel.SetLevel(zap.DebugLevel)
   344  
   345  	zapCfg := zap.NewDevelopmentConfig()
   346  	zapCfg.Level = atomicLevel
   347  
   348  	z, err := zapCfg.Build()
   349  	if err != nil {
   350  		panic(err)
   351  	}
   352  	return z.Sugar()
   353  }
   354  
   355  func getFakeClient(executionID string) *fake.Clientset {
   356  	initObjects := []runtime.Object{
   357  		&corev1.Pod{
   358  			ObjectMeta: metav1.ObjectMeta{
   359  				Name:      executionID,
   360  				Namespace: "default",
   361  				Labels: map[string]string{
   362  					"job-name": executionID,
   363  				},
   364  			},
   365  			Status: corev1.PodStatus{
   366  				Phase: corev1.PodSucceeded,
   367  			},
   368  		},
   369  	}
   370  	fakeClient := fake.NewSimpleClientset(initObjects...)
   371  	return fakeClient
   372  }
   373  
   374  type FakeExecutionMetric struct {
   375  }
   376  
   377  func (FakeExecutionMetric) IncAndObserveExecuteTest(execution testkube.Execution, dashboardURI string) {
   378  }
   379  
   380  type FakeEmitter struct {
   381  }
   382  
   383  func (FakeEmitter) Notify(event testkube.Event) {
   384  }
   385  
   386  type FakeResultRepository struct {
   387  }
   388  
   389  func (r FakeResultRepository) GetNextExecutionNumber(ctx context.Context, testName string) (number int32, err error) {
   390  	//TODO implement me
   391  	panic("implement me")
   392  }
   393  
   394  func (r FakeResultRepository) GetByNameAndTest(ctx context.Context, name, testName string) (testkube.Execution, error) {
   395  	//TODO implement me
   396  	panic("implement me")
   397  }
   398  
   399  func (r FakeResultRepository) GetLatestByTest(ctx context.Context, testName string) (*testkube.Execution, error) {
   400  	//TODO implement me
   401  	panic("implement me")
   402  }
   403  
   404  func (r FakeResultRepository) GetLatestByTests(ctx context.Context, testNames []string) (executions []testkube.Execution, err error) {
   405  	//TODO implement me
   406  	panic("implement me")
   407  }
   408  
   409  func (r FakeResultRepository) GetExecutions(ctx context.Context, filter result.Filter) ([]testkube.Execution, error) {
   410  	//TODO implement me
   411  	panic("implement me")
   412  }
   413  
   414  func (r FakeResultRepository) GetExecutionTotals(ctx context.Context, paging bool, filter ...result.Filter) (result testkube.ExecutionsTotals, err error) {
   415  	//TODO implement me
   416  	panic("implement me")
   417  }
   418  
   419  func (r FakeResultRepository) Insert(ctx context.Context, result testkube.Execution) error {
   420  	//TODO implement me
   421  	panic("implement me")
   422  }
   423  
   424  func (r FakeResultRepository) Update(ctx context.Context, result testkube.Execution) error {
   425  	//TODO implement me
   426  	panic("implement me")
   427  }
   428  
   429  func (r FakeResultRepository) GetLabels(ctx context.Context) (labels map[string][]string, err error) {
   430  	//TODO implement me
   431  	panic("implement me")
   432  }
   433  
   434  func (r FakeResultRepository) DeleteByTest(ctx context.Context, testName string) error {
   435  	//TODO implement me
   436  	panic("implement me")
   437  }
   438  
   439  func (r FakeResultRepository) DeleteByTestSuite(ctx context.Context, testSuiteName string) error {
   440  	//TODO implement me
   441  	panic("implement me")
   442  }
   443  
   444  func (r FakeResultRepository) DeleteAll(ctx context.Context) error {
   445  	//TODO implement me
   446  	panic("implement me")
   447  }
   448  
   449  func (r FakeResultRepository) DeleteByTests(ctx context.Context, testNames []string) (err error) {
   450  	//TODO implement me
   451  	panic("implement me")
   452  }
   453  
   454  func (r FakeResultRepository) DeleteByTestSuites(ctx context.Context, testSuiteNames []string) (err error) {
   455  	//TODO implement me
   456  	panic("implement me")
   457  }
   458  
   459  func (r FakeResultRepository) DeleteForAllTestSuites(ctx context.Context) (err error) {
   460  	//TODO implement me
   461  	panic("implement me")
   462  }
   463  
   464  func (r FakeResultRepository) GetTestMetrics(ctx context.Context, name string, limit, last int) (metrics testkube.ExecutionsMetrics, err error) {
   465  	//TODO implement me
   466  	panic("implement me")
   467  }
   468  
   469  func (r FakeResultRepository) Count(ctx context.Context, filter result.Filter) (count int64, err error) {
   470  	//TODO implement me
   471  	panic("implement me")
   472  }
   473  
   474  func (FakeResultRepository) GetExecution(ctx context.Context, id string) (testkube.Execution, error) {
   475  	return testkube.Execution{}, nil
   476  }
   477  
   478  func (FakeResultRepository) Get(ctx context.Context, id string) (testkube.Execution, error) {
   479  	return testkube.Execution{}, nil
   480  }
   481  
   482  func (FakeResultRepository) UpdateResult(ctx context.Context, id string, execution testkube.Execution) error {
   483  	return nil
   484  }
   485  func (FakeResultRepository) StartExecution(ctx context.Context, id string, startTime time.Time) error {
   486  	return nil
   487  }
   488  func (FakeResultRepository) EndExecution(ctx context.Context, execution testkube.Execution) error {
   489  	return nil
   490  }
   491  
   492  type FakeConfigRepository struct {
   493  }
   494  
   495  func (FakeConfigRepository) GetUniqueClusterId(ctx context.Context) (string, error) {
   496  	return "", nil
   497  }
   498  
   499  func (FakeConfigRepository) GetTelemetryEnabled(ctx context.Context) (ok bool, err error) {
   500  	return false, nil
   501  }
   502  
   503  func (FakeConfigRepository) Get(ctx context.Context) (testkube.Config, error) {
   504  	return testkube.Config{}, nil
   505  }
   506  
   507  func (FakeConfigRepository) Upsert(ctx context.Context, config testkube.Config) (testkube.Config, error) {
   508  	return config, nil
   509  }
   510  
   511  type FakeTestsClient struct {
   512  }
   513  
   514  func (FakeTestsClient) List(selector string) (*testsv3.TestList, error) {
   515  	return &testsv3.TestList{}, nil
   516  }
   517  
   518  func (FakeTestsClient) ListLabels() (map[string][]string, error) {
   519  	return map[string][]string{}, nil
   520  }
   521  
   522  func (FakeTestsClient) Get(name string) (*testsv3.Test, error) {
   523  	return &testsv3.Test{}, nil
   524  }
   525  
   526  func (FakeTestsClient) Create(test *testsv3.Test, disableSecretCreation bool, options ...v3.Option) (*testsv3.Test, error) {
   527  	return &testsv3.Test{}, nil
   528  }
   529  
   530  func (FakeTestsClient) Update(test *testsv3.Test, disableSecretCreation bool, options ...v3.Option) (*testsv3.Test, error) {
   531  	return &testsv3.Test{}, nil
   532  }
   533  
   534  func (FakeTestsClient) Delete(name string) error {
   535  	return nil
   536  }
   537  
   538  func (FakeTestsClient) DeleteAll() error {
   539  	return nil
   540  }
   541  
   542  func (FakeTestsClient) CreateTestSecrets(test *testsv3.Test, disableSecretCreation bool) error {
   543  	return nil
   544  }
   545  
   546  func (FakeTestsClient) UpdateTestSecrets(test *testsv3.Test, disableSecretCreation bool) error {
   547  	return nil
   548  }
   549  
   550  func (FakeTestsClient) LoadTestVariablesSecret(test *testsv3.Test) (*corev1.Secret, error) {
   551  	return &corev1.Secret{}, nil
   552  }
   553  
   554  func (FakeTestsClient) GetCurrentSecretUUID(testName string) (string, error) {
   555  	return "", nil
   556  }
   557  
   558  func (FakeTestsClient) GetSecretTestVars(testName, secretUUID string) (map[string]string, error) {
   559  	return map[string]string{}, nil
   560  }
   561  
   562  func (FakeTestsClient) ListByNames(names []string) ([]testsv3.Test, error) {
   563  	return []testsv3.Test{}, nil
   564  }
   565  
   566  func (FakeTestsClient) DeleteByLabels(selector string) error {
   567  	return nil
   568  }
   569  
   570  func (FakeTestsClient) UpdateStatus(test *testsv3.Test) error {
   571  	return nil
   572  }
   573  
   574  type FakeExecutorsClient struct {
   575  }
   576  
   577  func (FakeExecutorsClient) List(selector string) (*executorv1.ExecutorList, error) {
   578  	return &executorv1.ExecutorList{}, nil
   579  }
   580  
   581  func (FakeExecutorsClient) Get(name string) (*executorv1.Executor, error) {
   582  	return &executorv1.Executor{}, nil
   583  }
   584  
   585  func (FakeExecutorsClient) GetByType(executorType string) (*executorv1.Executor, error) {
   586  	return &executorv1.Executor{}, nil
   587  }
   588  
   589  func (FakeExecutorsClient) Create(executor *executorv1.Executor) (*executorv1.Executor, error) {
   590  	return &executorv1.Executor{}, nil
   591  }
   592  
   593  func (FakeExecutorsClient) Delete(name string) error {
   594  	return nil
   595  }
   596  
   597  func (FakeExecutorsClient) Update(executor *executorv1.Executor) (*executorv1.Executor, error) {
   598  	return &executorv1.Executor{}, nil
   599  }
   600  
   601  func (FakeExecutorsClient) DeleteByLabels(selector string) error {
   602  	return nil
   603  }