2
2
3
3
import java .io .File ;
4
4
import java .io .IOException ;
5
+ import java .net .ConnectException ;
6
+ import java .net .Socket ;
7
+ import java .net .URI ;
8
+ import java .net .URISyntaxException ;
9
+ import java .net .http .HttpClient ;
10
+ import java .net .http .HttpRequest ;
11
+ import java .net .http .HttpResponse ;
12
+ import java .security .KeyManagementException ;
13
+ import java .security .NoSuchAlgorithmException ;
14
+ import java .security .cert .CertificateException ;
15
+ import java .security .cert .X509Certificate ;
16
+ import java .time .LocalTime ;
17
+ import java .time .temporal .ChronoUnit ;
5
18
import java .util .ArrayList ;
6
19
import java .util .List ;
7
- import java . util . Scanner ;
8
- import java . util . concurrent . atomic . AtomicBoolean ;
20
+
21
+ import javax . net . ssl .* ;
9
22
10
23
import org .slf4j .Logger ;
11
24
import org .slf4j .LoggerFactory ;
12
25
13
26
import io .javaoperatorsdk .jenvtest .*;
14
27
import io .javaoperatorsdk .jenvtest .binary .BinaryManager ;
15
28
29
+ import static io .javaoperatorsdk .jenvtest .KubeAPIServer .STARTUP_TIMEOUT ;
30
+
16
31
public class KubeAPIServerProcess {
17
32
18
33
private static final Logger log = LoggerFactory .getLogger (KubeAPIServerProcess .class );
19
34
private static final Logger apiLog = LoggerFactory .getLogger (KubeAPIServerProcess .class
20
35
.getName () + ".APIServerProcessLogs" );
36
+ public static final int POLLING_INTERVAL = 150 ;
21
37
22
38
private final CertManager certManager ;
23
39
private final BinaryManager binaryManager ;
24
40
private final KubeAPIServerConfig config ;
25
41
private volatile Process apiServerProcess ;
26
42
private volatile boolean stopped = false ;
27
43
private final UnexpectedProcessStopHandler processStopHandler ;
44
+ private int apiServerPort ;
28
45
29
46
public KubeAPIServerProcess (CertManager certManager , BinaryManager binaryManager ,
30
47
UnexpectedProcessStopHandler processStopHandler ,
@@ -42,7 +59,7 @@ public int startApiServer(int etcdPort) {
42
59
throw new JenvtestException (
43
60
"Missing binary for API Server on path: " + apiServerBinary .getAbsolutePath ());
44
61
}
45
- var apiServerPort = Utils .findFreePort ();
62
+ apiServerPort = Utils .findFreePort ();
46
63
var command = createCommand (apiServerBinary , apiServerPort , etcdPort );
47
64
apiServerProcess = new ProcessBuilder (command )
48
65
.start ();
@@ -85,27 +102,33 @@ private List<String> createCommand(File apiServerBinary, int apiServerPort, int
85
102
86
103
public void waitUntilDefaultNamespaceCreated () {
87
104
try {
88
- AtomicBoolean started = new AtomicBoolean (false );
89
- var proc = new ProcessBuilder (binaryManager .binaries ().getKubectl ().getPath (), "get" , "ns" ,
90
- "--watch" ).start ();
91
- var procWaiter = new Thread (() -> {
92
- log .debug ("Starting proc waiter thread." );
93
- try (Scanner sc = new Scanner (proc .getInputStream ())) {
94
- while (sc .hasNextLine ()) {
95
- String line = sc .nextLine ();
96
- log .debug ("kubectl ns watch: {}" , line );
97
- if (line .contains ("default" )) {
98
- started .set (true );
99
- return ;
100
- }
101
- }
105
+ var client = getHttpClient ();
106
+ var request = getHttpRequest ();
107
+ var startedAt = LocalTime .now ();
108
+ while (true ) {
109
+ if (ready (client , request )) {
110
+ return ;
102
111
}
103
- });
104
- procWaiter .start ();
105
- procWaiter .join (KubeAPIServer .STARTUP_TIMEOUT );
106
- if (!started .get ()) {
107
- throw new JenvtestException ("API Server did not start properly" );
112
+ if (LocalTime .now ().isAfter (startedAt .plus (STARTUP_TIMEOUT , ChronoUnit .MILLIS ))) {
113
+ throw new JenvtestException ("API Server did not start properly" );
114
+ }
115
+ Thread .sleep (POLLING_INTERVAL );
108
116
}
117
+ } catch (InterruptedException e ) {
118
+ Thread .currentThread ().interrupt ();
119
+ throw new JenvtestException (e );
120
+ }
121
+ }
122
+
123
+ private boolean ready (HttpClient client , HttpRequest request ) {
124
+ try {
125
+ var response = client .send (request , HttpResponse .BodyHandlers .ofString ());
126
+ log .trace ("Ready Response message:{} code: {}" , response .body (), response .statusCode ());
127
+ return response .statusCode () == 200 ;
128
+ } catch (ConnectException e ) {
129
+ // still want to retry
130
+ log .warn ("Cannot connect to the server" , e );
131
+ return false ;
109
132
} catch (IOException e ) {
110
133
throw new JenvtestException (e );
111
134
} catch (InterruptedException e ) {
@@ -114,6 +137,69 @@ public void waitUntilDefaultNamespaceCreated() {
114
137
}
115
138
}
116
139
140
+ private HttpRequest getHttpRequest () {
141
+ try {
142
+ return HttpRequest .newBuilder ()
143
+ .uri (new URI ("https://127.0.0.1:" + apiServerPort + "/readyz" ))
144
+ .GET ()
145
+ .build ();
146
+ } catch (URISyntaxException e ) {
147
+ throw new RuntimeException (e );
148
+ }
149
+ }
150
+
151
+ private static HttpClient getHttpClient () {
152
+ try {
153
+ var sslContext = SSLContext .getInstance ("TLS" );
154
+ sslContext .init (
155
+ null ,
156
+ new TrustManager [] {
157
+ new X509ExtendedTrustManager () {
158
+ @ Override
159
+ public void checkClientTrusted (X509Certificate [] chain , String authType ,
160
+ Socket socket ) throws CertificateException {
161
+
162
+ }
163
+
164
+ public X509Certificate [] getAcceptedIssuers () {
165
+ return null ;
166
+ }
167
+
168
+ public void checkClientTrusted (
169
+ final X509Certificate [] a_certificates ,
170
+ final String a_auth_type ) {}
171
+
172
+ public void checkServerTrusted (
173
+ final X509Certificate [] a_certificates ,
174
+ final String a_auth_type ) {}
175
+
176
+
177
+ public void checkServerTrusted (
178
+ final X509Certificate [] a_certificates ,
179
+ final String a_auth_type ,
180
+ final Socket a_socket ) {}
181
+
182
+ @ Override
183
+ public void checkClientTrusted (X509Certificate [] chain , String authType ,
184
+ SSLEngine engine ) throws CertificateException {
185
+
186
+ }
187
+
188
+ public void checkServerTrusted (
189
+ final X509Certificate [] a_certificates ,
190
+ final String a_auth_type ,
191
+ final SSLEngine a_engine ) {}
192
+ }
193
+ },
194
+ null );
195
+ return HttpClient .newBuilder ()
196
+ .sslContext (sslContext )
197
+ .build ();
198
+ } catch (NoSuchAlgorithmException | KeyManagementException e ) {
199
+ throw new JenvtestException (e );
200
+ }
201
+ }
202
+
117
203
public void stopApiServer () {
118
204
if (stopped ) {
119
205
return ;
0 commit comments