Skip to content

Commit 3057ef2

Browse files
authored
Merge pull request #1159 from ffazzini/copy-binary-data-to-pod
add overloading method to copy in memory binary data to pod
2 parents 2fbc0b0 + c7d549e commit 3057ef2

File tree

2 files changed

+82
-10
lines changed

2 files changed

+82
-10
lines changed

util/src/main/java/io/kubernetes/client/Copy.java

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import io.kubernetes.client.openapi.models.V1Pod;
2020
import io.kubernetes.client.util.exception.CopyNotSupportedException;
2121
import java.io.BufferedInputStream;
22+
import java.io.ByteArrayInputStream;
2223
import java.io.File;
2324
import java.io.FileInputStream;
2425
import java.io.FileOutputStream;
@@ -179,15 +180,7 @@ public void copyFileToPod(
179180
throws ApiException, IOException {
180181

181182
// Run decoding and extracting processes
182-
String parentPath = destPath.getParent() != null ? destPath.getParent().toString() : ".";
183-
final Process proc =
184-
this.exec(
185-
namespace,
186-
pod,
187-
new String[] {"sh", "-c", "base64 -d | tar -xmf - -C " + parentPath},
188-
container,
189-
true,
190-
false);
183+
final Process proc = execCopyToPod(namespace, pod, container, destPath);
191184

192185
// Send encoded archive output stream
193186
File srcFile = new File(srcPath.toUri());
@@ -205,6 +198,39 @@ public void copyFileToPod(
205198
}
206199
}
207200

201+
public void copyFileToPod(
202+
String namespace, String pod, String container, byte[] src, Path destPath)
203+
throws ApiException, IOException {
204+
205+
// Run decoding and extracting processes
206+
final Process proc = execCopyToPod(namespace, pod, container, destPath);
207+
208+
try (ArchiveOutputStream archiveOutputStream =
209+
new TarArchiveOutputStream(new Base64OutputStream(proc.getOutputStream(), true, 0, null))) {
210+
211+
ArchiveEntry tarEntry = new TarArchiveEntry(new File(destPath.getFileName().toString()));
212+
((TarArchiveEntry) tarEntry).setSize(src.length);
213+
214+
archiveOutputStream.putArchiveEntry(tarEntry);
215+
ByteStreams.copy(new ByteArrayInputStream(src), archiveOutputStream);
216+
archiveOutputStream.closeArchiveEntry();
217+
} finally {
218+
proc.destroy();
219+
}
220+
}
221+
222+
private Process execCopyToPod(String namespace, String pod, String container, Path destPath)
223+
throws ApiException, IOException {
224+
String parentPath = destPath.getParent() != null ? destPath.getParent().toString() : ".";
225+
return this.exec(
226+
namespace,
227+
pod,
228+
new String[] {"sh", "-c", "base64 -d | tar -xmf - -C " + parentPath},
229+
container,
230+
true,
231+
false);
232+
}
233+
208234
private boolean isTarPresentInContainer(String namespace, String pod, String container)
209235
throws ApiException, IOException {
210236
final Process proc =

util/src/test/java/io/kubernetes/client/CopyTest.java

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public void run() {
9494
}
9595

9696
@Test
97-
public void testCopyFileToPod() throws IOException, ApiException, InterruptedException {
97+
public void testCopyFileToPod() throws IOException, InterruptedException {
9898

9999
File testFile = File.createTempFile("testfile", null);
100100
testFile.deleteOnExit();
@@ -139,4 +139,50 @@ public void run() {
139139
.withQueryParam("command", equalTo("-c"))
140140
.withQueryParam("command", equalTo("base64 -d | tar -xmf - -C /")));
141141
}
142+
143+
@Test
144+
public void testCopyBinaryDataToPod() throws InterruptedException {
145+
146+
byte[] testSrc = new byte[0];
147+
148+
Copy copy = new Copy(client);
149+
150+
wireMockRule.stubFor(
151+
get(urlPathEqualTo("/api/v1/namespaces/" + namespace + "/pods/" + podName + "/exec"))
152+
.willReturn(
153+
aResponse()
154+
.withStatus(404)
155+
.withHeader("Content-Type", "application/json")
156+
.withBody("{}")));
157+
158+
// When attempting to write to the process outputstream in copyFileToPod, the
159+
// WebSocketStreamHandler is in a wait state because no websocket is created by mock, which
160+
// blocks the main thread. So here we execute the method in a thread.
161+
Thread t =
162+
new Thread(
163+
new Runnable() {
164+
public void run() {
165+
try {
166+
copy.copyFileToPod(
167+
namespace, podName, "", testSrc, Paths.get("/copied-binarydata"));
168+
} catch (IOException | ApiException ex) {
169+
ex.printStackTrace();
170+
}
171+
}
172+
});
173+
t.start();
174+
Thread.sleep(2000);
175+
t.interrupt();
176+
177+
verify(
178+
getRequestedFor(
179+
urlPathEqualTo("/api/v1/namespaces/" + namespace + "/pods/" + podName + "/exec"))
180+
.withQueryParam("stdin", equalTo("true"))
181+
.withQueryParam("stdout", equalTo("true"))
182+
.withQueryParam("stderr", equalTo("true"))
183+
.withQueryParam("tty", equalTo("false"))
184+
.withQueryParam("command", equalTo("sh"))
185+
.withQueryParam("command", equalTo("-c"))
186+
.withQueryParam("command", equalTo("base64 -d | tar -xmf - -C /")));
187+
}
142188
}

0 commit comments

Comments
 (0)