Skip to content

Instantly share code, notes, and snippets.

@michaelsauter
Last active July 6, 2020 09:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save michaelsauter/6b1f70eb3a6d544de0198fcd08b4ed83 to your computer and use it in GitHub Desktop.
Save michaelsauter/6b1f70eb3a6d544de0198fcd08b4ed83 to your computer and use it in GitHub Desktop.
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
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
Copy link
Author

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