Skip to content

Commit 6c0d168

Browse files
Merge branch 'release-1.25.72' into develop
* release-1.25.72: Bumping version to 1.25.72 Update changelog based on model updates Add support for cluster id
2 parents 112aaa4 + 2c5ca39 commit 6c0d168

File tree

10 files changed

+130
-27
lines changed

10 files changed

+130
-27
lines changed

.changes/1.25.72.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[
2+
{
3+
"category": "``eks``",
4+
"description": "Adding support for local Amazon EKS clusters on Outposts",
5+
"type": "api-change"
6+
}
7+
]

CHANGELOG.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
CHANGELOG
33
=========
44

5+
1.25.72
6+
=======
7+
8+
* api-change:``eks``: Adding support for local Amazon EKS clusters on Outposts
9+
10+
511
1.25.71
612
=======
713

awscli/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"""
1818
import os
1919

20-
__version__ = '1.25.71'
20+
__version__ = '1.25.72'
2121

2222
#
2323
# Get our data path to be added to botocore's search path

awscli/customizations/eks/get_token.py

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
from awscli.customizations.commands import BasicCommand
2424
from awscli.customizations.utils import uni_print
25+
from awscli.customizations.utils import validate_mutually_exclusive
2526

2627
AUTH_SERVICE = "sts"
2728
AUTH_COMMAND = "GetCallerIdentity"
@@ -62,7 +63,7 @@
6263

6364
TOKEN_PREFIX = 'k8s-aws-v1.'
6465

65-
CLUSTER_NAME_HEADER = 'x-k8s-aws-id'
66+
K8S_AWS_ID_HEADER = 'x-k8s-aws-id'
6667

6768

6869
class GetTokenCommand(BasicCommand):
@@ -78,9 +79,9 @@ class GetTokenCommand(BasicCommand):
7879
{
7980
'name': 'cluster-name',
8081
'help_text': (
81-
"Specify the name of the Amazon EKS cluster to create a token for."
82+
"Specify the name of the Amazon EKS cluster to create a token for. (Note: for local clusters on AWS Outposts, please use --cluster-id parameter)"
8283
),
83-
'required': True,
84+
'required': False,
8485
},
8586
{
8687
'name': 'role-arn',
@@ -93,6 +94,14 @@ class GetTokenCommand(BasicCommand):
9394
),
9495
'required': False,
9596
},
97+
{
98+
'name': 'cluster-id',
99+
# When EKS in-region cluster supports cluster-id, we will need to update this help text
100+
'help_text': (
101+
"Specify the id of the Amazon EKS cluster to create a token for. (Note: for local clusters on AWS Outposts only)"
102+
),
103+
'required': False,
104+
},
96105
]
97106

98107
def get_expiration_time(self):
@@ -106,7 +115,17 @@ def _run_main(self, parsed_args, parsed_globals):
106115
sts_client = client_factory.get_sts_client(
107116
region_name=parsed_globals.region, role_arn=parsed_args.role_arn
108117
)
109-
token = TokenGenerator(sts_client).get_token(parsed_args.cluster_name)
118+
119+
validate_mutually_exclusive(parsed_args, ['cluster_name'], ['cluster_id'])
120+
121+
if parsed_args.cluster_id:
122+
identifier = parsed_args.cluster_id
123+
elif parsed_args.cluster_name:
124+
identifier = parsed_args.cluster_name
125+
else:
126+
return ValueError("Either parameter --cluster-name or --cluster-id must be specified.")
127+
128+
token = TokenGenerator(sts_client).get_token(identifier)
110129

111130
# By default STS signs the url for 15 minutes so we are creating a
112131
# rfc3339 timestamp with expiration in 14 minutes as part of the token, which
@@ -193,18 +212,18 @@ class TokenGenerator(object):
193212
def __init__(self, sts_client):
194213
self._sts_client = sts_client
195214

196-
def get_token(self, cluster_name):
215+
def get_token(self, k8s_aws_id):
197216
"""Generate a presigned url token to pass to kubectl."""
198-
url = self._get_presigned_url(cluster_name)
217+
url = self._get_presigned_url(k8s_aws_id)
199218
token = TOKEN_PREFIX + base64.urlsafe_b64encode(
200219
url.encode('utf-8')
201220
).decode('utf-8').rstrip('=')
202221
return token
203222

204-
def _get_presigned_url(self, cluster_name):
223+
def _get_presigned_url(self, k8s_aws_id):
205224
return self._sts_client.generate_presigned_url(
206225
'get_caller_identity',
207-
Params={'ClusterName': cluster_name},
226+
Params={K8S_AWS_ID_HEADER: k8s_aws_id},
208227
ExpiresIn=URL_TIMEOUT,
209228
HttpMethod='GET',
210229
)
@@ -222,7 +241,7 @@ def get_sts_client(self, region_name=None, role_arn=None):
222241
client_kwargs['aws_secret_access_key'] = creds['SecretAccessKey']
223242
client_kwargs['aws_session_token'] = creds['SessionToken']
224243
sts = self._session.create_client('sts', **client_kwargs)
225-
self._register_cluster_name_handlers(sts)
244+
self._register_k8s_aws_id_handlers(sts)
226245
return sts
227246

228247
def _get_role_credentials(self, region_name, role_arn):
@@ -231,22 +250,20 @@ def _get_role_credentials(self, region_name, role_arn):
231250
RoleArn=role_arn, RoleSessionName='EKSGetTokenAuth'
232251
)['Credentials']
233252

234-
def _register_cluster_name_handlers(self, sts_client):
253+
def _register_k8s_aws_id_handlers(self, sts_client):
235254
sts_client.meta.events.register(
236255
'provide-client-params.sts.GetCallerIdentity',
237-
self._retrieve_cluster_name,
256+
self._retrieve_k8s_aws_id,
238257
)
239258
sts_client.meta.events.register(
240259
'before-sign.sts.GetCallerIdentity',
241-
self._inject_cluster_name_header,
260+
self._inject_k8s_aws_id_header,
242261
)
243262

244-
def _retrieve_cluster_name(self, params, context, **kwargs):
245-
if 'ClusterName' in params:
246-
context['eks_cluster'] = params.pop('ClusterName')
263+
def _retrieve_k8s_aws_id(self, params, context, **kwargs):
264+
if K8S_AWS_ID_HEADER in params:
265+
context[K8S_AWS_ID_HEADER] = params.pop(K8S_AWS_ID_HEADER)
247266

248-
def _inject_cluster_name_header(self, request, **kwargs):
249-
if 'eks_cluster' in request.context:
250-
request.headers[CLUSTER_NAME_HEADER] = request.context[
251-
'eks_cluster'
252-
]
267+
def _inject_k8s_aws_id_header(self, request, **kwargs):
268+
if K8S_AWS_ID_HEADER in request.context:
269+
request.headers[K8S_AWS_ID_HEADER] = request.context[K8S_AWS_ID_HEADER]

awscli/customizations/eks/update_kubeconfig.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,17 @@ def get_user_entry(self):
288288
Return a user entry generated using
289289
the previously obtained description.
290290
"""
291+
cluster_description = self._get_cluster_description()
292+
region = cluster_description.get("arn").split(":")[3]
293+
outpost_config = cluster_description.get("outpostConfig")
291294

