Add codepipeline.update_pipeline

This commit is contained in:
gruebel 2019-12-15 17:28:59 +01:00
parent c84e465e4c
commit b2c44ce50d
5 changed files with 267 additions and 5 deletions

View File

@ -1263,7 +1263,7 @@
- [ ] update_deployment_group - [ ] update_deployment_group
## codepipeline ## codepipeline
5% implemented 8% implemented
- [ ] acknowledge_job - [ ] acknowledge_job
- [ ] acknowledge_third_party_job - [ ] acknowledge_third_party_job
- [ ] create_custom_action_type - [ ] create_custom_action_type
@ -1299,7 +1299,7 @@
- [ ] start_pipeline_execution - [ ] start_pipeline_execution
- [ ] tag_resource - [ ] tag_resource
- [ ] untag_resource - [ ] untag_resource
- [ ] update_pipeline - [X] update_pipeline
## codestar ## codestar
0% implemented 0% implemented

View File

@ -17,3 +17,12 @@ class PipelineNotFoundException(JsonRESTError):
super(PipelineNotFoundException, self).__init__( super(PipelineNotFoundException, self).__init__(
"PipelineNotFoundException", message "PipelineNotFoundException", message
) )
class ResourceNotFoundException(JsonRESTError):
code = 400
def __init__(self, message):
super(ResourceNotFoundException, self).__init__(
"ResourceNotFoundException", message
)

View File

@ -11,6 +11,7 @@ from moto.iam import iam_backends
from moto.codepipeline.exceptions import ( from moto.codepipeline.exceptions import (
InvalidStructureException, InvalidStructureException,
PipelineNotFoundException, PipelineNotFoundException,
ResourceNotFoundException,
) )
from moto.core import BaseBackend, BaseModel from moto.core import BaseBackend, BaseModel
@ -19,7 +20,10 @@ DEFAULT_ACCOUNT_ID = "123456789012"
class CodePipeline(BaseModel): class CodePipeline(BaseModel):
def __init__(self, region, pipeline): def __init__(self, region, pipeline):
self.pipeline = self._add_default_values(pipeline) # the version number for a new pipeline is always 1
pipeline["version"] = 1
self.pipeline = self.add_default_values(pipeline)
self.tags = {} self.tags = {}
self._arn = "arn:aws:codepipeline:{0}:{1}:{2}".format( self._arn = "arn:aws:codepipeline:{0}:{1}:{2}".format(
@ -36,7 +40,7 @@ class CodePipeline(BaseModel):
"updated": iso_8601_datetime_with_milliseconds(self._updated), "updated": iso_8601_datetime_with_milliseconds(self._updated),
} }
def _add_default_values(self, pipeline): def add_default_values(self, pipeline):
for stage in pipeline["stages"]: for stage in pipeline["stages"]:
for action in stage["actions"]: for action in stage["actions"]:
if "runOrder" not in action: if "runOrder" not in action:
@ -106,6 +110,23 @@ class CodePipelineBackend(BaseBackend):
return codepipeline.pipeline, codepipeline.metadata return codepipeline.pipeline, codepipeline.metadata
def update_pipeline(self, pipeline):
codepipeline = self.pipelines.get(pipeline["name"])
if not codepipeline:
raise ResourceNotFoundException(
"The account with id '{0}' does not include a pipeline with the name '{1}'".format(
DEFAULT_ACCOUNT_ID, pipeline["name"]
)
)
# version number is auto incremented
pipeline["version"] = codepipeline.pipeline["version"] + 1
codepipeline._updated = datetime.utcnow()
codepipeline.pipeline = codepipeline.add_default_values(pipeline)
return codepipeline.pipeline
codepipeline_backends = {} codepipeline_backends = {}
for region in Session().get_available_regions("codepipeline"): for region in Session().get_available_regions("codepipeline"):

View File

@ -22,3 +22,10 @@ class CodePipelineResponse(BaseResponse):
) )
return json.dumps({"pipeline": pipeline, "metadata": metadata}) return json.dumps({"pipeline": pipeline, "metadata": metadata})
def update_pipeline(self):
pipeline = self.codepipeline_backend.update_pipeline(
self._get_param("pipeline")
)
return json.dumps({"pipeline": pipeline})

View File

