##// END OF EJS Templates
integrations: fix bug where deleting a repo did not delete integrations
dan -
r427:b1411a81 default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -0,0 +1,78 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import pytest
22 import requests
23 from mock import Mock, patch
24
25 from rhodecode import events
26 from rhodecode.model.db import Session, Integration
27 from rhodecode.model.integration import IntegrationModel
28 from rhodecode.integrations.types.base import IntegrationTypeBase
29
30
31 class TestIntegrationType(IntegrationTypeBase):
32 """ Test integration type class """
33
34 key = 'test-integration'
35 display_name = 'Test integration type'
36
37 def __init__(self, settings):
38 super(IntegrationTypeBase, self).__init__(settings)
39 self.sent_events = [] # for testing
40
41 def send_event(self, event):
42 self.sent_events.append(event)
43
44
45 @pytest.fixture
46 def repo_integration_stub(request, repo_stub):
47 settings = {'test_key': 'test_value'}
48 integration = IntegrationModel().create(
49 TestIntegrationType, settings=settings, repo=repo_stub, enabled=True,
50 name='test repo integration')
51
52 @request.addfinalizer
53 def cleanup():
54 IntegrationModel().delete(integration)
55
56 return integration
57
58
59 @pytest.fixture
60 def global_integration_stub(request):
61 settings = {'test_key': 'test_value'}
62 integration = IntegrationModel().create(
63 TestIntegrationType, settings=settings, enabled=True,
64 name='test global integration')
65
66 @request.addfinalizer
67 def cleanup():
68 IntegrationModel().delete(integration)
69
70 return integration
71
72
73 def test_delete_repo_with_integration_deletes_integration(repo_integration):
74 Session().delete(repo_integration.repo)
75 Session().commit()
76 Session().expire_all()
77 assert Integration.get(repo_integration.integration_id) is None
78
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,118 +1,132 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2011-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21
22 22 """
23 23 Model for integrations
24 24 """
25 25
26 26
27 27 import logging
28 28 import traceback
29 29
30 30 from pylons import tmpl_context as c
31 31 from pylons.i18n.translation import _, ungettext
32 32 from sqlalchemy import or_
33 33 from sqlalchemy.sql.expression import false, true
34 34 from mako import exceptions
35 35
36 36 import rhodecode
37 37 from rhodecode import events
38 38 from rhodecode.lib import helpers as h
39 39 from rhodecode.lib.caching_query import FromCache
40 40 from rhodecode.lib.utils import PartialRenderer
41 41 from rhodecode.model import BaseModel
42 42 from rhodecode.model.db import Integration, User
43 43 from rhodecode.model.meta import Session
44 44 from rhodecode.integrations import integration_type_registry
45 from rhodecode.integrations.types.base import IntegrationTypeBase
45 46
46 47 log = logging.getLogger(__name__)
47 48
48 49
49 50 class IntegrationModel(BaseModel):
50 51
51 52 cls = Integration
52 53
53 54 def __get_integration(self, integration):
54 55 if isinstance(integration, Integration):
55 56 return integration
56 57 elif isinstance(integration, (int, long)):
57 58 return self.sa.query(Integration).get(integration)
58 59 else:
59 60 if integration:
60 61 raise Exception('integration must be int, long or Instance'
61 62 ' of Integration got %s' % type(integration))
62 63
64 def create(self, IntegrationType, enabled, name, settings, repo=None):
65 """ Create an IntegrationType integration """
66 integration = Integration(
67 integration_type=IntegrationType.key,
68 settings={},
69 repo=repo,
70 enabled=enabled,
71 name=name
72 )
73 self.sa.add(integration)
74 self.sa.commit()
75 return integration
76
63 77 def delete(self, integration):
64 78 try:
65 79 integration = self.__get_integration(integration)
66 80 if integration:
67 Session().delete(integration)
81 self.sa.delete(integration)
68 82 return True
69 83 except Exception:
70 84 log.error(traceback.format_exc())
71 85 raise
72 86 return False
73 87
74 88 def get_integration_handler(self, integration):
75 89 TypeClass = integration_type_registry.get(integration.integration_type)
76 90 if not TypeClass:
77 91 log.error('No class could be found for integration type: {}'.format(
78 92 integration.integration_type))
79 93 return None
80 94
81 95 return TypeClass(integration.settings)
82 96
83 97 def send_event(self, integration, event):
84 98 """ Send an event to an integration """
85 99 handler = self.get_integration_handler(integration)
86 100 if handler:
87 101 handler.send_event(event)
88 102
89 103 def get_integrations(self, repo=None):
90 104 if repo:
91 105 return self.sa.query(Integration).filter(
92 106 Integration.repo_id==repo.repo_id).all()
93 107
94 108 # global integrations
95 109 return self.sa.query(Integration).filter(
96 110 Integration.repo_id==None).all()
97 111
98 112 def get_for_event(self, event, cache=False):
99 113 """
100 114 Get integrations that match an event
101 115 """
102 116 query = self.sa.query(Integration).filter(Integration.enabled==True)
103 117
104 118 if isinstance(event, events.RepoEvent): # global + repo integrations
105 119 query = query.filter(
106 120 or_(Integration.repo_id==None,
107 121 Integration.repo_id==event.repo.repo_id))
108 122 if cache:
109 123 query = query.options(FromCache(
110 124 "sql_cache_short",
111 125 "get_enabled_repo_integrations_%i" % event.repo.repo_id))
112 126 else: # only global integrations
113 127 query = query.filter(Integration.repo_id==None)
114 128 if cache:
115 129 query = query.options(FromCache(
116 130 "sql_cache_short", "get_enabled_global_integrations"))
117 131
118 132 return query.all()
General Comments 0
You need to be logged in to leave comments. Login now