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

     1  import com.sap.piper.k8s.ContainerMap
     2  
     3  import com.sap.piper.JenkinsUtils
     4  import com.sap.piper.SidecarUtils
     5  import com.sap.piper.Utils
     6  import org.junit.After
     7  import org.junit.Before
     8  import org.junit.Rule
     9  import org.junit.Test
    10  import org.junit.rules.RuleChain
    11  
    12  import util.BasePiperTest
    13  import util.JenkinsLoggingRule
    14  import util.JenkinsReadYamlRule
    15  import util.JenkinsShellCallRule
    16  import util.JenkinsStepRule
    17  import util.PluginMock
    18  import util.Rules
    19  
    20  import static org.hamcrest.Matchers.*
    21  import static org.junit.Assert.assertThat
    22  import static org.junit.Assert.assertTrue
    23  import static org.junit.Assert.assertEquals
    24  import static org.junit.Assert.assertFalse
    25  
    26  class DockerExecuteTest extends BasePiperTest {
    27      private DockerMock docker
    28      private JenkinsLoggingRule loggingRule = new JenkinsLoggingRule(this)
    29      private JenkinsStepRule stepRule = new JenkinsStepRule(this)
    30      private JenkinsShellCallRule shellRule = new JenkinsShellCallRule(this)
    31  
    32      @Rule
    33      public RuleChain ruleChain = Rules
    34          .getCommonRules(this)
    35          .around(new JenkinsReadYamlRule(this))
    36          .around(loggingRule)
    37          .around(stepRule)
    38          .around(shellRule)
    39  
    40      def bodyExecuted
    41      def containerName
    42  
    43      @Before
    44      void init() {
    45          bodyExecuted = false
    46          docker = new DockerMock()
    47          JenkinsUtils.metaClass.static.isPluginActive = { def s -> new PluginMock(s).isActive() }
    48          binding.setVariable('docker', docker)
    49          shellRule.setReturnValue(JenkinsShellCallRule.Type.REGEX, "docker .*", 0)
    50          Utils.metaClass.echo = { def m -> }
    51      }
    52  
    53      @After
    54      public void tearDown() {
    55          Utils.metaClass = null
    56      }
    57  
    58      @Test
    59      void testExecuteInsideContainerOfExistingPod() throws Exception {
    60          List usedDockerEnvVars
    61          helper.registerAllowedMethod('container', [String.class, Closure.class], { String container, Closure body ->
    62              containerName = container
    63              body()
    64          })
    65          helper.registerAllowedMethod('withEnv', [List.class, Closure.class], { List envVars, Closure body ->
    66              usedDockerEnvVars = envVars
    67              body()
    68          })
    69          binding.setVariable('env', [POD_NAME: 'testpod', ON_K8S: 'true'])
    70          ContainerMap.instance.setMap(['testpod': ['maven:3.5-jdk-8-alpine': 'mavenexec']])
    71          stepRule.step.dockerExecute(script: nullScript,
    72              dockerImage: 'maven:3.5-jdk-8-alpine',
    73              dockerEnvVars: ['http_proxy': 'http://proxy:8000']) {
    74              bodyExecuted = true
    75          }
    76          assertTrue(loggingRule.log.contains('Executing inside a Kubernetes Container'))
    77          assertEquals('mavenexec', containerName)
    78          assertEquals(usedDockerEnvVars[0].toString(), "http_proxy=http://proxy:8000")
    79          assertTrue(bodyExecuted)
    80      }
    81  
    82      @Test
    83      void testExecuteInsideNewlyCreatedPod() throws Exception {
    84          helper.registerAllowedMethod('dockerExecuteOnKubernetes', [Map.class, Closure.class], { Map config, Closure body -> body() })
    85          binding.setVariable('env', [ON_K8S: 'true'])
    86          ContainerMap.instance.setMap(['testpod': ['maven:3.5-jdk-8-alpine': 'mavenexec']])
    87          stepRule.step.dockerExecute(script: nullScript,
    88              dockerImage: 'maven:3.5-jdk-8-alpine',
    89              dockerEnvVars: ['http_proxy': 'http://proxy:8000']) {
    90              bodyExecuted = true
    91          }
    92          assertTrue(loggingRule.log.contains('Executing inside a Kubernetes Pod'))
    93          assertTrue(bodyExecuted)
    94      }
    95  
    96      @Test
    97      void testExecuteInsidePodWithEmptyContainerMap() throws Exception {
    98          helper.registerAllowedMethod('dockerExecuteOnKubernetes', [Map.class, Closure.class], { Map config, Closure body -> body() })
    99          binding.setVariable('env', [POD_NAME: 'testpod', ON_K8S: 'true'])
   100          ContainerMap.instance.setMap([:])
   101          stepRule.step.dockerExecute(script: nullScript,
   102              dockerImage: 'maven:3.5-jdk-8-alpine',
   103              dockerEnvVars: ['http_proxy': 'http://proxy:8000']) {
   104              bodyExecuted = true
   105          }
   106          assertTrue(loggingRule.log.contains('Executing inside a Kubernetes Pod'))
   107          assertTrue(bodyExecuted)
   108      }
   109  
   110      @Test
   111      void testExecuteInsidePodWithStageKeyEmptyValue() throws Exception {
   112          helper.registerAllowedMethod('dockerExecuteOnKubernetes', [Map.class, Closure.class], { Map config, Closure body -> body() })
   113          binding.setVariable('env', [POD_NAME: 'testpod', ON_K8S: 'true'])
   114          ContainerMap.instance.setMap(['testpod': [:]])
   115          stepRule.step.dockerExecute(script: nullScript,
   116              dockerImage: 'maven:3.5-jdk-8-alpine',
   117              dockerEnvVars: ['http_proxy': 'http://proxy:8000']) {
   118              bodyExecuted = true
   119          }
   120          assertTrue(loggingRule.log.contains('Executing inside a Kubernetes Pod'))
   121          assertTrue(bodyExecuted)
   122      }
   123  
   124      @Test
   125      void testExecuteInsidePodWithCustomCommandAndShell() throws Exception {
   126          Map kubernetesConfig = [:]
   127          helper.registerAllowedMethod('dockerExecuteOnKubernetes', [Map.class, Closure.class], { Map config, Closure body ->
   128              kubernetesConfig = config
   129              return body()
   130          })
   131          binding.setVariable('env', [ON_K8S: 'true'])
   132          stepRule.step.dockerExecute(
   133              script: nullScript,
   134              containerCommand: '/busybox/tail -f /dev/null',
   135              containerShell: '/busybox/sh',
   136              dockerImage: 'maven:3.5-jdk-8-alpine'
   137          ) {
   138              bodyExecuted = true
   139          }
   140          assertTrue(loggingRule.log.contains('Executing inside a Kubernetes Pod'))
   141          assertThat(kubernetesConfig.containerCommand, is('/busybox/tail -f /dev/null'))
   142          assertThat(kubernetesConfig.containerShell, is('/busybox/sh'))
   143          assertTrue(bodyExecuted)
   144      }
   145  
   146      @Test
   147      void testExecuteInsidePodWithCustomUserShort() throws Exception {
   148          Map kubernetesConfig = [:]
   149          helper.registerAllowedMethod('dockerExecuteOnKubernetes', [Map.class, Closure.class], { Map config, Closure body ->
   150              kubernetesConfig = config
   151              return body()
   152          })
   153          binding.setVariable('env', [ON_K8S: 'true'])
   154          stepRule.step.dockerExecute(
   155              script: nullScript,
   156              dockerImage: 'maven:3.5-jdk-8-alpine',
   157              dockerOptions: ["-u 0:0", "-v foo:bar"]
   158          ) {
   159              bodyExecuted = true
   160          }
   161  
   162          assertTrue(loggingRule.log.contains('Executing inside a Kubernetes Pod'))
   163          assertThat(kubernetesConfig.securityContext, is([
   164              'runAsUser': 0,
   165              'runAsGroup': 0
   166          ]))
   167          assertTrue(bodyExecuted)
   168      }
   169  
   170      @Test
   171      void testExecuteInsidePodWithCustomUserLong() throws Exception {
   172          Map kubernetesConfig = [:]
   173          helper.registerAllowedMethod('dockerExecuteOnKubernetes', [Map.class, Closure.class], { Map config, Closure body ->
   174              kubernetesConfig = config
   175              return body()
   176          })
   177          binding.setVariable('env', [ON_K8S: 'true'])
   178          stepRule.step.dockerExecute(
   179              script: nullScript,
   180              dockerImage: 'maven:3.5-jdk-8-alpine',
   181              dockerOptions: ["--user 0:0", "-v foo:bar"]
   182          ) {
   183              bodyExecuted = true
   184          }
   185  
   186          assertTrue(loggingRule.log.contains('Executing inside a Kubernetes Pod'))
   187          assertThat(kubernetesConfig.securityContext, is([
   188              'runAsUser': 0,
   189              'runAsGroup': 0
   190          ]))
   191          assertTrue(bodyExecuted)
   192      }
   193  
   194      @Test
   195      void testExecuteInsidePodWithCustomUserNoGroup() throws Exception {
   196          Map kubernetesConfig = [:]
   197          helper.registerAllowedMethod('dockerExecuteOnKubernetes', [Map.class, Closure.class], { Map config, Closure body ->
   198              kubernetesConfig = config
   199              return body()
   200          })
   201          binding.setVariable('env', [ON_K8S: 'true'])
   202          stepRule.step.dockerExecute(
   203              script: nullScript,
   204              dockerImage: 'maven:3.5-jdk-8-alpine',
   205              dockerOptions: ["-v foo:bar", "-u 0"]
   206          ) {
   207              bodyExecuted = true
   208          }
   209  
   210          assertTrue(loggingRule.log.contains('Executing inside a Kubernetes Pod'))
   211          assertThat(kubernetesConfig.securityContext, is([
   212              'runAsUser': 0
   213          ]))
   214          assertTrue(bodyExecuted)
   215      }
   216  
   217      @Test
   218      void testExecuteInsidePodWithCustomUserGroupString() throws Exception {
   219          Map kubernetesConfig = [:]
   220          helper.registerAllowedMethod('dockerExecuteOnKubernetes', [Map.class, Closure.class], { Map config, Closure body ->
   221              kubernetesConfig = config
   222              return body()
   223          })
   224          binding.setVariable('env', [ON_K8S: 'true'])
   225          stepRule.step.dockerExecute(
   226              script: nullScript,
   227              dockerImage: 'maven:3.5-jdk-8-alpine',
   228              dockerOptions: ["-v foo:bar", "-u root:wheel"]
   229          ) {
   230              bodyExecuted = true
   231          }
   232  
   233          assertTrue(loggingRule.log.contains('Executing inside a Kubernetes Pod'))
   234          assertThat(kubernetesConfig.securityContext, is([
   235              'runAsUser': 'root',
   236              'runAsGroup': 'wheel'
   237          ]))
   238          assertTrue(bodyExecuted)
   239      }
   240  
   241      @Test
   242      void testExecuteInsideDockerContainer() throws Exception {
   243          stepRule.step.dockerExecute(script: nullScript, dockerImage: 'maven:3.5-jdk-8-alpine') {
   244              bodyExecuted = true
   245          }
   246          assertEquals('maven:3.5-jdk-8-alpine', docker.getImageNames()[0])
   247          assertTrue(docker.isImagePulled())
   248          assertEquals('--env http_proxy --env https_proxy --env no_proxy --env HTTP_PROXY --env HTTPS_PROXY --env NO_PROXY', docker.getParameters().trim())
   249          assertTrue(bodyExecuted)
   250      }
   251  
   252      @Test
   253      void testSkipDockerImagePull() throws Exception {
   254          nullScript.commonPipelineEnvironment.configuration = [steps: [dockerExecute: [dockerPullImage: false]]]
   255          stepRule.step.dockerExecute(
   256              script: nullScript,
   257              dockerImage: 'maven:3.5-jdk-8-alpine'
   258          ) {
   259              bodyExecuted = true
   260          }
   261          assertThat(docker.imagePullCount, is(0))
   262          assertThat(bodyExecuted, is(true))
   263      }
   264  
   265      @Test
   266      void testPullSidecarWithDedicatedCredentialsAndRegistry() {
   267          nullScript.commonPipelineEnvironment.configuration =
   268          [
   269              steps: [
   270                  dockerExecute: [
   271                      dockerRegistryUrl: 'https://registry.example.org',
   272                      dockerRegistryCredentialsId: 'mySecrets',
   273                      sidecarRegistryUrl: 'https://sidecarregistry.example.org',
   274                      sidecarRegistryCredentialsId: 'mySidecarRegistryCredentials',
   275                  ]
   276              ]
   277          ]
   278          stepRule.step.dockerExecute(
   279              script: nullScript,
   280              dockerImage: 'maven:3.5-jdk-8-alpine',
   281              dockerRegistryCredentialsId: 'mySecrets',
   282              sidecarImage: 'ubuntu',
   283          ) {
   284              bodyExecuted = true
   285          }
   286          // not clear which image has been pulled with which registry, but at least
   287          // both registries are involved.
   288          assertThat(docker.registriesWithCredentials, is([
   289              [
   290                  registry: 'https://registry.example.org',
   291                  credentialsId: 'mySecrets',
   292              ],
   293              [
   294                  registry: 'https://sidecarregistry.example.org',
   295                  credentialsId: 'mySidecarRegistryCredentials',
   296              ]
   297          ]))
   298          assertThat(docker.imagePullCount, is(2))
   299          assertThat(bodyExecuted, is(true))
   300      }
   301  
   302      @Test
   303      void testPullSidecarWithSameCredentialsAndRegistryLikeBaseImageWhenNothingElseIsSpecified() {
   304          nullScript.commonPipelineEnvironment.configuration =
   305          [
   306              steps: [
   307                  dockerExecute: [
   308                      dockerRegistryUrl: 'https://registry.example.org',
   309                  ]
   310              ]
   311          ]
   312          stepRule.step.dockerExecute(
   313              script: nullScript,
   314              dockerImage: 'maven:3.5-jdk-8-alpine',
   315              dockerRegistryCredentialsId: 'mySecrets',
   316              sidecarImage: 'ubuntu',
   317          ) {
   318              bodyExecuted = true
   319          }
   320          // from getting an empty list we derive withRegistry has not been called
   321          // if it would have been called we would have the registry provided above.
   322          assertThat(docker.registriesWithCredentials, is([
   323              [
   324                  registry: 'https://registry.example.org',
   325                  credentialsId: 'mySecrets',
   326              ],
   327              [
   328                  registry: 'https://registry.example.org',
   329                  credentialsId: 'mySecrets',
   330              ],
   331          ]))
   332          assertThat(docker.imagePullCount, is(2))
   333          assertThat(bodyExecuted, is(true))
   334      }
   335  
   336      @Test
   337      void testPullWithRegistryOnlyAndNoCredentials() {
   338          nullScript.commonPipelineEnvironment.configuration =
   339          [
   340              steps: [
   341                  dockerExecute: [
   342                      dockerRegistryUrl: 'https://registry.example.org',
   343                  ]
   344              ]
   345          ]
   346          stepRule.step.dockerExecute(
   347              script: nullScript,
   348              dockerImage: 'maven:3.5-jdk-8-alpine'
   349          ) {
   350              bodyExecuted = true
   351          }
   352          // from getting an empty list we derive withRegistry has not been called
   353          // if it would have been called we would have the registry provided above.
   354          assertThat(docker.registriesWithCredentials, is([
   355              [
   356                  registry: 'https://registry.example.org',
   357              ]
   358          ]))
   359          assertThat(docker.imagePullCount, is(1))
   360          assertThat(bodyExecuted, is(true))
   361      }
   362  
   363      @Test
   364      void testPullWithCredentials() throws Exception {
   365  
   366          nullScript.commonPipelineEnvironment.configuration =
   367          [
   368              steps: [
   369                  dockerExecute: [
   370                      dockerRegistryUrl: 'https://registry.example.org',
   371                      dockerRegistryCredentialsId: 'mySecrets',
   372                  ]
   373              ]
   374          ]
   375          stepRule.step.dockerExecute(
   376              script: nullScript,
   377              dockerImage: 'maven:3.5-jdk-8-alpine'
   378          ) {
   379              bodyExecuted = true
   380          }
   381          assertThat(docker.registriesWithCredentials, is([
   382              [
   383                  registry: 'https://registry.example.org',
   384                  credentialsId: 'mySecrets',
   385              ]
   386          ]))
   387          assertThat(docker.imagePullCount, is(1))
   388          assertThat(bodyExecuted, is(true))
   389      }
   390  
   391      @Test
   392      void testSkipSidecarImagePull() throws Exception {
   393          stepRule.step.dockerExecute(
   394              script: nullScript,
   395              dockerName: 'maven',
   396              dockerImage: 'maven:3.5-jdk-8-alpine',
   397              sidecarEnvVars: ['testEnv': 'testVal'],
   398              sidecarImage: 'selenium/standalone-chrome',
   399              sidecarVolumeBind: ['/dev/shm': '/dev/shm'],
   400              sidecarName: 'testAlias',
   401              sidecarPorts: ['4444': '4444', '1111': '1111'],
   402              sidecarPullImage: false
   403          ) {
   404              bodyExecuted = true
   405          }
   406          assertThat(docker.imagePullCount, is(1))
   407          assertThat(bodyExecuted, is(true))
   408      }
   409  
   410      @Test
   411      void testExecuteInsideDockerContainerWithParameters() throws Exception {
   412          stepRule.step.dockerExecute(script: nullScript,
   413              dockerImage: 'maven:3.5-jdk-8-alpine',
   414              dockerOptions: '-description=lorem ipsum',
   415              dockerVolumeBind: ['my_vol': '/my_vol'],
   416              dockerEnvVars: ['http_proxy': 'http://proxy:8000']) {
   417              bodyExecuted = true
   418          }
   419          assertTrue(docker.getParameters().contains('--env https_proxy '))
   420          assertTrue(docker.getParameters().contains('--env http_proxy=http://proxy:8000'))
   421          assertTrue(docker.getParameters().contains('description=lorem\\ ipsum'))
   422          assertTrue(docker.getParameters().contains('--volume my_vol:/my_vol'))
   423          assertTrue(bodyExecuted)
   424      }
   425  
   426      @Test
   427      void testExecuteInsideDockerContainerWithDockerOptionsList() throws Exception {
   428          stepRule.step.dockerExecute(script: nullScript,
   429              dockerImage: 'maven:3.5-jdk-8-alpine',
   430              dockerOptions: ['-it', '--network=my-network', 'description=lorem ipsum'],
   431              dockerEnvVars: ['http_proxy': 'http://proxy:8000']) {
   432              bodyExecuted = true
   433          }
   434          assertTrue(docker.getParameters().contains('--env http_proxy=http://proxy:8000'))
   435          assertTrue(docker.getParameters().contains('-it'))
   436          assertTrue(docker.getParameters().contains('--network=my-network'))
   437          assertTrue(docker.getParameters().contains('description=lorem\\ ipsum'))
   438      }
   439  
   440      @Test
   441      void testDockerNotInstalledResultsInLocalExecution() throws Exception {
   442          shellRule.setReturnValue(JenkinsShellCallRule.Type.REGEX, "docker .*", 1)
   443          stepRule.step.dockerExecute(script: nullScript,
   444              dockerOptions: '-it') {
   445              bodyExecuted = true
   446          }
   447          assertTrue(loggingRule.log.contains('Cannot connect to docker daemon'))
   448          assertTrue(loggingRule.log.contains('Running on local environment'))
   449          assertTrue(bodyExecuted)
   450          assertFalse(docker.isImagePulled())
   451      }
   452  
   453      @Test
   454      void testSidecarDefault() {
   455          stepRule.step.dockerExecute(
   456              script: nullScript,
   457              dockerName: 'maven',
   458              dockerImage: 'maven:3.5-jdk-8-alpine',
   459              sidecarEnvVars: ['testEnv': 'testVal'],
   460              sidecarImage: 'selenium/standalone-chrome',
   461              sidecarVolumeBind: ['/dev/shm': '/dev/shm'],
   462              sidecarName: 'testAlias',
   463              sidecarPorts: ['4444': '4444', '1111': '1111']
   464          ) {
   465              bodyExecuted = true
   466          }
   467  
   468          assertThat(bodyExecuted, is(true))
   469          assertThat(docker.imagePullCount, is(2))
   470          assertThat(docker.sidecarParameters, allOf(
   471              containsString('--env testEnv=testVal'),
   472              containsString('--volume /dev/shm:/dev/shm'),
   473              containsString('--network sidecar-'),
   474              containsString('--network-alias testAlias')
   475          ))
   476          assertThat(docker.parameters, allOf(
   477              containsString('--network sidecar-'),
   478              containsString('--network-alias maven')
   479          ))
   480      }
   481  
   482      @Test
   483      void testSidecarHealthCheck() {
   484          stepRule.step.dockerExecute(
   485              script: nullScript,
   486              dockerImage: 'maven:3.5-jdk-8-alpine',
   487              sidecarImage: 'selenium/standalone-chrome',
   488              sidecarName: 'testAlias',
   489              sidecarReadyCommand: "isReady.sh"
   490          ) {}
   491          assertThat(shellRule.shell, hasItem("docker exec uniqueId isReady.sh"))
   492      }
   493  
   494      @Test
   495      void testSidecarKubernetes() {
   496          boolean dockerExecuteOnKubernetesCalled = false
   497          binding.setVariable('env', [ON_K8S: 'true'])
   498          helper.registerAllowedMethod('dockerExecuteOnKubernetes', [Map.class, Closure.class], { params, body ->
   499              dockerExecuteOnKubernetesCalled = true
   500              assertThat(params.dockerImage, is('maven:3.5-jdk-8-alpine'))
   501              assertThat(params.containerName, is('maven'))
   502              assertThat(params.sidecarEnvVars, is(['testEnv': 'testVal']))
   503              assertThat(params.sidecarName, is('selenium'))
   504              assertThat(params.sidecarImage, is('selenium/standalone-chrome'))
   505              assertThat(params.containerName, is('maven'))
   506              assertThat(params.containerPortMappings['selenium/standalone-chrome'], hasItem(allOf(hasEntry('containerPort', 4444), hasEntry('hostPort', 4444))))
   507              assertThat(params.dockerWorkspace, is('/home/piper'))
   508              body()
   509          })
   510          stepRule.step.dockerExecute(
   511              script: nullScript,
   512              containerPortMappings: [
   513                  'selenium/standalone-chrome': [[name: 'selPort', containerPort: 4444, hostPort: 4444]]
   514              ],
   515              dockerImage: 'maven:3.5-jdk-8-alpine',
   516              dockerName: 'maven',
   517              dockerWorkspace: '/home/piper',
   518              sidecarEnvVars: ['testEnv': 'testVal'],
   519              sidecarImage: 'selenium/standalone-chrome',
   520              sidecarName: 'selenium',
   521              sidecarVolumeBind: ['/dev/shm': '/dev/shm']
   522          ) {
   523              bodyExecuted = true
   524          }
   525          assertThat(bodyExecuted, is(true))
   526          assertThat(dockerExecuteOnKubernetesCalled, is(true))
   527      }
   528  
   529      @Test
   530      void testSidecarKubernetesHealthCheck() {
   531          binding.setVariable('env', [ON_K8S: 'true'])
   532  
   533          helper.registerAllowedMethod('dockerExecuteOnKubernetes', [Map.class, Closure.class], { params, body ->
   534              body()
   535              SidecarUtils sidecarUtils = new SidecarUtils(nullScript)
   536              sidecarUtils.waitForSidecarReadyOnKubernetes(params.sidecarName, params.sidecarReadyCommand)
   537          })
   538  
   539          def containerCalled = false
   540          helper.registerAllowedMethod('container', [Map.class, Closure.class], { params, body ->
   541              containerCalled = true
   542              assertThat(params.name, is('testAlias'))
   543              body()
   544          })
   545  
   546          stepRule.step.dockerExecute(
   547              script: nullScript,
   548              dockerImage: 'maven:3.5-jdk-8-alpine',
   549              sidecarImage: 'selenium/standalone-chrome',
   550              sidecarName: 'testAlias',
   551              sidecarReadyCommand: "isReady.sh"
   552          ) {}
   553  
   554          assertThat(containerCalled, is(true))
   555          assertThat(shellRule.shell, hasItem("isReady.sh"))
   556      }
   557  
   558      private class DockerMock {
   559          private List imageNames = []
   560          private boolean imagePulled = false
   561          private int imagePullCount = 0
   562          private String parameters
   563          private String sidecarParameters
   564          private List registriesWithCredentials = []
   565          private String credentialsId
   566  
   567          DockerMock image(String imageName) {
   568              this.imageNames << imageName
   569              return this
   570          }
   571  
   572          void pull() {
   573              imagePullCount++
   574              imagePulled = true
   575          }
   576  
   577          void withRegistry(String  registry, String credentialsId, Closure c) {
   578              this.registriesWithCredentials << [registry: registry, credentialsId: credentialsId]
   579              c()
   580          }
   581  
   582          void withRegistry(String  registry, Closure c) {
   583              this.registriesWithCredentials << [registry: registry]
   584              c()
   585          }
   586  
   587          void inside(String parameters, body) {
   588              this.parameters = parameters
   589              body()
   590          }
   591  
   592          void withRun(String parameters, body) {
   593              this.sidecarParameters = parameters
   594              body([id: 'uniqueId'])
   595          }
   596  
   597          def getImageNames() {
   598              return imageNames
   599          }
   600  
   601          boolean isImagePulled() {
   602              return imagePulled
   603          }
   604  
   605          String getParameters() {
   606              return parameters
   607          }
   608      }
   609  }