Add codepipeline.get_pipeline
This commit is contained in:
parent
076c8ace5f
commit
c84e465e4c
@ -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
|
||||||
|
@ -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
|
||||||
|
)
|
||||||
|
@ -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"):
|
||||||
|
@ -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})
|
||||||
|
@ -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")
|
||||||
|
Loading…
Reference in New Issue
Block a user