29
29
import co .elastic .clients .transport .Version ;
30
30
import co .elastic .clients .transport .endpoints .DelegatingJsonEndpoint ;
31
31
import co .elastic .clients .transport .rest_client .RestClientTransport ;
32
+ import org .apache .commons .io .FileUtils ;
32
33
import org .apache .http .HttpHost ;
33
34
import org .apache .http .auth .AuthScope ;
34
35
import org .apache .http .auth .UsernamePasswordCredentials ;
40
41
import org .testcontainers .utility .DockerImageName ;
41
42
42
43
import javax .net .ssl .SSLContext ;
44
+ import java .io .File ;
43
45
import java .io .IOException ;
44
46
import java .io .InputStream ;
45
47
import java .net .HttpURLConnection ;
46
48
import java .net .URL ;
47
49
import java .nio .charset .StandardCharsets ;
48
50
import java .time .Duration ;
51
+ import java .time .Instant ;
52
+ import java .time .temporal .ChronoUnit ;
49
53
import java .util .Base64 ;
50
54
51
55
public class ElasticsearchTestServer implements AutoCloseable {
@@ -58,6 +62,7 @@ public class ElasticsearchTestServer implements AutoCloseable {
58
62
private ElasticsearchClient client ;
59
63
60
64
private static ElasticsearchTestServer global ;
65
+ private static final String artifactsApiUrl = "https://artifacts-api.elastic.co/v1/versions/" ;
61
66
62
67
public static synchronized ElasticsearchTestServer global () {
63
68
if (global == null ) {
@@ -112,14 +117,70 @@ AuthScope.ANY, new UsernamePasswordCredentials("elastic", "changeme")
112
117
client = new ElasticsearchClient (transport );
113
118
}
114
119
120
+ private Version selectLatestVersion (Version version , String info ) {
121
+ if (info .contains (version .toString ())) {
122
+ return version ;
123
+ }
124
+ // if no version X.Y.0 was found, we give up
125
+ if (version .maintenance () == 0 ) {
126
+ throw new RuntimeException ("Elasticsearch server container version: " + version + " not yet " +
127
+ "available" );
128
+ }
129
+ return selectLatestVersion (new Version (version .major (), version .minor (), version .maintenance () - 1 ,
130
+ false ), info );
131
+ }
132
+
133
+ private String fetchAndWriteVersionInfo (File file ) throws IOException {
134
+ String versionInfo = IOUtils .toString (new URL (artifactsApiUrl ), StandardCharsets .UTF_8 );
135
+ FileUtils .writeStringToFile (file , versionInfo , StandardCharsets .UTF_8 );
136
+ return versionInfo ;
137
+ }
138
+
139
+ private Version getLatestAvailableServerVersion (Version version ) {
140
+ try {
141
+ // check if there's cached information
142
+ ClassLoader classLoader = getClass ().getClassLoader ();
143
+ URL location = classLoader .getResource ("./co/elastic/clients/version.json" );
144
+
145
+ // writing the info on file before returning
146
+ if (location == null ) {
147
+ File file = new File (classLoader .getResource ("./co/elastic/clients" ).getFile () + "/version" +
148
+ ".json" );
149
+ String versionInfo = fetchAndWriteVersionInfo (file );
150
+ return selectLatestVersion (version , versionInfo );
151
+ }
152
+
153
+ File file = new File (location .getFile ());
154
+
155
+ // info file was found, but it's expired
156
+ if (Instant .ofEpochMilli (file .lastModified ()).isBefore (Instant .now ().minus (24 ,
157
+ ChronoUnit .HOURS ))) {
158
+ String versionInfo = fetchAndWriteVersionInfo (file );
159
+ return selectLatestVersion (version , versionInfo );
160
+ }
161
+
162
+ // info file exists and it has new info
163
+ String versionInfo = FileUtils .readFileToString (file , StandardCharsets .UTF_8 );
164
+ return selectLatestVersion (version , versionInfo );
165
+
166
+ } catch (IOException e ) {
167
+ throw new RuntimeException (e );
168
+ }
169
+ }
170
+
115
171
public synchronized ElasticsearchTestServer start () {
116
172
if (this .client != null ) {
117
173
return this ;
118
174
}
119
175
120
- Version version = Version .VERSION .major () < 8 ? new Version (7 ,17 ,5 ,false ) : new Version (8 ,12 ,0 ,false );
176
+ Version version = getLatestAvailableServerVersion (Version .VERSION );
177
+
178
+ // using specific stable version for tests with plugins
179
+ if (plugins .length > 0 ) {
180
+ version = Version .VERSION .major () < 8 ? new Version (7 , 17 , 25 , false ) : new Version (8 , 16 , 0 ,
181
+ false );
182
+ }
121
183
122
- // Note we could use version.major() + "." + version.minor() + "-SNAPSHOT" but plugins won't install on a snapshot version
123
184
String esImage = "docker.elastic.co/elasticsearch/elasticsearch:" + version ;
124
185
125
186
DockerImageName image ;
@@ -166,10 +227,11 @@ public static <Req> JsonData getJsonResponse(ElasticsearchClient client, Req req
166
227
167
228
try {
168
229
@ SuppressWarnings ("unchecked" )
169
- JsonEndpoint <Req , JsonData , ErrorResponse > endpoint0 = (JsonEndpoint <Req , JsonData , ErrorResponse >) request .getClass ()
230
+ JsonEndpoint <Req , JsonData , ErrorResponse > endpoint0 = (JsonEndpoint <Req , JsonData ,
231
+ ErrorResponse >) request .getClass ()
170
232
.getDeclaredField ("_ENDPOINT" ).get (null );
171
233
endpoint = endpoint0 ;
172
- } catch (IllegalAccessException | NoSuchFieldException e ) {
234
+ } catch (IllegalAccessException | NoSuchFieldException e ) {
173
235
throw new RuntimeException (e );
174
236
}
175
237
0 commit comments