github.com/kubeshop/testkube@v1.17.23/contrib/executor/kubepug/pkg/runner/runner_test.go (about)

     1  package runner
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"path/filepath"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  
    11  	"github.com/kubeshop/testkube/pkg/api/v1/testkube"
    12  	"github.com/kubeshop/testkube/pkg/envs"
    13  	"github.com/kubeshop/testkube/pkg/executor/content"
    14  	"github.com/kubeshop/testkube/pkg/utils/test"
    15  )
    16  
    17  func TestRunString_Integration(t *testing.T) {
    18  	test.IntegrationTest(t)
    19  	t.Parallel()
    20  
    21  	ctx := context.Background()
    22  
    23  	t.Run("runner should return success and empty result on empty string", func(t *testing.T) {
    24  		t.Parallel()
    25  
    26  		tempDir, err := os.MkdirTemp("", "*")
    27  		assert.NoErrorf(t, err, "failed to create temp dir: %v", err)
    28  		defer os.RemoveAll(tempDir)
    29  
    30  		err = os.WriteFile(filepath.Join(tempDir, "test-content"), []byte(""), 0644)
    31  		if err != nil {
    32  			assert.FailNow(t, "Unable to write postman runner test content file")
    33  		}
    34  
    35  		runner, err := NewRunner(context.Background(), envs.Params{DataDir: tempDir})
    36  		assert.NoError(t, err)
    37  
    38  		execution := testkube.NewQueuedExecution()
    39  		execution.Content = testkube.NewStringTestContent("")
    40  		execution.Command = []string{"kubepug"}
    41  		execution.Args = []string{
    42  			"--format=json",
    43  			"--input-file",
    44  			"<runPath>",
    45  		}
    46  
    47  		result, err := runner.Run(ctx, *execution)
    48  
    49  		assert.NoError(t, err)
    50  		assert.Equal(t, testkube.ExecutionStatusPassed, result.Status)
    51  		assert.Equal(t, 2, len(result.Steps))
    52  		assert.Equal(t, "passed", result.Steps[0].Status)
    53  		assert.Equal(t, "passed", result.Steps[1].Status)
    54  	})
    55  
    56  	t.Run("runner should return success and empty result on passing yaml", func(t *testing.T) {
    57  		t.Parallel()
    58  
    59  		data := `
    60  apiVersion: v1
    61  kind: ConfigMap
    62  metadata:
    63    annotations:
    64      control-plane.alpha.kubernetes.io/leader: '{"holderIdentity":"ingress-nginx-controller-646d5d4d67-7nx7r"}'
    65    creationTimestamp: "2021-10-07T13:44:37Z"
    66    name: ingress-controller-leader
    67    namespace: default
    68    resourceVersion: "170745168"
    69    uid: 9bb57467-b5c4-41fe-83a8-9513ae86fbff
    70  `
    71  
    72  		tempDir, err := os.MkdirTemp("", "*")
    73  		assert.NoErrorf(t, err, "failed to create temp dir: %v", err)
    74  		defer os.RemoveAll(tempDir)
    75  
    76  		err = os.WriteFile(filepath.Join(tempDir, "test-content"), []byte(data), 0644)
    77  		if err != nil {
    78  			assert.FailNow(t, "Unable to write postman runner test content file")
    79  		}
    80  
    81  		runner, err := NewRunner(context.Background(), envs.Params{DataDir: tempDir})
    82  		assert.NoError(t, err)
    83  
    84  		execution := testkube.NewQueuedExecution()
    85  		execution.Command = []string{"kubepug"}
    86  		execution.Args = []string{
    87  			"--format=json",
    88  			"--input-file",
    89  			"<runPath>",
    90  		}
    91  		execution.Content = testkube.NewStringTestContent("")
    92  
    93  		result, err := runner.Run(ctx, *execution)
    94  
    95  		assert.NoError(t, err)
    96  		assert.Equal(t, testkube.ExecutionStatusPassed, result.Status)
    97  		assert.Equal(t, 2, len(result.Steps))
    98  		assert.Equal(t, "passed", result.Steps[0].Status)
    99  		assert.Equal(t, "passed", result.Steps[1].Status)
   100  	})
   101  
   102  	t.Run("runner should return failure and list of deprecated APIs result on yaml containing deprecated API", func(t *testing.T) {
   103  		t.Parallel()
   104  
   105  		data := `
   106  ---
   107  apiVersion: v1
   108  kind: Service
   109  metadata:
   110    name: testkube-dashboard
   111    namespace: testkube
   112  spec:
   113    ports:
   114      - name: http
   115        port: 8001
   116        targetPort: 80
   117    selector:
   118      app: testkube-dashboard
   119  ---
   120  apiVersion: apps/v1beta2
   121  kind: Deployment
   122  metadata:
   123    name: testkube-dashboard
   124    namespace: testkube
   125  spec:
   126    replicas: 1
   127    selector:
   128      matchLabels:
   129        app: testkube-dashboard
   130    strategy:
   131      type: RollingUpdate
   132    template:
   133      metadata:
   134        labels:
   135          app: testkube-dashboard
   136      spec:
   137        containers:
   138          - name: petstore-backend
   139            image: docker.io/kubeshop/testkube-dashboard:latest
   140            ports:
   141              - name: http
   142                containerPort: 80
   143            livenessProbe:
   144              httpGet:
   145              path: /index.html
   146              port: 80
   147              initialDelaySeconds: 15
   148              timeoutSeconds: 2
   149              periodSeconds: 5
   150              failureThreshold: 1
   151            readinessProbe:
   152              httpGet:
   153                path: /index.html
   154                port: 80
   155              initialDelaySeconds: 15
   156              periodSeconds: 5
   157              failureThreshold: 1
   158  `
   159  
   160  		tempDir, err := os.MkdirTemp("", "*")
   161  		assert.NoErrorf(t, err, "failed to create temp dir: %v", err)
   162  		defer os.RemoveAll(tempDir)
   163  
   164  		err = os.WriteFile(filepath.Join(tempDir, "test-content"), []byte(data), 0644)
   165  		if err != nil {
   166  			assert.FailNow(t, "Unable to write postman runner test content file")
   167  		}
   168  
   169  		runner, err := NewRunner(context.Background(), envs.Params{DataDir: tempDir})
   170  		assert.NoError(t, err)
   171  
   172  		execution := testkube.NewQueuedExecution()
   173  		execution.Command = []string{"kubepug"}
   174  		execution.Args = []string{
   175  			"--format=json",
   176  			"--input-file",
   177  			"<runPath>",
   178  		}
   179  		execution.Content = testkube.NewStringTestContent("")
   180  
   181  		result, err := runner.Run(ctx, *execution)
   182  
   183  		assert.NoError(t, err)
   184  		assert.Equal(t, testkube.ExecutionStatusFailed, result.Status)
   185  		assert.Equal(t, 2, len(result.Steps))
   186  		assert.Equal(t, "passed", result.Steps[0].Status)
   187  		assert.Equal(t, "failed", result.Steps[1].Status)
   188  	})
   189  }
   190  
   191  func TestRunFileURI_Integration(t *testing.T) {
   192  	test.IntegrationTest(t)
   193  	t.Parallel()
   194  
   195  	ctx := context.Background()
   196  
   197  	t.Run("runner should return success on valid yaml gist file URI", func(t *testing.T) {
   198  		t.Parallel()
   199  
   200  		tempDir, err := os.MkdirTemp("", "*")
   201  		assert.NoErrorf(t, err, "failed to create temp dir: %v", err)
   202  		defer os.RemoveAll(tempDir)
   203  
   204  		runner, err := NewRunner(context.Background(), envs.Params{DataDir: tempDir})
   205  		assert.NoError(t, err)
   206  
   207  		execution := testkube.NewQueuedExecution()
   208  		execution.Command = []string{"kubepug"}
   209  		execution.Args = []string{
   210  			"--format=json",
   211  			"--input-file",
   212  			"<runPath>",
   213  		}
   214  		uri := "https://gist.githubusercontent.com/vLia/" +
   215  			"b3df9e43f55fd43d1bca93cdfd5ae27c/raw/535e8db46f33693a793c616fc1e2b4d77c4b06d2/example-k8s-pod-yaml"
   216  		execution.Content = &testkube.TestContent{
   217  			Type_: string(testkube.TestContentTypeFileURI),
   218  			Uri:   uri,
   219  		}
   220  
   221  		_, err = content.NewFetcher(tempDir).FetchURI(uri)
   222  		assert.NoError(t, err)
   223  
   224  		result, err := runner.Run(ctx, *execution)
   225  
   226  		assert.NoError(t, err)
   227  		assert.Equal(t, testkube.ExecutionStatusPassed, result.Status)
   228  		assert.Equal(t, 2, len(result.Steps))
   229  		assert.Equal(t, "passed", result.Steps[0].Status)
   230  		assert.Equal(t, "passed", result.Steps[1].Status)
   231  	})
   232  
   233  	t.Run("runner should return failure on yaml gist file URI with deprecated/deleted APIs", func(t *testing.T) {
   234  		t.Parallel()
   235  
   236  		tempDir, err := os.MkdirTemp("", "*")
   237  		assert.NoErrorf(t, err, "failed to create temp dir: %v", err)
   238  		defer os.RemoveAll(tempDir)
   239  
   240  		runner, err := NewRunner(context.Background(), envs.Params{DataDir: tempDir})
   241  		assert.NoError(t, err)
   242  
   243  		execution := testkube.NewQueuedExecution()
   244  		execution.Command = []string{"kubepug"}
   245  		execution.Args = []string{
   246  			"--format=json",
   247  			"--input-file",
   248  			"<runPath>",
   249  		}
   250  		uri := "https://gist.githubusercontent.com/vLia/" +
   251  			"91289de9cc8b6953be5f90b0a52fa8d3/raw/7d49329a16cb2d9d27371553658280a975ca2223/example-k8s-pod-yaml-deprecated"
   252  		execution.Content = &testkube.TestContent{
   253  			Type_: string(testkube.TestContentTypeFileURI),
   254  			Uri:   uri,
   255  		}
   256  
   257  		_, err = content.NewFetcher(tempDir).FetchURI(uri)
   258  		assert.NoError(t, err)
   259  
   260  		result, err := runner.Run(ctx, *execution)
   261  
   262  		assert.NoError(t, err)
   263  		assert.Equal(t, testkube.ExecutionStatusFailed, result.Status)
   264  		assert.Equal(t, 2, len(result.Steps))
   265  		assert.Equal(t, "passed", result.Steps[0].Status)
   266  		assert.Equal(t, "failed", result.Steps[1].Status)
   267  	})
   268  }
   269  
   270  func TestRunGitFile_Integration(t *testing.T) {
   271  	test.IntegrationTest(t)
   272  	t.Parallel()
   273  
   274  	ctx := context.Background()
   275  
   276  	t.Run("runner should return error on non-existent Git path", func(t *testing.T) {
   277  		t.Parallel()
   278  
   279  		tempDir, err := os.MkdirTemp("", "*")
   280  		assert.NoErrorf(t, err, "failed to create temp dir: %v", err)
   281  		defer os.RemoveAll(tempDir)
   282  
   283  		runner, err := NewRunner(context.Background(), envs.Params{DataDir: tempDir})
   284  		assert.NoError(t, err)
   285  
   286  		execution := testkube.NewQueuedExecution()
   287  		execution.Command = []string{"kubepug"}
   288  		execution.Args = []string{
   289  			"--format=json",
   290  			"--input-file",
   291  			"<runPath>",
   292  		}
   293  
   294  		repo := &testkube.Repository{
   295  			Uri:    "https://github.com/kubeshop/testkube",
   296  			Branch: "develop",
   297  			Path:   "contrib/executor/kubepug/pkg/runner/test-files/fake-manifest.yaml",
   298  		}
   299  		_, err = content.NewFetcher(tempDir).FetchGit(repo)
   300  		assert.NoError(t, err)
   301  
   302  		execution.Content = &testkube.TestContent{
   303  			Type_:      string(testkube.TestContentTypeGitFile),
   304  			Repository: repo,
   305  		}
   306  
   307  		_, err = runner.Run(ctx, *execution)
   308  
   309  		assert.Error(t, err)
   310  	})
   311  
   312  	t.Run("runner should return deprecated and deleted APIs on Git file containing deprecated and delete API definitions", func(t *testing.T) {
   313  		t.Parallel()
   314  
   315  		tempDir, err := os.MkdirTemp("", "*")
   316  		assert.NoErrorf(t, err, "failed to create temp dir: %v", err)
   317  		defer os.RemoveAll(tempDir)
   318  
   319  		runner, err := NewRunner(context.Background(), envs.Params{DataDir: tempDir})
   320  		assert.NoError(t, err)
   321  
   322  		execution := testkube.NewQueuedExecution()
   323  		execution.Command = []string{"kubepug"}
   324  		execution.Args = []string{
   325  			"--format=json",
   326  			"--input-file",
   327  			"<runPath>",
   328  		}
   329  
   330  		repo := &testkube.Repository{
   331  			Uri:    "https://github.com/kubeshop/testkube",
   332  			Branch: "develop",
   333  			Path:   "contrib/executor/kubepug/pkg/runner/test-files/manifest-deprecated.yaml",
   334  		}
   335  		_, err = content.NewFetcher(tempDir).FetchGit(repo)
   336  		assert.NoError(t, err)
   337  
   338  		execution.Content = &testkube.TestContent{
   339  			Type_:      string(testkube.TestContentTypeGitFile),
   340  			Repository: repo,
   341  		}
   342  
   343  		result, err := runner.Run(ctx, *execution)
   344  
   345  		assert.NoError(t, err)
   346  		assert.Equal(t, testkube.ExecutionStatusFailed, result.Status)
   347  		assert.Equal(t, 2, len(result.Steps))
   348  		assert.Equal(t, "passed", result.Steps[0].Status)
   349  		assert.Equal(t, "failed", result.Steps[1].Status)
   350  	})
   351  }
   352  
   353  func TestRunGitDirectory_Integration(t *testing.T) {
   354  	test.IntegrationTest(t)
   355  	t.Parallel()
   356  
   357  	ctx := context.Background()
   358  
   359  	t.Run("runner should return success on manifests from Git directory", func(t *testing.T) {
   360  		t.Parallel()
   361  
   362  		tempDir, err := os.MkdirTemp("", "*")
   363  		assert.NoErrorf(t, err, "failed to create temp dir: %v", err)
   364  		defer os.RemoveAll(tempDir)
   365  
   366  		runner, err := NewRunner(context.Background(), envs.Params{DataDir: tempDir})
   367  		assert.NoError(t, err)
   368  
   369  		execution := testkube.NewQueuedExecution()
   370  		execution.Command = []string{"kubepug"}
   371  		execution.Args = []string{
   372  			"--format=json",
   373  			"--input-file",
   374  			"<runPath>",
   375  		}
   376  
   377  		repo := &testkube.Repository{
   378  			Uri:    "https://github.com/kubeshop/testkube",
   379  			Branch: "develop",
   380  			Path:   "contrib/executor/kubepug/pkg/runner/test-files/manifest-valid",
   381  		}
   382  		_, err = content.NewFetcher(tempDir).FetchGit(repo)
   383  		assert.NoError(t, err)
   384  
   385  		execution.Content = &testkube.TestContent{
   386  			Type_:      string(testkube.TestContentTypeGitDir),
   387  			Repository: repo,
   388  		}
   389  
   390  		result, err := runner.Run(ctx, *execution)
   391  
   392  		assert.NoError(t, err)
   393  		assert.Equal(t, testkube.ExecutionStatusPassed, result.Status)
   394  		assert.Equal(t, 2, len(result.Steps))
   395  		assert.Equal(t, "passed", result.Steps[0].Status)
   396  		assert.Equal(t, "passed", result.Steps[1].Status)
   397  	})
   398  }
   399  
   400  func TestRunWithSpecificK8sVersion_Integration(t *testing.T) {
   401  	test.IntegrationTest(t)
   402  	t.Parallel()
   403  
   404  	ctx := context.Background()
   405  
   406  	t.Run("runner should return failure and list of deprecated APIs result "+
   407  		"on yaml containing deprecated API with current K8s version", func(t *testing.T) {
   408  		t.Parallel()
   409  
   410  		data := `
   411  ---
   412  apiVersion: v1
   413  kind: Service
   414  metadata:
   415    name: testkube-dashboard
   416    namespace: testkube
   417  spec:
   418    ports:
   419      - name: http
   420        port: 8001
   421        targetPort: 80
   422    selector:
   423      app: testkube-dashboard
   424  ---
   425  apiVersion: apps/v1beta2
   426  kind: Deployment
   427  metadata:
   428    name: testkube-dashboard
   429    namespace: testkube
   430  spec:
   431    replicas: 1
   432    selector:
   433      matchLabels:
   434        app: testkube-dashboard
   435    strategy:
   436      type: RollingUpdate
   437    template:
   438      metadata:
   439        labels:
   440          app: testkube-dashboard
   441      spec:
   442        containers:
   443          - name: petstore-backend
   444            image: docker.io/kubeshop/testkube-dashboard:latest
   445            ports:
   446              - name: http
   447                containerPort: 80
   448            livenessProbe:
   449              httpGet:
   450              path: /index.html
   451              port: 80
   452              initialDelaySeconds: 15
   453              timeoutSeconds: 2
   454              periodSeconds: 5
   455              failureThreshold: 1
   456            readinessProbe:
   457              httpGet:
   458                path: /index.html
   459                port: 80
   460              initialDelaySeconds: 15
   461              periodSeconds: 5
   462              failureThreshold: 1
   463  `
   464  
   465  		tempDir, err := os.MkdirTemp("", "*")
   466  		assert.NoErrorf(t, err, "failed to create temp dir: %v", err)
   467  		defer os.RemoveAll(tempDir)
   468  
   469  		err = os.WriteFile(filepath.Join(tempDir, "test-content"), []byte(data), 0644)
   470  		if err != nil {
   471  			assert.FailNow(t, "Unable to write postman runner test content file")
   472  		}
   473  
   474  		runner, err := NewRunner(context.Background(), envs.Params{DataDir: tempDir})
   475  		assert.NoError(t, err)
   476  
   477  		execution := testkube.NewQueuedExecution()
   478  		execution.Command = []string{"kubepug"}
   479  		execution.Args = []string{
   480  			"--format=json",
   481  			"--input-file",
   482  			"<runPath>",
   483  		}
   484  		execution.Content = testkube.NewStringTestContent("")
   485  
   486  		result, err := runner.Run(ctx, *execution)
   487  
   488  		assert.NoError(t, err)
   489  		assert.Equal(t, testkube.ExecutionStatusFailed, result.Status)
   490  		assert.Equal(t, 2, len(result.Steps))
   491  		assert.Equal(t, "passed", result.Steps[0].Status)
   492  		assert.Equal(t, "failed", result.Steps[1].Status)
   493  	})
   494  
   495  	t.Run("runner should return success on yaml containing deprecated API with old K8s version", func(t *testing.T) {
   496  		t.Parallel()
   497  
   498  		data := `
   499  ---
   500  apiVersion: v1
   501  kind: Service
   502  metadata:
   503    name: testkube-dashboard
   504    namespace: testkube
   505  spec:
   506    ports:
   507      - name: http
   508        port: 8001
   509        targetPort: 80
   510    selector:
   511      app: testkube-dashboard
   512  ---
   513  apiVersion: apps/v1beta2
   514  kind: Deployment
   515  metadata:
   516    name: testkube-dashboard
   517    namespace: testkube
   518  spec:
   519    replicas: 1
   520    selector:
   521      matchLabels:
   522        app: testkube-dashboard
   523    strategy:
   524      type: RollingUpdate
   525    template:
   526      metadata:
   527        labels:
   528          app: testkube-dashboard
   529      spec:
   530        containers:
   531          - name: petstore-backend
   532            image: docker.io/kubeshop/testkube-dashboard:latest
   533            ports:
   534              - name: http
   535                containerPort: 80
   536            livenessProbe:
   537              httpGet:
   538              path: /index.html
   539              port: 80
   540              initialDelaySeconds: 15
   541              timeoutSeconds: 2
   542              periodSeconds: 5
   543              failureThreshold: 1
   544            readinessProbe:
   545              httpGet:
   546                path: /index.html
   547                port: 80
   548              initialDelaySeconds: 15
   549              periodSeconds: 5
   550              failureThreshold: 1
   551  `
   552  
   553  		tempDir, err := os.MkdirTemp("", "*")
   554  		assert.NoErrorf(t, err, "failed to create temp dir: %v", err)
   555  		defer os.RemoveAll(tempDir)
   556  
   557  		err = os.WriteFile(filepath.Join(tempDir, "test-content"), []byte(data), 0644)
   558  		if err != nil {
   559  			assert.FailNow(t, "Unable to write postman runner test content file")
   560  		}
   561  
   562  		runner, err := NewRunner(context.Background(), envs.Params{DataDir: tempDir})
   563  		assert.NoError(t, err)
   564  
   565  		execution := testkube.NewQueuedExecution()
   566  		execution.Command = []string{"kubepug"}
   567  		execution.Args = []string{
   568  			"--format=json",
   569  			"--input-file",
   570  			"<runPath>",
   571  			"--k8s-version=v1.7.0", // last version apps/v1beta2/Deployment was valid
   572  		}
   573  		execution.Content = testkube.NewStringTestContent("")
   574  
   575  		result, err := runner.Run(ctx, *execution)
   576  
   577  		assert.NoError(t, err)
   578  		assert.Equal(t, testkube.ExecutionStatusPassed, result.Status)
   579  		assert.Equal(t, 2, len(result.Steps))
   580  		assert.Equal(t, "passed", result.Steps[0].Status)
   581  		assert.Equal(t, "passed", result.Steps[1].Status)
   582  	})
   583  }