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