Skip to content

Commit

Permalink
seleniumExecuteTests - add step to run Selenium tests (#318)
Browse files Browse the repository at this point in the history
It comes with an extension to executeDocker and executeDockerOnKubernetes to run sidecar containers.

This helps to execute Selenium tests using two Docker images:

1. Execution runtime for tests (e.g. node image)
2. Selenium instance which holds Selenium server + browser

* add documentation & some name cleanup
* include PR feedback
* add step documentation to structure
  • Loading branch information
OliverNocon committed Oct 4, 2018
1 parent d0d4cac commit 7a961ef
Show file tree
Hide file tree
Showing 12 changed files with 735 additions and 80 deletions.
Binary file added documentation/docs/images/k8s_env.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
90 changes: 75 additions & 15 deletions documentation/docs/steps/dockerExecute.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,73 @@

## Description

Executes a closure inside a docker container with the specified docker image.
Executes a closure inside a docker container with the specified docker image.
The workspace is mounted into the docker image.
Proxy environment variables defined on the Jenkins machine are also available in the Docker container.

## Parameters

| parameter | mandatory | default | possible values |
| -------------------|-----------|-----------------------------------|----------------------------|
| `script` | no | empty `globalPipelineEnvironment` | |
| `dockerImage` | no | '' | |
| `dockerEnvVars` | no | [:] | |
| `dockerOptions` | no | '' | |
| `dockerVolumeBind` | no | [:] | |
| parameter | mandatory | default | possible values |
| ----------|-----------|---------|-----------------|
|script|yes|||
|containerPortMappings|no|||
|dockerEnvVars|no|`[:]`||
|dockerImage|no|`''`||
|dockerName|no|||
|dockerOptions|no|`''`||
|dockerVolumeBind|no|`[:]`||
|dockerWorkspace|no|||
|jenkinsKubernetes|no|`[jnlpAgent:s4sdk/jenkins-agent-k8s:latest]`||
|sidecarEnvVars|no|||
|sidecarImage|no|||
|sidecarName|no|||
|sidecarOptions|no|||
|sidecarVolumeBind|no|||
|sidecarWorkspace|no|||

* `script` defines the global script environment of the Jenkinsfile run. Typically `this` is passed to this parameter. This allows the function to access the [`commonPipelineEnvironment`](commonPipelineEnvironment.md) for storing the measured duration.
* `dockerImage` Name of the docker image that should be used. If empty, Docker is not used.
* `dockerEnvVars` Environment variables to set in the container, e.g. [http_proxy:'proxy:8080']
* `containerPortMappings`: Map which defines per docker image the port mappings, like `containerPortMappings: ['selenium/standalone-chrome': [[name: 'selPort', containerPort: 4444, hostPort: 4444]]]`
* `dockerEnvVars`: Environment variables to set in the container, e.g. [http_proxy:'proxy:8080']
* `dockerImage`: Name of the docker image that should be used. If empty, Docker is not used and the command is executed directly on the Jenkins system.
* `dockerName`: only relevant for Kubernetes case: Name of the container launching `dockerImage`
* `dockerOptions` Docker options to be set when starting the container. It can be a list or a string.
* `dockerVolumeBind` Volumes that should be mounted into the container.
* `dockerWorkspace`: only relevant for Kubernetes case: specifies a dedicated user home directory for the container which will be passed as value for environment variable `HOME`
* `sidecarEnvVars` defines environment variables for the sidecar container, similar to `dockerEnvVars`
* `sidecarImage`: Name of the docker image of the sidecar container. Do not provide this value if no sidecar container is required.
* `sidecarName`: as `dockerName` for the sidecar container
* `sidecarOptions`: as `dockerOptions` for the sidecar container
* `sidecarVolumeBind`: as `dockerVolumeBind` for the sidecar container
* `sidecarWorkspace`: as `dockerWorkspace` for the sidecar container


## Kubernetes support
If the Jenkins is setup on a Kubernetes cluster, then you can execute the closure inside a container of a pod by setting an environment variable `ON_K8S` to `true`. However, it will ignore both `dockeOptions` and `dockerVolumeBind` values.
If the Jenkins is setup on a Kubernetes cluster, then you can execute the closure inside a container of a pod by setting an environment variable `ON_K8S` to `true`. However, it will ignore `containerPortMappings`, `dockerOptions` and `dockerVolumeBind` values.

## Step configuration
none

We recommend to define values of step parameters via [config.yml file](../configuration.md).

In following sections the configuration is possible:

| parameter | general | step | stage |
| ----------|-----------|---------|-----------------|
|script||||
|containerPortMappings||X|X|
|dockerEnvVars||X|X|
|dockerImage||X|X|
|dockerName||X|X|
|dockerOptions||X|X|
|dockerVolumeBind||X|X|
|dockerWorkspace||X|X|
|jenkinsKubernetes|X|||
|sidecarEnvVars||X|X|
|sidecarImage||X|X|
|sidecarName||X|X|
|sidecarOptions||X|X|
|sidecarVolumeBind||X|X|
|sidecarWorkspace||X|X|


## Return value
none
Expand All @@ -38,7 +79,7 @@ none
## Exceptions
none

## Example 1: Run closure inside a docker container
## Example 1: Run closure inside a docker container

```groovy
dockerExecute(dockerImage: 'maven:3.5-jdk-7'){
Expand All @@ -48,7 +89,7 @@ dockerExecute(dockerImage: 'maven:3.5-jdk-7'){
## Example 2: Run closure inside a container in a kubernetes pod

```sh
# set environment variable
# set environment variable
export ON_K8S=true"
```
Expand All @@ -58,7 +99,26 @@ dockerExecute(script: this, dockerImage: 'maven:3.5-jdk-7'){
}
```
In the above example, the `dockerEcecute` step will internally invoke [dockerExecuteOnKubernetes](dockerExecuteOnKubernetes.md) step and execute the closure inside a pod.
In the above example, the `dockerEcecute` step will internally invoke [dockerExecuteOnKubernetes](dockerExecuteOnKubernetes.md) step and execute the closure inside a pod.
## Example 3: Run closure inside a container which is attached to a sidecar container (as for example used in [seleniumExecuteTests](seleniumExecuteTests.md):
```groovy
dockerExecute(
script: script,
containerPortMappings: [containerPortMappings:'selenium/standalone-chrome':[containerPort: 4444, hostPort: 4444]],
dockerImage: 'node:8-stretch',
dockerName: 'node',
dockerWorkspace: '/home/node',
sidecarImage: 'selenium/standalone-chrome',
sidecarName: 'selenium',
) {
git url: 'https://github.wdf.sap.corp/XXXXX/WebDriverIOTest.git'
sh '''npm install
node index.js
'''
}
```
Expand Down
89 changes: 71 additions & 18 deletions documentation/docs/steps/dockerExecuteOnKubernetes.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,64 @@

Executes a closure inside a container in a kubernetes pod. Proxy environment variables defined on the Jenkins machine are also available in the container.

## Prerequisites
## Prerequisites
* The Jenkins should be running on kubernetes.
* An environment variable `ON_K8S` should be created on Jenkins and initialized to `true`.

* An environment variable `ON_K8S` should be created on Jenkins and initialized to `true`. This could for example be done via _Jenkins_ - _Manage Jenkins_ - _Configure System_ - _Global properties_ - _Environment variables_

![Jenkins environment variable configuration](../images/k8s_env.png)

## Parameters

| parameter | mandatory | default | possible values |
| -------------------|-----------|-----------------------------------|----------------------------|
| `script` | no | empty `globalPipelineEnvironment` | |
| `dockerImage` | yes | | |
| `dockerEnvVars` | no | [:] | |
| `dockerWorkspace` | no | '' | |
| `containerMap` | no | [:] | |
| parameter | mandatory | default | possible values |
| ----------|-----------|---------|-----------------|
|script|yes|||
|containerCommands|no|||
|containerEnvVars|no|||
|containerMap|no|`[:]`||
|containerName|no|||
|containerPortMappings|no|||
|containerWorkspaces|no|||
|dockerEnvVars|no|`[:]`||
|dockerImage|yes|||
|dockerWorkspace|no|`''`||
|jenkinsKubernetes|no|`[jnlpAgent:s4sdk/jenkins-agent-k8s:latest]`||
|stashExcludes|no|`[workspace:nohup.out]`||
|stashIncludes|no|`[workspace:**/*.*]`||

* `script` defines the global script environment of the Jenkins file run. Typically `this` is passed to this parameter. This allows the function to access the [`commonPipelineEnvironment`](commonPipelineEnvironment.md) for storing the measured duration.
* `containerCommands` specifies start command for containers to overwrite Piper default (`/usr/bin/tail -f /dev/null`). If container's defaultstart command should be used provide empty string like: `['selenium/standalone-chrome': '']`.
* `containerEnvVars` specifies environment variables per container. If not provided `dockerEnvVars` will be used.
* `containerMap` A map of docker image to the name of the container. The pod will be created with all the images from this map and they are labled based on the value field of each map entry.
Example: `['maven:3.5-jdk-8-alpine': 'mavenExecute', 'selenium/standalone-chrome': 'selenium', 'famiko/jmeter-base': 'checkJMeter', 's4sdk/docker-cf-cli': 'cloudfoundry']`

* `containerName`: optional configuration in combination with containerMap to define the container where the commands should be executed in
* `containerPortMappings`: Map which defines per docker image the port mappings, like `containerPortMappings: ['selenium/standalone-chrome': [[name: 'selPort', containerPort: 4444, hostPort: 4444]]]`
* `containerWorkspaces` specifies workspace (=home directory of user) per container. If not provided `dockerWorkspace` will be used. If empty, home directory will not be set.
* `dockerImage` Name of the docker image that should be used. If empty, Docker is not used.
* `dockerEnvVars` Environment variables to set in the container, e.g. [http_proxy:'proxy:8080']
* `dockerWorkspace` Docker options to be set when starting the container. It can be a list or a string.
* `containerMap` A map of docker image to the name of the container. The pod will be created with all the images from this map and they are labled based on the value field of each map entry.
Ex `['maven:3.5-jdk-8-alpine': 'mavenExecute', 'famiko/jmeter-base': 'checkJMeter', 's4sdk/docker-cf-cli': 'cloudfoundry']`

## Step configuration
none

We recommend to define values of step parameters via [config.yml file](../configuration.md).

In following sections the configuration is possible:

| parameter | general | step | stage |
| ----------|-----------|---------|-----------------|
|script||||
|containerCommands||X|X|
|containerEnvVars||X|X|
|containerMap||X|X|
|containerName||X|X|
|containerPortMappings||X|X|
|containerWorkspaces||X|X|
|dockerEnvVars||X|X|
|dockerImage||X|X|
|dockerWorkspace||X|X|
|jenkinsKubernetes|X|||
|stashExcludes||X|X|
|stashIncludes||X|X|

## Return value
none
Expand All @@ -39,36 +74,54 @@ none

## Example 1: Run a closure in a single container pod
```sh
# set environment variable
# set environment variable
export ON_K8S=true"
```
```groovy
dockerExecuteOnKubernetes(script: script, dockerImage: 'maven:3.5-jdk-7'){
sh "mvn clean install"
sh "mvn clean install"
}
```
In the above example, a pod will be created with a docker container of image `maven:3.5-jdk-7`. The closure will be then executed inside the container.
## Example 2: Run a closure in a multi-container pod
```sh
# set environment variable
# set environment variable
export ON_K8S=true"
```

```groovy
dockerExecuteOnKubernetes(script: script, containerMap: ['maven:3.5-jdk-8-alpine': 'maven', 's4sdk/docker-cf-cli': 'cfcli']){
container('maven'){
sh "mvn clean install"
sh "mvn clean install"
}
container('cfcli'){
sh "cf plugins"
}
}
```

In the above example, a pod will be created with multiple Docker containers that are passed as a `containerMap`. The containers can be chosen for executing by referring their labels as shown in the example.
In the above example, a pod will be created with multiple Docker containers that are passed as a `containerMap`. The containers can be chosen for executing by referring their labels as shown in the example.

## Example 3: Running a closure in a dedicated container of a multi-container pod

```sh
# set environment variable
export ON_K8S=true"
```
```groovy
dockerExecuteOnKubernetes(
script: script,
containerCommands: ['selenium/standalone-chrome': ''],
containerMap: ['maven:3.5-jdk-8-alpine': 'maven', 'selenium/standalone-chrome': 'selenium'],
containerName: 'maven',
containerPortMappings: ['selenium/standalone-chrome': [containerPort: 4444, hostPort: 4444]]
containerWorkspaces: ['selenium/standalone-chrome': '']
){
echo "Executing inside a Kubernetes Pod inside 'maven' container to run Selenium tests"
sh "mvn clean install"
}
```
Loading

0 comments on commit 7a961ef

Please sign in to comment.