/
DockerConnectionDetector.java
187 lines (162 loc) · 6.75 KB
/
DockerConnectionDetector.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package io.fabric8.maven.docker.access;
import java.io.*;
import java.util.*;
import io.fabric8.maven.docker.access.util.LocalSocketUtil;
import io.fabric8.maven.docker.util.*;
import javax.annotation.Nonnull;
import static io.fabric8.maven.docker.util.EnvUtil.getUserHome;
/**
* Detector for determining the Docker access mechanism
*/
public class DockerConnectionDetector {
final List<DockerHostProvider> dockerHostProviders;
public DockerConnectionDetector(List<DockerHostProvider> externalProviders) {
dockerHostProviders = new ArrayList<>();
dockerHostProviders.addAll(getDefaultEnvProviders());
if (externalProviders != null) {
dockerHostProviders.addAll(externalProviders);
}
Collections.sort(dockerHostProviders,new DockerHostProvider.Comparator());
}
private Collection<? extends DockerHostProvider> getDefaultEnvProviders() {
return Arrays.asList(new EnvDockerHostProvider(),
new UnixSocketDockerHostProvider(),
new WindowsPipeDockerHostProvider());
}
/**
* Provider of environment variables like 'DOCKER_HOST'
*/
public interface DockerHostProvider {
/**
* Get value of the docker host as detected by this provider. Return null if it couldn't be detected.
*
* @return the docker host parameter or null
* @param certPath
*/
ConnectionParameter getConnectionParameter(String certPath) throws IOException;
/**
* Get the priority of the env provider. A priority of -1 means, this is a 'fallback' called
* as last resort.
*
* @return priority, the higher, the earlier the provider is called.
* The highest priority of internal providers are not larger than 100.
*/
int getPriority();
class Comparator implements java.util.Comparator<DockerHostProvider> {
@Override
public int compare(DockerHostProvider o1, DockerHostProvider o2) {
return o2.getPriority() - o1.getPriority();
}
}
}
/**
* Get the docker host url.
* <ol>
* <li>From <dockerHost> configuration</li>
* <li>From <machine> configuration</li>
* <li>From DOCKER_HOST environment variable</li>
* <li>Default to /var/run/docker.sock</li>
* </ol>
* @param dockerHost The dockerHost configuration setting
* @return The docker host url
* @throws IOException when URL handling fails
*/
public ConnectionParameter detectConnectionParameter(String dockerHost, String certPath) throws IOException {
if (dockerHost != null) {
return new ConnectionParameter(dockerHost, certPath);
}
for (DockerHostProvider provider : dockerHostProviders) {
ConnectionParameter value = provider.getConnectionParameter(certPath);
if (value != null) {
return value;
}
}
throw new IllegalArgumentException("No <dockerHost> given, no DOCKER_HOST environment variable, " +
"no read/writable '/var/run/docker.sock' or '//./pipe/docker_engine' " +
"and no external provider like Docker machine configured");
}
// ====================================================================================================
// Lookup from the enviroment
class EnvDockerHostProvider implements DockerHostProvider {
@Override
public ConnectionParameter getConnectionParameter(String certPath) throws IOException {
String connect = System.getenv("DOCKER_HOST");
return connect != null ? new ConnectionParameter(connect, certPath) : null;
}
@Override
public int getPriority() {
return 100;
}
}
// Check for a unix socket
class UnixSocketDockerHostProvider implements DockerHostProvider {
@Override
public ConnectionParameter getConnectionParameter(String certPath) throws IOException {
File unixSocket = new File("/var/run/docker.sock");
if (unixSocket.exists() && unixSocket.canRead() && unixSocket.canWrite() && LocalSocketUtil.canConnectUnixSocket(unixSocket)) {
return new ConnectionParameter("unix:///var/run/docker.sock", certPath);
} else {
return null;
}
}
@Override
public int getPriority() {
return 55;
}
}
// Check for a windows pipe
class WindowsPipeDockerHostProvider implements DockerHostProvider {
@Override
public ConnectionParameter getConnectionParameter(String certPath) throws IOException {
File windowsPipe = new File("//./pipe/docker_engine");
if (windowsPipe.exists()) {
return new ConnectionParameter("npipe:////./pipe/docker_engine", certPath);
} else {
return null;
}
}
@Override
public int getPriority() {
return 50;
}
}
public static class ConnectionParameter {
private final String url;
private String certPath;
public ConnectionParameter(@Nonnull String url, String certPath) throws IOException {
this.url = EnvUtil.convertTcpToHttpUrl(url);
initCertPath(certPath);
}
public String getUrl() {
return url;
}
public String getCertPath() {
return certPath;
}
/**
* Get the docker certificate location
* <ol>
* <li>From <certPath> a given cert config argument</li>
* <li>From DOCKER_CERT_PATH environment variable</li>
* <li>Default to ${user.home}/.docker</li>
* </ol>
* @param certPath the configured certification path which is used directly if set
*/
private void initCertPath(String certPath) throws IOException {
this.certPath = certPath != null ? certPath : System.getenv("DOCKER_CERT_PATH");
// Try default locations as last resort
if (this.certPath == null) {
File dockerHome = new File(getUserHome() + "/.docker");
if (dockerHome.isDirectory()) {
String[] entries = dockerHome.list(SuffixFileFilter.PEM_FILTER);
if (entries == null) {
throw new IOException("Can not read directory " + dockerHome + ". Please check file permissions.");
}
if (entries.length > 0) {
this.certPath = dockerHome.getAbsolutePath();
}
}
}
}
}
}