292-
region = self._get_cluster_description().get("arn").split(":")[3]
295+
if outpost_config is None:
296+
cluster_identification_parameter = "--cluster-name"
297+
cluster_identification_value = self._cluster_name
298+
else:
299+
# If cluster contains outpostConfig, use id for identification
300+
cluster_identification_parameter = "--cluster-id"
301+
cluster_identification_value = cluster_description.get("id")
293302

294303
generated_user = OrderedDict([
295304
("name", self._get_cluster_description().get("arn", "")),
@@ -302,8 +311,8 @@ def get_user_entry(self):
302311
region,
303312
"eks",
304313
"get-token",
305-
"--cluster-name",
306-
self._cluster_name,
314+
cluster_identification_parameter,
315+
cluster_identification_value,
307316
]),
308317
("command", "aws"),
309318
]))

doc/source/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
# The short X.Y version.
5353
version = '1.25.'
5454
# The full version, including alpha/beta/rc tags.
55-
release = '1.25.71'
55+
release = '1.25.72'
5656

5757
# The language for content autogenerated by Sphinx. Refer to documentation
5858
# for a list of supported languages.

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ universal = 0
33

44
[metadata]
55
requires_dist =
6-
botocore==1.27.70
6+
botocore==1.27.71
77
docutils>=0.10,<0.17
88
s3transfer>=0.6.0,<0.7.0
99
PyYAML>=3.10,<5.5

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def find_version(*file_paths):
2424

2525

2626
install_requires = [
27-
'botocore==1.27.70',
27+
'botocore==1.27.71',
2828
'docutils>=0.10,<0.17',
2929
's3transfer>=0.6.0,<0.7.0',
3030
'PyYAML>=3.10,<5.5',

tests/functional/eks/test_util.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,40 @@ def describe_cluster_response():
6262
}
6363
}
6464

