Skip to content

Commit e9e8c29

Browse files
authored
feature: support for /project endpoint (getKubeconfig) (#3)
1 parent a8714cb commit e9e8c29

12 files changed

Lines changed: 483 additions & 23 deletions

File tree

modules/examples/README.md

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,38 @@ IbmCloudCodeEngine ceClient = new IbmCloudCodeEngine("Code Engine Client", authe
2323
ceClient.setServiceUrl("https://api." + System.getenv("CE_PROJECT_REGION") + ".codeengine.cloud.ibm.com/api/v1");
2424
```
2525

26+
### Get a Delegated Refresh Token from IAM using an HTTP client
27+
This example uses Java's `HttpURLConnection`, but you may use the HTTP client of your choice.
28+
```java
29+
URL iamUrl = new URL("https://iam.cloud.ibm.com/identity/token?"
30+
+ "grant_type=urn:ibm:params:oauth:grant-type:apikey&"
31+
+ "response_type=delegated_refresh_token&"
32+
+ "receiver_client_ids=ce&"
33+
+ "delegated_refresh_token_expiry=3600&"
34+
+ "apikey="
35+
+ System.getenv("CE_API_KEY"));
36+
HttpURLConnection iamConnection = (HttpURLConnection) iamUrl.openConnection();
37+
iamConnection.setRequestMethod("POST");
38+
iamConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
39+
BufferedReader iamInput = new BufferedReader(new InputStreamReader(iamConnection.getInputStream()));
40+
String iamResponse = "";
41+
String iamInputLine = "";
42+
while ((iamInputLine = iamInput.readLine()) != null) {
43+
iamResponse = iamResponse + iamInputLine;
44+
}
45+
iamInput.close();
46+
JSONObject iamJson = new JSONObject(iamResponse);
47+
String delegatedRefreshToken = iamJson.getString("delegated_refresh_token");
48+
```
49+
2650
### Use the Code Engine client to get a Kubernetes config
2751
```java
28-
ListKubeconfigOptions options = new ListKubeconfigOptions.Builder()
52+
GetKubeconfigOptions options = new GetKubeconfigOptions.Builder()
2953
.id(ceProjectID)
30-
.refreshToken(authenticator.requestToken().getRefreshToken())
54+
.xDelegatedRefreshToken(authenticator.requestToken().getRefreshToken())
3155
.build();
32-
Response<String> kubeConfigResponse = ceClient.listKubeconfig(options).execute();
33-
```
56+
Response<String> kubeConfigResponse = ceClient.getKubeconfig(options).execute();
57+
```
58+
59+
## Deprecated endpoint
60+
The `/namespaces/{id}/config` endpoint function, `listKubeconfig()`, is deprecated, and will be removed before Code Engine is out of Beta. Please use the `getKubeconfig()` function, demonstrated in the example above.

modules/examples/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929
<artifactId>client-java</artifactId>
3030
<version>9.0.0</version>
3131
</dependency>
32+
<dependency>
33+
<groupId>org.json</groupId>
34+
<artifactId>json</artifactId>
35+
<version>20180130</version>
36+
</dependency>
3237
</dependencies>
3338

3439
<properties>

modules/examples/src/main/java/com/ibm/cloud/code_engine/ibm_cloud_code_engine/v1/IbmCloudCodeEngineExamples.java

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,18 @@
1313

1414
package com.ibm.cloud.code_engine.ibm_cloud_code_engine.v1;
1515

16-
import com.ibm.cloud.code_engine.ibm_cloud_code_engine.v1.model.ListKubeconfigOptions;
16+
import com.ibm.cloud.code_engine.ibm_cloud_code_engine.v1.model.GetKubeconfigOptions;
1717
import com.ibm.cloud.sdk.core.security.IamAuthenticator;
1818
import com.ibm.cloud.sdk.core.http.Response;
1919

2020
import java.io.Reader;
2121
import java.io.StringReader;
22+
import java.net.HttpURLConnection;
23+
import java.net.URL;
24+
import java.io.BufferedReader;
25+
import java.io.InputStreamReader;
26+
27+
import org.json.JSONObject;
2228
import io.kubernetes.client.util.KubeConfig;
2329
import io.kubernetes.client.openapi.ApiClient;
2430
import io.kubernetes.client.util.Config;
@@ -43,15 +49,33 @@ public static void main(String[] args) throws Exception {
4349
IbmCloudCodeEngine ceClient = new IbmCloudCodeEngine("Code Engine Client", authenticator);
4450
ceClient.setServiceUrl("https://api." + System.getenv("CE_PROJECT_REGION") + ".codeengine.cloud.ibm.com/api/v1");
4551

46-
// Get an IAM refresh token using the authenticator.
47-
String refreshToken = authenticator.requestToken().getRefreshToken();
52+
// Get an IAM delegated refresh token using an HTTP client
53+
URL iamUrl = new URL("https://iam.cloud.ibm.com/identity/token?"
54+
+ "grant_type=urn:ibm:params:oauth:grant-type:apikey&"
55+
+ "response_type=delegated_refresh_token&"
56+
+ "receiver_client_ids=ce&"
57+
+ "delegated_refresh_token_expiry=3600&"
58+
+ "apikey="
59+
+ System.getenv("CE_API_KEY"));
60+
HttpURLConnection iamConnection = (HttpURLConnection) iamUrl.openConnection();
61+
iamConnection.setRequestMethod("POST");
62+
iamConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
63+
BufferedReader iamInput = new BufferedReader(new InputStreamReader(iamConnection.getInputStream()));
64+
String iamResponse = "";
65+
String iamInputLine = "";
66+
while ((iamInputLine = iamInput.readLine()) != null) {
67+
iamResponse = iamResponse + iamInputLine;
68+
}
69+
iamInput.close();
70+
JSONObject iamJson = new JSONObject(iamResponse);
71+
String delegatedRefreshToken = iamJson.getString("delegated_refresh_token");
4872

4973
// Get Code Egnine project config using the Code Engine Client
50-
ListKubeconfigOptions options = new ListKubeconfigOptions.Builder()
74+
GetKubeconfigOptions options = new GetKubeconfigOptions.Builder()
5175
.id(System.getenv("CE_PROJECT_ID"))
52-
.refreshToken(refreshToken)
76+
.xDelegatedRefreshToken(delegatedRefreshToken)
5377
.build();
54-
Response<String> kubeConfigResponse = ceClient.listKubeconfig(options).execute();
78+
Response<String> kubeConfigResponse = ceClient.getKubeconfig(options).execute();
5579

5680
// Setup Kubernetes client using the project config
5781
String kubeConfigString = kubeConfigResponse.getResult();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* (C) Copyright IBM Corp. 2020.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
14+
package com.ibm.cloud.code_engine.ibm_cloud_code_engine.v1;
15+
16+
import com.ibm.cloud.code_engine.ibm_cloud_code_engine.v1.model.ListKubeconfigOptions;
17+
import com.ibm.cloud.sdk.core.security.IamAuthenticator;
18+
import com.ibm.cloud.sdk.core.http.Response;
19+
20+
import java.io.Reader;
21+
import java.io.StringReader;
22+
import io.kubernetes.client.util.KubeConfig;
23+
import io.kubernetes.client.openapi.ApiClient;
24+
import io.kubernetes.client.util.Config;
25+
import io.kubernetes.client.openapi.Configuration;
26+
import io.kubernetes.client.openapi.apis.CoreV1Api;
27+
import io.kubernetes.client.openapi.models.V1ConfigMapList;
28+
29+
public class IbmCloudCodeEngineExamplesDeprecated {
30+
31+
// Suppress utility class error by making private constructor
32+
private IbmCloudCodeEngineExamplesDeprecated() {
33+
throw new IllegalStateException("Just an example");
34+
}
35+
36+
public static void main(String[] args) throws Exception {
37+
38+
// Create an IAM authenticator.
39+
IamAuthenticator authenticator = new IamAuthenticator(System.getenv("CE_API_KEY"));
40+
authenticator.setClientIdAndSecret("bx", "bx");
41+
42+
// Construct the Code Engine Client
43+
IbmCloudCodeEngine ceClient = new IbmCloudCodeEngine("Code Engine Client", authenticator);
44+
ceClient.setServiceUrl("https://api." + System.getenv("CE_PROJECT_REGION") + ".codeengine.cloud.ibm.com/api/v1");
45+
46+
// Get an IAM refresh token using the authenticator.
47+
String refreshToken = authenticator.requestToken().getRefreshToken();
48+
49+
// Get Code Egnine project config using the Code Engine Client
50+
ListKubeconfigOptions options = new ListKubeconfigOptions.Builder()
51+
.id(System.getenv("CE_PROJECT_ID"))
52+
.refreshToken(refreshToken)
53+
.build();
54+
Response<String> kubeConfigResponse = ceClient.listKubeconfig(options).execute();
55+
56+
// Setup Kubernetes client using the project config
57+
String kubeConfigString = kubeConfigResponse.getResult();
58+
Reader kubeConfigReader = new StringReader(kubeConfigString);
59+
KubeConfig config = KubeConfig.loadKubeConfig(kubeConfigReader);
60+
ApiClient client = Config.fromConfig(config);
61+
Configuration.setDefaultApiClient(client);
62+
63+
// Get something from project.
64+
CoreV1Api api = new CoreV1Api();
65+
V1ConfigMapList configMapList = api.listNamespacedConfigMap(config.getNamespace(), null, null, null, null, null, null, null, null, null);
66+
System.out.printf("Project %s has %d configmaps.", System.getenv("CE_PROJECT_ID"), configMapList.getItems().size());
67+
}
68+
}

modules/ibm-cloud-code-engine/src/main/java/com/ibm/cloud/code_engine/ibm_cloud_code_engine/v1/IbmCloudCodeEngine.java

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* (C) Copyright IBM Corp. 2020.
2+
* (C) Copyright IBM Corp. 2021.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
55
* the License. You may obtain a copy of the License at
@@ -18,6 +18,7 @@
1818
package com.ibm.cloud.code_engine.ibm_cloud_code_engine.v1;
1919

2020
import com.ibm.cloud.code_engine.common.SdkCommon;
21+
import com.ibm.cloud.code_engine.ibm_cloud_code_engine.v1.model.GetKubeconfigOptions;
2122
import com.ibm.cloud.code_engine.ibm_cloud_code_engine.v1.model.ListKubeconfigOptions;
2223
import com.ibm.cloud.sdk.core.http.RequestBuilder;
2324
import com.ibm.cloud.sdk.core.http.ResponseConverter;
@@ -31,7 +32,7 @@
3132
import java.util.Map.Entry;
3233

3334
/**
34-
* The purpose is to provide an API to get Kubeconfig for IBM Cloud Code Engine Project.
35+
* The purpose is to provide an API to get Kubeconfig file for IBM Cloud Code Engine Project.
3536
*
3637
* @version v1
3738
*/
@@ -78,9 +79,10 @@ public IbmCloudCodeEngine(String serviceName, Authenticator authenticator) {
7879
}
7980

8081
/**
81-
* Retrieve KUBECONFIG for a specified project.
82+
* Deprecated soon: Retrieve KUBECONFIG for a specified project.
8283
*
83-
* Returns the KUBECONFIG, similar to the output of `kubectl config view --minify=true`.
84+
* **Deprecated soon**: This API will be deprecated soon. Use the [GET /project/{id}/config](#get-kubeconfig) API
85+
* instead. Returns the KUBECONFIG file, similar to the output of `kubectl config view --minify=true`.
8486
*
8587
* @param listKubeconfigOptions the {@link ListKubeconfigOptions} containing the options for the call
8688
* @return a {@link ServiceCall} with a result of type {@link String}
@@ -95,8 +97,51 @@ public ServiceCall<String> listKubeconfig(ListKubeconfigOptions listKubeconfigOp
9597
for (Entry<String, String> header : sdkHeaders.entrySet()) {
9698
builder.header(header.getKey(), header.getValue());
9799
}
98-
builder.header("Accept", "text/plain");
99100
builder.header("Refresh-Token", listKubeconfigOptions.refreshToken());
101+
if (listKubeconfigOptions.accept() != null) {
102+
builder.header("Accept", listKubeconfigOptions.accept());
103+
}
104+
ResponseConverter<String> responseConverter = ResponseConverterUtils.getString();
105+
return createServiceCall(builder.build(), responseConverter);
106+
}
107+
108+
/**
109+
* Retrieve KUBECONFIG for a specified project.
110+
*
111+
* Returns the KUBECONFIG, similar to the output of `kubectl config view --minify=true`. There are 2 tokens in the
112+
* Request Header and a query parameter that you must provide.
113+
* These values can be generated as follows: 1. Auth Header Pass the generated IAM Token as the Authorization header
114+
* from the CLI as `token=cat $HOME/.bluemix/config.json | jq .IAMToken -r`. Generate the token with the [Create an
115+
* IAM access token for a user or service ID using an API
116+
* key](https://cloud.ibm.com/apidocs/iam-identity-token-api#gettoken-apikey) API.
117+
*
118+
* 2. X-Delegated-Refresh-Token Header Generate an IAM Delegated Refresh Token for Code Engine with the [Create an IAM
119+
* access token and delegated refresh token for a user or service
120+
* ID](https://cloud.ibm.com/apidocs/iam-identity-token-api#gettoken-apikey-delegatedrefreshtoken) API. Specify the
121+
* `receiver_client_ids` value to be `ce` and the `delegated_refresh_token_expiry` value to be `3600`.
122+
*
123+
* 3. Project ID In order to retrieve the Kubeconfig file for a specific Code Engine project, use the CLI to extract
124+
* the ID
125+
* `id=ibmcloud ce project get -n ${CE_PROJECT_NAME} -o jsonpath={.guid}` You must be logged into the account where
126+
* the project was created to retrieve the ID.
127+
*
128+
* @param getKubeconfigOptions the {@link GetKubeconfigOptions} containing the options for the call
129+
* @return a {@link ServiceCall} with a result of type {@link String}
130+
*/
131+
public ServiceCall<String> getKubeconfig(GetKubeconfigOptions getKubeconfigOptions) {
132+
com.ibm.cloud.sdk.core.util.Validator.notNull(getKubeconfigOptions,
133+
"getKubeconfigOptions cannot be null");
134+
Map<String, String> pathParamsMap = new HashMap<String, String>();
135+
pathParamsMap.put("id", getKubeconfigOptions.id());
136+
RequestBuilder builder = RequestBuilder.get(RequestBuilder.resolveRequestUrl(getServiceUrl(), "/project/{id}/config", pathParamsMap));
137+
Map<String, String> sdkHeaders = SdkCommon.getSdkHeaders("ibm_cloud_code_engine", "v1", "getKubeconfig");
138+
for (Entry<String, String> header : sdkHeaders.entrySet()) {
139+
builder.header(header.getKey(), header.getValue());
140+
}
141+
builder.header("X-Delegated-Refresh-Token", getKubeconfigOptions.xDelegatedRefreshToken());
142+
if (getKubeconfigOptions.accept() != null) {
143+
builder.header("Accept", getKubeconfigOptions.accept());
144+
}
100145
ResponseConverter<String> responseConverter = ResponseConverterUtils.getString();
101146
return createServiceCall(builder.build(), responseConverter);
102147
}

0 commit comments

Comments
 (0)