1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements. See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License. You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
19 from aria.cli.env import _Environment
20 from aria.core import Core
21 from aria.exceptions import DependentActiveExecutionsError, DependentAvailableNodesError
22 from aria.modeling.exceptions import ParameterException
23 from aria.storage import exceptions as storage_exceptions
25 from .base_test import ( # pylint: disable=unused-import
28 assert_exception_raised,
31 from ..mock import models as mock_models
34 class TestServicesList(TestCliBase):
36 @pytest.mark.parametrize('sort_by, order, sort_by_in_output, order_in_output', [
37 ('', '', 'created_at', 'asc'),
38 ('', ' --descending', 'created_at', 'desc'),
39 (' --sort-by name', '', 'name', 'asc'),
40 (' --sort-by name', ' --descending', 'name', 'desc')
42 def test_no_specified_service_template(self, monkeypatch, mock_storage, sort_by, order,
43 sort_by_in_output, order_in_output):
45 monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
46 self.invoke('services list{sort_by}{order}'.format(sort_by=sort_by, order=order))
47 assert 'Listing all services...' in self.logger_output_string
48 assert 'Listing services for service template' not in self.logger_output_string
50 mock_storage.service.list.assert_called_once_with(sort={sort_by_in_output: order_in_output},
52 assert 'Services:' in self.logger_output_string
53 assert mock_models.SERVICE_TEMPLATE_NAME in self.logger_output_string
54 assert mock_models.SERVICE_NAME in self.logger_output_string
56 @pytest.mark.parametrize('sort_by, order, sort_by_in_output, order_in_output', [
57 ('', '', 'created_at', 'asc'),
58 ('', ' --descending', 'created_at', 'desc'),
59 (' --sort-by name', '', 'name', 'asc'),
60 (' --sort-by name', ' --descending', 'name', 'desc')
62 def test_specified_service_template(self, monkeypatch, mock_storage, sort_by, order,
63 sort_by_in_output, order_in_output):
65 monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
66 self.invoke('services list -t test_st{sort_by}{order}'.format(sort_by=sort_by, order=order))
67 assert 'Listing services for service template test_st...' in self.logger_output_string
68 assert 'Listing all services...' not in self.logger_output_string
70 mock_storage.service.list.assert_called_once_with(sort={sort_by_in_output: order_in_output},
71 filters={'service_template': mock.ANY})
72 assert 'Services:' in self.logger_output_string
73 assert mock_models.SERVICE_TEMPLATE_NAME in self.logger_output_string
74 assert mock_models.SERVICE_NAME in self.logger_output_string
77 class TestServicesCreate(TestCliBase):
79 def test_header_string(self, monkeypatch, mock_storage):
80 monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
81 self.invoke('services create -t test_st test_s')
82 assert 'Creating new service from service template test_st...' in self.logger_output_string
84 def test_no_exception(self, monkeypatch, mock_storage):
86 monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
88 m = mock.MagicMock(return_value=mock_models.create_service_with_dependencies())
89 monkeypatch.setattr(Core, 'create_service', m)
90 self.invoke('services create -t test_st test_s')
91 assert "Service created. The service's name is test_s" in self.logger_output_string
93 def test_raises_storage_error_resulting_from_name_uniqueness(self, monkeypatch,
95 monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
96 monkeypatch.setattr(Core,
98 raise_exception(storage_exceptions.NotFoundError,
99 msg='UNIQUE constraint failed'))
100 assert_exception_raised(
101 self.invoke('services create -t test_st test_s'),
102 expected_exception=storage_exceptions.NotFoundError,
103 expected_msg='There already a exists a service with the same name')
105 assert "Service created. The service's name is test_s" not in self.logger_output_string
107 def test_raises_other_storage_error(self, monkeypatch, mock_object):
108 monkeypatch.setattr(_Environment, 'model_storage', mock_object)
109 monkeypatch.setattr(Core,
111 raise_exception(storage_exceptions.NotFoundError))
113 assert_exception_raised(
114 self.invoke('services create -t test_st test_s'),
115 expected_exception=storage_exceptions.NotFoundError)
117 assert "Service created. The service's name is test_s" not in self.logger_output_string
119 def test_raises_inputs_exception(self, monkeypatch, mock_storage):
120 monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
121 monkeypatch.setattr(Core,
123 raise_exception(ParameterException))
125 assert_exception_raised(
126 self.invoke('services create -t with_inputs test_s'),
127 expected_exception=ParameterException)
129 assert "Service created. The service's name is test_s" not in self.logger_output_string
132 class TestServicesDelete(TestCliBase):
134 def test_header_string(self, monkeypatch, mock_storage):
135 monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
136 self.invoke('services delete test_s')
137 assert 'Deleting service test_s...' in self.logger_output_string
139 def test_delete_no_exception(self, monkeypatch, mock_storage, mock_object):
141 monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
142 monkeypatch.setattr(Core, 'delete_service', mock_object)
143 self.invoke('services delete test_s')
144 assert 'Service test_s deleted' in self.logger_output_string
146 def test_delete_active_execution_error(self, monkeypatch, mock_storage):
147 monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
148 mock_service_with_execution = \
149 mock.MagicMock(return_value=mock_models.create_service_with_dependencies(
150 include_execution=True))
151 monkeypatch.setattr(mock_storage.service, 'get', mock_service_with_execution)
152 assert_exception_raised(
153 self.invoke('services delete test_s'),
154 expected_exception=DependentActiveExecutionsError,
155 expected_msg="Can't delete service `{name}` - there is an active execution "
156 "for this service. Active execution ID: 1".format(
157 name=mock_models.SERVICE_NAME))
159 def test_delete_available_nodes_error(self, monkeypatch, mock_storage):
160 monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
161 assert_exception_raised(
162 self.invoke('services delete test_s'),
163 expected_exception=DependentAvailableNodesError,
164 expected_msg="Can't delete service `{name}` - there are available nodes "
165 "for this service. Available node IDs: 1".format(
166 name=mock_models.SERVICE_NAME))
168 def test_delete_available_nodes_error_with_force(self, monkeypatch, mock_storage):
169 monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
170 self.invoke('services delete service_with_available_nodes --force')
172 assert mock_storage.service.delete.call_count == 1
173 assert 'Service service_with_available_nodes deleted' in self.logger_output_string
176 class TestServicesOutputs(TestCliBase):
178 def test_header_string(self, monkeypatch, mock_storage):
179 monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
180 self.invoke('services outputs test_s')
181 assert 'Showing outputs for service test_s...' in self.logger_output_string
183 def test_outputs_no_outputs(self, monkeypatch, mock_storage):
184 monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
185 self.invoke('services outputs service_with_no_outputs')
187 assert 'No outputs' in self.logger_output_string
188 assert 'output1' not in self.logger_output_string
189 assert 'value1' not in self.logger_output_string
191 def test_outputs_one_output(self, monkeypatch, mock_storage):
192 monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
193 s = mock_models.create_service_with_dependencies(include_output=True)
194 monkeypatch.setattr(mock_storage.service, 'get_by_name', mock.MagicMock(return_value=s))
196 self.invoke('services outputs test_s')
198 assert 'output1' in self.logger_output_string
199 assert 'value1' in self.logger_output_string
200 assert 'No outputs' not in self.logger_output_string
203 class TestServicesInputs(TestCliBase):
205 def test_header_string(self, monkeypatch, mock_storage):
206 monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
207 self.invoke('services inputs test_s')
208 assert 'Showing inputs for service test_s...' in self.logger_output_string
210 def test_inputs_no_inputs(self, monkeypatch, mock_storage):
211 monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
212 self.invoke('services inputs service_with_no_inputs')
214 assert 'No inputs' in self.logger_output_string
215 assert 'input1' not in self.logger_output_string
216 assert 'value1' not in self.logger_output_string
218 def test_inputs_one_input(self, monkeypatch, mock_storage):
219 monkeypatch.setattr(_Environment, 'model_storage', mock_storage)
220 s = mock_models.create_service_with_dependencies(include_input=True)
221 monkeypatch.setattr(mock_storage.service, 'get_by_name', mock.MagicMock(return_value=s))
223 self.invoke('services inputs test_s')
225 assert 'input1' in self.logger_output_string
226 assert 'value1' in self.logger_output_string
227 assert 'No inputs' not in self.logger_output_string