Migrating trigger functionality
Migrating trigger functionality to work with the app and workflow resources instead of the plan and pipeline resources. Change-Id: I5674c6dfc4e7d7813480cb8c9108012a5838dd22 Closes-Bug: #1495693
This commit is contained in:
parent
4d469df2d9
commit
706b1e1253
|
@ -16,6 +16,8 @@ import requests
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from functionaltests.api import base
|
from functionaltests.api import base
|
||||||
|
from functionaltests.api.common import apputils
|
||||||
|
|
||||||
|
|
||||||
assembly_data = {'name': 'test_assembly',
|
assembly_data = {'name': 'test_assembly',
|
||||||
'description': 'desc assembly'}
|
'description': 'desc assembly'}
|
||||||
|
@ -53,8 +55,15 @@ class TestTriggerController(base.TestCase):
|
||||||
self.assertIsNotNone(trigger_uri)
|
self.assertIsNotNone(trigger_uri)
|
||||||
return uuid, trigger_uri
|
return uuid, trigger_uri
|
||||||
|
|
||||||
|
def _create_app(self):
|
||||||
|
data = apputils.get_sample_data()
|
||||||
|
resp = self.client.create_app(data=data)
|
||||||
|
bdy = json.loads(resp.body)
|
||||||
|
trigger_uri = bdy['trigger_uri']
|
||||||
|
return trigger_uri
|
||||||
|
|
||||||
def test_trigger_post(self):
|
def test_trigger_post(self):
|
||||||
assembly_uuid, plan_uuid, trigger_uri = self._create_assembly()
|
trigger_uri = self._create_app()
|
||||||
# Using requests instead of self.client to test unauthenticated request
|
# Using requests instead of self.client to test unauthenticated request
|
||||||
status_url = 'https://api.github.com/repos/u/r/statuses/{sha}'
|
status_url = 'https://api.github.com/repos/u/r/statuses/{sha}'
|
||||||
body_dict = {'sender': {'url': 'https://api.github.com'},
|
body_dict = {'sender': {'url': 'https://api.github.com'},
|
||||||
|
@ -64,8 +73,6 @@ class TestTriggerController(base.TestCase):
|
||||||
resp = requests.post(trigger_uri, data=body)
|
resp = requests.post(trigger_uri, data=body)
|
||||||
self.assertEqual(resp.status_code, 202)
|
self.assertEqual(resp.status_code, 202)
|
||||||
|
|
||||||
self._delete_assembly(assembly_uuid, plan_uuid)
|
|
||||||
|
|
||||||
def test_trigger_post_with_empty_body(self):
|
def test_trigger_post_with_empty_body(self):
|
||||||
assembly_uuid, plan_uuid, trigger_uri = self._create_assembly()
|
assembly_uuid, plan_uuid, trigger_uri = self._create_assembly()
|
||||||
# Using requests instead of self.client to test unauthenticated request
|
# Using requests instead of self.client to test unauthenticated request
|
||||||
|
|
|
@ -19,30 +19,11 @@ from tempest_lib import exceptions as tempest_exceptions
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from functionaltests.api import base
|
from functionaltests.api import base
|
||||||
|
from functionaltests.api.common import apputils
|
||||||
|
|
||||||
|
|
||||||
class TestAppController(base.TestCase):
|
class TestAppController(base.TestCase):
|
||||||
|
|
||||||
def _get_sample_data(self):
|
|
||||||
data = dict()
|
|
||||||
data["name"] = "test_app_1"
|
|
||||||
data["description"] = "descp"
|
|
||||||
data["languagepack"] = "python"
|
|
||||||
data["trigger_actions"] = ["test", "build", "deploy"]
|
|
||||||
data["ports"] = [80]
|
|
||||||
|
|
||||||
source = {}
|
|
||||||
source['repository'] = "https://github.com"
|
|
||||||
source['revision'] = "master"
|
|
||||||
data["source"] = source
|
|
||||||
|
|
||||||
workflow = {}
|
|
||||||
workflow["test_cmd"] = "./unit_tests.sh"
|
|
||||||
workflow["run_cmd"] = "python app.py"
|
|
||||||
data["workflow_config"] = workflow
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
def _assert_app_data(self, actual, expected):
|
def _assert_app_data(self, actual, expected):
|
||||||
self.assertEqual(actual["name"], expected["name"])
|
self.assertEqual(actual["name"], expected["name"])
|
||||||
self.assertEqual(actual["description"], expected["description"])
|
self.assertEqual(actual["description"], expected["description"])
|
||||||
|
@ -71,13 +52,13 @@ class TestAppController(base.TestCase):
|
||||||
self.client.delete_created_apps()
|
self.client.delete_created_apps()
|
||||||
|
|
||||||
def test_app_create(self):
|
def test_app_create(self):
|
||||||
data = self._get_sample_data()
|
data = apputils.get_sample_data()
|
||||||
resp = self.client.create_app(data=data)
|
resp = self.client.create_app(data=data)
|
||||||
self.assertEqual(resp.status, 201)
|
self.assertEqual(resp.status, 201)
|
||||||
|
|
||||||
def test_app_create_bad_port_data(self):
|
def test_app_create_bad_port_data(self):
|
||||||
try:
|
try:
|
||||||
bad_data = self._get_sample_data()
|
bad_data = apputils.get_sample_data()
|
||||||
bad_data["ports"][0] = -1
|
bad_data["ports"][0] = -1
|
||||||
self.client.create_plan(data=bad_data)
|
self.client.create_plan(data=bad_data)
|
||||||
except tempest_exceptions.BadRequest:
|
except tempest_exceptions.BadRequest:
|
||||||
|
@ -89,7 +70,7 @@ class TestAppController(base.TestCase):
|
||||||
headers={'content-type': 'application/json'})
|
headers={'content-type': 'application/json'})
|
||||||
|
|
||||||
def test_app_patch(self):
|
def test_app_patch(self):
|
||||||
data = self._get_sample_data()
|
data = apputils.get_sample_data()
|
||||||
create_resp = self.client.create_app(data=data)
|
create_resp = self.client.create_app(data=data)
|
||||||
self.assertEqual(create_resp.status, 201)
|
self.assertEqual(create_resp.status, 201)
|
||||||
|
|
||||||
|
@ -116,7 +97,7 @@ class TestAppController(base.TestCase):
|
||||||
self.assertEqual(app_body["source"]["repository"], "newrepo")
|
self.assertEqual(app_body["source"]["repository"], "newrepo")
|
||||||
|
|
||||||
def test_app_get(self):
|
def test_app_get(self):
|
||||||
data = self._get_sample_data()
|
data = apputils.get_sample_data()
|
||||||
create_resp = self.client.create_app(data=data)
|
create_resp = self.client.create_app(data=data)
|
||||||
self.assertEqual(create_resp.status, 201)
|
self.assertEqual(create_resp.status, 201)
|
||||||
id = create_resp.id
|
id = create_resp.id
|
||||||
|
@ -129,7 +110,7 @@ class TestAppController(base.TestCase):
|
||||||
self._assert_app_data(yaml_data, data)
|
self._assert_app_data(yaml_data, data)
|
||||||
|
|
||||||
def test_apps_get_all(self):
|
def test_apps_get_all(self):
|
||||||
data = self._get_sample_data()
|
data = apputils.get_sample_data()
|
||||||
create_resp = self.client.create_app(data)
|
create_resp = self.client.create_app(data)
|
||||||
self.assertEqual(create_resp.status, 201)
|
self.assertEqual(create_resp.status, 201)
|
||||||
resp, body = self.client.get(
|
resp, body = self.client.get(
|
||||||
|
@ -141,7 +122,7 @@ class TestAppController(base.TestCase):
|
||||||
self.assertEqual(filtered[0]['id'], id)
|
self.assertEqual(filtered[0]['id'], id)
|
||||||
|
|
||||||
def test_app_delete(self):
|
def test_app_delete(self):
|
||||||
data = self._get_sample_data()
|
data = apputils.get_sample_data()
|
||||||
create_resp = self.client.create_app(data)
|
create_resp = self.client.create_app(data)
|
||||||
self.assertEqual(create_resp.status, 201)
|
self.assertEqual(create_resp.status, 201)
|
||||||
id = create_resp.id
|
id = create_resp.id
|
||||||
|
|
|
@ -106,7 +106,6 @@ class AppsController(rest.RestController):
|
||||||
|
|
||||||
new_app = handler.create(app_data)
|
new_app = handler.create(app_data)
|
||||||
created_app = app.App.from_db_model(new_app, pecan.request.host_url)
|
created_app = app.App.from_db_model(new_app, pecan.request.host_url)
|
||||||
|
|
||||||
return created_app
|
return created_app
|
||||||
|
|
||||||
@exception.wrap_wsme_pecan_controller_exception
|
@exception.wrap_wsme_pecan_controller_exception
|
||||||
|
|
|
@ -47,10 +47,12 @@ class App(api_types.Base):
|
||||||
workflow_config = {wtypes.text: wtypes.text}
|
workflow_config = {wtypes.text: wtypes.text}
|
||||||
trigger_uuid = wtypes.text
|
trigger_uuid = wtypes.text
|
||||||
trigger_actions = [wtypes.text]
|
trigger_actions = [wtypes.text]
|
||||||
|
trigger_uri = wtypes.text
|
||||||
trust_id = wtypes.text
|
trust_id = wtypes.text
|
||||||
trust_user = wtypes.text
|
trust_user = wtypes.text
|
||||||
app_url = wtypes.text
|
app_url = wtypes.text
|
||||||
status = wtypes.text
|
status = wtypes.text
|
||||||
|
repo_token = wtypes.text
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(App, self).__init__(*args, **kwargs)
|
super(App, self).__init__(*args, **kwargs)
|
||||||
|
@ -67,6 +69,8 @@ class App(api_types.Base):
|
||||||
json = m.as_dict()
|
json = m.as_dict()
|
||||||
json['type'] = m.__tablename__
|
json['type'] = m.__tablename__
|
||||||
json['uri'] = '%s/v1/apps/%s' % (host_url, m.id)
|
json['uri'] = '%s/v1/apps/%s' % (host_url, m.id)
|
||||||
|
json['trigger_uri'] = ('%s/v1/triggers/%s' %
|
||||||
|
(host_url, m.trigger_uuid))
|
||||||
return cls(**(json))
|
return cls(**(json))
|
||||||
|
|
||||||
def as_dict(self, db_model):
|
def as_dict(self, db_model):
|
||||||
|
|
|
@ -18,8 +18,7 @@ from oslo_config import cfg
|
||||||
import pecan
|
import pecan
|
||||||
from pecan import rest
|
from pecan import rest
|
||||||
|
|
||||||
from solum.api.handlers import pipeline_handler
|
from solum.api.handlers import app_handler
|
||||||
from solum.api.handlers import plan_handler
|
|
||||||
from solum.common import exception
|
from solum.common import exception
|
||||||
from solum.openstack.common import log as logging
|
from solum.openstack.common import log as logging
|
||||||
|
|
||||||
|
@ -47,6 +46,7 @@ class TriggerController(rest.RestController):
|
||||||
status_url = None
|
status_url = None
|
||||||
collab_url = None
|
collab_url = None
|
||||||
workflow = None
|
workflow = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
query = query_dict(pecan.request.query_string)
|
query = query_dict(pecan.request.query_string)
|
||||||
if 'workflow' in query:
|
if 'workflow' in query:
|
||||||
|
@ -96,11 +96,11 @@ class TriggerController(rest.RestController):
|
||||||
raise exception.BadRequest(reason=info_msg)
|
raise exception.BadRequest(reason=info_msg)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
handler = plan_handler.PlanHandler(None)
|
handler = app_handler.AppHandler(None)
|
||||||
handler.trigger_workflow(trigger_id, commit_sha, status_url,
|
handler.trigger_workflow(trigger_id, commit_sha, status_url,
|
||||||
collab_url, workflow=workflow)
|
collab_url, workflow=workflow)
|
||||||
except exception.ResourceNotFound:
|
except exception.ResourceNotFound as e:
|
||||||
handler = pipeline_handler.PipelineHandler(None)
|
LOG.error("Incorrect trigger url.")
|
||||||
handler.trigger_workflow(trigger_id)
|
raise e
|
||||||
|
|
||||||
pecan.response.status = 202
|
pecan.response.status = 202
|
||||||
|
|
|
@ -78,7 +78,9 @@ class WorkflowsController(rest.RestController):
|
||||||
data.source = app_model.source
|
data.source = app_model.source
|
||||||
|
|
||||||
wf_data = data.as_dict(workflow.Workflow)
|
wf_data = data.as_dict(workflow.Workflow)
|
||||||
return workflow.Workflow.from_db_model(handler.create(wf_data),
|
return workflow.Workflow.from_db_model(handler.create(wf_data,
|
||||||
|
commit_sha='',
|
||||||
|
status_url=''),
|
||||||
pecan.request.host_url)
|
pecan.request.host_url)
|
||||||
|
|
||||||
@exception.wrap_pecan_controller_exception
|
@exception.wrap_pecan_controller_exception
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from solum.api.handlers import handler
|
from solum.api.handlers import handler
|
||||||
|
from solum.api.handlers import workflow_handler
|
||||||
|
from solum.common import exception
|
||||||
|
from solum.common import keystone_utils
|
||||||
from solum import objects
|
from solum import objects
|
||||||
from solum.openstack.common import log as logging
|
from solum.openstack.common import log as logging
|
||||||
|
|
||||||
|
@ -62,6 +65,10 @@ class AppHandler(handler.Handler):
|
||||||
db_obj.project_id = self.context.tenant
|
db_obj.project_id = self.context.tenant
|
||||||
db_obj.deleted = False
|
db_obj.deleted = False
|
||||||
|
|
||||||
|
# create a delegation trust_id\token, if required
|
||||||
|
db_obj.trust_id = keystone_utils.create_delegation_token(self.context)
|
||||||
|
db_obj.trust_user = self.context.user_name
|
||||||
|
|
||||||
db_obj.name = data.get('name')
|
db_obj.name = data.get('name')
|
||||||
db_obj.description = data.get('description')
|
db_obj.description = data.get('description')
|
||||||
db_obj.languagepack = data.get('languagepack')
|
db_obj.languagepack = data.get('languagepack')
|
||||||
|
@ -69,14 +76,53 @@ class AppHandler(handler.Handler):
|
||||||
db_obj.ports = data.get('ports')
|
db_obj.ports = data.get('ports')
|
||||||
db_obj.source = data.get('source')
|
db_obj.source = data.get('source')
|
||||||
db_obj.workflow_config = data.get('workflow_config')
|
db_obj.workflow_config = data.get('workflow_config')
|
||||||
db_obj.trigger_uuid = data.get('trigger_uuid')
|
db_obj.trigger_uuid = str(uuid.uuid4())
|
||||||
db_obj.trigger_actions = data.get('trigger_actions')
|
db_obj.trigger_actions = data.get('trigger_actions')
|
||||||
db_obj.trust_id = data.get('trust_id')
|
|
||||||
db_obj.trust_user = data.get('trust_user')
|
|
||||||
|
|
||||||
db_obj.create(self.context)
|
db_obj.create(self.context)
|
||||||
return db_obj
|
return db_obj
|
||||||
|
|
||||||
|
def trigger_workflow(self, trigger_id, commit_sha='',
|
||||||
|
status_url=None, collab_url=None, workflow=None):
|
||||||
|
"""Get trigger by trigger id and start git workflow associated."""
|
||||||
|
# Note: self.context will be None at this point as this is a
|
||||||
|
# non-authenticated request.
|
||||||
|
app_obj = objects.registry.App.get_by_trigger_id(None, trigger_id)
|
||||||
|
# get the trust context and authenticate it.
|
||||||
|
try:
|
||||||
|
self.context = keystone_utils.create_delegation_context(
|
||||||
|
app_obj, self.context)
|
||||||
|
self.context.tenant = app_obj.project_id
|
||||||
|
self.context.user = app_obj.user_id
|
||||||
|
self.context.user_name = app_obj.trust_user
|
||||||
|
|
||||||
|
except exception.AuthorizationFailure as auth_ex:
|
||||||
|
LOG.warn(auth_ex)
|
||||||
|
return
|
||||||
|
|
||||||
|
# TODO(devkulkarni): Call repo_utils.verify_artifact
|
||||||
|
# as we are calling it in the plan_handler to verify
|
||||||
|
# the collaborator
|
||||||
|
self._build_artifact(app_obj, commit_sha=commit_sha,
|
||||||
|
status_url=status_url, wf=workflow)
|
||||||
|
|
||||||
|
def _build_artifact(self, app, commit_sha='',
|
||||||
|
status_url=None, wf=None):
|
||||||
|
|
||||||
|
if wf is None:
|
||||||
|
wf = ['unittest', 'build', 'deploy']
|
||||||
|
wfhand = workflow_handler.WorkflowHandler(self.context)
|
||||||
|
|
||||||
|
wfdata = {
|
||||||
|
'app_id': app.id,
|
||||||
|
'name': "%s" % app.name,
|
||||||
|
'description': '',
|
||||||
|
'source': app.source,
|
||||||
|
'config': app.workflow_config,
|
||||||
|
'actions': wf
|
||||||
|
}
|
||||||
|
wfhand.create(wfdata, commit_sha=commit_sha, status_url=status_url)
|
||||||
|
|
||||||
def get_all(self):
|
def get_all(self):
|
||||||
"""Return all apps."""
|
"""Return all apps."""
|
||||||
all_apps = objects.registry.AppList.get_all(self.context)
|
all_apps = objects.registry.AppList.get_all(self.context)
|
||||||
|
|
|
@ -64,7 +64,7 @@ class WorkflowHandler(handler.Handler):
|
||||||
db_obj = objects.registry.Workflow.get_by_uuid(self.context, id)
|
db_obj = objects.registry.Workflow.get_by_uuid(self.context, id)
|
||||||
db_obj.destroy(self.context)
|
db_obj.destroy(self.context)
|
||||||
|
|
||||||
def create(self, data):
|
def create(self, data, commit_sha, status_url):
|
||||||
"""Create a new workflow."""
|
"""Create a new workflow."""
|
||||||
db_obj = objects.registry.Workflow()
|
db_obj = objects.registry.Workflow()
|
||||||
db_obj.id = str(uuid.uuid4())
|
db_obj.id = str(uuid.uuid4())
|
||||||
|
|
|
@ -18,19 +18,16 @@ import mock
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
from solum.api.controllers.v1 import trigger
|
from solum.api.controllers.v1 import trigger
|
||||||
from solum.common import exception
|
|
||||||
from solum.tests import base
|
from solum.tests import base
|
||||||
from solum.tests import fakes
|
from solum.tests import fakes
|
||||||
|
|
||||||
|
|
||||||
@mock.patch('pecan.request', new_callable=fakes.FakePecanRequest)
|
@mock.patch('pecan.request', new_callable=fakes.FakePecanRequest)
|
||||||
@mock.patch('pecan.response', new_callable=fakes.FakePecanResponse)
|
@mock.patch('pecan.response', new_callable=fakes.FakePecanResponse)
|
||||||
@mock.patch('solum.api.controllers.v1.trigger.plan_handler'
|
@mock.patch('solum.api.controllers.v1.trigger.app_handler'
|
||||||
'.PlanHandler')
|
'.AppHandler')
|
||||||
@mock.patch('solum.api.controllers.v1.trigger.pipeline_handler'
|
|
||||||
'.PipelineHandler')
|
|
||||||
class TestTriggerController(base.BaseTestCase):
|
class TestTriggerController(base.BaseTestCase):
|
||||||
def test_trigger_post_with_empty_body(self, pipe_mock, assem_mock,
|
def test_trigger_post_with_empty_body(self, assem_mock,
|
||||||
resp_mock, request_mock):
|
resp_mock, request_mock):
|
||||||
obj = trigger.TriggerController()
|
obj = trigger.TriggerController()
|
||||||
obj.post('test_id')
|
obj.post('test_id')
|
||||||
|
@ -38,7 +35,7 @@ class TestTriggerController(base.BaseTestCase):
|
||||||
tw = assem_mock.return_value.trigger_workflow
|
tw = assem_mock.return_value.trigger_workflow
|
||||||
assert not tw.called
|
assert not tw.called
|
||||||
|
|
||||||
def test_trigger_post_on_github_webhook(self, pipe_mock, assem_mock,
|
def test_trigger_post_on_github_webhook(self, assem_mock,
|
||||||
resp_mock, request_mock):
|
resp_mock, request_mock):
|
||||||
status_url = 'https://api.github.com/repos/u/r/statuses/{sha}'
|
status_url = 'https://api.github.com/repos/u/r/statuses/{sha}'
|
||||||
body_dict = {'sender': {'url': 'https://api.github.com'},
|
body_dict = {'sender': {'url': 'https://api.github.com'},
|
||||||
|
@ -53,7 +50,7 @@ class TestTriggerController(base.BaseTestCase):
|
||||||
tw.assert_called_once_with('test_id', 'asdf', expected_st_url, None,
|
tw.assert_called_once_with('test_id', 'asdf', expected_st_url, None,
|
||||||
workflow=None)
|
workflow=None)
|
||||||
|
|
||||||
def test_trigger_post_on_github_comment_webhook(self, pipe_mock,
|
def test_trigger_post_on_github_comment_webhook(self,
|
||||||
assem_mock, resp_mock,
|
assem_mock, resp_mock,
|
||||||
request_mock):
|
request_mock):
|
||||||
cfg.CONF.api.rebuild_phrase = "solum retry tests"
|
cfg.CONF.api.rebuild_phrase = "solum retry tests"
|
||||||
|
@ -78,7 +75,6 @@ class TestTriggerController(base.BaseTestCase):
|
||||||
|
|
||||||
@mock.patch('httplib2.Http.request')
|
@mock.patch('httplib2.Http.request')
|
||||||
def test_trigger_post_on_mismatch_comment_pub_repo(self, http_mock,
|
def test_trigger_post_on_mismatch_comment_pub_repo(self, http_mock,
|
||||||
pipe_mock,
|
|
||||||
assem_mock, resp_mock,
|
assem_mock, resp_mock,
|
||||||
request_mock):
|
request_mock):
|
||||||
cfg.CONF.api.rebuild_phrase = "solum retry tests"
|
cfg.CONF.api.rebuild_phrase = "solum retry tests"
|
||||||
|
@ -102,7 +98,6 @@ class TestTriggerController(base.BaseTestCase):
|
||||||
|
|
||||||
@mock.patch('httplib2.Http.request')
|
@mock.patch('httplib2.Http.request')
|
||||||
def test_trigger_post_on_valid_comment_pub_repo(self, http_mock,
|
def test_trigger_post_on_valid_comment_pub_repo(self, http_mock,
|
||||||
pipe_mock,
|
|
||||||
assem_mock, resp_mock,
|
assem_mock, resp_mock,
|
||||||
request_mock):
|
request_mock):
|
||||||
cfg.CONF.api.rebuild_phrase = "solum retry tests"
|
cfg.CONF.api.rebuild_phrase = "solum retry tests"
|
||||||
|
@ -127,7 +122,7 @@ class TestTriggerController(base.BaseTestCase):
|
||||||
tw.assert_called_once_with('test_id', 'asdf', expected_st_url,
|
tw.assert_called_once_with('test_id', 'asdf', expected_st_url,
|
||||||
expected_clb_url, workflow=None)
|
expected_clb_url, workflow=None)
|
||||||
|
|
||||||
def test_trigger_post_on_comment_missing_login(self, pipe_mock,
|
def test_trigger_post_on_comment_missing_login(self,
|
||||||
assem_mock, resp_mock,
|
assem_mock, resp_mock,
|
||||||
request_mock):
|
request_mock):
|
||||||
cfg.CONF.api.rebuild_phrase = "solum retry tests"
|
cfg.CONF.api.rebuild_phrase = "solum retry tests"
|
||||||
|
@ -148,7 +143,7 @@ class TestTriggerController(base.BaseTestCase):
|
||||||
tw = assem_mock.return_value.trigger_workflow
|
tw = assem_mock.return_value.trigger_workflow
|
||||||
assert not tw.called
|
assert not tw.called
|
||||||
|
|
||||||
def test_trigger_post_on_wrong_github_webhook(self, pipe_mock, assem_mock,
|
def test_trigger_post_on_wrong_github_webhook(self, assem_mock,
|
||||||
resp_mock, request_mock):
|
resp_mock, request_mock):
|
||||||
status_url = 'https://api.github.com/repos/u/r/statuses/{sha}'
|
status_url = 'https://api.github.com/repos/u/r/statuses/{sha}'
|
||||||
body_dict = {'sender': {'url': 'https://api.github.com'},
|
body_dict = {'sender': {'url': 'https://api.github.com'},
|
||||||
|
@ -161,7 +156,7 @@ class TestTriggerController(base.BaseTestCase):
|
||||||
tw = assem_mock.return_value.trigger_workflow
|
tw = assem_mock.return_value.trigger_workflow
|
||||||
assert not tw.called
|
assert not tw.called
|
||||||
|
|
||||||
def test_trigger_post_on_unknown_git_webhook(self, pipe_mock, assem_mock,
|
def test_trigger_post_on_unknown_git_webhook(self, assem_mock,
|
||||||
resp_mock, request_mock):
|
resp_mock, request_mock):
|
||||||
body_dict = {"pull_request": {"head": {"sha": "asdf"}}}
|
body_dict = {"pull_request": {"head": {"sha": "asdf"}}}
|
||||||
request_mock.body = json.dumps(body_dict)
|
request_mock.body = json.dumps(body_dict)
|
||||||
|
@ -171,7 +166,7 @@ class TestTriggerController(base.BaseTestCase):
|
||||||
tw = assem_mock.return_value.trigger_workflow
|
tw = assem_mock.return_value.trigger_workflow
|
||||||
assert not tw.called
|
assert not tw.called
|
||||||
|
|
||||||
def test_trigger_post_on_non_github_webhook(self, pipe_mock, assem_mock,
|
def test_trigger_post_on_non_github_webhook(self, assem_mock,
|
||||||
resp_mock, request_mock):
|
resp_mock, request_mock):
|
||||||
body_dict = {"sender": {"url": "https://non-github.com"},
|
body_dict = {"sender": {"url": "https://non-github.com"},
|
||||||
"pull_request": {"head": {"sha": "asdf"}}}
|
"pull_request": {"head": {"sha": "asdf"}}}
|
||||||
|
@ -182,7 +177,7 @@ class TestTriggerController(base.BaseTestCase):
|
||||||
tw = assem_mock.return_value.trigger_workflow
|
tw = assem_mock.return_value.trigger_workflow
|
||||||
assert not tw.called
|
assert not tw.called
|
||||||
|
|
||||||
def test_trigger_post_on_github_ping_webhook(self, pipe_mock, assem_mock,
|
def test_trigger_post_on_github_ping_webhook(self, assem_mock,
|
||||||
resp_mock, request_mock):
|
resp_mock, request_mock):
|
||||||
body_dict = {"sender": {"url": "https://api.github.com"},
|
body_dict = {"sender": {"url": "https://api.github.com"},
|
||||||
"zen": "Keep it logically awesome."}
|
"zen": "Keep it logically awesome."}
|
||||||
|
@ -191,41 +186,4 @@ class TestTriggerController(base.BaseTestCase):
|
||||||
obj.post('test_id')
|
obj.post('test_id')
|
||||||
self.assertEqual(501, resp_mock.status)
|
self.assertEqual(501, resp_mock.status)
|
||||||
tw = assem_mock.return_value.trigger_workflow
|
tw = assem_mock.return_value.trigger_workflow
|
||||||
assert not tw.called
|
assert not tw.called
|
||||||
|
|
||||||
def test_trigger_post_pipeline(self, pipe_mock, assem_mock,
|
|
||||||
resp_mock, request_mock):
|
|
||||||
status_url = 'https://api.github.com/repos/u/r/statuses/{sha}'
|
|
||||||
body_dict = {'sender': {'url': 'https://api.github.com'},
|
|
||||||
'pull_request': {'head': {'sha': 'asdf'}},
|
|
||||||
'repository': {'statuses_url': status_url}}
|
|
||||||
request_mock.body = json.dumps(body_dict)
|
|
||||||
obj = trigger.TriggerController()
|
|
||||||
assem_mock.return_value.trigger_workflow.side_effect = (
|
|
||||||
exception.ResourceNotFound(name='trigger', id='test_id'))
|
|
||||||
obj.post('test_id')
|
|
||||||
|
|
||||||
self.assertEqual(202, resp_mock.status)
|
|
||||||
tw = pipe_mock.return_value.trigger_workflow
|
|
||||||
tw.assert_called_once_with('test_id')
|
|
||||||
|
|
||||||
def test_trigger_post_none(self, pipe_mock, assem_mock,
|
|
||||||
resp_mock, request_mock):
|
|
||||||
status_url = 'https://api.github.com/repos/u/r/statuses/{sha}'
|
|
||||||
body_dict = {'sender': {'url': 'https://api.github.com'},
|
|
||||||
'pull_request': {'head': {'sha': 'asdf'}},
|
|
||||||
'repository': {'statuses_url': status_url}}
|
|
||||||
request_mock.body = json.dumps(body_dict)
|
|
||||||
expected_st_url = 'https://api.github.com/repos/u/r/statuses/asdf'
|
|
||||||
obj = trigger.TriggerController()
|
|
||||||
assem_mock.return_value.trigger_workflow.side_effect = (
|
|
||||||
exception.ResourceNotFound(name='trigger', id='test_id'))
|
|
||||||
pipe_mock.return_value.trigger_workflow.side_effect = (
|
|
||||||
exception.ResourceNotFound(name='trigger', id='test_id'))
|
|
||||||
obj.post('test_id')
|
|
||||||
self.assertEqual(404, resp_mock.status)
|
|
||||||
tw = assem_mock.return_value.trigger_workflow
|
|
||||||
tw.assert_called_once_with('test_id', 'asdf', expected_st_url, None,
|
|
||||||
workflow=None)
|
|
||||||
tw = pipe_mock.return_value.trigger_workflow
|
|
||||||
tw.assert_called_once_with('test_id')
|
|
|
@ -51,7 +51,8 @@ class TestAppHandler(base.BaseTestCase):
|
||||||
get_by_uuid.assert_called_once_with(self.ctx, 'test_id')
|
get_by_uuid.assert_called_once_with(self.ctx, 'test_id')
|
||||||
self.assertTrue(db_obj.destroy.called)
|
self.assertTrue(db_obj.destroy.called)
|
||||||
|
|
||||||
def test_app_create(self, mock_registry):
|
@mock.patch('solum.common.clients.OpenStackClients.keystone')
|
||||||
|
def test_app_create(self, mock_kc, mock_registry):
|
||||||
data = {'name': 'fakeapp',
|
data = {'name': 'fakeapp',
|
||||||
'description': 'fake app for testing'}
|
'description': 'fake app for testing'}
|
||||||
db_obj = fakes.FakeApp()
|
db_obj = fakes.FakeApp()
|
||||||
|
|
|
@ -91,8 +91,7 @@ class TestWorkflowHandler(base.BaseTestCase):
|
||||||
|
|
||||||
handler = workflow_handler.WorkflowHandler(self.ctx)
|
handler = workflow_handler.WorkflowHandler(self.ctx)
|
||||||
|
|
||||||
res = handler.create(workflow_data)
|
res = handler.create(workflow_data, commit_sha='', status_url='')
|
||||||
|
|
||||||
self.assertEqual(wf_obj, res)
|
self.assertEqual(wf_obj, res)
|
||||||
git_info = {
|
git_info = {
|
||||||
'source_url': app_obj.source['repository'],
|
'source_url': app_obj.source['repository'],
|
||||||
|
|
|
@ -46,14 +46,14 @@ def _get_solum_client():
|
||||||
|
|
||||||
def main(args):
|
def main(args):
|
||||||
client = _get_solum_client()
|
client = _get_solum_client()
|
||||||
plan = client.plans.find(name_or_id=args.app)
|
app = client.apps.find(name_or_id=args.app)
|
||||||
status_url = 'https://api.github.com/repos/{repo}/statuses/{sha}'.format(
|
status_url = 'https://api.github.com/repos/{repo}/statuses/{sha}'.format(
|
||||||
repo=args.repo, sha=args.sha)
|
repo=args.repo, sha=args.sha)
|
||||||
body_dict = {'sender': {'url': 'https://api.github.com'},
|
body_dict = {'sender': {'url': 'https://api.github.com'},
|
||||||
'pull_request': {'head': {'sha': args.sha}},
|
'pull_request': {'head': {'sha': args.sha}},
|
||||||
'repository': {'statuses_url': status_url}}
|
'repository': {'statuses_url': status_url}}
|
||||||
body = json.dumps(body_dict)
|
body = json.dumps(body_dict)
|
||||||
trigger_uri = plan.trigger_uri
|
trigger_uri = app.trigger_uri
|
||||||
if args.workflow:
|
if args.workflow:
|
||||||
trigger_uri = "%s?workflow=%s" % (trigger_uri, args.workflow)
|
trigger_uri = "%s?workflow=%s" % (trigger_uri, args.workflow)
|
||||||
resp = requests.post(trigger_uri, data=body)
|
resp = requests.post(trigger_uri, data=body)
|
||||||
|
|
Loading…
Reference in New Issue