Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/unit test openshift apply #42

Merged
merged 1 commit into from
Nov 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
.idea/
.gradle
target
bin
.classpath
.settings
.project
jenkins-pipeline-shared-libraries.iml
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,7 @@ File: [src/com/puzzleitc/jenkins/DockerHub.groovy](src/com/puzzleitc/jenkins/Doc

Tests can be executed with `./gradlew clean test`

Documentation for the test framework can be found here: <https://github.com/ExpediaGroup/jenkins-spock>
Source: [src/com/puzzleitc/jenkins/DockerHub.groovy](src/com/puzzleitc/jenkins/DockerHub.groovy)
* Documentation for the spock test framework can be found here: <https://spockframework.org/>
* Documentation for the Jenkins test framework can be found here: <https://github.com/ExpediaGroup/jenkins-spock>
* [JenkinsPipelineSpecification](https://www.javadoc.io/doc/com.homeaway.devtools.jenkins/jenkins-spock/2.0.1/com/homeaway/devtools/jenkins/testing/JenkinsPipelineSpecification.html)
* Source: [src/com/puzzleitc/jenkins/DockerHub.groovy](src/com/puzzleitc/jenkins/DockerHub.groovy)
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ dependencies {
testImplementation "org.jenkins-ci.plugins.workflow:workflow-scm-step:2.11@jar" // provides checkout()
testImplementation "org.jenkins-ci.plugins:credentials-binding:1.20@jar" // provides withCredentials() step
testImplementation "org.jenkins-ci.plugins:script-security:1.68@jar"
testImplementation "com.openshift.jenkins.plugins:openshift-client:1.0.35@jar"
testImplementation "org.jenkins-ci.plugins:ansicolor:0.5.2@jar"
}

// this is needed for spock to find all the source code in the var directory
Expand Down
207 changes: 207 additions & 0 deletions test/groovy/vars/OpenshiftApplySpec.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
package groovy.vars

import com.homeaway.devtools.jenkins.testing.JenkinsPipelineSpecification
import groovy.json.JsonSlurper

class OpenshiftApplySpec extends JenkinsPipelineSpecification {

def openshiftApply = loadPipelineScriptForTest('vars/openshiftApply.groovy')

def setup() {
explicitlyMockPipelineStep('executable')
}

def 'it should fail when parameter is not set'(args) {

when:
openshiftApply.call(args)

then:
1 * getPipelineMock("echo").call({ it.contains("missing required step parameter: '${args.missing}'") })
1 * getPipelineMock("error").call('Build failed') >> { throw new RuntimeException() }
thrown(RuntimeException)

where:
args << [[project : "myproject",
appLabel: "label",
missing : "configuration"],
[configuration: "configuration",
appLabel : "label",
missing : "project"],
[project : "myproject",
configuration: "configuration",
missing : "appLabel"]]

}

def 'it calls install oc_3_11 tool and oc convert'(args) {

def output = '{ "operation": "describe", "actions": [ { "err": "", "verb": "describe", "cmd": "oc --server=https://openshift.openshift.com --insecure-skip-tls-verify --namespace=myproject --token=XXXXX", "out": "Name: test-app\\nNamespace: myproject\\nLabels: pp=label\\nSelector: app=label", "status": 0 } ], "status": 0}'
output = new JsonSlurper().parseText(output)

setup:
openshiftApply.getBinding().setVariable('env', [:])
openshiftApply.getBinding().setVariable('secretValue', 'dGVzdA==')

when:
openshiftApply.call(args)

then:
2 * getPipelineMock('sh').call({ ['script': 'command -v oc', 'returnStatus': 'true'] }) >> 1
1 * getPipelineMock('executable').call(['name': 'oc', 'toolName': 'oc_3_11']) >> '/path/bin'
1 * getPipelineMock('openshift.raw').call('whoami') >> [out: "jenkins"]
1 * getPipelineMock('openshift.raw').call(['convert', '-f', 'null/temp.yaml']) >> [actions: [[cmd: "oc --server=https://openshift.puzzle.ch --insecure-skip-tls-verify --namespace=pitc-jenkinscicd-prod --token=XXXXX convert -f /var/lib/jenkins/workspace/sgilgen/shared-library-test/1636550271093/temp.yaml"]]]
1 * getPipelineMock('openshift.apply').call([args.configuration, '-l', 'app=label', '--prune']) >> output

where:
args << [[configuration : "[ { apiVersion: 'extensions/v1beta1', kind: 'Deployment', spec: { template: { spec: { containers: [ { name: 'mycontainer', }, ], }, }, }, }, ]",
project : "myproject",
cluster : "oc4-test-cluster",
appLabel : "label",
waitForRollout: false]]

}

def 'it should not call oc validate for oc4'(args) {

def output = '{ "operation": "describe", "actions": [ { "err": "", "verb": "describe", "cmd": "oc --server=https://openshift.openshift.com --insecure-skip-tls-verify --namespace=myproject --token=XXXXX", "out": "Name: test-app\\nNamespace: myproject\\nLabels: pp=label\\nSelector: app=label", "status": 0 } ], "status": 0}'
output = new JsonSlurper().parseText(output)

setup:
openshiftApply.getBinding().setVariable('env', [:])
openshiftApply.getBinding().setVariable('secretValue', 'dGVzdA==')

when:
openshiftApply.call(args)

then:
1 * getPipelineMock('sh')({ [script: 'command -v oc', returnStatus: true] }) >> 0
1 * getPipelineMock('sh')(_) >> { _arguments ->
assert '#!/bin/sh -e\noc version -o json >/dev/null 2>&1' == _arguments[0]['script']
assert true == _arguments[0]['returnStatus']
return 0
}
1 * getPipelineMock('openshift.raw').call('whoami') >> [out: "jenkins"]
1 * getPipelineMock('openshift.raw')(_) >> { _arguments ->
assert 'apply' == _arguments[0][0]
assert '-f' == _arguments[0][1]
assert 'null/temp.yaml' == _arguments[0][2]
assert '--dry-run=server' == _arguments[0][3]
return [actions: [[cmd: "oc --server=https://openshift.openshift.com --insecure-skip-tls-verify --namespace=myproject --token=XXXXX apply -f /temp.yaml"]]]
}
1 * getPipelineMock('openshift.apply').call([args.configuration, '-l', 'app=label', '--prune']) >> output

where:
args << [[configuration : "[ { apiVersion: 'extensions/v1beta1', kind: 'Deployment', spec: { template: { spec: { containers: [ { name: 'mycontainer', }, ], }, }, }, }, ]",
project : "myproject",
cluster : "oc4-test-cluster",
appLabel : "label",
waitForRollout: false]]

}

def 'it should wait for rollout with default selector'(args) {

def output = '{ "operation": "describe", "actions": [ { "err": "", "verb": "describe", "cmd": "oc --server=https://openshift.openshift.com --insecure-skip-tls-verify --namespace=myproject --token=XXXXX", "out": "Name: test-app\\nNamespace: myproject\\nLabels: pp=label\\nSelector: app=label", "status": 0 } ], "status": 0}'
output = new JsonSlurper().parseText(output)

// mock RolloutManager
def myRollout = Mock(RolloutManager)
// mock Selector to return the RolloutManager mock and check the method is called once
def mySelector = Mock(Selector) {
1 * rollout() >> myRollout
}

setup:
openshiftApply.getBinding().setVariable('env', [:])
openshiftApply.getBinding().setVariable('secretValue', 'dGVzdA==')

when:
openshiftApply.call(args)

then:
1 * getPipelineMock('sh')({ [script: 'command -v oc', returnStatus: true] }) >> 0
1 * getPipelineMock('sh')(_) >> { _arguments ->
assert '#!/bin/sh -e\noc version -o json >/dev/null 2>&1' == _arguments[0]['script']
assert true == _arguments[0]['returnStatus']
return 0
}
1 * getPipelineMock('openshift.raw').call('whoami') >> [out: "jenkins"]
1 * getPipelineMock('openshift.raw').call(['apply', '-f', 'null/temp.yaml', '--dry-run=server']) >> [actions: [[cmd: "oc --server=https://openshift.openshift.com --insecure-skip-tls-verify --namespace=myproject --token=XXXXX apply -f /temp.yaml"]]]
1 * getPipelineMock('openshift.apply').call([args.configuration, '-l', 'app=label', '--prune']) >> output
1 * getPipelineMock('echo')("waiting for 'deployment' with selector 'label' to be rolled out")
1 * getPipelineMock('openshift.selector')(_) >> { _arguments ->
assert 'deployment' == _arguments[0][0]
assert 'label' == _arguments[0][1]
return mySelector // the Selector mock returning the RolloutManager mock on the rollout method
}

where:
args << [[configuration : "[ { apiVersion: 'extensions/v1beta1', kind: 'Deployment', spec: { template: { spec: { containers: [ { name: 'mycontainer', }, ], }, }, }, }, ]",
project : "myproject",
cluster : "oc4-test-cluster",
appLabel : "label",
rolloutKind : "deployment",
waitForRollout: true]]

}

def 'it should wait for rollout with rolloutSelector'(args) {

def output = '{ "operation": "describe", "actions": [ { "err": "", "verb": "describe", "cmd": "oc --server=https://openshift.openshift.com --insecure-skip-tls-verify --namespace=myproject --token=XXXXX", "out": "Name: test-app\\nNamespace: myproject\\nLabels: pp=label\\nSelector: app=label", "status": 0 } ], "status": 0}'
output = new JsonSlurper().parseText(output)

// mock RolloutManager
def myRollout = Mock(RolloutManager)
// mock Selector to return the RolloutManager mock and check the method is called once
def mySelector = Mock(Selector) {
1 * rollout() >> myRollout
}

setup:
openshiftApply.getBinding().setVariable('env', [:])
openshiftApply.getBinding().setVariable('secretValue', 'dGVzdA==')

when:
openshiftApply.call(args)

then:
1 * getPipelineMock('sh')({ [script: 'command -v oc', returnStatus: true] }) >> 0
1 * getPipelineMock('sh')(_) >> { _arguments ->
assert '#!/bin/sh -e\noc version -o json >/dev/null 2>&1' == _arguments[0]['script']
assert true == _arguments[0]['returnStatus']
return 0
}
1 * getPipelineMock('openshift.raw').call('whoami') >> [out: "jenkins"]
1 * getPipelineMock('openshift.raw').call(['apply', '-f', 'null/temp.yaml', '--dry-run=server']) >> [actions: [[cmd: "oc --server=https://openshift.openshift.com --insecure-skip-tls-verify --namespace=myproject --token=XXXXX apply -f /temp.yaml"]]]
1 * getPipelineMock('openshift.apply').call([args.configuration, '-l', 'app=label', '--prune']) >> output
1 * getPipelineMock('echo')("waiting for 'deployment' with selector [test:selector] to be rolled out")
1 * getPipelineMock('openshift.selector')(_) >> { _arguments ->
assert 'deployment' == _arguments[0][0]
assert [test: 'selector'] == _arguments[0][1]
return mySelector // the Selector mock returning the RolloutManager mock on the rollout method
}

where:
args << [[configuration : "[ { apiVersion: 'extensions/v1beta1', kind: 'Deployment', spec: { template: { spec: { containers: [ { name: 'mycontainer', }, ], }, }, }, }, ]",
project : "myproject",
cluster : "oc4-test-cluster",
appLabel : "label",
rolloutKind : "deployment",
waitForRollout: true,
rolloutSelector: [test: 'selector']
]]
}


}

// Interface used to mock openshift Selector
interface Selector {
def rollout()
}

// Interface used to mock openshift RolloutManager
interface RolloutManager {
def status()
}
2 changes: 0 additions & 2 deletions test/groovy/vars/OpenshiftProcessSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ class OpenshiftProcessSpec extends JenkinsPipelineSpecification {
def openshiftProcess = loadPipelineScriptForTest('vars/openshiftProcess.groovy')

def setup() {
explicitlyMockPipelineStep('ansiColor')
explicitlyMockPipelineStep('executable')
explicitlyMockPipelineStep('fail')
}

def 'it should fail when templateFilePath is not set'() {
Expand Down