Skip to content

Commit 94a38a5

Browse files
shawkinsmanusa
authored andcommitted
fix #4234: fixing the skip method for base64 inputstream
1 parent 6b13cd2 commit 94a38a5

File tree

4 files changed

+103
-36
lines changed

4 files changed

+103
-36
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Fix #2811: Approve/Reject CSR not supported in v1beta1 CertificateSigningRequest API
77
* Fix #4216: Update metadata when `replaceStatus()` is called
88
* Fix #4217: patchStatus doesn't increment metadata.generation field in Kubernetes Mock Server (CRUD)
9+
* Fix #4234: corrected the skip method for base64 inputstream
910

1011
#### Improvements
1112
* Fix #3227 : Move `config.openshift.io` apiGroup resources out of `openshift-model/`

kubernetes-client/src/main/java/io/fabric8/kubernetes/client/utils/internal/Base64.java

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717

1818
import io.fabric8.kubernetes.client.KubernetesClientException;
1919

20+
import java.io.IOException;
21+
22+
//@formatter:off
2023
/**
2124
* <p>Encodes and decodes to and from Base64 notation.</p>
2225
* <p>Homepage: <a href="http://iharder.net/base64">http://iharder.net/base64</a>.</p>
@@ -1329,7 +1332,7 @@ public static byte[] decode( String s, int options ) throws java.io.IOException
13291332
* @see Base64
13301333
* @since 1.3
13311334
*/
1332-
public static class InputStream extends java.io.FilterInputStream {
1335+
public static class InputStream extends java.io.InputStream {
13331336

13341337
private boolean encode; // Encoding or decoding
13351338
private int position; // Current position in the buffer
@@ -1340,6 +1343,7 @@ public static class InputStream extends java.io.FilterInputStream {
13401343
private boolean breakLines; // Break lines at less than 80 characters
13411344
private int options; // Record options used to create the stream.
13421345
private byte[] decodabet; // Local copies to avoid extra method calls
1346+
private java.io.InputStream in;
13431347

13441348

13451349
/**
@@ -1375,7 +1379,7 @@ public InputStream( java.io.InputStream in ) {
13751379
*/
13761380
public InputStream( java.io.InputStream in, int options ) {
13771381

1378-
super( in );
1382+
this.in = in;
13791383
this.options = options; // Record for later
13801384
this.breakLines = (options & DO_BREAK_LINES) > 0;
13811385
this.encode = (options & ENCODE) > 0;
@@ -1385,6 +1389,11 @@ public InputStream( java.io.InputStream in, int options ) {
13851389
this.lineLength = 0;
13861390
this.decodabet = getDecodabet(options);
13871391
} // end constructor
1392+
1393+
@Override
1394+
public void close() throws IOException {
1395+
in.close();
1396+
}
13881397

13891398
/**
13901399
* Reads enough of the input stream to convert
@@ -1489,40 +1498,6 @@ else if( i == 0 ){
14891498
} // end else
14901499
} // end read
14911500

1492-
1493-
/**
1494-
* Calls {@link #read()} repeatedly until the end of stream
1495-
* is reached or <var>len</var> bytes are read.
1496-
* Returns number of bytes read into array or -1 if
1497-
* end of stream is encountered.
1498-
*
1499-
* @param dest array to hold values
1500-
* @param off offset for array
1501-
* @param len max number of bytes to read into array
1502-
* @return bytes read into array or -1 if end of stream is encountered.
1503-
* @since 1.3
1504-
*/
1505-
@Override
1506-
public int read( byte[] dest, int off, int len )
1507-
throws java.io.IOException {
1508-
int i;
1509-
int b;
1510-
for( i = 0; i < len; i++ ) {
1511-
b = read();
1512-
1513-
if( b >= 0 ) {
1514-
dest[off + i] = (byte) b;
1515-
}
1516-
else if( i == 0 ) {
1517-
return -1;
1518-
}
1519-
else {
1520-
break; // Out of 'for' loop
1521-
} // Out of 'for' loop
1522-
} // end for: each byte read
1523-
return i;
1524-
} // end read
1525-
15261501
} // end inner class InputStream
15271502

15281503

@@ -1756,3 +1731,4 @@ public void resumeEncoding() {
17561731

17571732

17581733
} // end class Base64
1734+
//@formatter:on
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Copyright (C) 2015 Red Hat, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.fabric8.kubernetes.client.utils.internal;
17+
18+
import org.junit.jupiter.api.Test;
19+
20+
import java.io.ByteArrayInputStream;
21+
import java.io.IOException;
22+
import java.nio.charset.StandardCharsets;
23+
24+
import static org.junit.jupiter.api.Assertions.assertEquals;
25+
26+
class Base64Test {
27+
28+
@Test
29+
void testSkip() throws IOException {
30+
Base64.InputStream is = new Base64.InputStream(
31+
new ByteArrayInputStream(Base64.encodeBytesToBytes("hello".getBytes(StandardCharsets.UTF_8))));
32+
assertEquals(104, is.read());
33+
assertEquals(3, is.skip(3));
34+
assertEquals(111, is.read());
35+
assertEquals(-1, is.read());
36+
}
37+
}

kubernetes-itests/src/test/java/io/fabric8/kubernetes/PodIT.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
import io.fabric8.kubernetes.client.dsl.ExecWatch;
3333
import io.fabric8.kubernetes.client.dsl.PodResource;
3434
import io.fabric8.kubernetes.client.readiness.Readiness;
35+
import io.fabric8.kubernetes.client.utils.InputStreamPumper;
36+
import org.awaitility.Awaitility;
3537
import org.junit.jupiter.api.Test;
3638
import org.slf4j.Logger;
3739
import org.slf4j.LoggerFactory;
@@ -49,6 +51,7 @@
4951
import java.util.List;
5052
import java.util.concurrent.CompletableFuture;
5153
import java.util.concurrent.CountDownLatch;
54+
import java.util.concurrent.Executors;
5255
import java.util.concurrent.TimeUnit;
5356
import java.util.concurrent.atomic.AtomicBoolean;
5457
import java.util.stream.Collectors;
@@ -215,6 +218,43 @@ public void onExit(int code, Status status) {
215218
assertNotNull(out.toString());
216219
}
217220

221+
@Test
222+
void execExitCode() throws Exception {
223+
client.pods().withName("pod-standard").waitUntilReady(POD_READY_WAIT_IN_SECONDS, TimeUnit.SECONDS);
224+
ByteArrayOutputStream out = new ByteArrayOutputStream();
225+
ExecWatch watch = client.pods().withName("pod-standard")
226+
.writingOutput(out)
227+
.exec("sh", "-c", "echo 'hello world!'");
228+
assertEquals(0, watch.exitCode().join());
229+
assertNotNull("hello world!", out.toString());
230+
}
231+
232+
@Test
233+
void execInteractiveShell() throws Exception {
234+
client.pods().withName("pod-standard").waitUntilReady(POD_READY_WAIT_IN_SECONDS, TimeUnit.SECONDS);
235+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
236+
ExecWatch watch = client.pods().withName("pod-standard")
237+
.redirectingInput()
238+
.redirectingOutput()
239+
.redirectingError()
240+
.withTTY()
241+
.exec("sh", "-i");
242+
243+
InputStreamPumper.pump(watch.getOutput(), baos::write, Executors.newSingleThreadExecutor());
244+
245+
watch.getInput().write("whoami\n".getBytes(StandardCharsets.UTF_8));
246+
watch.getInput().flush();
247+
248+
Awaitility.await().atMost(30, TimeUnit.SECONDS).until(() -> {
249+
return new String(baos.toByteArray(), StandardCharsets.UTF_8).contains("root");
250+
});
251+
252+
watch.close();
253+
254+
// no error is expected
255+
assertEquals(-1, watch.getError().read());
256+
}
257+
218258
@Test
219259
void readFile() throws IOException {
220260
client.pods().withName("pod-standard").waitUntilReady(POD_READY_WAIT_IN_SECONDS, TimeUnit.SECONDS);
@@ -285,6 +325,19 @@ void uploadDir() throws IOException {
285325
}
286326
}
287327

328+
@Test
329+
void copyDir() throws IOException {
330+
client.pods().withName("pod-standard").waitUntilReady(POD_READY_WAIT_IN_SECONDS, TimeUnit.SECONDS);
331+
332+
final Path tmpDir = Files.createTempDirectory("copyFile");
333+
334+
PodResource podResource = client.pods().withName("pod-standard");
335+
podResource.dir("/etc").copy(tmpDir);
336+
337+
Path msg = tmpDir.resolve("/etc/hosts");
338+
assertTrue(Files.exists(msg));
339+
}
340+
288341
@Test
289342
void copyFile() throws IOException {
290343
client.pods().withName("pod-standard").waitUntilReady(POD_READY_WAIT_IN_SECONDS, TimeUnit.SECONDS);

0 commit comments

Comments
 (0)