Add codepipeline.get_pipeline

This commit is contained in:
gruebel 2019-12-15 16:54:58 +01:00
parent 076c8ace5f
commit c84e465e4c
5 changed files with 187 additions and 7 deletions

View File

@ -1263,7 +1263,7 @@
- [ ] update_deployment_group - [ ] update_deployment_group
## codepipeline ## codepipeline
2% implemented 5% implemented
- [ ] acknowledge_job - [ ] acknowledge_job
- [ ] acknowledge_third_party_job - [ ] acknowledge_third_party_job
- [ ] create_custom_action_type - [ ] create_custom_action_type
@ -1275,7 +1275,7 @@
- [ ] disable_stage_transition - [ ] disable_stage_transition
- [ ] enable_stage_transition - [ ] enable_stage_transition
- [ ] get_job_details - [ ] get_job_details
- [ ] get_pipeline - [X] get_pipeline
- [ ] get_pipeline_execution - [ ] get_pipeline_execution
- [ ] get_pipeline_state - [ ] get_pipeline_state
- [ ] get_third_party_job_details - [ ] get_third_party_job_details

View File

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

View File

@ -1,21 +1,41 @@
import json import json
from datetime import datetime
from boto3 import Session from boto3 import Session
from moto.core.utils import iso_8601_datetime_with_milliseconds
from moto.iam.exceptions import IAMNotFoundException from moto.iam.exceptions import IAMNotFoundException
from moto.iam import iam_backends from moto.iam import iam_backends
from moto.codepipeline.exceptions import InvalidStructureException from moto.codepipeline.exceptions import (
InvalidStructureException,
PipelineNotFoundException,
)
from moto.core import BaseBackend, BaseModel from moto.core import BaseBackend, BaseModel
DEFAULT_ACCOUNT_ID = "123456789012" DEFAULT_ACCOUNT_ID = "123456789012"
class CodePipeline(BaseModel): class CodePipeline(BaseModel):
def __init__(self, pipeline): def __init__(self, region, pipeline):
self.pipeline = self._add_default_values(pipeline) self.pipeline = self._add_default_values(pipeline)
self.tags = {} self.tags = {}
self._arn = "arn:aws:codepipeline:{0}:{1}:{2}".format(
region, DEFAULT_ACCOUNT_ID, pipeline["name"]
)
self._created = datetime.utcnow()
self._updated = datetime.utcnow()
@property
def metadata(self):
return {
"pipelineArn": self._arn,
"created": iso_8601_datetime_with_milliseconds(self._created),
"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"]:
@ -28,6 +48,8 @@ class CodePipeline(BaseModel):
if "inputArtifacts" not in action: if "inputArtifacts" not in action:
action["inputArtifacts"] = [] action["inputArtifacts"] = []
return pipeline
class CodePipelineBackend(BaseBackend): class CodePipelineBackend(BaseBackend):
def __init__(self): def __init__(self):
@ -37,7 +59,7 @@ class CodePipelineBackend(BaseBackend):
def iam_backend(self): def iam_backend(self):
return iam_backends["global"] return iam_backends["global"]
def create_pipeline(self, pipeline, tags): def create_pipeline(self, region, pipeline, tags):
if pipeline["name"] in self.pipelines: if pipeline["name"] in self.pipelines:
raise InvalidStructureException( raise InvalidStructureException(
"A pipeline with the name '{0}' already exists in account '{1}'".format( "A pipeline with the name '{0}' already exists in account '{1}'".format(
@ -64,7 +86,7 @@ class CodePipelineBackend(BaseBackend):
"Pipeline has only 1 stage(s). There should be a minimum of 2 stages in a pipeline" "Pipeline has only 1 stage(s). There should be a minimum of 2 stages in a pipeline"
) )
self.pipelines[pipeline["name"]] = CodePipeline(pipeline) self.pipelines[pipeline["name"]] = CodePipeline(region, pipeline)
if tags: if tags:
new_tags = {tag["key"]: tag["value"] for tag in tags} new_tags = {tag["key"]: tag["value"] for tag in tags}
@ -72,6 +94,18 @@ class CodePipelineBackend(BaseBackend):
return pipeline, tags return pipeline, tags
def get_pipeline(self, name):
codepipeline = self.pipelines.get(name)
if not codepipeline:
raise PipelineNotFoundException(
"Account '{0}' does not have a pipeline with name '{1}'".format(
DEFAULT_ACCOUNT_ID, name
)
)
return codepipeline.pipeline, codepipeline.metadata
codepipeline_backends = {} codepipeline_backends = {}
for region in Session().get_available_regions("codepipeline"): for region in Session().get_available_regions("codepipeline"):

View File

@ -11,7 +11,14 @@ class CodePipelineResponse(BaseResponse):
def create_pipeline(self): def create_pipeline(self):
pipeline, tags = self.codepipeline_backend.create_pipeline( pipeline, tags = self.codepipeline_backend.create_pipeline(
self._get_param("pipeline"), self._get_param("tags") self.region, self._get_param("pipeline"), self._get_param("tags")
) )
return json.dumps({"pipeline": pipeline, "tags": tags}) return json.dumps({"pipeline": pipeline, "tags": tags})
def get_pipeline(self):
pipeline, metadata = self.codepipeline_backend.get_pipeline(
self._get_param("name")
)
return json.dumps({"pipeline": pipeline, "metadata": metadata})

View File

@ -1,8 +1,10 @@
import json import json
from datetime import datetime, timezone
import boto3 import boto3
import sure # noqa import sure # noqa
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from freezegun import freeze_time
from nose.tools import assert_raises from nose.tools import assert_raises
from moto import mock_codepipeline, mock_iam from moto import mock_codepipeline, mock_iam
@ -343,6 +345,134 @@ def test_create_pipeline_errors():
) )
@freeze_time("2019-01-01 12:00:00")
@mock_codepipeline
def test_get_pipeline():
client = boto3.client("codepipeline", region_name="us-east-1")
client.create_pipeline(
pipeline={
"name": "test-pipeline",
"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",
},
},
],
},
],
},
tags=[{"key": "key", "value": "value"}],
)
response = client.get_pipeline(name="test-pipeline")
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": "test-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": [],
}
],
},
],
}
)
response["metadata"].should.equal(
{
"pipelineArn": "arn:aws:codepipeline:us-east-1:123456789012:test-pipeline",
"created": datetime.now(timezone.utc),
"updated": datetime.now(timezone.utc),
}
)
@mock_codepipeline
def test_get_pipeline_errors():
client = boto3.client("codepipeline", region_name="us-east-1")
with assert_raises(ClientError) as e:
response = client.get_pipeline(name="not-existing")
ex = e.exception
ex.operation_name.should.equal("GetPipeline")
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.response["Error"]["Code"].should.contain("PipelineNotFoundException")
ex.response["Error"]["Message"].should.equal(
"Account '123456789012' does not have a pipeline with 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")