Skip to content

Commit e25ef39

Browse files
authored
feature: support for /project endpoint (get_kubeconfig) (#3)
* feature: support for /project endpoint (get_kubeconfig) * drop tests for Python 3.5 * update readme for Python 3.6
1 parent 1879522 commit e25ef39

File tree

7 files changed

+322
-32
lines changed

7 files changed

+322
-32
lines changed

.travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ notifications:
1313

1414
matrix:
1515
include:
16-
- python: 3.5
1716
- python: 3.6
1817
- python: 3.7
1918
- python: 3.8

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ Service Name | Imported Class Name
5050

5151
* An [IBM Cloud][ibm-cloud-onboarding] account.
5252
* An IAM API key to allow the SDK to access your account. Create one [here](https://cloud.ibm.com/iam/apikeys).
53-
* Python 3.5.3 or above.
53+
* Python 3.6 or above.
5454

5555
## Installation
5656

example/README.md

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
## Running example.py
44

55
To run the example, create a Code Engine project from the Console or Code Engine CLI, and run the following commands from this directory:
6-
1. `pip3 install kubernetes`
6+
1. `pip install kubernetes`
77
2. `export CE_API_KEY=<Your IBM Cloud API key>`
88
3. `export CE_PROJECT_ID=<Your Code Engine project ID>`
99
4. `export CE_PROJECT_REGION=<The region (e.g. 'us-south') of your Code Engine project>`
10-
5. `python3 example.py`
10+
5. `python example.py`
11+
12+
Note: Requires Python 3.6 or later.
1113

1214
## How-to
1315

@@ -28,11 +30,28 @@ ce_client.set_service_url(
2830
)
2931
```
3032

33+
### Use an HTTP library to get a Delegated Refresh Token from IAM
34+
```python
35+
iam_response = requests.post('https://iam.cloud.ibm.com/identity/token', headers={
36+
'Content-Type': 'application/x-www-form-urlencoded'
37+
}, data={
38+
'grant_type': 'urn:ibm:params:oauth:grant-type:apikey',
39+
'apikey': os.environ.get('CE_API_KEY'),
40+
'response_type': 'delegated_refresh_token',
41+
'receiver_client_ids': 'ce',
42+
'delegated_refresh_token_expiry': '3600'
43+
})
44+
delegated_refresh_token = iam_response.json()['delegated_refresh_token']
45+
```
46+
3147
### Use the Code Engine client to get a Kubernetes config
3248
```python
33-
refresh_token = authenticator.token_manager.request_token().get('refresh_token')
34-
kubeconfig_response = ce_client.list_kubeconfig(
35-
refresh_token=refresh_token,
49+
kubeconfig_response = ce_client.get_kubeconfig(
50+
x_delegated_refresh_token=delegated_refresh_token,
3651
id=os.environ.get('CE_PROJECT_ID'),
3752
)
53+
kubeconfig_string = kubeconfig_response.get_result().content
3854
```
55+
56+
## Deprecated endpoint
57+
The `/namespaces/{id}/config` endpoint function, `list_kubeconfig()`, is deprecated, and will be removed before Code Engine is out of Beta. Please use the `get_kubeconfig()` function, demonstrated in the example above.

example/example.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import os
66
import tempfile
77
import kubernetes
8+
import requests
9+
import json
810
from ibm_code_engine_sdk.ibm_cloud_code_engine_v1 import IbmCloudCodeEngineV1
911
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator
1012

@@ -29,18 +31,28 @@
2931
'https://api.' + os.environ.get('CE_PROJECT_REGION') + '.codeengine.cloud.ibm.com/api/v1'
3032
)
3133

32-
# Get IAM tokens using the authenticator
33-
refresh_token = authenticator.token_manager.request_token().get('refresh_token')
34+
# Get a Delegated Refresh Token from IAM
35+
iam_response = requests.post('https://iam.cloud.ibm.com/identity/token', headers={
36+
'Content-Type': 'application/x-www-form-urlencoded'
37+
}, data={
38+
'grant_type': 'urn:ibm:params:oauth:grant-type:apikey',
39+
'apikey': os.environ.get('CE_API_KEY'),
40+
'response_type': 'delegated_refresh_token',
41+
'receiver_client_ids': 'ce',
42+
'delegated_refresh_token_expiry': '3600'
43+
})
44+
delegated_refresh_token = iam_response.json()['delegated_refresh_token']
3445

3546
# Get Code Engine project config using the Code Engine client.
36-
kubeconfig_response = ce_client.list_kubeconfig(
37-
refresh_token=refresh_token,
47+
kubeconfig_response = ce_client.get_kubeconfig(
48+
x_delegated_refresh_token=delegated_refresh_token,
3849
id=os.environ.get('CE_PROJECT_ID'),
3950
)
51+
kubeconfig_string = kubeconfig_response.get_result().content
4052

4153
# Setup Kubernetes client using project config
4254
kubeconfig_file, kubeconfig_filename = tempfile.mkstemp()
43-
os.write(kubeconfig_file, kubeconfig_response.get_result().content)
55+
os.write(kubeconfig_file, kubeconfig_string)
4456
kubernetes.config.load_kube_config(config_file=kubeconfig_filename)
4557
kube_client = kubernetes.client.CoreV1Api()
4658

example/example_deprecated.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""
2+
Example of IBM Cloud Code Engine SDK usage
3+
"""
4+
5+
import os
6+
import tempfile
7+
import kubernetes
8+
from ibm_code_engine_sdk.ibm_cloud_code_engine_v1 import IbmCloudCodeEngineV1
9+
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator
10+
11+
if (os.environ.get('CE_API_KEY') == None or
12+
os.environ.get('CE_PROJECT_REGION') == None or
13+
os.environ.get('CE_PROJECT_ID') == None):
14+
print(
15+
'You must set the envrionment variables CE_API_KEY, CE_PROJECT_REGION and CE_PROJECT_ID ' +
16+
'before using the example.'
17+
)
18+
19+
# Create an IAM authenticator.
20+
authenticator = IAMAuthenticator(
21+
apikey=os.environ.get('CE_API_KEY'),
22+
client_id='bx',
23+
client_secret='bx',
24+
)
25+
26+
# Construct the Code Engine client.
27+
ce_client = IbmCloudCodeEngineV1(authenticator=authenticator)
28+
ce_client.set_service_url(
29+
'https://api.' + os.environ.get('CE_PROJECT_REGION') + '.codeengine.cloud.ibm.com/api/v1'
30+
)
31+
32+
# Get IAM tokens using the authenticator
33+
refresh_token = authenticator.token_manager.request_token().get('refresh_token')
34+
35+
# Get Code Engine project config using the Code Engine client.
36+
kubeconfig_response = ce_client.list_kubeconfig(
37+
refresh_token=refresh_token,
38+
id=os.environ.get('CE_PROJECT_ID'),
39+
)
40+
kubeconfig_string = kubeconfig_response.get_result().content
41+
42+
# Setup Kubernetes client using project config
43+
kubeconfig_file, kubeconfig_filename = tempfile.mkstemp()
44+
os.write(kubeconfig_file, kubeconfig_string)
45+
kubernetes.config.load_kube_config(config_file=kubeconfig_filename)
46+
kube_client = kubernetes.client.CoreV1Api()
47+
48+
# Get something from project.
49+
contexts = kubernetes.config.list_kube_config_contexts(config_file=kubeconfig_filename)[0][0]
50+
namespace = contexts.get('context').get('namespace')
51+
configmaps = kube_client.list_namespaced_config_map(namespace)
52+
print(
53+
'Project ' + os.environ.get('CE_PROJECT_ID') +
54+
' has ' + str(len(configmaps.items)) + ' configmaps.'
55+
)

ibm_code_engine_sdk/ibm_cloud_code_engine_v1.py

Lines changed: 108 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# coding: utf-8
22

3-
# (C) Copyright IBM Corp. 2020.
3+
# (C) Copyright IBM Corp. 2021.
44
#
55
# Licensed under the Apache License, Version 2.0 (the "License");
66
# you may not use this file except in compliance with the License.
@@ -14,10 +14,10 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616

17-
# IBM OpenAPI SDK Code Generator Version: 3.12.0-64fe8d3f-20200820-144050
17+
# IBM OpenAPI SDK Code Generator Version: 3.15.0-45841b53-20201019-214802
1818

1919
"""
20-
The purpose is to provide an API to get Kubeconfig for IBM Cloud Code Engine Project
20+
The purpose is to provide an API to get Kubeconfig file for IBM Cloud Code Engine Project
2121
"""
2222

2323
from enum import Enum
@@ -81,20 +81,22 @@ def list_kubeconfig(self,
8181
**kwargs
8282
) -> DetailedResponse:
8383
"""
84-
Retrieve KUBECONFIG for a specified project.
84+
Deprecated soon: Retrieve KUBECONFIG for a specified project.
8585
86-
Returns the KUBECONFIG, similar to the output of `kubectl config view
87-
--minify=true`.
86+
**Deprecated soon**: This API will be deprecated soon. Use the [GET
87+
/project/{id}/config](#get-kubeconfig) API instead. Returns the KUBECONFIG file,
88+
similar to the output of `kubectl config view --minify=true`.
8889
8990
:param str refresh_token: The IAM Refresh token associated with the IBM
90-
Cloud account.
91-
:param str id: The id of the IBM Cloud Code Engine project.
92-
:param str accept: (optional) The type of the response: application/json or
93-
text/html. A character encoding can be specified by including a `charset`
94-
parameter. For example, 'text/html;charset=utf-8'.
91+
Cloud account. To retrieve your IAM token, run `ibmcloud iam oauth-tokens`.
92+
:param str id: The id of the IBM Cloud Code Engine project. To retrieve
93+
your project ID, run `ibmcloud ce project get -n <PROJECT_NAME>`.
94+
:param str accept: (optional) The type of the response: text/plain or
95+
application/json. A character encoding can be specified by including a
96+
`charset` parameter. For example, 'text/plain;charset=utf-8'.
9597
:param dict headers: A `dict` containing the request headers
9698
:return: A `DetailedResponse` containing the result, headers and HTTP status code.
97-
:rtype: DetailedResponse
99+
:rtype: DetailedResponse with `str` result
98100
"""
99101

100102
if refresh_token is None:
@@ -113,8 +115,82 @@ def list_kubeconfig(self,
113115
if 'headers' in kwargs:
114116
headers.update(kwargs.get('headers'))
115117

116-
url = '/namespaces/{0}/config'.format(
117-
*self.encode_path_vars(id))
118+
path_param_keys = ['id']
119+
path_param_values = self.encode_path_vars(id)
120+
path_param_dict = dict(zip(path_param_keys, path_param_values))
121+
url = '/namespaces/{id}/config'.format(**path_param_dict)
122+
request = self.prepare_request(method='GET',
123+
url=url,
124+
headers=headers)
125+
126+
response = self.send(request)
127+
return response
128+
129+
130+
def get_kubeconfig(self,
131+
x_delegated_refresh_token: str,
132+
id: str,
133+
*,
134+
accept: str = None,
135+
**kwargs
136+
) -> DetailedResponse:
137+
"""
138+
Retrieve KUBECONFIG for a specified project.
139+
140+
Returns the KUBECONFIG, similar to the output of `kubectl config view
141+
--minify=true`. There are 2 tokens in the Request Header and a query parameter
142+
that you must provide.
143+
These values can be generated as follows: 1. Auth Header Pass the generated IAM
144+
Token as the Authorization header from the CLI as `token=cat
145+
$HOME/.bluemix/config.json | jq .IAMToken -r`. Generate the token with the [Create
146+
an IAM access token for a user or service ID using an API
147+
key](https://cloud.ibm.com/apidocs/iam-identity-token-api#gettoken-apikey) API.
148+
2. X-Delegated-Refresh-Token Header Generate an IAM Delegated Refresh Token for
149+
Code Engine with the [Create an IAM access token and delegated refresh token for a
150+
user or service
151+
ID](https://cloud.ibm.com/apidocs/iam-identity-token-api#gettoken-apikey-delegatedrefreshtoken)
152+
API. Specify the `receiver_client_ids` value to be `ce` and the
153+
`delegated_refresh_token_expiry` value to be `3600`.
154+
3. Project ID In order to retrieve the Kubeconfig file for a specific Code Engine
155+
project, use the CLI to extract the ID
156+
`id=ibmcloud ce project get -n ${CE_PROJECT_NAME} -o jsonpath={.guid}` You must be
157+
logged into the account where the project was created to retrieve the ID.
158+
159+
:param str x_delegated_refresh_token: This IAM Delegated Refresh Token is
160+
specifically valid for Code Engine. Generate this token with the [Create an
161+
IAM access token and delegated refresh token for a user or service
162+
ID](https://cloud.ibm.com/apidocs/iam-identity-token-api#gettoken-apikey-delegatedrefreshtoken)
163+
API. Specify the `receiver_client_ids` value to be `ce` and the
164+
`delegated_refresh_token_expiry` value to be `3600`.
165+
:param str id: The id of the IBM Cloud Code Engine project.
166+
:param str accept: (optional) The type of the response: text/plain or
167+
application/json. A character encoding can be specified by including a
168+
`charset` parameter. For example, 'text/plain;charset=utf-8'.
169+
:param dict headers: A `dict` containing the request headers
170+
:return: A `DetailedResponse` containing the result, headers and HTTP status code.
171+
:rtype: DetailedResponse with `str` result
172+
"""
173+
174+
if x_delegated_refresh_token is None:
175+
raise ValueError('x_delegated_refresh_token must be provided')
176+
if id is None:
177+
raise ValueError('id must be provided')
178+
headers = {
179+
'X-Delegated-Refresh-Token': x_delegated_refresh_token,
180+
'Accept': accept
181+
}
182+
sdk_headers = get_sdk_headers(service_name=self.DEFAULT_SERVICE_NAME,
183+
service_version='V1',
184+
operation_id='get_kubeconfig')
185+
headers.update(sdk_headers)
186+
187+
if 'headers' in kwargs:
188+
headers.update(kwargs.get('headers'))
189+
190+
path_param_keys = ['id']
191+
path_param_values = self.encode_path_vars(id)
192+
path_param_dict = dict(zip(path_param_keys, path_param_values))
193+
url = '/project/{id}/config'.format(**path_param_dict)
118194
request = self.prepare_request(method='GET',
119195
url=url,
120196
headers=headers)
@@ -130,12 +206,27 @@ class ListKubeconfigEnums:
130206

131207
class Accept(str, Enum):
132208
"""
133-
The type of the response: application/json or text/html. A character encoding can
209+
The type of the response: text/plain or application/json. A character encoding can
210+
be specified by including a `charset` parameter. For example,
211+
'text/plain;charset=utf-8'.
212+
"""
213+
TEXT_PLAIN = 'text/plain'
214+
APPLICATION_JSON = 'application/json'
215+
216+
217+
class GetKubeconfigEnums:
218+
"""
219+
Enums for get_kubeconfig parameters.
220+
"""
221+
222+
class Accept(str, Enum):
223+
"""
224+
The type of the response: text/plain or application/json. A character encoding can
134225
be specified by including a `charset` parameter. For example,
135-
'text/html;charset=utf-8'.
226+
'text/plain;charset=utf-8'.
136227
"""
228+
TEXT_PLAIN = 'text/plain'
137229
APPLICATION_JSON = 'application/json'
138-
TEXT_HTML = 'text/html'
139230

140231

141232
##############################################################################

0 commit comments

Comments
 (0)