mirror of
https://github.com/SAP/jenkins-library.git
synced 2024-12-12 10:55:20 +02:00
Merge branch 'master' into pr/collectDependingOn
This commit is contained in:
commit
d207aeadd4
27
documentation/docs/steps/kanikoExecute.md
Normal file
27
documentation/docs/steps/kanikoExecute.md
Normal file
@ -0,0 +1,27 @@
|
||||
# ${docGenStepName}
|
||||
|
||||
## ${docGenDescription}
|
||||
|
||||
## Prerequsites
|
||||
|
||||
When pushing to a container registry, you need to maintain the respective credentials in your Jenkins credentials store:
|
||||
|
||||
Kaniko expects a Docker `config.json` file containing the credential information for registries.
|
||||
You can create it like explained in the Docker Success Center in the articale about [How to generate a new auth in the config.json file](https://success.docker.com/article/generate-new-auth-in-config-json-file).
|
||||
|
||||
Please copy this file and upload it to your Jenkins for example<br />
|
||||
via _Jenkins_ -> _Credentials_ -> _System_ -> _Global credentials (unrestricted)_ -> _ Add Credentials_ ->
|
||||
|
||||
* Kind: _Secret file_
|
||||
* File: upload your `config.json` file
|
||||
* ID: specify id which you then use for the configuration of `dockerConfigJsonCredentialsId` (see below)
|
||||
|
||||
## Example
|
||||
|
||||
```groovy
|
||||
kanikoExecute script:this
|
||||
```
|
||||
|
||||
## ${docGenParameters}
|
||||
|
||||
## ${docGenConfiguration}
|
@ -239,6 +239,15 @@ steps:
|
||||
healthEndpoint: ''
|
||||
influxWriteData:
|
||||
influxServer: ''
|
||||
kanikoExecute:
|
||||
containerBuildOptions: '--skip-tls-verify-pull'
|
||||
containerCommand: '/busybox/tail -f /dev/null'
|
||||
containerPreparationCommand: 'rm /kaniko/.docker/config.json'
|
||||
containerShell: '/busybox/sh'
|
||||
customTlsCertificateLinks: []
|
||||
dockerfile: Dockerfile
|
||||
dockerImage: 'gcr.io/kaniko-project/executor:debug'
|
||||
dockerOptions: "-u 0 --entrypoint=''"
|
||||
karmaExecuteTests:
|
||||
containerPortMappings:
|
||||
'node:8-stretch':
|
||||
|
143
test/groovy/KanikoExecuteTest.groovy
Normal file
143
test/groovy/KanikoExecuteTest.groovy
Normal file
@ -0,0 +1,143 @@
|
||||
#!groovy
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.ExpectedException
|
||||
import org.junit.rules.RuleChain
|
||||
import util.*
|
||||
|
||||
import static org.hamcrest.Matchers.*
|
||||
import static org.junit.Assert.assertThat
|
||||
|
||||
class KanikoExecuteTest extends BasePiperTest {
|
||||
private JenkinsStepRule stepRule = new JenkinsStepRule(this)
|
||||
private JenkinsShellCallRule shellRule = new JenkinsShellCallRule(this)
|
||||
private JenkinsReadFileRule readFileRule = new JenkinsReadFileRule(this, 'test/resources/kaniko/')
|
||||
private JenkinsWriteFileRule writeFileRule = new JenkinsWriteFileRule(this)
|
||||
private JenkinsDockerExecuteRule dockerExecuteRule = new JenkinsDockerExecuteRule(this)
|
||||
|
||||
@Rule
|
||||
public RuleChain rules = Rules
|
||||
.getCommonRules(this)
|
||||
.around(new JenkinsReadYamlRule(this))
|
||||
.around(shellRule)
|
||||
.around(readFileRule)
|
||||
.around(writeFileRule)
|
||||
.around(dockerExecuteRule)
|
||||
.around(stepRule)
|
||||
|
||||
def fileMap = [:]
|
||||
|
||||
@Before
|
||||
void init() {
|
||||
binding.variables.env.WORKSPACE = '/path/to/current/workspace'
|
||||
|
||||
helper.registerAllowedMethod('file', [Map], { m ->
|
||||
fileMap = m
|
||||
return m
|
||||
})
|
||||
|
||||
helper.registerAllowedMethod('withCredentials', [List, Closure], { l, c ->
|
||||
binding.setProperty(fileMap.variable, 'config.json')
|
||||
try {
|
||||
c()
|
||||
} finally {
|
||||
binding.setProperty(fileMap.variable, null)
|
||||
}
|
||||
})
|
||||
|
||||
UUID.metaClass.static.randomUUID = { -> 1}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDefaults() {
|
||||
stepRule.step.kanikoExecute(
|
||||
script: nullScript
|
||||
)
|
||||
assertThat(shellRule.shell, hasItem('#!/busybox/sh rm /kaniko/.docker/config.json'))
|
||||
assertThat(shellRule.shell, hasItem(allOf(
|
||||
startsWith('#!/busybox/sh'),
|
||||
containsString('mv 1-config.json /kaniko/.docker/config.json'),
|
||||
containsString('/kaniko/executor'),
|
||||
containsString('--dockerfile /path/to/current/workspace/Dockerfile'),
|
||||
containsString('--context /path/to/current/workspace'),
|
||||
containsString('--skip-tls-verify-pull'),
|
||||
containsString('--no-push')
|
||||
)))
|
||||
|
||||
assertThat(writeFileRule.files.values()[0], is('{"auths":{}}'))
|
||||
|
||||
assertThat(dockerExecuteRule.dockerParams, allOf(
|
||||
hasEntry('containerCommand', '/busybox/tail -f /dev/null'),
|
||||
hasEntry('containerShell', '/busybox/sh'),
|
||||
hasEntry('dockerImage', 'gcr.io/kaniko-project/executor:debug'),
|
||||
hasEntry('dockerOptions', "-u 0 --entrypoint=''")
|
||||
|
||||
))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCustomDockerCredentials() {
|
||||
stepRule.step.kanikoExecute(
|
||||
script: nullScript,
|
||||
dockerConfigJsonCredentialsId: 'myDockerConfigJson'
|
||||
)
|
||||
|
||||
assertThat(fileMap.credentialsId, is('myDockerConfigJson'))
|
||||
assertThat(writeFileRule.files.values()[0], allOf(
|
||||
containsString('docker.my.domain.com:4444'),
|
||||
containsString('"auth": "myAuth"'),
|
||||
containsString('"email": "my.user@domain.com"')
|
||||
))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCustomImage() {
|
||||
stepRule.step.kanikoExecute(
|
||||
script: nullScript,
|
||||
containerImageNameAndTag: 'my.docker.registry/path/myImageName:myTag'
|
||||
)
|
||||
|
||||
assertThat(shellRule.shell, hasItem(allOf(
|
||||
startsWith('#!/busybox/sh'),
|
||||
containsString('mv 1-config.json /kaniko/.docker/config.json'),
|
||||
containsString('/kaniko/executor'),
|
||||
containsString('--dockerfile /path/to/current/workspace/Dockerfile'),
|
||||
containsString('--context /path/to/current/workspace'),
|
||||
containsString('--skip-tls-verify-pull'),
|
||||
containsString('--destination my.docker.registry/path/myImageName:myTag')
|
||||
)))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPreserveDestination() {
|
||||
stepRule.step.kanikoExecute(
|
||||
script: nullScript,
|
||||
containerBuildOptions: '--destination my.docker.registry/path/myImageName:myTag'
|
||||
)
|
||||
|
||||
assertThat(shellRule.shell, hasItem(allOf(
|
||||
startsWith('#!/busybox/sh'),
|
||||
containsString('mv 1-config.json /kaniko/.docker/config.json'),
|
||||
containsString('/kaniko/executor'),
|
||||
containsString('--dockerfile /path/to/current/workspace/Dockerfile'),
|
||||
containsString('--context /path/to/current/workspace'),
|
||||
containsString('--destination my.docker.registry/path/myImageName:myTag')
|
||||
)))
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCustomCertificates() {
|
||||
stepRule.step.kanikoExecute(
|
||||
script: nullScript,
|
||||
customTlsCertificateLinks: ['http://link.one', 'http://link.two']
|
||||
)
|
||||
|
||||
assertThat(shellRule.shell, hasItem(allOf(
|
||||
startsWith('#!/busybox/sh'),
|
||||
containsString('rm /kaniko/.docker/config.json'),
|
||||
containsString('wget http://link.one -O - >> /kaniko/ssl/certs/ca-certificates.crt'),
|
||||
containsString('wget http://link.two -O - >> /kaniko/ssl/certs/ca-certificates.crt'),
|
||||
)))
|
||||
}
|
||||
}
|
8
test/resources/kaniko/config.json
Normal file
8
test/resources/kaniko/config.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"auths": {
|
||||
"docker.my.domain.com:4444": {
|
||||
"auth": "myAuth",
|
||||
"email": "my.user@domain.com"
|
||||
}
|
||||
}
|
||||
}
|
127
vars/kanikoExecute.groovy
Normal file
127
vars/kanikoExecute.groovy
Normal file
@ -0,0 +1,127 @@
|
||||
import groovy.text.GStringTemplateEngine
|
||||
|
||||
import static com.sap.piper.Prerequisites.checkScript
|
||||
|
||||
import com.sap.piper.GenerateDocumentation
|
||||
import com.sap.piper.ConfigurationHelper
|
||||
import com.sap.piper.Utils
|
||||
|
||||
import groovy.transform.Field
|
||||
|
||||
@Field def STEP_NAME = getClass().getName()
|
||||
|
||||
@Field Set GENERAL_CONFIG_KEYS = []
|
||||
@Field Set STEP_CONFIG_KEYS = [
|
||||
/**
|
||||
* Defines the build options for the [kaniko](https://github.com/GoogleContainerTools/kaniko) build.
|
||||
*/
|
||||
'containerBuildOptions',
|
||||
/** @see dockerExecute */
|
||||
'containerCommand',
|
||||
/** Defines the full name of the Docker image to be created including registry, image name and tag like `my.docker.registry/path/myImageName:myTag`.*/
|
||||
'containerImageNameAndTag',
|
||||
/** @see dockerExecute */
|
||||
'containerShell',
|
||||
/**
|
||||
* Defines the command to prepare the Kaniko container.
|
||||
* By default the contained credentials are removed in order to allow anonymous access to container registries.
|
||||
*/
|
||||
'containerPreparationCommand',
|
||||
/**
|
||||
* List containing download links of custom TLS certificates. This is required to ensure trusted connections to registries with custom certificates.
|
||||
*/
|
||||
'customTlsCertificateLinks',
|
||||
/**
|
||||
* Defines the location of the Dockerfile relative to the Jenkins workspace.
|
||||
*/
|
||||
'dockerfile',
|
||||
/**
|
||||
* Defines the id of the file credentials in your Jenkins credentials store which contain the file `.docker/config.json`.
|
||||
* You can find more details about the Docker credentials in the [Docker documentation](https://docs.docker.com/engine/reference/commandline/login/).
|
||||
*/
|
||||
'dockerConfigJsonCredentialsId',
|
||||
/** @see dockerExecute */
|
||||
'dockerEnvVars',
|
||||
/** @see dockerExecute */
|
||||
'dockerOptions',
|
||||
/** @see dockerExecute */
|
||||
'dockerImage'
|
||||
]
|
||||
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS
|
||||
|
||||
/**
|
||||
* Executes a [Kaniko](https://github.com/GoogleContainerTools/kaniko) build for creating a Docker container.
|
||||
*/
|
||||
@GenerateDocumentation
|
||||
void call(Map parameters = [:]) {
|
||||
handlePipelineStepErrors(stepName: STEP_NAME, stepParameters: parameters) {
|
||||
|
||||
final script = checkScript(this, parameters) ?: this
|
||||
|
||||
// load default & individual configuration
|
||||
Map config = ConfigurationHelper.newInstance(this)
|
||||
.loadStepDefaults()
|
||||
.mixinGeneralConfig(script.commonPipelineEnvironment, GENERAL_CONFIG_KEYS)
|
||||
.mixinStepConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS)
|
||||
.mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, STEP_CONFIG_KEYS)
|
||||
.mixin(parameters, PARAMETER_KEYS)
|
||||
.use()
|
||||
|
||||
new Utils().pushToSWA([
|
||||
step: STEP_NAME
|
||||
], config)
|
||||
|
||||
def buildOptions = new GStringTemplateEngine().createTemplate(config.containerBuildOptions).make([config: config, env: env]).toString()
|
||||
|
||||
if (!buildOptions.contains('--destination')) {
|
||||
if (config.containerImageNameAndTag) {
|
||||
buildOptions += " --destination ${config.containerImageNameAndTag}"
|
||||
} else {
|
||||
buildOptions += " --no-push"
|
||||
}
|
||||
}
|
||||
|
||||
dockerExecute(
|
||||
script: script,
|
||||
containerCommand: config.containerCommand,
|
||||
containerShell: config.containerShell,
|
||||
dockerEnvVars: config.dockerEnvVars,
|
||||
dockerImage: config.dockerImage,
|
||||
dockerOptions: config.dockerOptions
|
||||
) {
|
||||
// prepare kaniko container for running with proper Docker config.json and custom certificates
|
||||
// custom certificates will be downloaded and appended to ca-certificates.crt file used in container
|
||||
sh """#!${config.containerShell}
|
||||
${config.containerPreparationCommand}
|
||||
${getCertificateUpdate(config.customTlsCertificateLinks)}
|
||||
"""
|
||||
|
||||
def uuid = UUID.randomUUID().toString()
|
||||
if (config.dockerConfigJsonCredentialsId) {
|
||||
// write proper config.json with credentials
|
||||
withCredentials([file(credentialsId: config.dockerConfigJsonCredentialsId, variable: 'dockerConfigJson')]) {
|
||||
writeFile file: "${uuid}-config.json", text: readFile(dockerConfigJson)
|
||||
}
|
||||
} else {
|
||||
// empty config.json to allow anonymous authentication
|
||||
writeFile file: "${uuid}-config.json", text: '{"auths":{}}'
|
||||
}
|
||||
|
||||
// execute Kaniko
|
||||
sh """#!${config.containerShell}
|
||||
mv ${uuid}-config.json /kaniko/.docker/config.json
|
||||
/kaniko/executor --dockerfile ${env.WORKSPACE}/${config.dockerfile} --context ${env.WORKSPACE} ${buildOptions}"""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getCertificateUpdate(List certLinks) {
|
||||
String certUpdate = ''
|
||||
|
||||
if (!certLinks) return certUpdate
|
||||
|
||||
certLinks.each {link ->
|
||||
certUpdate += "wget ${link} -O - >> /kaniko/ssl/certs/ca-certificates.crt\n"
|
||||
}
|
||||
return certUpdate
|
||||
}
|
Loading…
Reference in New Issue
Block a user