github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/test/groovy/DockerExecuteOnKubernetesTest.groovy (about)

     1  import com.sap.piper.JenkinsUtils
     2  import com.sap.piper.Utils
     3  
     4  import org.junit.After
     5  import org.junit.Before
     6  import org.junit.Rule
     7  import org.junit.Test
     8  import org.junit.rules.ExpectedException
     9  import org.junit.rules.RuleChain
    10  
    11  import groovy.json.JsonSlurper
    12  import util.BasePiperTest
    13  import util.JenkinsDockerExecuteRule
    14  import util.JenkinsLoggingRule
    15  import util.JenkinsReadYamlRule
    16  import util.JenkinsShellCallRule
    17  import util.JenkinsStepRule
    18  import util.PluginMock
    19  import util.Rules
    20  
    21  import hudson.AbortException
    22  
    23  import static org.hamcrest.Matchers.*
    24  import static org.junit.Assert.assertThat
    25  import static org.junit.Assert.assertTrue
    26  import static org.junit.Assert.assertEquals
    27  import static org.junit.Assert.assertFalse
    28  import static org.junit.Assert.assertNotNull
    29  import static org.junit.Assert.assertNull
    30  
    31  class DockerExecuteOnKubernetesTest extends BasePiperTest {
    32      private ExpectedException exception = ExpectedException.none()
    33      private JenkinsShellCallRule shellRule = new JenkinsShellCallRule(this)
    34      private JenkinsLoggingRule loggingRule = new JenkinsLoggingRule(this)
    35      private JenkinsStepRule stepRule = new JenkinsStepRule(this)
    36      private ExpectedException thrown = new ExpectedException()
    37  
    38      @Rule
    39      public RuleChain ruleChain = Rules
    40          .getCommonRules(this)
    41          .around(new JenkinsReadYamlRule(this))
    42          .around(exception)
    43          .around(shellRule)
    44          .around(loggingRule)
    45          .around(stepRule)
    46          .around(thrown)
    47      int whichDockerReturnValue = 0
    48      def bodyExecuted
    49      def dockerImage
    50      def containerMap
    51      def dockerEnvVars
    52      def dockerWorkspace
    53      def podName = ''
    54      def podLabel = ''
    55      def podNodeSelector = ''
    56      def containersList = []
    57      def imageList = []
    58      def containerName = ''
    59      def containerShell = ''
    60      def envList = []
    61      def portList = []
    62      def containerCommands = []
    63      def pullImageMap = [:]
    64      def namespace
    65      def securityContext
    66      def inheritFrom
    67      def yamlMergeStrategy
    68      def podSpec
    69      Map resources =  [:]
    70      List stashList = []
    71      List unstashList = []
    72      def utilsMock = newUtilsMock()
    73  
    74      Utils newUtilsMock() {
    75          def utilsMock = new Utils()
    76          utilsMock.steps = [
    77              stash  : { m -> stashList.add(m) },
    78              unstash  : { m -> unstashList.add(m) }
    79          ]
    80          utilsMock.echo = { def m -> }
    81          return utilsMock
    82      }
    83  
    84      @Before
    85      void init() {
    86          containersList = []
    87          imageList = []
    88          envList = []
    89          portList = []
    90          containerCommands = []
    91          resources = [:]
    92          bodyExecuted = false
    93          podSpec = null
    94          JenkinsUtils.metaClass.static.isPluginActive = { def s -> new PluginMock(s).isActive() }
    95          helper.registerAllowedMethod('sh', [Map.class], { return whichDockerReturnValue })
    96          helper.registerAllowedMethod('container', [Map.class, Closure.class], { Map config, Closure body ->
    97              container(config) {
    98                  body()
    99              }
   100          })
   101          helper.registerAllowedMethod('merge', [], {
   102              return 'merge'
   103          })
   104          helper.registerAllowedMethod('podTemplate', [Map.class, Closure.class], { Map options, Closure body ->
   105              podName = options.name
   106              podLabel = options.label
   107              namespace = options.namespace
   108              inheritFrom = options.inheritFrom
   109              yamlMergeStrategy = options.yamlMergeStrategy
   110              podNodeSelector = options.nodeSelector
   111              podSpec = new JsonSlurper().parseText(options.yaml)  // this yaml is actually json
   112              def containers = podSpec.spec.containers
   113              securityContext = podSpec.spec.securityContext
   114  
   115              containers.each { container ->
   116                  containersList.add(container.name)
   117                  imageList.add(container.image.toString())
   118                  envList.add(container.env)
   119                  if (container.ports) {
   120                      portList.add(container.ports)
   121                  }
   122                  if (container.command) {
   123                      containerCommands.add(container.command)
   124                  }
   125                  pullImageMap.put(container.image.toString(), container.imagePullPolicy == "Always")
   126                  resources.put(container.name, container.resources)
   127              }
   128              body()
   129          })
   130      }
   131  
   132      @Test
   133      void testRunOnPodNoContainerMapOnlyDockerImage() throws Exception {
   134          stepRule.step.dockerExecuteOnKubernetes(
   135              script: nullScript,
   136              juStabUtils: utilsMock,
   137              dockerImage: 'maven:3.5-jdk-8-alpine',
   138              dockerOptions: '-it',
   139              dockerVolumeBind: ['my_vol': '/my_vol'],
   140              dockerEnvVars: ['http_proxy': 'http://proxy:8000'], dockerWorkspace: '/home/piper'
   141          ) {
   142              bodyExecuted = true
   143          }
   144          assertThat(containersList, hasItem('container-exec'))
   145          assertThat(imageList, hasItem('maven:3.5-jdk-8-alpine'))
   146          assertThat(envList.toString(), containsString('http_proxy'))
   147          assertThat(envList.toString(), containsString('http://proxy:8000'))
   148          assertThat(envList.toString(), containsString('/home/piper'))
   149          assertThat(bodyExecuted, is(true))
   150          assertThat(containerCommands.size(), is(1))
   151      }
   152  
   153      @Test
   154      void testDockerExecuteOnKubernetesEmptyContainerMapNoDockerImage() throws Exception {
   155          stepRule.step.dockerExecuteOnKubernetes(
   156              script: nullScript,
   157              juStabUtils: utilsMock,
   158              containerMap: [:],
   159              dockerEnvVars: ['customEnvKey': 'customEnvValue']) {
   160              bodyExecuted = true
   161          }
   162          assertTrue(bodyExecuted)
   163      }
   164  
   165      @Test
   166      void testDockerExecuteOnKubernetesWithCustomContainerMap() throws Exception {
   167          stepRule.step.dockerExecuteOnKubernetes(script: nullScript, juStabUtils: utilsMock,
   168              containerMap: ['maven:3.5-jdk-8-alpine': 'mavenexecute']) {
   169              container(name: 'mavenexecute') {
   170                  bodyExecuted = true
   171              }
   172          }
   173          assertEquals('mavenexecute', containerName)
   174          assertTrue(containersList.contains('mavenexecute'))
   175          assertTrue(imageList.contains('maven:3.5-jdk-8-alpine'))
   176          assertTrue(bodyExecuted)
   177          assertThat(containerCommands.size(), is(1))
   178      }
   179  
   180      @Test
   181      void testInheritFromPodTemplate() throws Exception {
   182          nullScript.commonPipelineEnvironment.configuration = ['general': ['jenkinsKubernetes': ['inheritFrom': 'default']]]
   183          stepRule.step.dockerExecuteOnKubernetes(script: nullScript, juStabUtils: utilsMock,
   184              containerMap: ['maven:3.5-jdk-8-alpine': 'mavenexecute']) {
   185              container(name: 'mavenexecute') {
   186                  bodyExecuted = true
   187              }
   188          }
   189          assertEquals(inheritFrom, 'default')
   190          assertEquals(yamlMergeStrategy, 'merge')
   191          assertTrue(bodyExecuted)
   192      }
   193  
   194      @Test
   195      void testDockerExecuteOnKubernetesWithCustomJnlpWithContainerMap() throws Exception {
   196          nullScript.commonPipelineEnvironment.configuration = ['general': ['jenkinsKubernetes': ['jnlpAgent': 'myJnalpAgent']]]
   197          stepRule.step.dockerExecuteOnKubernetes(script: nullScript, juStabUtils: utilsMock,
   198              containerMap: ['maven:3.5-jdk-8-alpine': 'mavenexecute']) {
   199              container(name: 'mavenexecute') {
   200                  bodyExecuted = true
   201              }
   202          }
   203          assertEquals('mavenexecute', containerName)
   204          assertTrue(containersList.contains('mavenexecute'))
   205          assertTrue(imageList.contains('maven:3.5-jdk-8-alpine'))
   206          assertTrue(containersList.contains('jnlp'))
   207          assertTrue(imageList.contains('myJnalpAgent'))
   208          assertTrue(bodyExecuted)
   209      }
   210  
   211  
   212      @Test
   213      void testDockerExecuteOnKubernetesWithCustomJnlpWithDockerImage() throws Exception {
   214          nullScript.commonPipelineEnvironment.configuration = ['general': ['jenkinsKubernetes': ['jnlpAgent': 'myJnalpAgent']]]
   215          stepRule.step.dockerExecuteOnKubernetes(
   216              script: nullScript,
   217              juStabUtils: utilsMock,
   218              dockerImage: 'maven:3.5-jdk-8-alpine') {
   219              bodyExecuted = true
   220          }
   221          assertEquals('container-exec', containerName)
   222          assertTrue(containersList.contains('jnlp'))
   223          assertTrue(containersList.contains('container-exec'))
   224          assertTrue(imageList.contains('myJnalpAgent'))
   225          assertTrue(imageList.contains('maven:3.5-jdk-8-alpine'))
   226          assertTrue(bodyExecuted)
   227      }
   228  
   229      @Test
   230      void testDockerExecuteOnKubernetesWithCustomWorkspace() throws Exception {
   231          stepRule.step.dockerExecuteOnKubernetes(script: nullScript, juStabUtils: utilsMock,
   232              containerMap: ['maven:3.5-jdk-8-alpine': 'mavenexecute'],
   233              dockerWorkspace: '/home/piper') {
   234              container(name: 'mavenexecute') {
   235                  bodyExecuted = true
   236              }
   237          }
   238          assertTrue(envList.toString().contains('/home/piper'))
   239          assertTrue(bodyExecuted)
   240      }
   241  
   242      @Test
   243      void testDockerExecuteOnKubernetesWithCustomEnv() throws Exception {
   244          stepRule.step.dockerExecuteOnKubernetes(script: nullScript, juStabUtils: utilsMock,
   245              containerMap: ['maven:3.5-jdk-8-alpine': 'mavenexecute'],
   246              dockerEnvVars: ['customEnvKey': 'customEnvValue']) {
   247              container(name: 'mavenexecute') {
   248                  bodyExecuted = true
   249              }
   250          }
   251          assertTrue(envList.toString().contains('customEnvKey') && envList.toString().contains('customEnvValue'))
   252          assertTrue(bodyExecuted)
   253      }
   254  
   255      @Test
   256      void testDockerExecuteOnKubernetesNoResourceLimitsOnEmptyResourcesMap() throws Exception {
   257  
   258          nullScript.commonPipelineEnvironment.configuration = [general:
   259              [jenkinsKubernetes: [
   260                  resources: [
   261                      DEFAULT: [
   262                          requests: [
   263                              memory: '1Gi',
   264                              cpu: '0.25'
   265                          ],
   266                          limits: [
   267                              memory: '2Gi',
   268                              cpu: '1'
   269                          ]
   270                      ],
   271                      mavenexecute: [:]
   272                  ]
   273              ]
   274          ]]
   275          stepRule.step.dockerExecuteOnKubernetes(script: nullScript, juStabUtils: utilsMock,
   276              containerMap: ['maven:3.5-jdk-8-alpine': 'mavenexecute'], {
   277                  bodyExecuted = true
   278              })
   279  
   280          assertNull(resources.mavenexecute)
   281          assertTrue(bodyExecuted)
   282      }
   283  
   284      @Test
   285      void testDockerExecuteOnKubernetesWithDefaultResourceLimits() throws Exception {
   286  
   287          nullScript.commonPipelineEnvironment.configuration = [general:
   288              [jenkinsKubernetes: [
   289                  resources: [DEFAULT: [
   290                      requests: [
   291                          memory: '1Gi',
   292                          cpu: '0.25'
   293                      ],
   294                      limits: [
   295                          memory: '2Gi',
   296                          cpu: '1'
   297                      ]
   298                  ]
   299              ]
   300          ]]]
   301          stepRule.step.dockerExecuteOnKubernetes(script: nullScript, juStabUtils: utilsMock,
   302              containerMap: ['maven:3.5-jdk-8-alpine': 'mavenexecute'], {
   303                  bodyExecuted = true
   304              })
   305  
   306          assertEquals(requests: [memory: '1Gi',cpu: '0.25'],limits: [memory: '2Gi',cpu: '1'], resources.jnlp)
   307          assertEquals(requests: [memory: '1Gi',cpu: '0.25'],limits: [memory: '2Gi',cpu: '1'], resources.mavenexecute)
   308          assertTrue(bodyExecuted)
   309      }
   310  
   311      @Test
   312      void testDockerExecuteOnKubernetesWithSpecificResourcLimitsParametersAreTakingPrecendence() throws Exception {
   313  
   314          // the settings here are expected to be overwritten by the parameters provided via signature
   315          nullScript.commonPipelineEnvironment.configuration = [general:
   316              [jenkinsKubernetes: [
   317                  resources: [
   318                      mavenexecute: [
   319                      requests: [
   320                          memory: '2Gi',
   321                          cpu: '0.75'
   322                      ],
   323                      limits: [
   324                          memory: '4Gi',
   325                          cpu: '2'
   326                      ]
   327                  ]
   328              ]
   329          ]]]
   330          stepRule.step.dockerExecuteOnKubernetes(script: nullScript, juStabUtils: utilsMock,
   331              containerMap: ['maven:3.5-jdk-8-alpine': 'mavenexecute'],
   332              resources: [
   333                      mavenexecute: [
   334                      requests: [
   335                          memory: '8Gi',
   336                          cpu: '2'
   337                      ],
   338                      limits: [
   339                          memory: '16Gi',
   340                          cpu: '4'
   341                      ]
   342                  ]
   343              ]) {
   344                  bodyExecuted = true
   345              }
   346  
   347          assertEquals(requests: [memory: '8Gi',cpu: '2'],limits: [memory: '16Gi',cpu: '4'], resources.mavenexecute)
   348          assertTrue(bodyExecuted)
   349      }
   350  
   351      @Test
   352      void testDockerExecuteOnKubernetesWithSpecificResourceLimits() throws Exception {
   353  
   354          nullScript.commonPipelineEnvironment.configuration = [general:
   355              [jenkinsKubernetes: [
   356                  resources: [
   357                      DEFAULT: [
   358                          requests: [
   359                              memory: '1Gi',
   360                              cpu: '0.25'
   361                          ],
   362                          limits: [
   363                              memory: '2Gi',
   364                              cpu: '1'
   365                          ]
   366                      ],
   367                      mavenexecute: [
   368                          requests: [
   369                              memory: '2Gi',
   370                              cpu: '0.75'
   371                          ],
   372                          limits: [
   373                              memory: '4Gi',
   374                              cpu: '2'
   375                          ]
   376                      ],
   377                      jnlp: [
   378                          requests: [
   379                              memory: '3Gi',
   380                              cpu: '0.33'
   381                          ],
   382                          limits: [
   383                              memory: '6Gi',
   384                              cpu: '3'
   385                          ]
   386                      ],
   387                      mysidecar: [
   388                          requests: [
   389                              memory: '10Gi',
   390                              cpu: '5.00'
   391                          ],
   392                          limits: [
   393                              memory: '20Gi',
   394                              cpu: '10'
   395                          ]
   396                      ]
   397                  ]
   398              ]
   399          ]]
   400          stepRule.step.dockerExecuteOnKubernetes(script: nullScript, juStabUtils: utilsMock,
   401              containerMap: ['maven:3.5-jdk-8-alpine': 'mavenexecute'],
   402              sidecarImage: 'ubuntu',
   403              sidecarName: 'mysidecar') {
   404                  bodyExecuted = true
   405              }
   406  
   407          assertEquals(requests: [memory: '10Gi',cpu: '5.00'],limits: [memory: '20Gi',cpu: '10'], resources.mysidecar)
   408          assertEquals(requests: [memory: '3Gi',cpu: '0.33'],limits: [memory: '6Gi',cpu: '3'], resources.jnlp)
   409          assertEquals(requests: [memory: '2Gi',cpu: '0.75'],limits: [memory: '4Gi',cpu: '2'], resources.mavenexecute)
   410          assertTrue(bodyExecuted)
   411      }
   412  
   413      @Test
   414      void testDockerExecuteOnKubernetesUpperCaseContainerName() throws Exception {
   415          stepRule.step.dockerExecuteOnKubernetes(script: nullScript, juStabUtils: utilsMock,
   416              containerMap: ['maven:3.5-jdk-8-alpine': 'MAVENEXECUTE'],
   417              dockerEnvVars: ['customEnvKey': 'customEnvValue']) {
   418              container(name: 'mavenexecute') {
   419                  bodyExecuted = true
   420              }
   421          }
   422          assertEquals('mavenexecute', containerName)
   423          assertTrue(containersList.contains('mavenexecute'))
   424          assertTrue(imageList.contains('maven:3.5-jdk-8-alpine'))
   425          assertTrue(bodyExecuted)
   426      }
   427  
   428      @Test
   429      void testSidecarDefaultWithContainerMap() {
   430          List portMapping = []
   431          helper.registerAllowedMethod('portMapping', [Map.class], { m ->
   432              portMapping.add(m)
   433              return m
   434          })
   435          stepRule.step.dockerExecuteOnKubernetes(
   436              script: nullScript,
   437              juStabUtils: utilsMock,
   438              containerCommands: ['selenium/standalone-chrome': ''],
   439              containerEnvVars: [
   440                  'selenium/standalone-chrome': ['customEnvKey': 'customEnvValue']
   441              ],
   442              containerMap: [
   443                  'maven:3.5-jdk-8-alpine'    : 'mavenexecute',
   444                  'selenium/standalone-chrome': 'selenium'
   445              ],
   446              containerName: 'mavenexecute',
   447              containerPortMappings: [
   448                  'selenium/standalone-chrome': [[containerPort: 4444]]
   449              ],
   450              containerWorkspaces: [
   451                  'selenium/standalone-chrome': ''
   452              ],
   453              dockerWorkspace: '/home/piper'
   454          ) {
   455              bodyExecuted = true
   456          }
   457  
   458          assertThat(bodyExecuted, is(true))
   459          assertThat(containerName, is('mavenexecute'))
   460  
   461          assertThat(containersList, allOf(
   462              hasItem('mavenexecute'),
   463              hasItem('selenium'),
   464          ))
   465          assertThat(imageList, allOf(
   466              hasItem('maven:3.5-jdk-8-alpine'),
   467              hasItem('selenium/standalone-chrome'),
   468          ))
   469          assertThat(portList, hasItem([[name: 'selenium0', containerPort: 4444]]))
   470          assertThat(containerCommands.size(), is(1))
   471          assertThat(envList, hasItem(hasItem(allOf(hasEntry('name', 'customEnvKey'), hasEntry('value', 'customEnvValue')))))
   472      }
   473  
   474      @Test
   475      void testSidecarDefaultWithParameters() {
   476          List portMapping = []
   477          helper.registerAllowedMethod('portMapping', [Map.class], { m ->
   478              portMapping.add(m)
   479              return m
   480          })
   481          stepRule.step.dockerExecuteOnKubernetes(
   482              script: nullScript,
   483              juStabUtils: utilsMock,
   484              containerMap: ['maven:3.5-jdk-8-alpine': 'mavenexecute'],
   485              containerName: 'mavenexecute',
   486              dockerOptions: '-it',
   487              dockerVolumeBind: ['my_vol': '/my_vol'],
   488              dockerEnvVars: ['http_proxy': 'http://proxy:8000'],
   489              dockerWorkspace: '/home/piper',
   490              sidecarEnvVars: ['testEnv': 'testVal'],
   491              sidecarWorkspace: '/home/piper/sidecar',
   492              sidecarImage: 'postgres',
   493              sidecarName: 'postgres',
   494              sidecarReadyCommand: 'pg_isready'
   495          ) {
   496              bodyExecuted = true
   497          }
   498  
   499          assertThat(bodyExecuted, is(true))
   500  
   501          assertThat(containersList, allOf(hasItem('postgres'), hasItem('mavenexecute')))
   502          assertThat(imageList, allOf(hasItem('maven:3.5-jdk-8-alpine'), hasItem('postgres')))
   503  
   504          assertThat(envList, hasItem(hasItem(allOf(hasEntry('name', 'testEnv'), hasEntry('value', 'testVal')))))
   505          assertThat(envList, hasItem(hasItem(allOf(hasEntry('name', 'HOME'), hasEntry('value', '/home/piper/sidecar')))))
   506      }
   507  
   508      @Test
   509      void testDockerExecuteOnKubernetesWithCustomShell() {
   510          stepRule.step.dockerExecuteOnKubernetes(
   511              script: nullScript,
   512              juStabUtils: utilsMock,
   513              dockerImage: 'maven:3.5-jdk-8-alpine',
   514              containerShell: '/busybox/sh'
   515          ) {
   516              //nothing to exeute
   517          }
   518          assertThat(containerShell, is('/busybox/sh'))
   519      }
   520  
   521      @Test
   522      void testDockerExecuteOnKubernetesWithCustomContainerCommand() {
   523          stepRule.step.dockerExecuteOnKubernetes(
   524              script: nullScript,
   525              juStabUtils: utilsMock,
   526              dockerImage: 'maven:3.5-jdk-8-alpine',
   527              containerCommand: '/busybox/tail -f /dev/null'
   528          ) {
   529              //nothing to exeute
   530          }
   531          assertThat(containerCommands, hasItem(['/bin/sh', '-c', '/busybox/tail -f /dev/null']))
   532      }
   533  
   534      @Test
   535      void testSkipDockerImagePull() throws Exception {
   536          stepRule.step.dockerExecuteOnKubernetes(
   537              script: nullScript,
   538              juStabUtils: utilsMock,
   539              dockerPullImage: false,
   540              containerMap: ['maven:3.5-jdk-8-alpine': 'mavenexecute']
   541          ) {
   542              container(name: 'mavenexecute') {
   543                  bodyExecuted = true
   544              }
   545          }
   546          assertEquals(false, pullImageMap.get('maven:3.5-jdk-8-alpine'))
   547          assertTrue(bodyExecuted)
   548      }
   549  
   550      @Test
   551      void testSkipSidecarImagePull() throws Exception {
   552          stepRule.step.dockerExecuteOnKubernetes(
   553              script: nullScript,
   554              juStabUtils: utilsMock,
   555              containerCommands: ['selenium/standalone-chrome': ''],
   556              containerEnvVars: [
   557                  'selenium/standalone-chrome': ['customEnvKey': 'customEnvValue']
   558              ],
   559              containerMap: [
   560                  'maven:3.5-jdk-8-alpine'    : 'mavenexecute',
   561                  'selenium/standalone-chrome': 'selenium'
   562              ],
   563              containerName: 'mavenexecute',
   564              containerWorkspaces: [
   565                  'selenium/standalone-chrome': ''
   566              ],
   567              containerPullImageFlags: [
   568                  'maven:3.5-jdk-8-alpine'    : true,
   569                  'selenium/standalone-chrome': false
   570              ],
   571              dockerWorkspace: '/home/piper'
   572          ) {
   573              bodyExecuted = true
   574          }
   575          assertEquals(true, pullImageMap.get('maven:3.5-jdk-8-alpine'))
   576          assertEquals(false, pullImageMap.get('selenium/standalone-chrome'))
   577          assertTrue(bodyExecuted)
   578      }
   579  
   580      @Test
   581      void testDockerExecuteOnKubernetesWithCustomNamespace() {
   582          def expectedNamespace = "sandbox"
   583          nullScript.commonPipelineEnvironment.configuration = [general: [jenkinsKubernetes: [namespace: expectedNamespace]]]
   584  
   585          stepRule.step.dockerExecuteOnKubernetes(
   586              script: nullScript,
   587              juStabUtils: utilsMock,
   588              dockerImage: 'maven:3.5-jdk-8-alpine',
   589          ) { bodyExecuted = true }
   590          assertTrue(bodyExecuted)
   591          assertThat(namespace, is(equalTo(expectedNamespace)))
   592      }
   593  
   594      @Test
   595      void testDockerExecuteWithAdditionalPodProperties() {
   596          nullScript.commonPipelineEnvironment.configuration = [general: [jenkinsKubernetes: [
   597              additionalPodProperties: [
   598                  tolerations:[
   599                      [
   600                          key: "key1",
   601                          operator: "Equal",
   602                          value: "value1",
   603                          effect: "NoSchedule",
   604                      ],
   605                      [
   606                          key: "key2",
   607                          operator: "Equal",
   608                          value: "value2",
   609                          effect: "NoExecute",
   610                      ],
   611                  ],
   612                  subdomain: 'foo',
   613                  shareProcessNamespace: false
   614              ]
   615          ]]]
   616  
   617          stepRule.step.dockerExecuteOnKubernetes(
   618              script: nullScript,
   619              juStabUtils: utilsMock,
   620              dockerImage: 'maven:3.5-jdk-8-alpine',
   621          ) { bodyExecuted = true }
   622          assertTrue(bodyExecuted)
   623          assertEquals(
   624              [
   625                  [
   626                      "key": "key1",
   627                      "operator": "Equal",
   628                      "value": "value1",
   629                      "effect": "NoSchedule"
   630                  ],
   631                  [
   632                      "key": "key2",
   633                      "operator": "Equal",
   634                      "value": "value2",
   635                      "effect": "NoExecute"
   636                  ]
   637              ], podSpec.spec.tolerations)
   638          assertEquals('foo', podSpec.spec.subdomain)
   639          assertFalse(podSpec.spec.shareProcessNamespace)
   640          assertThat(loggingRule.log, containsString('Additional pod properties found ([tolerations, subdomain, shareProcessNamespace]). Providing additional pod properties is some kind of expert mode. In case of any problems caused by these additional properties only limited support can be provided.'))
   641  
   642      }
   643  
   644      @Test
   645      void testDockerExecuteWithAdditionalPodPropertiesContainerPropertyIsNotOverwritten() {
   646          nullScript.commonPipelineEnvironment.configuration = [general: [jenkinsKubernetes: [
   647              additionalPodProperties: [
   648                  containers:[
   649                      [
   650                          some: "stupid",
   651                          stuff: "here",
   652                      ]
   653                  ],
   654                  subdomain: 'foo',
   655                  shareProcessNamespace: false,
   656              ]
   657          ]]]
   658  
   659          stepRule.step.dockerExecuteOnKubernetes(
   660              script: nullScript,
   661              juStabUtils: utilsMock,
   662              dockerImage: 'maven:3.5-jdk-8-alpine',
   663          ) { bodyExecuted = true }
   664          assertTrue(bodyExecuted)
   665  
   666          // This is not contained in the configuration above.
   667          assertNotNull(podSpec.spec.containers[0].name)
   668  
   669          // This is contained in the config above.
   670          assertNull(podSpec.spec.some)
   671          assertNull(podSpec.spec.stuff)
   672  
   673          assertEquals('foo', podSpec.spec.subdomain)
   674          assertFalse(podSpec.spec.shareProcessNamespace)
   675      }
   676  
   677      @Test
   678      void testDockerExecuteOnKubernetesWithSecurityContext() {
   679          def expectedSecurityContext = [runAsUser: 1000, fsGroup: 1000]
   680          nullScript.commonPipelineEnvironment.configuration = [general: [jenkinsKubernetes: [
   681              securityContext: expectedSecurityContext]]]
   682          stepRule.step.dockerExecuteOnKubernetes(
   683              script: nullScript,
   684              juStabUtils: utilsMock,
   685              dockerImage: 'maven:3.5-jdk-8-alpine',
   686          ) { bodyExecuted = true }
   687          assertTrue(bodyExecuted)
   688          assertThat(securityContext, is(equalTo(expectedSecurityContext)))
   689      }
   690  
   691      @Test
   692      void testDockerExecuteOnKubernetesCustomNode() {
   693  
   694          stepRule.step.dockerExecuteOnKubernetes(
   695              script: nullScript,
   696              juStabUtils: utilsMock,
   697              dockerImage: 'maven:3.5-jdk-8-alpine',
   698              nodeSelector: 'size:big'
   699          ) { bodyExecuted = true }
   700          assertTrue(bodyExecuted)
   701          assertThat(podNodeSelector, is('size:big'))
   702      }
   703  
   704      @Test
   705      void testDockerExecuteOnKubernetesCustomJnlpViaEnv() {
   706  
   707          nullScript.commonPipelineEnvironment.configuration = [
   708              general: [jenkinsKubernetes: [jnlpAgent: 'config/jnlp:latest']]
   709          ]
   710          binding.variables.env.JENKINS_JNLP_IMAGE = 'env/jnlp:latest'
   711          stepRule.step.dockerExecuteOnKubernetes(
   712              script: nullScript,
   713              juStabUtils: utilsMock,
   714              dockerImage: 'maven:3.5-jdk-8-alpine',
   715          ) { bodyExecuted = true }
   716          assertTrue(bodyExecuted)
   717  
   718          assertThat(containersList, allOf(
   719              hasItem('jnlp'),
   720              hasItem('container-exec')
   721          ))
   722          assertThat(imageList, allOf(
   723              hasItem('env/jnlp:latest'),
   724              hasItem('maven:3.5-jdk-8-alpine'),
   725          ))
   726      }
   727  
   728      @Test
   729      void testDockerExecuteOnKubernetesCustomJnlpViaConfig() {
   730  
   731          nullScript.commonPipelineEnvironment.configuration = [
   732              general: [jenkinsKubernetes: [jnlpAgent: 'config/jnlp:latest']]
   733          ]
   734          //binding.variables.env.JENKINS_JNLP_IMAGE = 'config/jnlp:latest'
   735          stepRule.step.dockerExecuteOnKubernetes(
   736              script: nullScript,
   737              juStabUtils: utilsMock,
   738              dockerImage: 'maven:3.5-jdk-8-alpine',
   739          ) { bodyExecuted = true }
   740          assertTrue(bodyExecuted)
   741  
   742          assertThat(containersList, allOf(
   743              hasItem('jnlp'),
   744              hasItem('container-exec')
   745          ))
   746          assertThat(imageList, allOf(
   747              hasItem('config/jnlp:latest'),
   748              hasItem('maven:3.5-jdk-8-alpine'),
   749          ))
   750      }
   751  
   752      @Test
   753      void testDockerExecuteOnKubernetesExecutionFails() {
   754  
   755          thrown.expect(AbortException)
   756          thrown.expectMessage('Execution failed.')
   757  
   758          nullScript.commonPipelineEnvironment.configuration = [
   759              general: [jenkinsKubernetes: [jnlpAgent: 'config/jnlp:latest']]
   760          ]
   761          //binding.variables.env.JENKINS_JNLP_IMAGE = 'config/jnlp:latest'
   762          stepRule.step.dockerExecuteOnKubernetes(
   763              script: nullScript,
   764              juStabUtils: utilsMock,
   765              dockerImage: 'maven:3.5-jdk-8-alpine',
   766          ) { throw new AbortException('Execution failed.') }
   767      }
   768  
   769      @Test
   770      void testDockerExecuteOnKubernetesAnnotations(){
   771          stepRule.step.dockerExecuteOnKubernetes(
   772              script: nullScript,
   773              juStabUtils: utilsMock,
   774              annotations: ['testAnnotation':'testValue']
   775          )
   776          {
   777              bodyExecuted = true
   778          }
   779          assertEquals(['testAnnotation':'testValue'], podSpec.metadata.annotations)
   780      }
   781  
   782      @Test
   783      void testStashIncludesAndExcludes() {
   784          nullScript.commonPipelineEnvironment.configuration = [
   785              steps: [
   786                  dockerExecuteOnKubernetes: [
   787                      stashExcludes: [
   788                          workspace: 'workspace/exclude.test',
   789                          stashBack: 'container/exclude.test'
   790                      ],
   791                      stashIncludes: [
   792                          workspace: 'workspace/include.test',
   793                          stashBack: 'container/include.test'
   794                      ]
   795                  ]
   796              ]
   797          ]
   798          stepRule.step.dockerExecuteOnKubernetes(
   799              script: nullScript,
   800              juStabUtils: utilsMock,
   801              dockerImage: 'maven:3.5-jdk-8-alpine',
   802          ) {
   803              bodyExecuted = true
   804          }
   805          assertThat(stashList, hasItem(allOf(
   806              hasEntry('allowEmpty', true),
   807              hasEntry('includes', 'workspace/include.test'),
   808              hasEntry('excludes', 'workspace/exclude.test'))))
   809          assertThat(stashList, hasItem(allOf(
   810              hasEntry('allowEmpty', true),
   811              hasEntry('includes', 'container/include.test'),
   812              hasEntry('excludes', 'container/exclude.test'))))
   813      }
   814  
   815      @Test
   816      void testUnstash() {
   817          stepRule.step.dockerExecuteOnKubernetes(
   818              script: nullScript,
   819              juStabUtils: utilsMock,
   820              dockerImage: 'maven:3.5-jdk-8-alpine',
   821          ) {}
   822          assertEquals(2, unstashList.size())
   823          assertTrue(unstashList[0].startsWith('workspace-'))
   824          assertTrue(unstashList[1].startsWith('container-'))
   825      }
   826  
   827      @Test
   828      void testDockerExecuteWithVolumeProperties() {
   829          stepRule.step.dockerExecuteOnKubernetes(
   830              script: nullScript,
   831              juStabUtils: utilsMock,
   832              containerName: 'mycontainer',
   833              initContainerImage: 'ppiper/cf-cli',
   834              dockerImage: 'maven:3.5-jdk-8-alpine',
   835              containerMountPath: '/opt',
   836          ) { bodyExecuted = true }
   837          def containerSpec = podSpec.spec.containers.find{it.image == "maven:3.5-jdk-8-alpine"}
   838          def initContainerSpec = podSpec.spec.initContainers[0]
   839          assertTrue(bodyExecuted)
   840          assertEquals(
   841              [[
   842                   "name"    : "volume",
   843                   "emptyDir": [:]
   844               ]], podSpec.spec.volumes)
   845          assertEquals(
   846              [[
   847                  "name"     : "volume",
   848                  "mountPath": "/opt"
   849              ]], containerSpec.volumeMounts)
   850          assertEquals(
   851              [[
   852                   "name"     : "volume",
   853                   "mountPath": "/opt"
   854               ]], initContainerSpec.volumeMounts)
   855      }
   856  
   857      @Test
   858      void testInitContainerDefaultWithParameters() {
   859          stepRule.step.dockerExecuteOnKubernetes(
   860              script: nullScript,
   861              juStabUtils: utilsMock,
   862              containerName: 'mycontainer',
   863              initContainerImage: 'ppiper/cf-cli@sha256:latest',
   864              initContainerCommand: 'cp /usr/local/bin/cf7 /opt/bin/cf',
   865              dockerImage: 'maven:3.5-jdk-8-alpine',
   866              containerMountPath: '/opt',
   867          ) { bodyExecuted = true }
   868          def initContainer = podSpec.spec.initContainers[0]
   869          def expectedCommandOutput = ["sh", "-c", "cp /usr/local/bin/cf7 /opt/bin/cf"]
   870          assertTrue(bodyExecuted)
   871          assertEquals("ppiper-cf-cli-sha256-latest", initContainer.name)
   872          assertEquals("ppiper/cf-cli@sha256:latest", initContainer.image)
   873          assertThat(initContainer.command, is(equalTo(expectedCommandOutput)))
   874      }
   875  
   876      @Test
   877      void testInitContainerWithoutContainerCommand() {
   878          stepRule.step.dockerExecuteOnKubernetes(
   879              script: nullScript,
   880              juStabUtils: utilsMock,
   881              containerName: 'mycontainer',
   882              initContainerImage: 'ppiper/cf-cli@sha256:latest',
   883              dockerImage: 'maven:3.5-jdk-8-alpine',
   884              containerMountPath: '/opt',
   885          ) { bodyExecuted = true }
   886          def initContainer = podSpec.spec.initContainers[0]
   887          def expectedCommandOutput = ["/usr/bin/tail", "-f", "/dev/null"]
   888          assertTrue(bodyExecuted)
   889          assertThat(initContainer.command, is(equalTo(expectedCommandOutput)))
   890      }
   891  
   892  
   893      private container(options, body) {
   894          containerName = options.name
   895          containerShell = options.shell
   896          body()
   897      }
   898  }