问题描述:

I am trying to write my owns task types that orchestrate the tasks found in an existing plugin. I need to create a workflow for populating a few dozen docker images into a private repo in a way that they are correctly layered and the entire hierarchy can be rebuilt in one step.

I could rip out the logic from the plugin for my own tasks / execute the log directly somehow but it should be possible to compose tasks right ?

See stub below, I am naively trying to create a task within my task class constructor and creating a dependency on it. I know the constructor is not the right place as DI injection has not yet occurred.

class DockerRebaseImage extends DefaultTask {

@Input

def sourceImageName

@Input

def targetImageName

@Input

def targetRegistry

@Input

def tag

// 1. validate: ensure source image name does contain a tag, ensure tag is not latest.

// 2. pull source image.

// 3. retag source image for remote repo. <repository-name>:<tag> and <repository-name>:latest

// 4. push both tags.

DockerRebaseImage() {

def ensureExists = project.tasks.create(name: "ensureExists", type: DockerPullImage)

this.shouldRunAfter(ensureExists)

}

@TaskAction

def doRebase() {

println "rebasing image"

}

}

In this example I am composing 5 or so tasks -- I'd like to ensure the child tasks are anonymous / hidden otherwise at the end of the day I am going to end up with 500 tasks showing up in IDE's / the command line.


Here is my current solution, it's a start.I can't pipeline the subtasks --e.g., If I reorganise the code so that a push dependsOn tag tag never executes. I'll need to add some checks to short circuit the task --e.g., if remote images exist don't run the task or it's not going to scale.

class DockerHelper {

Project project

Object dockerClient

def ensureExists(repo, tag) {

def t = project.tasks.create("ensureExists\$$repo:$tag", DockerPullImage)

t.repository = repo

t.tag = tag

t.runRemoteCommand(dockerClient)

}

def push(image) {

def t = project.tasks.create("push\$$image", DockerPushImage)

t.imageName = image

t.runRemoteCommand(dockerClient)

}

def tagImage(source, target, tag) {

def t = project.tasks.create("tag\$${source}To\$$target:$tag", DockerTagImage)

t.imageId = source

t.repository = target

t.tag = tag

t.runRemoteCommand(dockerClient)

}

def tagPush(source, target,tag) {

tagImage(source, target, tag)

push("$target:$tag")

}

}

class DockerRebaseImage extends AbstractDockerRemoteApiTask {

@Input

def sourceImageName

@Input

def targetImageName

@Input

def targetRegistry

@Input

def tag

@Override

void runRemoteCommand(Object dockerClient) {

def helper = new DockerHelper(dockerClient: dockerClient, project: project)

if(sourceImageName.contains(":"))

throw new TaskInstantiationException("source image should not have a tag supplied explicetly.")

if(tag == "latest")

throw new TaskInstantiationException("rebasing a remote image should not occur off latest.")

helper.ensureExists(sourceImageName, tag)

helper.tagPush("$sourceImageName:$tag", "$targetRegistry/$targetImageName", tag)

helper.tagPush("$sourceImageName:$tag", "$targetRegistry/$targetImageName", "latest")

}

}


edit to silence SO. I don't need to explain why the linked question isn't the solution, it might be part of the solution but it isn't the solution.

相关阅读:
Top