Skip to content

Commit a13defe

Browse files
authored
Merge pull request #375 from brendandburns/copy
Add utilities for copying files.
2 parents 268d429 + 1e8e7da commit a13defe

File tree

3 files changed

+211
-0
lines changed

3 files changed

+211
-0
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
Copyright 2017, 2018 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 com.google.common.io.ByteStreams;
16+
import io.kubernetes.client.ApiClient;
17+
import io.kubernetes.client.ApiException;
18+
import io.kubernetes.client.Configuration;
19+
import io.kubernetes.client.Copy;
20+
import io.kubernetes.client.util.Config;
21+
import java.io.IOException;
22+
import java.io.InputStream;
23+
import java.nio.file.Paths;
24+
25+
/**
26+
* A simple example of how to use the Java API
27+
*
28+
* <p>Easiest way to run this: mvn exec:java
29+
* -Dexec.mainClass="io.kubernetes.client.examples.CopyExample"
30+
*
31+
* <p>From inside $REPO_DIR/examples
32+
*/
33+
public class CopyExample {
34+
public static void main(String[] args) throws IOException, ApiException, InterruptedException {
35+
String podName = "kube-addon-manager-minikube";
36+
String namespace = "kube-system";
37+
38+
ApiClient client = Config.defaultClient();
39+
Configuration.setDefaultApiClient(client);
40+
41+
Copy copy = new Copy();
42+
InputStream dataStream = copy.copyFileFromPod(namespace, podName, "/etc/motd");
43+
ByteStreams.copy(dataStream, System.out);
44+
45+
copy.copyDirectoryFromPod(namespace, podName, null, "/etc", Paths.get("/tmp/etc"));
46+
47+
System.out.println("Done!");
48+
}
49+
}

