6
6
7
7
import java .io .*;
8
8
import java .util .Scanner ;
9
+ import java .util .concurrent .atomic .AtomicBoolean ;
9
10
10
11
public class APIServer {
11
12
12
13
private static final Logger log = LoggerFactory .getLogger (APIServer .class );
13
14
public static final int STARTUP_TIMEOUT = 10_000 ;
14
15
15
16
private final APIServerConfig config ;
16
- private BinaryManager binaryManager ;
17
- private CertManager certManager ;
18
- private KubeConfigManager kubeConfigManager ;
17
+ private final BinaryManager binaryManager ;
18
+ private final CertManager certManager ;
19
+ private final KubeConfigManager kubeConfigManager ;
19
20
private Process etcdProcess ;
20
21
private volatile Process apiServerProcess ;
21
- private Thread startupWaiter ;
22
- private volatile boolean startedUpProperly ;
23
22
24
23
public APIServer () {
25
24
this (new APIServerConfig ());
@@ -39,7 +38,7 @@ public void start() {
39
38
startEtcd ();
40
39
startApiServer ();
41
40
kubeConfigManager .updateKubeConfig ();
42
- waitUntilDefaultNamespaceCreated ();
41
+ waitUntilDefaultNamespaceCreatedWithK ();
43
42
log .info ("API Server ready to use" );
44
43
}
45
44
@@ -58,6 +57,7 @@ public void stop() {
58
57
stopEtcd ();
59
58
kubeConfigManager .cleanupFromKubeConfig ();
60
59
cleanEtcdData ();
60
+ log .debug ("Fully stopped." );
61
61
}
62
62
63
63
private void stopApiServer () {
@@ -82,13 +82,30 @@ private void stopEtcd() {
82
82
log .debug ("etcd stopped" );
83
83
}
84
84
85
- private void waitUntilDefaultNamespaceCreated () {
85
+ private void waitUntilDefaultNamespaceCreatedWithK () {
86
86
try {
87
- startupWaiter .join (STARTUP_TIMEOUT );
88
- if (!startedUpProperly ) {
89
- throw new KubeApiException ("Something went wrong starting up KubeApi server. Check the logs" );
87
+ AtomicBoolean started = new AtomicBoolean (false );
88
+ var proc = new ProcessBuilder ("kubectl" ,"get" ,"ns" ,"--watch" ).start ();
89
+ var procWaiter = new Thread (() -> {
90
+ try (Scanner sc = new Scanner (proc .getInputStream ())){
91
+ while (sc .hasNextLine ()) {
92
+ String line = sc .nextLine ();
93
+ if (line .contains ("default" )) {
94
+ started .set (true );
95
+ return ;
96
+ }
97
+ }
90
98
}
99
+ });
100
+ procWaiter .start ();
101
+ procWaiter .join (APIServer .STARTUP_TIMEOUT );
102
+ if (!started .get ()) {
103
+ throw new KubeApiException ("API Server did not start properly. Check the log files." );
104
+ }
105
+ } catch (IOException e ) {
106
+ throw new KubeApiException (e );
91
107
} catch (InterruptedException e ) {
108
+ Thread .currentThread ().interrupt ();
92
109
throw new KubeApiException (e );
93
110
}
94
111
}
@@ -139,32 +156,9 @@ private void startApiServer() {
139
156
"--allow-privileged"
140
157
)
141
158
.start ();
142
-
143
- addStartupReadyHandler ();
144
- // todo detect premature termination
145
- // apiServerProcess.onExit()
146
159
log .debug ("API Server started" );
147
160
} catch (IOException e ) {
148
161
throw new RuntimeException (e );
149
162
}
150
163
}
151
-
152
- private void addStartupReadyHandler () {
153
- // alternative would be to use health checks? https://kubernetes.io/docs/reference/using-api/health-checks/
154
- // waits until fully started, otherwise default namespace might be missing
155
- this .startupWaiter = new Thread (() -> {
156
- // todo the scanner is not closed
157
- Scanner sc = new Scanner (apiServerProcess .getErrorStream ());
158
- while (sc .hasNextLine ()) {
159
- String line = sc .nextLine ();
160
- // if (line.contains("Caches are synced")) {
161
- if (line .contains ("all system priority classes are created successfully or already exist" )) {
162
- startedUpProperly = true ;
163
- return ;
164
- }
165
- }
166
- });
167
- this .startupWaiter .start ();
168
- }
169
-
170
164
}
0 commit comments