From fd0edd44ac4905571a411ab55d4941d79a1fff2f Mon Sep 17 00:00:00 2001 From: Ray Luo Date: Mon, 30 Nov 2015 23:05:17 -0800 Subject: [PATCH 1/7] cloudfront create-invalidation --paths --- awscli/customizations/cloudfront.py | 46 +++++++++++++++++ .../cloudfront/create-invalidation.rst | 7 ++- awscli/handlers.py | 2 + .../cloudfront/test_create_invalidation.py | 50 +++++++++++++++++++ 4 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 awscli/customizations/cloudfront.py create mode 100644 tests/functional/cloudfront/test_create_invalidation.py diff --git a/awscli/customizations/cloudfront.py b/awscli/customizations/cloudfront.py new file mode 100644 index 000000000000..bcf5a3536043 --- /dev/null +++ b/awscli/customizations/cloudfront.py @@ -0,0 +1,46 @@ +# Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. +from datetime import datetime + +from awscli.arguments import CustomArgument +from awscli.customizations.utils import validate_mutually_exclusive_handler + + +def register(event_handler): + """Provides a simpler --paths for ``aws cloudfront create-invalidation``""" + + event_handler.register( + 'building-argument-table.cloudfront.create-invalidation', _add_paths) + event_handler.register( + 'operation-args-parsed.cloudfront.create-invalidation', + validate_mutually_exclusive_handler(['invalidation_batch'], ['paths'])) + + +def _add_paths(argument_table, **kwargs): + argument_table['invalidation-batch'].required = False + argument_table['paths'] = PathsArgument() + + +class PathsArgument(CustomArgument): + + def __init__(self): + help = """The space-separated paths to be invalidated. + It will automatically generate a CallerReference for you.""" + super(PathsArgument, self).__init__('paths', nargs='+', help_text=help) + + def add_to_params(self, parameters, value): + if value: + parameters['InvalidationBatch'] = { + "CallerReference": datetime.utcnow().strftime('%Y%m%d%H%M%S'), + "Paths": {"Quantity": len(value), "Items": value}, + } diff --git a/awscli/examples/cloudfront/create-invalidation.rst b/awscli/examples/cloudfront/create-invalidation.rst index 7ee8991eb726..2b4416bf4ded 100644 --- a/awscli/examples/cloudfront/create-invalidation.rst +++ b/awscli/examples/cloudfront/create-invalidation.rst @@ -1,5 +1,10 @@ The following command creates an invalidation for a CloudFront distribution with the ID ``S11A16G5KZMEQD``:: + aws cloudfront create-invalidation --distribution-id S11A16G5KZMEQD \ + --paths /index.html /error.html + +Or you can use the following command to do the same thing. And you can have a chance to specify your own CallerReference here:: + aws cloudfront create-invalidation --invalidation-batch file://invbatch.json --distribution-id S11A16G5KZMEQD The distribution ID is available in the output of ``create-distribution`` and ``list-distributions``. @@ -14,7 +19,7 @@ The file ``invbatch.json`` is a JSON document in the current folder that specifi "CallerReference": "my-invalidation-2015-09-01" } -Output:: +Output of both commands:: { "Invalidation": { diff --git a/awscli/handlers.py b/awscli/handlers.py index c8be55502095..c5f780bac58b 100644 --- a/awscli/handlers.py +++ b/awscli/handlers.py @@ -33,6 +33,7 @@ from awscli.customizations.rds import register_rds_modify_split from awscli.customizations.putmetricdata import register_put_metric_data from awscli.customizations.sessendemail import register_ses_send_email +from awscli.customizations.cloudfront import register as cloudfront_register from awscli.customizations.iamvirtmfa import IAMVMFAWrapper from awscli.customizations.argrename import register_arg_renames from awscli.customizations.configure import register_configure_cmd @@ -108,6 +109,7 @@ def awscli_initialize(event_handlers): register_rds_modify_split(event_handlers) register_put_metric_data(event_handlers) register_ses_send_email(event_handlers) + cloudfront_register(event_handlers) IAMVMFAWrapper(event_handlers) register_arg_renames(event_handlers) register_configure_cmd(event_handlers) diff --git a/tests/functional/cloudfront/test_create_invalidation.py b/tests/functional/cloudfront/test_create_invalidation.py new file mode 100644 index 000000000000..10e05d096f66 --- /dev/null +++ b/tests/functional/cloudfront/test_create_invalidation.py @@ -0,0 +1,50 @@ +# Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. +from awscli.testutils import BaseAWSCommandParamsTest + + +class TestCreateInvalidation(BaseAWSCommandParamsTest): + + prefix = 'cloudfront create-invalidation --distribution-id my_id' + ' ' + + def test_invalidation_batch_only(self): + batch = "Paths={Quantity=2,Items=[foo.txt,bar.txt]},CallerReference=ab" + cmdline = self.prefix + '--invalidation-batch ' + batch + result = { + 'DistributionId': 'my_id', + 'InvalidationBatch': { + 'Paths': {'Items': ['foo.txt', 'bar.txt'], 'Quantity': 2}, + 'CallerReference': 'ab', + }, + } + self.assert_params_for_cmd(cmdline, result) + + def test_paths_only(self): + cmdline = self.prefix + '--paths index.html foo.txt' + result = { + 'DistributionId': 'my_id', + 'InvalidationBatch': { + 'Paths': {'Items': ['index.html', 'foo.txt'], 'Quantity': 2}, + }, + } + self.run_cmd(cmdline) + # There will be a CallerReference, but we don't really check it + del self.last_kwargs['InvalidationBatch']['CallerReference'] + self.assertEqual(self.last_kwargs, result) + + def test_invalidation_batch_and_paths(self): + cmdline = self.prefix + '--invalidation-batch {} --paths foo' + self.run_cmd(cmdline, expected_rc=255) + + def test_neither_invalidation_batch_or_paths(self): + self.run_cmd(self.prefix, expected_rc=255) From 0fbdab252cf8bc303bf5ca29ee5e704527fd7163 Mon Sep 17 00:00:00 2001 From: Ray Luo Date: Tue, 1 Dec 2015 09:56:17 -0800 Subject: [PATCH 2/7] Cloudfront is currently still in preview mode --- tests/functional/cloudfront/test_create_invalidation.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/functional/cloudfront/test_create_invalidation.py b/tests/functional/cloudfront/test_create_invalidation.py index 10e05d096f66..e81b22acf4da 100644 --- a/tests/functional/cloudfront/test_create_invalidation.py +++ b/tests/functional/cloudfront/test_create_invalidation.py @@ -10,7 +10,9 @@ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. -from awscli.testutils import BaseAWSCommandParamsTest +from awscli.testutils import BaseAWSPreviewCommandParamsTest as \ + BaseAWSCommandParamsTest + class TestCreateInvalidation(BaseAWSCommandParamsTest): From 27bf7c27923456b1a6bc9d41233eed06c9bc242f Mon Sep 17 00:00:00 2001 From: Ray Luo Date: Wed, 2 Dec 2015 13:42:26 -0800 Subject: [PATCH 3/7] Adjust documentation --- awscli/customizations/cloudfront.py | 8 ++++---- tests/functional/cloudfront/test_create_invalidation.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/awscli/customizations/cloudfront.py b/awscli/customizations/cloudfront.py index bcf5a3536043..fc05383779d7 100644 --- a/awscli/customizations/cloudfront.py +++ b/awscli/customizations/cloudfront.py @@ -34,12 +34,12 @@ def _add_paths(argument_table, **kwargs): class PathsArgument(CustomArgument): def __init__(self): - help = """The space-separated paths to be invalidated. - It will automatically generate a CallerReference for you.""" - super(PathsArgument, self).__init__('paths', nargs='+', help_text=help) + doc = """The space-separated paths to be invalidated. + Note: --invalidation-batch and --paths are mututally exclusive.""" + super(PathsArgument, self).__init__('paths', nargs='+', help_text=doc) def add_to_params(self, parameters, value): - if value: + if value is not None: parameters['InvalidationBatch'] = { "CallerReference": datetime.utcnow().strftime('%Y%m%d%H%M%S'), "Paths": {"Quantity": len(value), "Items": value}, diff --git a/tests/functional/cloudfront/test_create_invalidation.py b/tests/functional/cloudfront/test_create_invalidation.py index e81b22acf4da..263b54cc498c 100644 --- a/tests/functional/cloudfront/test_create_invalidation.py +++ b/tests/functional/cloudfront/test_create_invalidation.py @@ -17,7 +17,7 @@ class TestCreateInvalidation(BaseAWSCommandParamsTest): - prefix = 'cloudfront create-invalidation --distribution-id my_id' + ' ' + prefix = 'cloudfront create-invalidation --distribution-id my_id ' def test_invalidation_batch_only(self): batch = "Paths={Quantity=2,Items=[foo.txt,bar.txt]},CallerReference=ab" From 990e95e1d55a1e3011078bee92c0112cadc89541 Mon Sep 17 00:00:00 2001 From: Ray Luo Date: Wed, 2 Dec 2015 16:05:14 -0800 Subject: [PATCH 4/7] Make the CallerReference random --- awscli/customizations/cloudfront.py | 7 +++++-- awscli/examples/cloudfront/create-invalidation.rst | 4 +++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/awscli/customizations/cloudfront.py b/awscli/customizations/cloudfront.py index fc05383779d7..12d2d6de247c 100644 --- a/awscli/customizations/cloudfront.py +++ b/awscli/customizations/cloudfront.py @@ -10,7 +10,8 @@ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. -from datetime import datetime +import time +import random from awscli.arguments import CustomArgument from awscli.customizations.utils import validate_mutually_exclusive_handler @@ -40,7 +41,9 @@ def __init__(self): def add_to_params(self, parameters, value): if value is not None: + caller_reference = 'cli-%s-%s' % ( + int(time.time()), random.randint(1, 1000000)) parameters['InvalidationBatch'] = { - "CallerReference": datetime.utcnow().strftime('%Y%m%d%H%M%S'), + "CallerReference": caller_reference, "Paths": {"Quantity": len(value), "Items": value}, } diff --git a/awscli/examples/cloudfront/create-invalidation.rst b/awscli/examples/cloudfront/create-invalidation.rst index 2b4416bf4ded..06f1108032ea 100644 --- a/awscli/examples/cloudfront/create-invalidation.rst +++ b/awscli/examples/cloudfront/create-invalidation.rst @@ -3,7 +3,9 @@ The following command creates an invalidation for a CloudFront distribution with aws cloudfront create-invalidation --distribution-id S11A16G5KZMEQD \ --paths /index.html /error.html -Or you can use the following command to do the same thing. And you can have a chance to specify your own CallerReference here:: +The --paths will automatically generate a random CallerReference every time. + +Or you can use the following command to do the same thing, so that you can have a chance to specify your own CallerReference here:: aws cloudfront create-invalidation --invalidation-batch file://invbatch.json --distribution-id S11A16G5KZMEQD From 154632715d5decc2ce57d1cb505679243392a852 Mon Sep 17 00:00:00 2001 From: Ray Luo Date: Wed, 2 Dec 2015 17:03:29 -0800 Subject: [PATCH 5/7] Improve documentation --- awscli/customizations/cloudfront.py | 6 ++++-- awscli/examples/cloudfront/create-invalidation.rst | 4 ++-- tests/functional/cloudfront/test_create_invalidation.py | 1 - 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/awscli/customizations/cloudfront.py b/awscli/customizations/cloudfront.py index 12d2d6de247c..148294b8845d 100644 --- a/awscli/customizations/cloudfront.py +++ b/awscli/customizations/cloudfront.py @@ -35,8 +35,10 @@ def _add_paths(argument_table, **kwargs): class PathsArgument(CustomArgument): def __init__(self): - doc = """The space-separated paths to be invalidated. - Note: --invalidation-batch and --paths are mututally exclusive.""" + doc = ( + 'The space-separated paths to be invalidated.' + ' Note: --invalidation-batch and --paths are mututally exclusive.' + ) super(PathsArgument, self).__init__('paths', nargs='+', help_text=doc) def add_to_params(self, parameters, value): diff --git a/awscli/examples/cloudfront/create-invalidation.rst b/awscli/examples/cloudfront/create-invalidation.rst index 06f1108032ea..32b0f509b7e9 100644 --- a/awscli/examples/cloudfront/create-invalidation.rst +++ b/awscli/examples/cloudfront/create-invalidation.rst @@ -3,9 +3,9 @@ The following command creates an invalidation for a CloudFront distribution with aws cloudfront create-invalidation --distribution-id S11A16G5KZMEQD \ --paths /index.html /error.html -The --paths will automatically generate a random CallerReference every time. +The --paths will automatically generate a random ``CallerReference`` every time. -Or you can use the following command to do the same thing, so that you can have a chance to specify your own CallerReference here:: +Or you can use the following command to do the same thing, so that you can have a chance to specify your own ``CallerReference`` here:: aws cloudfront create-invalidation --invalidation-batch file://invbatch.json --distribution-id S11A16G5KZMEQD diff --git a/tests/functional/cloudfront/test_create_invalidation.py b/tests/functional/cloudfront/test_create_invalidation.py index 263b54cc498c..8c0b0a3378cb 100644 --- a/tests/functional/cloudfront/test_create_invalidation.py +++ b/tests/functional/cloudfront/test_create_invalidation.py @@ -14,7 +14,6 @@ BaseAWSCommandParamsTest - class TestCreateInvalidation(BaseAWSCommandParamsTest): prefix = 'cloudfront create-invalidation --distribution-id my_id ' From d7c109568f08550d661bec2f776121e4b71776ed Mon Sep 17 00:00:00 2001 From: Ray Luo Date: Wed, 2 Dec 2015 17:14:20 -0800 Subject: [PATCH 6/7] Use mock.ANY in test --- tests/functional/cloudfront/test_create_invalidation.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/functional/cloudfront/test_create_invalidation.py b/tests/functional/cloudfront/test_create_invalidation.py index 8c0b0a3378cb..97cdcb35bf4d 100644 --- a/tests/functional/cloudfront/test_create_invalidation.py +++ b/tests/functional/cloudfront/test_create_invalidation.py @@ -10,6 +10,8 @@ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. +import mock + from awscli.testutils import BaseAWSPreviewCommandParamsTest as \ BaseAWSCommandParamsTest @@ -36,11 +38,10 @@ def test_paths_only(self): 'DistributionId': 'my_id', 'InvalidationBatch': { 'Paths': {'Items': ['index.html', 'foo.txt'], 'Quantity': 2}, + 'CallerReference': mock.ANY, }, } self.run_cmd(cmdline) - # There will be a CallerReference, but we don't really check it - del self.last_kwargs['InvalidationBatch']['CallerReference'] self.assertEqual(self.last_kwargs, result) def test_invalidation_batch_and_paths(self): From 4169450b1d08a020fa2ade34553bd0f5c706abb1 Mon Sep 17 00:00:00 2001 From: Ray Luo Date: Mon, 7 Dec 2015 18:23:28 -0800 Subject: [PATCH 7/7] Add CHANGELOG --- CHANGELOG.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 009c20771b08..f31167639497 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,6 +7,8 @@ Next Release (TBD) * feature:``aws configure add-model``: Added command for updating commands in the CLI and clients in boto3. (`issue 1664 `__) +* feature:``aws cloudfront create-invalidation``: Add a new --paths option. + (`issue 1662 `__) 1.9.11