util/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
<artifactId>commons-codec</artifactId>
3333
<version>1.11</version>
3434
</dependency>
35+
<dependency>
36+
<groupId>org.apache.commons</groupId>
37+
<artifactId>commons-compress</artifactId>
38+
<version>1.18</version>
39+
</dependency>
3540
<dependency>
3641
<groupId>org.apache.commons</groupId>
3742
<artifactId>commons-lang3</artifactId>
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/*
2+
Copyright 2017, 2018 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 com.google.common.io.ByteStreams;
16+
import io.kubernetes.client.models.V1Pod;
17+
import java.io.BufferedInputStream;
18+
import java.io.File;
19+
import java.io.FileOutputStream;
20+
import java.io.IOException;
21+
import java.io.InputStream;
22+
import java.io.OutputStream;
23+
import java.nio.file.Path;
24+
import org.apache.commons.codec.binary.Base64InputStream;
25+
import org.apache.commons.compress.archivers.ArchiveEntry;
26+
import org.apache.commons.compress.archivers.ArchiveInputStream;
27+
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
28+
import org.slf4j.Logger;
29+
import org.slf4j.LoggerFactory;
30+
31+
public class Copy extends Exec {
32+
private static final Logger log = LoggerFactory.getLogger(Copy.class);
33+
34+
/** Simple Copy constructor, uses default configuration */
35+
public Copy() {
36+
super(Configuration.getDefaultApiClient());
37+
}
38+
39+
/**
40+
* Copy Constructor
41+
*
42+
* @param apiClient The api client to use.
43+
*/
44+
public Copy(ApiClient apiClient) {
45+
super(apiClient);
46+
}
47+
48+
public InputStream copyFileFromPod(String namespace, String pod, String srcPath)
49+
throws ApiException, IOException {
50+
return copyFileFromPod(namespace, pod, null, srcPath);
51+
}
52+
53+
public InputStream copyFileFromPod(V1Pod pod, String srcPath) throws ApiException, IOException {
54+
return copyFileFromPod(pod, null, srcPath);
55+
}
56+
57+
public InputStream copyFileFromPod(V1Pod pod, String container, String srcPath)
58+
throws ApiException, IOException {
59+
return copyFileFromPod(
60+
pod.getMetadata().getNamespace(), pod.getMetadata().getName(), container, srcPath);
61+
}
62+
63+
public InputStream copyFileFromPod(String namespace, String pod, String container, String srcPath)
64+
throws ApiException, IOException {
65+
Process proc =
66+
this.exec(
67+
namespace,
68+
pod,
69+
new String[] {"sh", "-c", "cat " + srcPath + " | base64"},
70+
container,
71+
false,
72+
false);
73+
return new Base64InputStream(proc.getInputStream());
74+
}
75+
76+
public void copyFileFromPod(
77+
String namespace, String name, String container, String srcPath, Path destination)
78+
throws ApiException, IOException {
79+
try (InputStream is = copyFileFromPod(namespace, name, srcPath);
80+
FileOutputStream fos = new FileOutputStream(destination.toFile())) {
81+
ByteStreams.copy(is, fos);
82+
fos.flush();
83+
}
84+
}
85+
86+
public void copyDirectoryFromPod(V1Pod pod, String srcPath, Path destination)
87+
throws ApiException, IOException {
88+
copyDirectoryFromPod(pod, null, srcPath, destination);
89+
}
90+
91+
public void copyDirectoryFromPod(V1Pod pod, String container, String srcPath, Path destination)
92+
throws ApiException, IOException {
93+
copyDirectoryFromPod(
94+
pod.getMetadata().getNamespace(),
95+
pod.getMetadata().getName(),
96+
container,
97+
srcPath,
98+
destination);
99+
}
100+
101+
public void copyDirectoryFromPod(String namespace, String pod, String srcPath, Path destination)
102+
throws ApiException, IOException {
103+
copyDirectoryFromPod(namespace, pod, null, srcPath, destination);
104+
}
105+
106+
public void copyDirectoryFromPod(
107+
String namespace, String pod, String container, String srcPath, Path destination)
108+
throws ApiException, IOException {
109+
// TODO: Test that 'tar' is present in the container?
110+
final Process proc =
111+
this.exec(
112+
namespace,
113+
pod,
114+
new String[] {"sh", "-c", "tar cf - " + srcPath + " | base64"},
115+
container,
116+
false,
117+
false);
118+
InputStream is = new Base64InputStream(new BufferedInputStream(proc.getInputStream()));
119+
try (ArchiveInputStream archive =
120+
new TarArchiveInputStream(is)) { // new GzipCompressorInputStream(is))) {
121+
for (ArchiveEntry entry = archive.getNextEntry();
122+
entry != null;
123+
entry = archive.getNextEntry()) {
124+
if (!archive.canReadEntryData(entry)) {
125+
log.error("Can't read: " + entry);
126+
continue;
127+
}
128+
File f = new File(destination.toFile(), entry.getName());
129+
if (entry.isDirectory()) {
130+
if (!f.isDirectory() && !f.mkdirs()) {
131+
throw new IOException("create directory failed: " + f);
132+
}
133+
} else {
134+
File parent = f.getParentFile();
135+
if (!parent.isDirectory() && !parent.mkdirs()) {
136+
throw new IOException("create directory failed: " + parent);
137+
}
138+
try (OutputStream fs = new FileOutputStream(f)) {
139+
System.out.println("Writing: " + f.getCanonicalPath());
140+
ByteStreams.copy(archive, fs);
141+
fs.flush();
142+
}
143+
}
144+
}
145+
}
146+
}
147+
148+
public static void copyFileFromPod(String namespace, String pod, String srcPath, Path dest)
149+
throws ApiException, IOException {
150+
Copy c = new Copy();
151+
InputStream is = c.copyFileFromPod(namespace, pod, null, srcPath);
152+
FileOutputStream os = new FileOutputStream(dest.toFile());
153+
ByteStreams.copy(is, os);
154+
os.flush();
155+
os.close();
156+
}
157+
}

0 commit comments

Comments
 (0)