Skip to content

Commit

Permalink
Avoid configuration resolution during project configuration (#82)
Browse files Browse the repository at this point in the history
  • Loading branch information
henryptung authored and uschi2000 committed Dec 6, 2016
1 parent 5e491ea commit 39d5caf
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,41 +17,31 @@ package com.palantir.gradle.docker

import org.gradle.api.Project

import com.google.common.base.Preconditions

class DockerComposeExtension {
Project project

private String template = 'docker-compose.yml.template'
private String dockerComposeFile = 'docker-compose.yml'
private Project project

private File resolvedDockerComposeTemplate = null
private File resolvedDockerComposeFile = null
private File template
private File dockerComposeFile

public DockerComposeExtension(Project project) {
this.project = project
this.template = project.file('docker-compose.yml.template')
this.dockerComposeFile = project.file('docker-compose.yml')
}

public void setTemplate(String dockerComposeTemplate) {
this.template = dockerComposeTemplate
Preconditions.checkArgument(project.file(dockerComposeTemplate).exists(),
"Could not find specified template file: %s", project.file(dockerComposeTemplate))
}

public void setDockerComposeFile(String dockerComposeFile) {
this.dockerComposeFile = dockerComposeFile
public void setTemplate(Object dockerComposeTemplate) {
this.template = project.file(dockerComposeTemplate)
}

File getResolvedDockerComposeTemplate() {
return resolvedDockerComposeTemplate
public void setDockerComposeFile(Object dockerComposeFile) {
this.dockerComposeFile = project.file(dockerComposeFile)
}

File getResolvedDockerComposeFile() {
return resolvedDockerComposeFile
File getTemplate() {
return template
}

public void resolvePathsAndValidate() {
resolvedDockerComposeFile = project.file(dockerComposeFile)
resolvedDockerComposeTemplate = project.file(template)
File getDockerComposeFile() {
return dockerComposeFile
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,53 +17,18 @@ package com.palantir.gradle.docker

import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.Copy

import com.google.common.base.Preconditions
import org.gradle.api.artifacts.Configuration

class DockerComposePlugin implements Plugin<Project> {
@Override
void apply(Project project) {
DockerComposeExtension ext =
project.extensions.create('dockerCompose', DockerComposeExtension, project)
if (!project.configurations.findByName('docker')) {
project.configurations.create('docker')
}
Configuration dockerConfiguration = project.configurations.maybeCreate('docker')

Copy generateDockerCompose = project.tasks.create('generateDockerCompose', Copy, {
description = 'Populates docker-compose.yml.template file with image versions specified by "docker" ' +
'dependencies'
project.tasks.create('generateDockerCompose', GenerateDockerCompose, {
it.ext = ext
it.configuration = dockerConfiguration
})

project.afterEvaluate {
ext.resolvePathsAndValidate()
if (ext.resolvedDockerComposeTemplate.exists()) {
def dockerDependencies = project.configurations.docker.resolvedConfiguration.resolvedArtifacts
def templateTokens = dockerDependencies.collectEntries {
def version = it.moduleVersion.id
[("{{${version.group}:${version.name}}}"): version.version]
}

generateDockerCompose.with {
from(ext.resolvedDockerComposeTemplate)
into(ext.resolvedDockerComposeFile.parentFile)
rename { fileName ->
fileName.replace(
ext.resolvedDockerComposeTemplate.name, ext.resolvedDockerComposeFile.name)
}
filter { String line -> replaceAll(line, templateTokens, ext) }
}
}
}
}

/** Replaces all occurrences of templatesTokens's keys by their corresponding values in the given line. */
static def replaceAll(String line, Map<String, String> templateTokens, DockerComposeExtension ext) {
templateTokens.each { mapping -> line = line.replace(mapping.key, mapping.value) }
def unmatchedTokens = line.findAll(/\{\{.*\}\}/)
Preconditions.checkState(unmatchedTokens.size() == 0,
"Failed to resolve Docker dependencies declared in %s: %s. Known dependencies: %s",
ext.resolvedDockerComposeTemplate, unmatchedTokens, templateTokens)
return line
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.palantir.gradle.docker

import com.google.common.base.Preconditions
import groovy.transform.Memoized
import groovy.util.logging.Slf4j
import org.gradle.api.DefaultTask
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ModuleVersionIdentifier
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction

@Slf4j
class GenerateDockerCompose extends DefaultTask {

DockerComposeExtension ext
Configuration configuration

GenerateDockerCompose() {
group = 'Docker'
}

@TaskAction
void run() {
if (!template.file) {
throw new IllegalStateException("Could not find specified template file ${template.file}")
}
def templateTokens = moduleDependencies.collectEntries {
[("{{${it.group}:${it.name}}}"): it.version]
}

dockerComposeFile.withPrintWriter { writer ->
template.eachLine { line ->
writer.println this.replaceAll(line, templateTokens)
}
}
}

@Override
String getDescription() {
def defaultDescription = "Populates ${ext.template.name} file with versions" +
" of dependencies from the '${configuration.name}' configuration"
return super.description ?: defaultDescription
}

@Input
@Memoized
Set<ModuleVersionIdentifier> getModuleDependencies() {
log.info "Resolving Docker template dependencies from configuration ${configuration.name}..."
return configuration.resolvedConfiguration
.resolvedArtifacts
*.moduleVersion
*.id
.toSet()
}

@InputFiles
File getTemplate() {
return ext.template
}

@OutputFile
File getDockerComposeFile() {
return ext.dockerComposeFile
}

/** Replaces all occurrences of templatesTokens's keys by their corresponding values in the given line. */
// Protected to work around GRADLE-1439
protected String replaceAll(String line, Map<String, String> templateTokens) {
templateTokens.each { mapping -> line = line.replace(mapping.key, mapping.value) }
def unmatchedTokens = line.findAll(/\{\{.*\}\}/)
Preconditions.checkState(unmatchedTokens.size() == 0,
"Failed to resolve Docker dependencies declared in %s: %s. Known dependencies: %s",
template, unmatchedTokens, templateTokens)
return line
}
}

0 comments on commit 39d5caf

Please sign in to comment.