Skip to content

Commit 5c13819

Browse files
authored
Merge pull request #24 from brendandburns/attach
Implement Attach
2 parents 518e621 + 0b0ac76 commit 5c13819

File tree

9 files changed

+516
-120
lines changed

9 files changed

+516
-120
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
Copyright 2017 The Kubernetes Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
package io.kubernetes.client.examples;
14+
15+
import io.kubernetes.client.ApiClient;
16+
import io.kubernetes.client.ApiException;
17+
import io.kubernetes.client.Configuration;
18+
import io.kubernetes.client.Attach;
19+
import io.kubernetes.client.apis.CoreV1Api;
20+
import io.kubernetes.client.models.V1Pod;
21+
import io.kubernetes.client.models.V1PodList;
22+
import io.kubernetes.client.util.Config;
23+
24+
import com.google.common.io.ByteStreams;
25+
26+
import java.io.BufferedReader;
27+
import java.io.InputStreamReader;
28+
import java.io.IOException;
29+
import java.io.OutputStream;
30+
31+
/**
32+
* A simple example of how to use the Java API
33+
*
34+
* Easiest way to run this:
35+
* mvn exec:java -Dexec.mainClass="io.kubernetes.client.examples.AttachExample"
36+
*
37+
* From inside $REPO_DIR/examples
38+
*/
39+
public class AttachExample {
40+
public static void main(String[] args) throws IOException, ApiException, InterruptedException {
41+
ApiClient client = Config.defaultClient();
42+
Configuration.setDefaultApiClient(client);
43+
44+
Attach attach = new Attach();
45+
final Attach.AttachResult result = attach.attach("default", "nginx-2371676037-czqx3", true);
46+
47+
new Thread(new Runnable() {
48+
public void run() {
49+
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
50+
OutputStream output = result.getStandardInputStream();
51+
try {
52+
while (true) {
53+
String line = in.readLine();
54+
output.write(line.getBytes());
55+
output.write('\n');
56+
output.flush();
57+
}
58+
} catch (IOException ex) {
59+
ex.printStackTrace();
60+
}
61+
}
62+
}).start();
63+
64+
new Thread(new Runnable() {
65+
public void run() {
66+
try {
67+
ByteStreams.copy(result.getStandardOutputStream(), System.out);
68+
} catch (IOException ex) {
69+
ex.printStackTrace();
70+
}
71+
}
72+
}).start();
73+
74+
Thread.sleep(10*1000);
75+
76+
System.exit(0);
77+
}
78+
}

examples/src/main/java/io/kubernetes/client/examples/Example.java

-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
/**
2727
* A simple example of how to use the Java API
2828
*
29-
* Requires kubectl proxy running
30-
*
3129
* Easiest way to run this:
3230
* mvn exec:java -Dexec.mainClass="io.kubernetes.client.examples.Example"
3331
*

examples/src/main/java/io/kubernetes/client/examples/ExecExample.java

+24-12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
/*
2+
Copyright 2017 The Kubernetes Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
113
package io.kubernetes.client.examples;
214

315
import io.kubernetes.client.ApiClient;
@@ -19,10 +31,8 @@
1931
/**
2032
* A simple example of how to use the Java API
2133
*
22-
* Requires kubectl proxy running
23-
*
2434
* Easiest way to run this:
25-
* mvn exec:java -Dex.mainClass="io.kubernetes.client.examples.Example"
35+
* mvn exec:java -Dexec.mainClass="io.kubernetes.client.examples.Example"
2636
*
2737
* From inside $REPO_DIR/kubernetes
2838
*/
@@ -32,19 +42,15 @@ public static void main(String[] args) throws IOException, ApiException, Interru
3242
Configuration.setDefaultApiClient(client);
3343

3444
Exec exec = new Exec();
35-
final Process proc = exec.exec("default", "nginx-2371676037-czqx3", new String[] {"sh", "-c", "echo foo"}, true);
45+
boolean tty = System.console() != null;
46+
// final Process proc = exec.exec("default", "nginx-2371676037-czqx3", new String[] {"sh", "-c", "echo foo"}, true, tty);
47+
final Process proc = exec.exec("default", "nginx-2371676037-czqx3", new String[] {"sh"}, true, tty);
48+
3649