@ -110,6 +110,7 @@ def test_create_pipeline():
], ],
}, },
], ],
"version": 1,
} }
) )
response["tags"].should.equal([{"key": "key", "value": "value"}]) response["tags"].should.equal([{"key": "key", "value": "value"}])
@ -447,6 +448,7 @@ def test_get_pipeline():
], ],
}, },
], ],
"version": 1,
} }
) )
response["metadata"].should.equal( response["metadata"].should.equal(
@ -463,7 +465,7 @@ def test_get_pipeline_errors():
client = boto3.client("codepipeline", region_name="us-east-1") client = boto3.client("codepipeline", region_name="us-east-1")
with assert_raises(ClientError) as e: with assert_raises(ClientError) as e:
response = client.get_pipeline(name="not-existing") client.get_pipeline(name="not-existing")
ex = e.exception ex = e.exception
ex.operation_name.should.equal("GetPipeline") ex.operation_name.should.equal("GetPipeline")
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
@ -473,6 +475,229 @@ def test_get_pipeline_errors():
) )
@mock_codepipeline
def test_update_pipeline():
client = boto3.client("codepipeline", region_name="us-east-1")
role_arn = get_role_arn()
with freeze_time("2019-01-01 12:00:00"):
created_time = datetime.now(timezone.utc)
client.create_pipeline(
pipeline={
"name": "test-pipeline",
"roleArn": role_arn,
"artifactStore": {
"type": "S3",
"location": "codepipeline-us-east-1-123456789012",
},
"stages": [
{
"name": "Stage-1",
"actions": [
{
"name": "Action-1",
"actionTypeId": {
"category": "Source",
"owner": "AWS",
"provider": "S3",
"version": "1",
},
"configuration": {
"S3Bucket": "test-bucket",
"S3ObjectKey": "test-object",
},
"outputArtifacts": [{"name": "artifact"},],
},
],
},
{
"name": "Stage-2",
"actions": [
{
"name": "Action-1",
"actionTypeId": {
"category": "Approval",
"owner": "AWS",
"provider": "Manual",
"version": "1",
},
},
],
},
],
},
tags=[{"key": "key", "value": "value"}],
)
with freeze_time("2019-01-02 12:00:00"):
updated_time = datetime.now(timezone.utc)
response = client.update_pipeline(
pipeline={
"name": "test-pipeline",
"roleArn": role_arn,
"artifactStore": {
"type": "S3",
"location": "codepipeline-us-east-1-123456789012",
},
"stages": [
{
"name": "Stage-1",
"actions": [
{
"name": "Action-1",
"actionTypeId": {
"category": "Source",
"owner": "AWS",
"provider": "S3",
"version": "1",
},
"configuration": {
"S3Bucket": "different-bucket",
"S3ObjectKey": "test-object",
},
"outputArtifacts": [{"name": "artifact"},],
},
],
},
{
"name": "Stage-2",
"actions": [
{
"name": "Action-1",
"actionTypeId": {
"category": "Approval",
"owner": "AWS",
"provider": "Manual",
"version": "1",
},
},
],
},
],
}
)
response["pipeline"].should.equal(
{
"name": "test-pipeline",
"roleArn": "arn:aws:iam::123456789012:role/test-role",
"artifactStore": {
"type": "S3",
"location": "codepipeline-us-east-1-123456789012",
},
"stages": [
{
"name": "Stage-1",
"actions": [
{
"name": "Action-1",
"actionTypeId": {
"category": "Source",
"owner": "AWS",
"provider": "S3",
"version": "1",
},
"runOrder": 1,
"configuration": {
"S3Bucket": "different-bucket",
"S3ObjectKey": "test-object",
},
"outputArtifacts": [{"name": "artifact"}],
"inputArtifacts": [],
}
],
},
{
"name": "Stage-2",
"actions": [
{
"name": "Action-1",
"actionTypeId": {
"category": "Approval",
"owner": "AWS",
"provider": "Manual",
"version": "1",
},
"runOrder": 1,
"configuration": {},
"outputArtifacts": [],
"inputArtifacts": [],
}
],
},
],
"version": 2,
}
)
response = client.get_pipeline(name="test-pipeline")
response["metadata"].should.equal(
{
"pipelineArn": "arn:aws:codepipeline:us-east-1:123456789012:test-pipeline",
"created": created_time,
"updated": updated_time,
}
)
@mock_codepipeline
def test_update_pipeline_errors():
client = boto3.client("codepipeline", region_name="us-east-1")
with assert_raises(ClientError) as e:
client.update_pipeline(
pipeline={
"name": "not-existing",
"roleArn": get_role_arn(),
"artifactStore": {
"type": "S3",
"location": "codepipeline-us-east-1-123456789012",
},
"stages": [
{
"name": "Stage-1",
"actions": [
{
"name": "Action-1",
"actionTypeId": {
"category": "Source",
"owner": "AWS",
"provider": "S3",
"version": "1",
},
"configuration": {
"S3Bucket": "test-bucket",
"S3ObjectKey": "test-object",
},
"outputArtifacts": [{"name": "artifact"},],
},
],
},
{
"name": "Stage-2",
"actions": [
{
"name": "Action-1",
"actionTypeId": {
"category": "Approval",
"owner": "AWS",
"provider": "Manual",
"version": "1",
},
},
],
},
],
}
)
ex = e.exception
ex.operation_name.should.equal("UpdatePipeline")
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 @mock_iam
def get_role_arn(): def get_role_arn():
iam = boto3.client("iam", region_name="us-east-1") iam = boto3.client("iam", region_name="us-east-1")