ansible/test/units/modules/cloud/amazon/test_data_pipeline.py
Sloane Hertel dbbad16385 [cloud] New module: Add module for managing AWS Datapipelines (cloud/amazon/data_pipeline) (#22878)
* New module for managing AWS Datapipelines

* Supports create/activate/deactivate and deletion
* Handles idempotent creation by embeding the version in the
uniqueId field
* Waits for requested state to be reached, as Botocore doesn't
have waiters yet for datapipelines

* rename module, fix imports, add tags option, improve exit_json results, fix a couple bugs, add a TODO so I don't forget

fix pep8

allow timeout to be used for pipeline creation

make .format syntax uniform

fix pep8

fix exception handling

allow pipeline to be modified, refactor, add some comments, remove unnecessary imports

pipeline activation may not be in the activated state long

remove datapipeline version option

change a loop to a list comprehension

create idempotence by hashing the options given to the module minus the objects (which can be modified)

small bugfix

* data_pipeline unittests

make unittests pep8

fix bug in unittests

* remove exception handling that serves no purpose

* Fix python3 incompatibilities in datapipeline tests and add placebo fixture maybe_sleep for faster tests

Fix python3 incompatibilities in data_pipeline build_unique_id()

Don't delete a pipeline in diff_pipeline() because it's unexpected

Don't use time.time() because it causes an issue with placebo testing

re-recorded tests

fix pep8 in data_pipeline

Remove disable_rollback from tests

Make sure unique identifier is a string

re-record tests

* improve documentation and add another example

* use a placebo fixture instead of redundant code in tests

fix tests for PLACEBO_RECORD=false

* Fix data_pipeline docs

use isinstance instead of type()

fix documentation

* fix documentation

* Remove use of undefined variable from data_pipeline module and fix license

* fix copyright header
2017-08-03 15:04:10 -04:00

254 lines
10 KiB
Python

# (c) 2017 Red Hat Inc.
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
import pytest
import boto3
import os
import json
import collections
from . placebo_fixtures import placeboify, maybe_sleep
from ansible.modules.cloud.amazon import data_pipeline
from ansible.module_utils._text import to_text
@pytest.fixture(scope='module')
def dp_setup():
"""
Yield a FakeModule object, data pipeline id of a vanilla data pipeline, and data pipeline objects
This fixture is module-scoped, since this can be reused for multiple tests.
"""
Dependencies = collections.namedtuple("Dependencies", ["module", "data_pipeline_id", "objects"])
# get objects to use to test populating and activating the data pipeline
if not os.getenv('PLACEBO_RECORD'):
objects = [{"name": "Every 1 day",
"id": "DefaultSchedule",
"fields": []},
{"name": "Default",
"id": "Default",
"fields": []}]
else:
s3 = boto3.client('s3')
data = s3.get_object(Bucket="ansible-test-datapipeline", Key="pipeline-object/new.json")
objects = json.loads(to_text(data['Body'].read()))
# create a module with vanilla data pipeline parameters
params = {'name': 'ansible-test-create-pipeline',
'description': 'ansible-datapipeline-unit-test',
'state': 'present',
'timeout': 300,
'objects': [],
'tags': {},
'parameters': [],
'values': []}
module = FakeModule(**params)
# yield a module, the data pipeline id, and the data pipeline objects (that are not yet defining the vanilla data pipeline)
if not os.getenv('PLACEBO_RECORD'):
yield Dependencies(module=module, data_pipeline_id='df-0590406117G8DPQZY2HA', objects=objects)
else:
connection = boto3.client('datapipeline')
changed, result = data_pipeline.create_pipeline(connection, module)
data_pipeline_id = result['data_pipeline']['pipeline_id']
yield Dependencies(module=module, data_pipeline_id=data_pipeline_id, objects=objects)
# remove data pipeline
if os.getenv('PLACEBO_RECORD'):
module.params.update(state='absent')
data_pipeline.delete_pipeline(connection, module)
class FakeModule(object):
def __init__(self, **kwargs):
self.params = kwargs
def fail_json(self, *args, **kwargs):
self.exit_args = args
self.exit_kwargs = kwargs
raise Exception('FAIL')
def exit_json(self, *args, **kwargs):
self.exit_args = args
self.exit_kwargs = kwargs
def test_create_pipeline_already_exists(placeboify, maybe_sleep, dp_setup):
connection = placeboify.client('datapipeline')
changed, result = data_pipeline.create_pipeline(connection, dp_setup.module)
assert changed is False
assert "Data Pipeline ansible-test-create-pipeline is present" in result['msg']
def test_pipeline_field(placeboify, maybe_sleep, dp_setup):
connection = placeboify.client('datapipeline')
pipeline_field_info = data_pipeline.pipeline_field(connection, dp_setup.data_pipeline_id, "@pipelineState")
assert pipeline_field_info == "PENDING"
def test_define_pipeline(placeboify, maybe_sleep, dp_setup):
connection = placeboify.client('datapipeline')
changed, result = data_pipeline.define_pipeline(connection, dp_setup.module, dp_setup.objects, dp_setup.data_pipeline_id)
assert 'has been updated' in result
def test_deactivate_pipeline(placeboify, maybe_sleep, dp_setup):
connection = placeboify.client('datapipeline')
changed, result = data_pipeline.deactivate_pipeline(connection, dp_setup.module)
assert "Data Pipeline ansible-test-create-pipeline deactivated" in result['msg']
def test_activate_without_population(placeboify, maybe_sleep, dp_setup):
connection = placeboify.client('datapipeline')
with pytest.raises(Exception) as error_message:
changed, result = data_pipeline.activate_pipeline(connection, dp_setup.module)
assert error_message == "You need to populate your pipeline before activation."
def test_create_pipeline(placeboify, maybe_sleep):
connection = placeboify.client('datapipeline')
params = {'name': 'ansible-unittest-create-pipeline',
'description': 'ansible-datapipeline-unit-test',
'state': 'present',
'timeout': 300,
'tags': {}}
m = FakeModule(**params)
changed, result = data_pipeline.create_pipeline(connection, m)
assert changed is True
assert result['msg'] == "Data Pipeline ansible-unittest-create-pipeline created."
data_pipeline.delete_pipeline(connection, m)
def test_create_pipeline_with_tags(placeboify, maybe_sleep):
connection = placeboify.client('datapipeline')
params = {'name': 'ansible-unittest-create-pipeline_tags',
'description': 'ansible-datapipeline-unit-test',
'state': 'present',
'tags': {'ansible': 'test'},
'timeout': 300}
m = FakeModule(**params)
changed, result = data_pipeline.create_pipeline(connection, m)
assert changed is True
assert result['msg'] == "Data Pipeline ansible-unittest-create-pipeline_tags created."
data_pipeline.delete_pipeline(connection, m)
def test_delete_nonexistent_pipeline(placeboify, maybe_sleep):
connection = placeboify.client('datapipeline')
params = {'name': 'ansible-test-nonexistent',
'description': 'ansible-test-nonexistent',
'state': 'absent',
'objects': [],
'tags': {'ansible': 'test'},
'timeout': 300}
m = FakeModule(**params)
changed, result = data_pipeline.delete_pipeline(connection, m)
assert changed is False
def test_delete_pipeline(placeboify, maybe_sleep):
connection = placeboify.client('datapipeline')
params = {'name': 'ansible-test-nonexistent',
'description': 'ansible-test-nonexistent',
'state': 'absent',
'objects': [],
'tags': {'ansible': 'test'},
'timeout': 300}
m = FakeModule(**params)
data_pipeline.create_pipeline(connection, m)
changed, result = data_pipeline.delete_pipeline(connection, m)
assert changed is True
def test_build_unique_id_different(placeboify, maybe_sleep):
m = FakeModule(**{'name': 'ansible-unittest-1', 'description': 'test-unique-id'})
m2 = FakeModule(**{'name': 'ansible-unittest-1', 'description': 'test-unique-id-different'})
assert data_pipeline.build_unique_id(m) != data_pipeline.build_unique_id(m2)
def test_build_unique_id_same(placeboify, maybe_sleep):
m = FakeModule(**{'name': 'ansible-unittest-1', 'description': 'test-unique-id', 'tags': {'ansible': 'test'}})
m2 = FakeModule(**{'name': 'ansible-unittest-1', 'description': 'test-unique-id', 'tags': {'ansible': 'test'}})
assert data_pipeline.build_unique_id(m) == data_pipeline.build_unique_id(m2)
def test_build_unique_id_obj(placeboify, maybe_sleep):
# check that the object can be different and the unique id should be the same; should be able to modify objects
m = FakeModule(**{'name': 'ansible-unittest-1', 'objects': [{'first': 'object'}]})
m2 = FakeModule(**{'name': 'ansible-unittest-1', 'objects': [{'second': 'object'}]})
assert data_pipeline.build_unique_id(m) == data_pipeline.build_unique_id(m2)
def test_format_tags(placeboify, maybe_sleep):
unformatted_tags = {'key1': 'val1', 'key2': 'val2', 'key3': 'val3'}
formatted_tags = data_pipeline.format_tags(unformatted_tags)
for tag_set in formatted_tags:
assert unformatted_tags[tag_set['key']] == tag_set['value']
def test_format_empty_tags(placeboify, maybe_sleep):
unformatted_tags = {}
formatted_tags = data_pipeline.format_tags(unformatted_tags)
assert formatted_tags == []
def test_pipeline_description(placeboify, maybe_sleep, dp_setup):
connection = placeboify.client('datapipeline')
dp_id = dp_setup.data_pipeline_id
pipelines = data_pipeline.pipeline_description(connection, dp_id)
assert dp_id == pipelines['pipelineDescriptionList'][0]['pipelineId']
def test_pipeline_description_nonexistent(placeboify, maybe_sleep):
hypothetical_pipeline_id = "df-015440025PF7YGLDK47C"
connection = placeboify.client('datapipeline')
with pytest.raises(Exception) as error:
data_pipeline.pipeline_description(connection, hypothetical_pipeline_id)
assert error == data_pipeline.DataPipelineNotFound
def test_check_dp_exists_true(placeboify, maybe_sleep, dp_setup):
connection = placeboify.client('datapipeline')
exists = data_pipeline.check_dp_exists(connection, dp_setup.data_pipeline_id)
assert exists is True
def test_check_dp_exists_false(placeboify, maybe_sleep):
hypothetical_pipeline_id = "df-015440025PF7YGLDK47C"
connection = placeboify.client('datapipeline')
exists = data_pipeline.check_dp_exists(connection, hypothetical_pipeline_id)
assert exists is False
def test_check_dp_status(placeboify, maybe_sleep, dp_setup):
inactive_states = ['INACTIVE', 'PENDING', 'FINISHED', 'DELETING']
connection = placeboify.client('datapipeline')
state = data_pipeline.check_dp_status(connection, dp_setup.data_pipeline_id, inactive_states)
assert state is True
def test_activate_pipeline(placeboify, maybe_sleep, dp_setup):
# use objects to define pipeline before activating
connection = placeboify.client('datapipeline')
data_pipeline.define_pipeline(connection,
module=dp_setup.module,
objects=dp_setup.objects,
dp_id=dp_setup.data_pipeline_id)
changed, result = data_pipeline.activate_pipeline(connection, dp_setup.module)
assert changed is True