Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Jenkinsfile.example
odsComponentPipeline(
imageStreamTag: 'ods/jenkins-agent-base:3.x'
) {
odsComponentStageImportOpenShiftImageOrElse(context) {
stage('Build') {
sh './gradlew build'
}
odsComponentStageBuildOpenShiftImage(context)
}
odsComponentStageRolloutOpenShiftDeployment(context)
withOpenShiftCluster('https://api.abc.com', 'foo-cd-cluster-abc-sa-credentials') {
odsComponentStageImportOpenShiftImage(context, [imagePullerSecret: 'xyz-image-puller'])
odsComponentStageRolloutOpenShiftDeployment(context)
}
}
// Three new methods to implement:
// Check if image is in a namespace from which it can be promoted.
// First, it searches for eligible namespaces by making use of a new pipeline option, 'imagePromotion',
// which defaults to ['dev->test', 'test->prod']. For example, if the target environment is 'test',
// eligible namespaces to promote from are 'dev' and 'test' (as the current namespace is always eligible).
// When an image for the commit we checked out exists in an eligible namespace, we call
// odsComponentStagePromoteImage. If the image does not exist, we execute the given closure.
odsComponentStageImportOpenShiftImageOrElse(IContext context, Map config = [:], Closure block)
// Promote image from namespace given in config. The config map takes an image name, a namespace
// to pull from, and optionally the name of an image puller secret. If that is given, that secret
// is read and an image pull across clusters is performed using the credentials in the secret.
odsComponentStageImportOpenShiftImage(IContext context, Map config = [:])
// Log into cluster identified by apiUrl using the credentials from serviceAccountCredentialsId,
// then execute given closure. The closure is wrapped in try/catch/finally, and in the finally
// block we log back into the current cluster.
withOpenShiftCluster(String apiUrl, String serviceAccountCredentialsId, Closure block)
// Advantages over current approach:
// - Images are promoted instead of rebuilt if the commit SHAs did not change.
// This requires to use 'git merge --ff-only' when merging (which is actually desirable anyway,
// as it prevents "loosing" commits in production)
// - Production namespace can be on another cluster
// - Multiple production namespaces on different clusters are possible
import org.ods.component.IContext
import org.ods.services.OpenShiftService
import org.ods.util.PipelineSteps
@SuppressWarnings('UnusedMethodParameter')
def call(IContext context, Map config = [:], Closure block) {
if (!config.apiUrl) {
error('''Param 'apiUrl' is required''')
}
if (!config.credentialsId) {
error('''Param 'credentialsId' is required''')
}
def steps = new PipelineSteps(this)
def currentApiUrl = OpenShiftService.getApiUrl(steps)
withCredentials([
usernamePassword(
credentialsId: config.credentialsId,
usernameVariable: 'OPENSHIFT_API_USER',
passwordVariable: 'OPENSHIFT_API_TOKEN'
)
]) {
def occuredException
try {
OpenShiftService.loginToExternalCluster(
steps, config.apiUrl, OPENSHIFT_API_TOKEN
)
block()
} catch (ex) {
occuredException = ex
} finally {
def tokenFile = '/var/run/secrets/kubernetes.io/serviceaccount/token'
OpenShiftService.loginToExternalCluster(
steps, currentApiUrl, readFile(tokenFile)
)
}
if (occuredException) {
throw occuredException
}
}
}
@renedupont

This comment has been minimized.

Copy link

renedupont commented Jul 1, 2020

  • Looks good! I saw an older blog entry about this topic where they used skopeo (at the very end of the article) but I think it should be able to work just with 'oc', right?

  • Did I understood the flow correctly?: in odsOnCluster we log into the cluster2 and pull the image from cluster1 and promote + deploy the image there. Wouldn't we need URL and secrets to login into cluster2 AND repo-URL + sa secret of cluster1 to pull the image from cluster1 while being logged into cluster2? Not sure if this is completly covered in your description and method heads or if I got this wrong?

  • minor thing: should odsOnCluster not rather be named odsComponentWithCluster, odsWithCluster or withOdsCluster?

@michaelsauter

This comment has been minimized.

Copy link
Owner Author

michaelsauter commented Jul 2, 2020

Thanks for reviewing.

  • We already have the import commands in the OpenShiftService and they work, so no need to use skopeo (though that certainly would also work)
  • String apiUrl, String serviceAccountCredentialsId give you the credentials of the "target cluster". the credentials / repo URL for the "source cluster" are stored inside a secret in the target cluster, which is referenced by the option imagePullerSecret.
  • Good point about the naming. I think that it should actually be named something ending in OpenShiftCluster now. So maybe withOpenShiftCluster? I would not use OdsCluster as no ODS needs to be installed in the target cluster, and I didn't use odsComponent as a prefix as it is pretty general - the method could be used in any context really.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.