65+
def describe_cluster_response_outpost_cluster():
66+
"""Get an example describe_cluster call (For mocking)"""
67+
return {
68+
"cluster": {
69+
"status": "ACTIVE",
70+
"endpoint": "https://endpoint.amazonaws.com",
71+
"name": EXAMPLE_NAME,
72+
"certificateAuthority": {
73+
"data": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpWR1Z6ZEdsdVp5QkVZWFJoRFFwVVpYTjBhVzVuSUVSaGRHRU5DbFJsYzNScGJtY2dSR0YwWVEwS2EzVmlaWEp1WlhSbGN6QWVGdzBLVkdWemRHbHVaeUJFWVhSaERRcFVaWE4wYVc1bklFUmhkR0ZWQkFNVERRcHJkV0psY201bGRHVnpNQUVpTUEwS1ZHVnpkR2x1WnlCRVlYUmhEUXBVWlhOMGFXNW5JRVJoZEdFTkNsUmxjM1JwYm1jZ1JHRjBZY3UvR1FnbmFTcDNZaHBDTWhGVVpYTjBhVzVuSUVSaGRHRXl3clZqeEpWNjNwNFVHRmpZdHdGR1drUldJVkV1VkdWemRHbHVaeUJFWVhSaGJzT0MxSVJiTDhPd0lpMVhiWGg2VkdWemRHbHVaeUJFWVhSaFpXVndTTk9VVUZKNmN5QWJaaFpnWVNkTUV3MEtGMVJsYzNScGJtY2dSR0YwWVFZRFZSMFBBUUVFQkFNQ0FsUmxjM1JwYm1jZ1JHRjBZUUV3RFFvR0NTcElEUXBVWlhOMGFXNW5JRVJoZEdGcEgxc1pPRTNMa3lrMU9DWUNHUloyTEZjM3paOCtHell3WEZSbGMzUnBibWNnUkdGMFlYMUR5NjFNMVlGV1AxWVRIMVJsYzNScGJtY2dSR0YwWVd0aE5oMVphM2dWUDBGaGNSWjdKaW9oZVc4N1JsUmxjM1JwYm1jZ1JHRjBZUVpIVHd4NE9IdzZmZz09DQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0t"
74+
},
75+
"roleArn": "arn:aws:iam::111222333444/eksRole",
76+
"resourcesVpcConfig": {
77+
"subnetIds": [
78+
"subnet-00000000000000000",
79+
"subnet-00000000000000001",
80+
"subnet-00000000000000002"
81+
],
82+
"vpcId": "vpc-00000000000000000",
83+
"securityGroupIds": [
84+
"sg-00000000000000000"
85+
]
86+
},
87+
"version": "1.10",
88+
"arn": "arn:aws:eks:region:111222333444:cluster/" + EXAMPLE_NAME,
89+
"createdAt": 1500000000.000,
90+
"id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
91+
"outpostConfig": {
92+
"outpostArns": [
93+
"arn:aws:outposts:us-west-2:111222333444:outpost/op-00000000000000000"
94+
],
95+
}
96+
}
97+
}
98+
6599
def describe_cluster_no_status_response():
66100
"""Get an example describe_cluster call (For mocking)"""
67101
return {

tests/unit/customizations/eks/test_update_kubeconfig.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from awscli.customizations.eks.ordered_yaml import ordered_yaml_load
3131
from tests.functional.eks.test_util import get_testdata
3232
from tests.functional.eks.test_util import (describe_cluster_response,
33+
describe_cluster_response_outpost_cluster,
3334
describe_cluster_no_status_response,
3435
describe_cluster_creating_response,
3536
describe_cluster_deleting_response)
@@ -185,6 +186,25 @@ def setUp(self):
185186
]))
186187
])
187188

189+
self._correct_user_entry_outpost_cluster = OrderedDict([
190+
("name", describe_cluster_response()["cluster"]["arn"]),
191+
("user", OrderedDict([
192+
("exec", OrderedDict([
193+
("apiVersion", API_VERSION),
194+
("args",
195+
[
196+
"--region",
197+
"region",
198+
"eks",
199+
"get-token",
200+
"--cluster-id",
201+
"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
202+
]),
203+
("command", "aws")
204+
]))
205+
]))
206+
])
207+
188208
self._mock_client = mock.Mock()
189209
self._mock_client.describe_cluster.return_value =\
190210
describe_cluster_response()
@@ -229,6 +249,16 @@ def test_get_user_entry(self):
229249
)
230250
self._session.create_client.assert_called_once_with("eks")
231251

252+
def test_get_user_entry_outpost_cluster(self):
253+
self._mock_client.describe_cluster.return_value =\
254+
describe_cluster_response_outpost_cluster()
255+
self.assertEqual(self._client.get_user_entry(),
256+
self._correct_user_entry_outpost_cluster)
257+
self._mock_client.describe_cluster.assert_called_once_with(
258+
name="ExampleCluster"
259+
)
260+
self._session.create_client.assert_called_once_with("eks")
261+
232262
def test_get_both(self):
233263
self.assertEqual(self._client.get_cluster_entry(),
234264
self._correct_cluster_entry)

0 commit comments

Comments
 (0)