-
Notifications
You must be signed in to change notification settings - Fork 865
/
YarnInstaller.java
196 lines (160 loc) · 7.48 KB
/
YarnInstaller.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
188
189
190
191
192
193
194
195
196
package com.github.eirslett.maven.plugins.frontend.lib;
import java.io.EOFException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class YarnInstaller {
public static final String INSTALL_PATH = "/node/yarn";
public static final String DEFAULT_YARN_DOWNLOAD_ROOT =
"https://github.com/yarnpkg/yarn/releases/download/";
private static final Object LOCK = new Object();
private static final String YARN_ROOT_DIRECTORY = "dist";
private String yarnVersion, yarnDownloadRoot, userName, password;
private final Logger logger;
private final InstallConfig config;
private final ArchiveExtractor archiveExtractor;
private final FileDownloader fileDownloader;
YarnInstaller(InstallConfig config, ArchiveExtractor archiveExtractor, FileDownloader fileDownloader) {
logger = LoggerFactory.getLogger(getClass());
this.config = config;
this.archiveExtractor = archiveExtractor;
this.fileDownloader = fileDownloader;
}
public YarnInstaller setYarnVersion(String yarnVersion) {
this.yarnVersion = yarnVersion;
return this;
}
public YarnInstaller setYarnDownloadRoot(String yarnDownloadRoot) {
this.yarnDownloadRoot = yarnDownloadRoot;
return this;
}
public YarnInstaller setUserName(String userName) {
this.userName = userName;
return this;
}
public YarnInstaller setPassword(String password) {
this.password = password;
return this;
}
public void install() throws InstallationException {
// use static lock object for a synchronized block
synchronized (LOCK) {
if (yarnDownloadRoot == null || yarnDownloadRoot.isEmpty()) {
yarnDownloadRoot = DEFAULT_YARN_DOWNLOAD_ROOT;
}
if (!yarnIsAlreadyInstalled()) {
if (!yarnVersion.startsWith("v")) {
throw new InstallationException("Yarn version has to start with prefix 'v'.");
}
installYarn();
}
}
}
private boolean yarnIsAlreadyInstalled() {
try {
YarnExecutorConfig executorConfig = new InstallYarnExecutorConfig(config);
File nodeFile = executorConfig.getYarnPath();
if (nodeFile.exists()) {
final String version =
new YarnExecutor(executorConfig, Arrays.asList("--version"), null).executeAndGetResult(logger).trim();
if (version.equals(yarnVersion.replaceFirst("^v", ""))) {
logger.info("Yarn {} is already installed.", version);
return true;
} else {
logger.info("Yarn {} was installed, but we need version {}", version, yarnVersion);
return false;
}
} else {
return false;
}
} catch (ProcessExecutionException e) {
return false;
}
}
private void installYarn() throws InstallationException {
try {
logger.info("Installing Yarn version {}", yarnVersion);
String downloadUrl = yarnDownloadRoot + yarnVersion;
String extension = "tar.gz";
String fileending = "/yarn-" + yarnVersion + "." + extension;
downloadUrl += fileending;
CacheDescriptor cacheDescriptor = new CacheDescriptor("yarn", yarnVersion, extension);
File archive = config.getCacheResolver().resolve(cacheDescriptor);
downloadFileIfMissing(downloadUrl, archive, userName, password);
File installDirectory = getInstallDirectory();
// We need to delete the existing yarn directory first so we clean out any old files, and
// so we can rename the package directory below.
try {
if (installDirectory.isDirectory()) {
FileUtils.deleteDirectory(installDirectory);
}
} catch (IOException e) {
logger.warn("Failed to delete existing Yarn installation.");
}
try {
extractFile(archive, installDirectory);
} catch (ArchiveExtractionException e) {
if (e.getCause() instanceof EOFException) {
// https://github.com/eirslett/frontend-maven-plugin/issues/794
// The downloading was probably interrupted and archive file is incomplete:
// delete it to retry from scratch
this.logger.error("The archive file {} is corrupted and will be deleted. "
+ "Please try the build again.", archive.getPath());
archive.delete();
if (installDirectory.exists()) {
FileUtils.deleteDirectory(installDirectory);
}
}
throw e;
}
ensureCorrectYarnRootDirectory(installDirectory, yarnVersion);
logger.info("Installed Yarn locally.");
} catch (DownloadException e) {
throw new InstallationException("Could not download Yarn", e);
} catch (ArchiveExtractionException | IOException e) {
throw new InstallationException("Could not extract the Yarn archive", e);
}
}
private File getInstallDirectory() {
File installDirectory = new File(config.getInstallDirectory(), INSTALL_PATH);
if (!installDirectory.exists()) {
logger.debug("Creating install directory {}", installDirectory);
installDirectory.mkdirs();
}
return installDirectory;
}
private void extractFile(File archive, File destinationDirectory) throws ArchiveExtractionException {
logger.info("Unpacking {} into {}", archive, destinationDirectory);
archiveExtractor.extract(archive.getPath(), destinationDirectory.getPath());
}
private void ensureCorrectYarnRootDirectory(File installDirectory, String yarnVersion) throws IOException {
File yarnRootDirectory = new File(installDirectory, YARN_ROOT_DIRECTORY);
if (!yarnRootDirectory.exists()) {
logger.debug("Yarn root directory not found, checking for yarn-{}", yarnVersion);
// Handle renaming Yarn 1.X root to YARN_ROOT_DIRECTORY
File yarnOneXDirectory = new File(installDirectory, "yarn-" + yarnVersion);
if (yarnOneXDirectory.isDirectory()) {
if (!yarnOneXDirectory.renameTo(yarnRootDirectory)) {
throw new IOException("Could not rename versioned yarn root directory to " + YARN_ROOT_DIRECTORY);
}
} else {
throw new FileNotFoundException("Could not find yarn distribution directory during extract");
}
}
}
private void downloadFileIfMissing(String downloadUrl, File destination, String userName, String password)
throws DownloadException {
if (!destination.exists()) {
downloadFile(downloadUrl, destination, userName, password);
}
}
private void downloadFile(String downloadUrl, File destination, String userName, String password)
throws DownloadException {
logger.info("Downloading {} to {}", downloadUrl, destination);
fileDownloader.download(downloadUrl, destination.getPath(), userName, password);
}
}