Skip to content

Commit aaa5db4

Browse files
committed
Initial support for rocket
1 parent d31abaa commit aaa5db4

File tree

4 files changed

+468
-114
lines changed

4 files changed

+468
-114
lines changed

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@
112112
</profiles>
113113

114114
<dependencies>
115+
<dependency>
116+
<groupId>com.coreos</groupId>
117+
<artifactId>appc</artifactId>
118+
<version>0.1.0-SNAPSHOT</version>
119+
</dependency>
120+
115121
<dependency>
116122
<groupId>com.spotify</groupId>
117123
<artifactId>docker-client</artifactId>
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/*
2+
* Copyright (c) 2015 CoreOS Inc.
3+
*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
22+
package com.coreos.appc.docker;
23+
24+
import static com.google.common.base.CharMatcher.WHITESPACE;
25+
import static java.nio.charset.StandardCharsets.UTF_8;
26+
27+
import java.io.IOException;
28+
import java.nio.file.Files;
29+
import java.nio.file.Path;
30+
import java.nio.file.Paths;
31+
import java.nio.file.StandardCopyOption;
32+
import java.nio.file.attribute.FileTime;
33+
import java.util.Collections;
34+
import java.util.List;
35+
36+
import com.coreos.appc.ContainerBuilder;
37+
import com.coreos.appc.ContainerFile;
38+
import com.google.common.base.Joiner;
39+
import com.google.common.base.Splitter;
40+
import com.google.common.collect.ImmutableList;
41+
import com.google.common.collect.Lists;
42+
import com.google.common.collect.Ordering;
43+
import com.spotify.docker.client.AnsiProgressHandler;
44+
import com.spotify.docker.client.DockerClient;
45+
46+
public class DockerContainerBuilder extends ContainerBuilder {
47+
final DockerClient docker;
48+
final String dockerBuildDir;
49+
final List<String> addFiles = Lists.newArrayList();
50+
51+
/**
52+
* Set to override the auto-generated dockerfile
53+
*/
54+
public Path dockerfile;
55+
56+
public DockerContainerBuilder(DockerClient docker, String dockerBuildDir) {
57+
this.docker = docker;
58+
this.dockerBuildDir = dockerBuildDir;
59+
}
60+
61+
private void createDockerFile() throws IOException {
62+
final List<String> commands = Lists.newArrayList();
63+
if (baseImage != null) {
64+
commands.add("FROM " + baseImage);
65+
}
66+
if (maintainer != null) {
67+
commands.add("MAINTAINER " + maintainer);
68+
}
69+
if (entryPoint != null) {
70+
commands.add("ENTRYPOINT " + entryPoint);
71+
}
72+
if (cmd != null) {
73+
// TODO(dano): we actually need to check whether the base image has an entrypoint
74+
if (entryPoint != null) {
75+
// CMD needs to be a list of arguments if ENTRYPOINT is set.
76+
if (cmd.startsWith("[") && cmd.endsWith("]")) {
77+
// cmd seems to be an argument list, so we're good
78+
commands.add("CMD " + cmd);
79+
} else {
80+
// cmd does not seem to be an argument list, so try to generate one.
81+
final List<String> args = ImmutableList.copyOf(
82+
Splitter.on(WHITESPACE).omitEmptyStrings().split(cmd));
83+
final StringBuilder cmdBuilder = new StringBuilder("[");
84+
for (String arg : args) {
85+
cmdBuilder.append('"').append(arg).append('"');
86+
}
87+
cmdBuilder.append(']');
88+
final String cmdString = cmdBuilder.toString();
89+
commands.add("CMD " + cmdString);
90+
log.warn("Entrypoint provided but cmd is not an explicit list. Attempting to "
91+
+ "generate CMD string in the form of an argument list.");
92+
log.warn("CMD " + cmdString);
93+
}
94+
} else {
95+
// no ENTRYPOINT set so use cmd verbatim
96+
commands.add("CMD " + cmd);
97+
}
98+
} else {
99+
commands.add("CMD []");
100+
}
101+
102+
for (String file : addFiles) {
103+
commands.add(String.format("ADD %s %s", file, file));
104+
}
105+
106+
if (env != null) {
107+
final List<String> sortedKeys = Ordering.natural().sortedCopy(env.keySet());
108+
for (String key : sortedKeys) {
109+
final String value = env.get(key);
110+
commands.add(String.format("ENV %s %s", key, value));
111+
}
112+
}
113+
114+
if (exposesSet != null && exposesSet.size() > 0) {
115+
// The values will be sorted with no duplicated since exposesSet is a TreeSet
116+
commands.add("EXPOSE " + Joiner.on(" ").join(exposesSet));
117+
}
118+
119+
// this will overwrite an existing file
120+
Files.createDirectories(Paths.get(dockerBuildDir));
121+
Files.write(Paths.get(dockerBuildDir, "Dockerfile"), commands, UTF_8);
122+
}
123+
124+
@Override
125+
public void addFiles(List<ContainerFile> containerFiles) throws IOException {
126+
List<String> copiedPaths = Lists.newArrayList();
127+
128+
for (ContainerFile containerFile : containerFiles) {
129+
final Path sourcePath = containerFile.sourcePath;
130+
131+
final Path destPath = Paths.get(dockerBuildDir, containerFile.imagePath);
132+
log.info(String.format("Copying %s -> %s", sourcePath, destPath));
133+
// ensure all directories exist because copy operation will fail if they don't
134+
Files.createDirectories(destPath.getParent());
135+
Files.copy(sourcePath, destPath, StandardCopyOption.REPLACE_EXISTING);
136+
Files.setLastModifiedTime(destPath, FileTime.fromMillis(0));
137+
// file location relative to docker directory, used later to generate Dockerfile
138+
final Path relativePath = Paths.get(containerFile.imagePath);
139+
copiedPaths.add(relativePath.toString());
140+
}
141+
142+
// The list of included files returned from DirectoryScanner can be in a different order
143+
// each time. This causes the ADD statements in the generated Dockerfile to appear in a
144+
// different order. We want to avoid this so each run of the plugin always generates the same
145+
// Dockerfile, which also makes testing easier. Sort the list of paths for each resource
146+
// before adding it to the allCopiedPaths list. This way we follow the ordering of the
147+
// resources in the pom, while making sure all the paths of each resource are always in the
148+
// same order.
149+
Collections.sort(copiedPaths);
150+
addFiles.addAll(copiedPaths);
151+
}
152+
153+
public void buildImage(String imageName) throws Exception {
154+
if (dockerfile == null) {
155+
createDockerFile();
156+
}
157+
158+
log.info("Building image " + imageName);
159+
docker.build(Paths.get(dockerBuildDir), imageName, new AnsiProgressHandler());
160+
log.info("Built " + imageName);
161+
}
162+
163+
}

0 commit comments

Comments
 (0)