Add the basic pipeline commands

Change-Id: I699e60a261c3c492706d8b5918f55d28b1bba10d
This commit is contained in:
Angus Salkeld
2014-06-23 10:42:09 +10:00
parent 8e26d2a67d
commit e875d88813
5 changed files with 365 additions and 2 deletions

View File

@@ -50,6 +50,7 @@ from solumclient.common import cli_utils
from solumclient.openstack.common import cliutils from solumclient.openstack.common import cliutils
from solumclient.openstack.common import strutils from solumclient.openstack.common import strutils
from solumclient.v1 import assembly as cli_assem from solumclient.v1 import assembly as cli_assem
from solumclient.v1 import pipeline as cli_pipe
from solumclient.v1 import plan as cli_plan from solumclient.v1 import plan as cli_plan
@@ -181,6 +182,65 @@ class ComponentCommands(cli_utils.CommandsBase):
cliutils.print_list(response, fields) cliutils.print_list(response, fields)
class PipelineCommands(cli_utils.CommandsBase):
"""Pipeline targets."""
def create(self):
"""Create a pipeline."""
self.parser.add_argument('plan_uri',
help="Tenant/project-wide unique "
"plan (uri/uuid or name)")
self.parser.add_argument('workbook_name',
help="Workbook name")
self.parser.add_argument('name',
help="Pipeline name")
args = self.parser.parse_args()
plan_uri = args.plan_uri
if '/' not in plan_uri:
# might be a plan uuid/name
# let's try and be helpful and get the real plan_uri.
plan = self.client.plans.find(name_or_id=args.plan_uri)
plan_uri = plan.uri
print('Note: using plan_uri=%s' % plan_uri)
pipeline = self.client.pipelines.create(
name=args.name,
plan_uri=plan_uri,
workbook_name=args.workbook_name)
fields = ['uuid', 'name', 'description',
'trigger_uri']
data = dict([(f, getattr(pipeline, f, ''))
for f in fields])
cliutils.print_dict(data, wrap=72)
def delete(self):
"""Delete an pipeline."""
self.parser.add_argument('pipeline_uuid',
help="Pipeline uuid or name")
args = self.parser.parse_args()
pipeline = self.client.pipelines.find(name_or_id=args.pipeline_uuid)
cli_pipe.PipelineManager(self.client).delete(
pipeline_id=str(pipeline.uuid))
def list(self):
"""List all pipelines."""
fields = ['uuid', 'name', 'description']
response = self.client.pipelines.list()
cliutils.print_list(response, fields)
def show(self):
"""Show a pipeline's resource."""
self.parser.add_argument('pipeline_uuid',
help="Pipeline uuid or name")
args = self.parser.parse_args()
response = self.client.pipelines.find(name_or_id=args.pipeline_uuid)
fields = ['uuid', 'name', 'description',
'trigger_uri']
data = dict([(f, getattr(response, f, ''))
for f in fields])
cliutils.print_dict(data, wrap=72)
class LanguagePackCommands(cli_utils.CommandsBase): class LanguagePackCommands(cli_utils.CommandsBase):
"""Language Pack targets.""" """Language Pack targets."""
@@ -239,6 +299,7 @@ def main():
resources = { resources = {
'app': AppCommands, 'app': AppCommands,
'assembly': AssemblyCommands, 'assembly': AssemblyCommands,
'pipeline': PipelineCommands,
'languagepack': LanguagePackCommands, 'languagepack': LanguagePackCommands,
'component': ComponentCommands 'component': ComponentCommands
} }

View File

