From 8331d480bab8b0556718d9af0c73e19eb0a05104 Mon Sep 17 00:00:00 2001 From: gruebel Date: Mon, 23 Dec 2019 19:50:16 +0100 Subject: [PATCH] Add codepipeline.untag_resource --- IMPLEMENTATION_COVERAGE.md | 8 ++-- moto/codepipeline/models.py | 14 ++++++ moto/codepipeline/responses.py | 7 +++ tests/test_codepipeline/test_codepipeline.py | 46 ++++++++++++++++++++ 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/IMPLEMENTATION_COVERAGE.md b/IMPLEMENTATION_COVERAGE.md index 5e6ef1c9e..a1b0ffb5e 100644 --- a/IMPLEMENTATION_COVERAGE.md +++ b/IMPLEMENTATION_COVERAGE.md @@ -1374,7 +1374,7 @@ - [ ] update_profiling_group ## codepipeline -13% implemented +22% implemented - [ ] acknowledge_job - [ ] acknowledge_third_party_job - [ ] create_custom_action_type @@ -1394,7 +1394,7 @@ - [ ] list_action_types - [ ] list_pipeline_executions - [X] list_pipelines -- [ ] list_tags_for_resource +- [X] list_tags_for_resource - [ ] list_webhooks - [ ] poll_for_jobs - [ ] poll_for_third_party_jobs @@ -1408,8 +1408,8 @@ - [ ] register_webhook_with_third_party - [ ] retry_stage_execution - [ ] start_pipeline_execution -- [ ] tag_resource -- [ ] untag_resource +- [X] tag_resource +- [X] untag_resource - [X] update_pipeline ## codestar diff --git a/moto/codepipeline/models.py b/moto/codepipeline/models.py index 4a8b89617..556682c10 100644 --- a/moto/codepipeline/models.py +++ b/moto/codepipeline/models.py @@ -192,6 +192,20 @@ class CodePipelineBackend(BaseBackend): for tag in tags: pipeline.tags.update({tag["key"]: tag["value"]}) + def untag_resource(self, arn, tag_keys): + name = arn.split(":")[-1] + pipeline = self.pipelines.get(name) + + if not pipeline: + raise ResourceNotFoundException( + "The account with id '{0}' does not include a pipeline with the name '{1}'".format( + ACCOUNT_ID, name + ) + ) + + for key in tag_keys: + pipeline.tags.pop(key, None) + codepipeline_backends = {} for region in Session().get_available_regions("codepipeline"): diff --git a/moto/codepipeline/responses.py b/moto/codepipeline/responses.py index df1bf220f..0223dfae6 100644 --- a/moto/codepipeline/responses.py +++ b/moto/codepipeline/responses.py @@ -53,3 +53,10 @@ class CodePipelineResponse(BaseResponse): ) return "" + + def untag_resource(self): + self.codepipeline_backend.untag_resource( + self._get_param("resourceArn"), self._get_param("tagKeys") + ) + + return "" diff --git a/tests/test_codepipeline/test_codepipeline.py b/tests/test_codepipeline/test_codepipeline.py index e71e24f76..a40efa05c 100644 --- a/tests/test_codepipeline/test_codepipeline.py +++ b/tests/test_codepipeline/test_codepipeline.py @@ -602,6 +602,52 @@ def test_tag_resource_errors(): ) +@mock_codepipeline +def test_untag_resource(): + client = boto3.client("codepipeline", region_name="us-east-1") + name = "test-pipeline" + create_basic_codepipeline(client, name) + + response = client.list_tags_for_resource( + resourceArn="arn:aws:codepipeline:us-east-1:123456789012:{}".format(name) + ) + response["tags"].should.equal([{"key": "key", "value": "value"}]) + + client.untag_resource( + resourceArn="arn:aws:codepipeline:us-east-1:123456789012:{}".format(name), + tagKeys=["key"], + ) + + response = client.list_tags_for_resource( + resourceArn="arn:aws:codepipeline:us-east-1:123456789012:{}".format(name) + ) + response["tags"].should.have.length_of(0) + + # removing a not existing tag should raise no exception + client.untag_resource( + resourceArn="arn:aws:codepipeline:us-east-1:123456789012:{}".format(name), + tagKeys=["key"], + ) + + +@mock_codepipeline +def test_untag_resource_errors(): + client = boto3.client("codepipeline", region_name="us-east-1") + + with assert_raises(ClientError) as e: + client.untag_resource( + resourceArn="arn:aws:codepipeline:us-east-1:123456789012:not-existing", + tagKeys=["key"], + ) + ex = e.exception + ex.operation_name.should.equal("UntagResource") + ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) + ex.response["Error"]["Code"].should.contain("ResourceNotFoundException") + ex.response["Error"]["Message"].should.equal( + "The account with id '123456789012' does not include a pipeline with the name 'not-existing'" + ) + + @mock_iam def get_role_arn(): client = boto3.client("iam", region_name="us-east-1")