Description
Describe the bug
I'm not sure if it is correct to create an Issue for current SNAPSHOT, but I wanted to contribute to fix a bug, so I hope that this is fine.
When trying to authenticate to GCP, the GCPAuthenticator composes a gcloud cmd where the args are added without empty spaces:
String cmdPath = (String) config.get(CMD_PATH);
String cmdArgs = (String) config.get(CMD_ARGS);
String fullCmd = cmdPath + cmdArgs;
try {
Process process = this.pb.command(Arrays.asList(fullCmd.split(" "))).start();
resulting in a cmd like:
/opt/google-cloud-sdk/bin/gcloudconfig config-helper --format=json
** Client Version **
13.0.1-SNAPSHOT
To Reproduce
Run the KubeConfigFileClientExample against GCP
or write a unit test, e.g.:
@Test
public void testRefresh() {
String cmdPath = "/usr/lib/google-cloud-sdk/bin/gcloud";
String cmdArgs = "config config-helper --format=json";
String[] cmdArgsSplit = cmdArgs.split(" ");
Map<String, Object> gcpConfig = new HashMap<String, Object>() {{
put(GCPAuthenticator.ACCESS_TOKEN, "eyXXX");
put(GCPAuthenticator.CMD_PATH, cmdPath);
put(GCPAuthenticator.CMD_ARGS, cmdArgs);
put(GCPAuthenticator.EXPIRY, "2121-08-05T02:30:24Z");
}};
String fakeExecResult =
"{\n"
+ " \"credential\": {\n"
+ " \"access_token\": \"new-fake-token\",\n"
+ " \"id_token\": \"id-fake-token\",\n"
+ " \"token_expiry\": \"2121-08-05T02:30:24Z\"\n"
+ " }\n"
+ "}";
ProcessBuilder mockPB = Mockito.mock(ProcessBuilder.class);
Process mockProcess = Mockito.mock(Process.class);
Mockito.when(mockProcess.exitValue()).thenReturn(0);
Mockito.when(mockProcess.getInputStream())
.thenReturn(new ByteArrayInputStream(fakeExecResult.getBytes(StandardCharsets.UTF_8)));
try {
Mockito.when(mockPB.command(Mockito.anyList())).thenCallRealMethod();
Mockito.when(mockPB.start()).thenReturn(mockProcess);
Mockito.when(mockPB.command()).thenCallRealMethod();
} catch (IOException ex) {
ex.printStackTrace();
fail("Unexpected exception: " + ex);
}
new GCPAuthenticator(mockPB).refresh(gcpConfig);
List<String> expectedCommand = new ArrayList<String>() {{
add(cmdPath);
add(cmdArgsSplit[0]);
add(cmdArgsSplit[1]);
add(cmdArgsSplit[2]);
}};
List<String> executedCommand = mockPB.command();
Assert.assertEquals(4, executedCommand.size());
MatcherAssert.assertThat(executedCommand, is(expectedCommand));
}
Expected behavior
the command /opt/google-cloud-sdk/bin/gcloud config config-helper --format=json
should be composed, which should then execute without errors
KubeConfig
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: xxx
server: https://xxxx
name: xxxdev
- cluster:
certificate-authority-data: xxx
server: https://xxx
name: xxxprod
contexts:
- context:
cluster: xxxdev
namespace: preview
user: xxxdev
name: dev
- context:
cluster: xxxprod
namespace: prod
user: xxxprod
name: prod
current-context: dev
kind: Config
preferences: {}
users:
- name: xxx
user:
auth-provider:
config:
access-token: xxx
cmd-args: config config-helper --format=json
cmd-path: /opt/google-cloud-sdk/bin/gcloud
expiry: "2021-06-29T13:37:37Z"
expiry-key: '{.credential.token_expiry}'
token-key: '{.credential.access_token}'
name: gcp
- name: xxxdev
user:
auth-provider:
config:
access-token: xxx
cmd-args: config config-helper --format=json
cmd-path: /opt/google-cloud-sdk/bin/gcloud
expiry: "2021-08-13T06:42:53Z"
expiry-key: '{.credential.token_expiry}'
token-key: '{.credential.access_token}'
name: gcp
- name: xxxprod
user:
auth-provider:
config:
access-token: xxx
cmd-args: config config-helper --format=json
cmd-path: /opt/google-cloud-sdk/bin/gcloud
expiry: "2021-08-13T18:55:38Z"
expiry-key: '{.credential.token_expiry}'
token-key: '{.credential.access_token}'
name: gcp
Server (please complete the following information):
- OS: Linux (endeavourOS)
- Cloud: GCP
Comment
Currently the GCPAuthenticator has side effects and they are untested. In my opinion the GCPAuthenticator should not directly rely on a ProcessBuilder, but when it does, then it should be explicitly tested.