-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathArtifactRepositoryHelpers.groovy
201 lines (168 loc) · 6.8 KB
/
ArtifactRepositoryHelpers.groovy
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
197
198
199
200
201
@groovy.transform.BaseScript com.ibm.dbb.groovy.ScriptLoader baseScript
import groovy.transform.*
import javax.net.ssl.SSLContext
import groovy.cli.commons.*
import java.net.http.*
import java.net.http.HttpRequest.BodyPublishers
import java.net.http.HttpResponse.BodyHandlers
import java.net.http.HttpResponse.BodyHandler
import java.util.concurrent.CompletableFuture
import java.nio.file.Paths
/** Very basic script to upload/download from an artifact repository server
*
* Version 1 - 2022
*
* This script requires JAVA 11 because it uses java.net.http.* APIs to create
* the HTTPClient and HTTPRequest, replacing the previous ArtifactoryHelper
*
* Version 2 - 2023-04
*
* Implemented a retry mechanism for upload and download (with Connection Keep-alive for upload)
*
* Version 3 - 2024-05
*
* Supporting different HTTP client configurations
*
*/
@Field int MAX_RESEND = 10;
def <T> CompletableFuture<HttpResponse<T>>
tryResend(HttpClient client, HttpRequest request, BodyHandler<T> handler,
int count, HttpResponse<T> resp) {
if (resp.statusCode() == 200 || count >= MAX_RESEND) {
return CompletableFuture.completedFuture(resp);
} else {
return client.sendAsync(request, handler)
.thenComposeAsync(r -> tryResend(client, request, handler, count+1, r));
}
}
run(args)
def upload(String url, String fileName, String user, String password, boolean verbose, String httpClientVersion) throws IOException {
System.setProperty("jdk.httpclient.allowRestrictedHeaders", "Connection")
println( "** ArtifactRepositoryHelper started for upload of $fileName to $url" );
// create http client
HttpClient.Builder httpClientBuilder = HttpClient.newBuilder()
.authenticator(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
"$user",
"$password".toCharArray());
}
});
// if ( disableSSLVerify ) {
// SSLContext sc = SSLContext.getInstance(DEFAULT_SSL_PROTOCOLS);
// sc.init(null, trustAllCertsTrustManager(), null);
// httpClientBuilder.sslContext(sc)
// }
HttpClient httpClient = httpClientBuilder.build();
// build http request
HttpRequest.Builder httpRequestBuilder = HttpRequest.newBuilder()
.uri(URI.create("$url"))
.header("Content-Type", "binary/octet-stream")
.header("Connection","Keep-Alive")
.PUT(BodyPublishers.ofFile(Paths.get(fileName)));
// set http client version if set
if (httpClientVersion) {
def httpVer = HttpClient.Version.valueOf(httpClientVersion)
if (httpVer) {
httpRequestBuilder.version(httpVer)
} else {
println("*! $httpClientVersion is invalid. Using default HTTP Client protocol version.");
}
}
HttpRequest request = httpRequestBuilder.build()
println("** Uploading $fileName to $url...");
HttpResponse.BodyHandler<String> handler = HttpResponse.BodyHandlers.ofString();
// submit request
CompletableFuture<HttpResponse<String>> response = httpClient.sendAsync(request, handler).thenComposeAsync(r -> tryResend(httpClient, request, handler, 1, r));
HttpResponse finalResponse = response.get()
if (verbose)
println("** Response: " + finalResponse);
def rc = evaluateHttpResponse(finalResponse, "upload", verbose)
if (rc == 0 ) {
println("** Upload completed.");
}
else {
println("*! Upload failed.");
}
}
def download(String url, String fileName, String user, String password, boolean verbose) throws IOException {
println("** ArtifactRepositoryHelper started for download of $url to $fileName.");
// create http client
HttpClient.Builder httpClientBuilder = HttpClient.newBuilder()
.authenticator(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
"$user",
"$password".toCharArray());
}
});
// if ( disableSSLVerify ) {
// SSLContext sc = SSLContext.getInstance(DEFAULT_SSL_PROTOCOLS);
// sc.init(null, trustAllCertsTrustManager(), null);
// httpClientBuilder.sslContext(sc)
// }
HttpClient httpClient = httpClientBuilder.build();
// build http request
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("$url"))
.GET()
.build();
// submit request
println("** Downloading $url to $fileName...");
HttpResponse.BodyHandler<InputStream> handler = HttpResponse.BodyHandlers.ofInputStream();
CompletableFuture<HttpResponse<String>> response = httpClient.sendAsync(request, handler).thenComposeAsync(r -> tryResend(httpClient, request, handler, 1, r));
HttpResponse finalResponse = response.get()
// evalulate response
rc = evaluateHttpResponse(finalResponse, "download", verbose)
if (rc == 0) {
// write file to output
def responseBody = finalResponse.body()
println("** Writing to file to $fileName.")
FileOutputStream fos = new FileOutputStream(fileName);
fos.write(responseBody.readAllBytes());
fos.close();
} else {
println("*! Download failed.");
}
}
def evaluateHttpResponse (HttpResponse response, String action, boolean verbose) {
int rc = 0
def statusCode = response.statusCode()
if (verbose) println "*** HTTP-Status Code: $statusCode"
def responseString = response.body()
if ((statusCode != 201) && (statusCode != 200)) {
rc = 1
println("** Artifactory $action failed with statusCode : $statusCode")
println("** Response: " + response);
throw new RuntimeException("Exception : Artifactory $action failed:" + statusCode);
}
return rc
}
//Parsing the command line
def run(String[] cliArgs) {
def cli = new CliBuilder(usage: "ArtifactRepositoryHelpers.groovy [options]", header: '', stopAtNonOption: false)
cli.h(longOpt:'help', 'Prints this message')
cli.u(longOpt:'url', args:1, required:true, 'Artifactory file uri location')
cli.fU(longOpt:'fileToUpload', args:1, 'The full path of the file to upload')
cli.fD(longOpt:'fileToDownload', args:1, 'The full path of the file to download')
cli.U(longOpt:'user', args:1, required:true, 'Artifactory user id')
cli.P(longOpt:'password', args:1, required:true, 'Artifactory password')
cli.ht(longOpt:'httpClientVersion', args:1, 'HTTP Client protocol version')
cli.v(longOpt:'verbose', 'Flag to turn on script trace')
def opts = cli.parse(cliArgs)
// if opt parsing fails, exit
if (opts == null || !opts) {
System.exit(1)
}
if (opts.h) {
cli.usage()
System.exit(0)
}
if ( opts.fU) {
upload(opts.u, opts.fU, opts.U, opts.P, opts.v)
} else {
download(opts.u, opts.fD, opts.U, opts.P, opts.v)
}
}