@@ -31,6 +31,7 @@ from solumclient.tests import base
from solumclient.v1 import assembly from solumclient.v1 import assembly
from solumclient.v1 import component from solumclient.v1 import component
from solumclient.v1 import languagepack from solumclient.v1 import languagepack
from solumclient.v1 import pipeline
from solumclient.v1 import plan from solumclient.v1 import plan
FAKE_ENV = {'OS_USERNAME': 'username', FAKE_ENV = {'OS_USERNAME': 'username',
@@ -77,7 +78,7 @@ class TestSolum(base.TestCase):
self.useFixture(fixtures.MonkeyPatch('os.environ', env)) self.useFixture(fixtures.MonkeyPatch('os.environ', env))
@mock.patch.object(extension.ExtensionManager, "map") @mock.patch.object(extension.ExtensionManager, "map")
def shell(self, argstr, mock_mgr_map): def shell(self, argstr, mock_mgr_map, exit_code=0):
class FakePlugin(BaseFakePlugin): class FakePlugin(BaseFakePlugin):
def authenticate(self, cls): def authenticate(self, cls):
cls.request( cls.request(
@@ -97,7 +98,7 @@ class TestSolum(base.TestCase):
solum.main() solum.main()
except SystemExit: except SystemExit:
exc_type, exc_value, exc_traceback = sys.exc_info() exc_type, exc_value, exc_traceback = sys.exc_info()
self.assertEqual(0, exc_value.code) self.assertEqual(exit_code, exc_value.code)
finally: finally:
out = sys.stdout.getvalue() out = sys.stdout.getvalue()
sys.stdout.close() sys.stdout.close()
@@ -179,6 +180,67 @@ class TestSolum(base.TestCase):
self.shell("assembly show app2") self.shell("assembly show app2")
mock_assembly_find.assert_called_once_with(name_or_id='app2') mock_assembly_find.assert_called_once_with(name_or_id='app2')
# Pipeline Tests #
@mock.patch.object(pipeline.PipelineManager, "list")
def test_pipeline_list(self, mock_pipeline_list):
self.make_env()
self.shell("pipeline list")
mock_pipeline_list.assert_called_once_with()
@mock.patch.object(pipeline.PipelineManager, "create")
def test_pipeline_create(self, mock_pipeline_create):
self.make_env()
self.shell("pipeline create http://example.com/a.yaml workbook test")
mock_pipeline_create.assert_called_once_with(
name='test',
workbook_name='workbook',
plan_uri='http://example.com/a.yaml')
@mock.patch.object(pipeline.PipelineManager, "create")
def test_pipeline_create_without_name(self, mock_pipeline_create):
self.make_env()
self.shell("pipeline create http://example.com/a.yaml workbook",
exit_code=2)
@mock.patch.object(plan.PlanManager, "find")
@mock.patch.object(pipeline.PipelineManager, "create")
def test_pipeline_create_with_plan_name(self, mock_pipeline_create,
mock_app_find):
class FakePlan(object):
uri = 'http://example.com/the-plan.yaml'
self.make_env()
mock_app_find.return_value = FakePlan()
self.shell("pipeline create the-plan-name workbook test")
mock_app_find.assert_called_once_with(name_or_id='the-plan-name')
mock_pipeline_create.assert_called_once_with(
name='test',
workbook_name='workbook',
plan_uri='http://example.com/the-plan.yaml')
@mock.patch.object(pipeline.PipelineManager, "delete")
@mock.patch.object(pipeline.PipelineManager, "find")
def test_pipeline_delete(self, mock_pipeline_find, mock_pipeline_delete):
self.make_env()
the_id = str(uuid.uuid4())
self.shell("pipeline delete %s" % the_id)
mock_pipeline_find.assert_called_once_with(
name_or_id=the_id)
mock_pipeline_delete.assert_called_once()
@mock.patch.object(pipeline.PipelineManager, "find")
def test_pipeline_get(self, mock_pipeline_find):
self.make_env()
the_id = str(uuid.uuid4())
self.shell("pipeline show %s" % the_id)
mock_pipeline_find.assert_called_once_with(name_or_id=the_id)
@mock.patch.object(pipeline.PipelineManager, "find")
def test_pipeline_get_by_name(self, mock_pipeline_find):
self.make_env()
self.shell("pipeline show app2")
mock_pipeline_find.assert_called_once_with(name_or_id='app2')
# Plan Tests # # Plan Tests #
@mock.patch.object(cliutils, "print_dict") @mock.patch.object(cliutils, "print_dict")
@mock.patch.object(plan.PlanManager, "create") @mock.patch.object(plan.PlanManager, "create")

View File

@@ -0,0 +1,183 @@
# Copyright 2014 - Rackspace Hosting
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from solumclient.openstack.common.apiclient import exceptions
from solumclient.openstack.common.apiclient import fake_client
from solumclient.tests import base
from solumclient.v1 import client as sclient
from solumclient.v1 import pipeline
pipeline_list = [
{
'uri': 'http://example.com/v1/pipelines/x1',
'name': 'database',
'type': 'pipeline',
'description': 'A mysql database',
'tags': ['small'],
'project_id': '1dae5a09ef2b4d8cbf3594b0eb4f6b94',
'user_id': '55f41cf46df74320b9486a35f5d28a11',
'component_links': [{
'href': 'http://example.com:9777/v1/components/x1',
'target_name': 'x1'}],
'operations_uri': 'http://example.com:9777/v1/operations/o1',
'sensors_uri': 'http://example.com:9777/v1/sensors/s1'
},
{
'uri': 'http://example.com/v1/pipelines/x2',
'name': 'load_balancer',
'type': 'pipeline',
'description': 'A load balancer',
'tags': ['small'],
'project_id': '1dae5a09ef2b4d8cbf3594b0eb4f6b94',
'user_id': '55f41cf46df74320b9486a35f5d28a11',
'component_links': [{
'href': 'http://example.com:9777/v1/components/x2',
'target_name': 'x2'}],
'operations_uri': 'http://example.com:9777/v1/operations/o2',
'sensors_uri': 'http://example.com:9777/v1/sensors/s2'
}
]
pipeline_fixture = {
'uri': 'http://example.com/v1/pipelines/x1',
'name': 'database',
'type': 'pipeline',
'description': 'A mysql database',
'tags': ['small'],
'project_id': '1dae5a09ef2b4d8cbf3594b0eb4f6b94',
'user_id': '55f41cf46df74320b9486a35f5d28a11',
'component_links': [{
'href': 'http://example.com:9777/v1/components/x1',
'target_name': 'x1'}],
'operations_uri': 'http://example.com:9777/v1/operations/o1',
'sensors_uri': 'http://example.com:9777/v1/sensors/s1'
}
fixtures_list = {
'/v1/pipelines': {
'GET': (
{},
pipeline_list
),
}
}
fixtures_get = {
'/v1/pipelines/x1': {
'GET': (
{},
pipeline_fixture
),
}
}
fixtures_create = {
'/v1/pipelines': {
'POST': (
{},
pipeline_fixture
),
}
}
fixtures_put = {
'/v1/pipelines/x1': {
'PUT': (
{},
pipeline_fixture
),
}
}
fixtures_delete = {
'/v1/pipelines/x1': {
'DELETE': (
{},
{},
),
}
}
class PipelineManagerTest(base.TestCase):
def assert_pipeline_object(self, pipeline_obj):
self.assertIn('Pipeline', repr(pipeline_obj))
self.assertEqual(pipeline_fixture['uri'], pipeline_obj.uri)
self.assertEqual(pipeline_fixture['type'], pipeline_obj.type)
self.assertEqual(pipeline_fixture['project_id'],
pipeline_obj.project_id)
self.assertEqual(pipeline_fixture['user_id'], pipeline_obj.user_id)
def test_list_all(self):
fake_http_client = fake_client.FakeHTTPClient(fixtures=fixtures_list)
api_client = sclient.Client(fake_http_client)
mgr = pipeline.PipelineManager(api_client)
pipelines = mgr.list()
self.assertEqual(len(pipelines), 2)
self.assertIn('Pipeline', repr(pipelines[0]))
self.assertEqual(pipeline_list[0]['uri'], pipelines[0].uri)
self.assertEqual(pipeline_list[1]['uri'], pipelines[1].uri)
def test_find_one(self):
fake_http_client = fake_client.FakeHTTPClient(fixtures=fixtures_list)
api_client = sclient.Client(fake_http_client)
mgr = pipeline.PipelineManager(api_client)
pipelines = mgr.findall(name='database')
self.assertEqual(len(pipelines), 1)
self.assertIn('Pipeline', repr(pipelines[0]))
self.assertEqual(pipeline_list[0]['uri'], pipelines[0].uri)
def test_find_one_only(self):
fake_http_client = fake_client.FakeHTTPClient(fixtures=fixtures_list)
api_client = sclient.Client(fake_http_client)
mgr = pipeline.PipelineManager(api_client)
result = mgr.find(name_or_id='database')
self.assertEqual(pipeline_list[0]['uri'], result.uri)
def test_find_none(self):
fake_http_client = fake_client.FakeHTTPClient(fixtures=fixtures_list)
api_client = sclient.Client(fake_http_client)
mgr = pipeline.PipelineManager(api_client)
self.assertRaises(exceptions.NotFound, mgr.find, name_or_id='what')
def test_create(self):
fake_http_client = fake_client.FakeHTTPClient(fixtures=fixtures_create)
api_client = sclient.Client(fake_http_client)
mgr = pipeline.PipelineManager(api_client)
pipeline_obj = mgr.create()
self.assert_pipeline_object(pipeline_obj)
def test_get(self):
fake_http_client = fake_client.FakeHTTPClient(fixtures=fixtures_get)
api_client = sclient.Client(fake_http_client)
mgr = pipeline.PipelineManager(api_client)
pipeline_obj = mgr.get(pipeline_id='x1')
self.assert_pipeline_object(pipeline_obj)
def test_put(self):
fake_http_client = fake_client.FakeHTTPClient(fixtures=fixtures_put)
api_client = sclient.Client(fake_http_client)
mgr = pipeline.PipelineManager(api_client)
pipeline_obj = mgr.put(pipeline_id='x1')
self.assert_pipeline_object(pipeline_obj)
def test_delete(self):
fake_http_client = fake_client.FakeHTTPClient(fixtures=fixtures_delete)
api_client = sclient.Client(fake_http_client)
mgr = pipeline.PipelineManager(api_client)
mgr.delete(pipeline_id='x1')
fake_http_client.assert_called('DELETE', '/v1/pipelines/x1')

View File

@@ -16,6 +16,7 @@ from solumclient.openstack.common.apiclient import client
from solumclient.v1 import assembly from solumclient.v1 import assembly
from solumclient.v1 import component from solumclient.v1 import component
from solumclient.v1 import languagepack from solumclient.v1 import languagepack
from solumclient.v1 import pipeline
from solumclient.v1 import plan from solumclient.v1 import plan
from solumclient.v1 import platform from solumclient.v1 import platform
@@ -30,6 +31,7 @@ class Client(client.BaseClient):
super(Client, self).__init__(http_client, extensions) super(Client, self).__init__(http_client, extensions)
self.assemblies = assembly.AssemblyManager(self) self.assemblies = assembly.AssemblyManager(self)
self.components = component.ComponentManager(self) self.components = component.ComponentManager(self)
self.pipelines = pipeline.PipelineManager(self)
self.platform = platform.PlatformManager(self) self.platform = platform.PlatformManager(self)
self.plans = plan.PlanManager(self) self.plans = plan.PlanManager(self)
self.languagepacks = languagepack.LanguagePackManager(self) self.languagepacks = languagepack.LanguagePackManager(self)

View File

@@ -0,0 +1,55 @@
# Copyright 2014 - Rackspace Hosting
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from solumclient.common import base as solum_base
from solumclient.openstack.common.apiclient import base as apiclient_base
from solumclient.openstack.common import uuidutils
class Pipeline(apiclient_base.Resource):
def __repr__(self):
return "<Pipeline %s>" % self._info
class PipelineManager(solum_base.CrudManager, solum_base.FindMixin):
resource_class = Pipeline
collection_key = 'pipelines'
key = 'pipeline'
def list(self, **kwargs):
return super(PipelineManager, self).list(base_url="/v1", **kwargs)
def create(self, **kwargs):
return super(PipelineManager, self).create(base_url="/v1", **kwargs)
def get(self, **kwargs):
return super(PipelineManager, self).get(base_url="/v1", **kwargs)
def put(self, **kwargs):
return super(PipelineManager, self).put(base_url="/v1", **kwargs)
def delete(self, **kwargs):
return super(PipelineManager, self).delete(base_url="/v1", **kwargs)
def find(self, **kwargs):
if 'pipeline_id' in kwargs:
return super(PipelineManager, self).get(base_url="/v1", **kwargs)
elif 'name_or_id' in kwargs:
name_or_uuid = kwargs['name_or_id']
if uuidutils.is_uuid_like(name_or_uuid):
return super(PipelineManager, self).get(
base_url="/v1",
pipeline_id=name_or_uuid)
else:
return super(PipelineManager, self).findone(name=name_or_uuid)