3750
new Thread(new Runnable() {
3851
public void run() {
39-
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
40-
OutputStream output = proc.getOutputStream();
4152
try {
42-
while (true) {
43-
String line = in.readLine();
44-
output.write(line.getBytes());
45-
output.write('\n');
46-
output.flush();
47-
}
53+
ByteStreams.copy(System.in, proc.getOutputStream());
4854
} catch (IOException ex) {
4955
ex.printStackTrace();
5056
}
@@ -62,6 +68,12 @@ public void run() {
6268
}).start();
6369

6470
proc.waitFor();
71+
try {
72+
// Wait for buffers to flush.
73+
Thread.sleep(2000);
74+
} catch (InterruptedException ex) {
75+
ex.printStackTrace();
76+
}
6577

6678
System.exit(0);
6779
}

examples/src/main/java/io/kubernetes/client/examples/WebSocketsExample.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
*/
1313
package io.kubernetes.client.examples;
1414

15+
import com.squareup.okhttp.ws.WebSocket;
1516
import io.kubernetes.client.ApiClient;
1617
import io.kubernetes.client.ApiException;
1718
import io.kubernetes.client.util.Config;
@@ -21,13 +22,14 @@
2122
import java.io.Closeable;
2223
import java.io.IOException;
2324
import java.io.InputStream;
25+
import java.io.OutputStream;
2426
import java.io.Reader;
2527

2628
public class WebSocketsExample {
2729
public static void main(String... args) throws ApiException, IOException {
2830
final ApiClient client = Config.defaultClient();
2931
WebSockets.stream(args[0], "GET", client, new WebSockets.SocketListener() {
30-
public void open(String protocol, Closeable close) {}
32+
public void open(String protocol, WebSocket socket) {}
3133
public void close() {
3234
// Trigger shutdown of the dispatcher's executor so this process can exit cleanly.
3335
client.getHttpClient().getDispatcher().getExecutorService().shutdown();

util/pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,4 @@
9393
<slf4jVersion>1.7.7</slf4jVersion>
9494
</properties>
9595
</project>
96+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/*
2+
Copyright 2017 The Kubernetes Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
package io.kubernetes.client;
14+
15+
import io.kubernetes.client.Configuration;
16+
import io.kubernetes.client.models.V1Pod;
17+
import io.kubernetes.client.util.WebSockets;
18+
import io.kubernetes.client.util.WebSocketStreamHandler;
19+
20+
import java.io.ByteArrayInputStream;
21+
import java.io.InputStream;
22+
import java.io.IOException;
23+
import java.io.OutputStream;
24+
import java.io.PipedInputStream;
25+
import java.io.PipedOutputStream;
26+
import java.io.Reader;
27+
28+
import org.apache.commons.lang.StringUtils;
29+
30+
public class Attach {
31+
private ApiClient apiClient;
32+
33+
/**
34+
* Simple Attach API constructor, uses default configuration
35+
*/
36+
public Attach() {
37+
this(Configuration.getDefaultApiClient());
38+
}
39+
40+
/**
41+
* Attach API Constructor
42+
* @param apiClient The api client to use.
43+
*/
44+
public Attach(ApiClient apiClient) {
45+
this.apiClient = apiClient;
46+
}
47+
48+
/**
49+
* Get the API client for these Attach operations.
50+
* @returns The API client that will be used.
51+
*/
52+
public ApiClient getApiClient() {
53+
return apiClient;
54+
}
55+
56+
/**
57+
* Set the API client for subsequent Attach operations.
58+
* @param apiClient The new API client to use.
59+
*/
60+
public void setApiClient(ApiClient apiClient) {
61+
this.apiClient = apiClient;
62+
}
63+
64+
private String makePath(String namespace, String name, String container, boolean stdin, boolean tty) {
65+
return "/api/v1/namespaces/" +
66+
namespace +
67+
"/pods/" +
68+
name +
69+
"/attach?" +
70+
"stdin=" + stdin +
71+
"&tty=" + tty +
72+
(container != null ? "&container=" + container : "");
73+
}
74+
75+
/**
76+
* Attach to a running AttachResult in a container. If there are multiple containers in the pod, uses
77+
* the first container in the Pod.
78+
*
79+
* @param namespace The namespace of the Pod
80+
* @param name The name of the Pod
81+
* @param command The command to run
82+
* @param stdin If true, pass a stdin stream into the container
83+
*/
84+
public AttachResult attach(String namespace, String name, boolean stdin) throws ApiException, IOException {
85+
return attach(namespace, name, null, stdin, false);
86+
}
87+
88+
/**
89+
* Attach to a running AttachResult in a container. If there are multiple containers in the pod, uses
90+
* the first container in the Pod.
91+
*
92+
* @param pod The pod where the command is run.
93+
* @param stdin If true, pass a stdin stream into the container
94+
*/
95+
public AttachResult attach(V1Pod pod, boolean stdin) throws ApiException, IOException {
96+
return attach(pod, stdin, false);
97+
}
98+
99+
100+
/**
101+
* Attach to a running AttachResult in a container. If there are multiple containers in the pod, uses
102+
* the first container in the Pod.
103+
*
104+
* @param pod The pod where the command is run.
105+
* @param stdin If true, pass a stdin stream into the container
106+
* @param tty If true, stdin is a tty.
107+
*/
108+
public AttachResult attach(V1Pod pod, boolean stdin, boolean tty) throws ApiException, IOException {
109+
return attach(pod, null, stdin, tty);
110+
}
111+
112+
/**
113+
* Attach to a running AttachResult in a container. If there are multiple containers in the pod, uses
114+
* the first container in the Pod.
115+
*
116+
* @param pod The pod where the command is run.
117+
* @param container The container in the Pod where the command is run.
118+
* @param stdin If true, pass a stdin stream into the container.
119+
* @param tty If true, stdin is a TTY (only applies if stdin is true)
120+
*/
121+
public AttachResult attach(V1Pod pod, String container, boolean stdin, boolean tty) throws ApiException, IOException {
122+
return attach(pod.getMetadata().getNamespace(), pod.getMetadata().getName(), container, stdin, tty);
123+
}
124+
125+
/**
126+
* Attach to a running AttachResult in a container. If there are multiple containers in the pod, uses
127+
* the first container in the Pod.
128+
*
129+
* @param namespace The namespace of the Pod
130+
* @param name The name of the Pod
131+
* @param container The container in the Pod where the command is run.
132+
* @param stdin If true, pass a stdin stream into the container.
133+
* @param tty If true, stdin is a TTY (only applies if stdin is true)
134+
*/
135+
public AttachResult attach(String namespace, String name, String container, boolean stdin, boolean tty) throws ApiException, IOException {
136+
String path = makePath(namespace, name, container, stdin, tty);
137+
138+
WebSocketStreamHandler handler = new WebSocketStreamHandler();
139+
AttachResult result = new AttachResult(handler);
140+
WebSockets.stream(path, "GET", apiClient, handler);
141+
142+
return result;
143+
}
144+
145+
/**
146+
* AttachResult contains the result of an Attach call, it includes streams for stdout
147+
* stderr and stdin.
148+
*/
149+
public static class AttachResult {
150+
private WebSocketStreamHandler handler;
151+
152+
153+
public AttachResult(WebSocketStreamHandler handler) throws IOException {
154+
this.handler = handler;
155+
}
156+
157+
public OutputStream getStandardInputStream() {
158+
return handler.getOutputStream(0);
159+
}
160+
161+
public InputStream getStandardOutputStream() throws IOException {
162+
return handler.getInputStream(1);
163+
}
164+
165+
public InputStream getErrorStream() throws IOException {
166+
return handler.getInputStream(2);
167+
}
168+
}
169+
}

0 commit comments

Comments
 (0)