|
1 | 1 | # Copyright 2023 Canonical Ltd. |
2 | 2 | # Licensed under the Apache V2, see LICENCE file for details. |
3 | 3 |
|
4 | | -from pathlib import Path |
| 4 | +import pytest |
5 | 5 | import unittest |
| 6 | +from pathlib import Path |
6 | 7 | from unittest import mock |
7 | 8 | from mock import patch, Mock, ANY |
| 9 | +from typing import Dict, Union |
8 | 10 |
|
9 | 11 | import yaml |
10 | 12 |
|
@@ -122,7 +124,6 @@ def test_dict_params_missing_data(self): |
122 | 124 |
|
123 | 125 |
|
124 | 126 | class TestAddApplicationChangeRun: |
125 | | - |
126 | 127 | async def test_run_with_charmhub_charm(self): |
127 | 128 | storage_label = "some-label" |
128 | 129 | storage_constraint = "ebs,100G,1" |
@@ -169,6 +170,93 @@ async def test_run_with_charmhub_charm(self): |
169 | 170 | charm_origin=ANY, |
170 | 171 | num_units="num_units") |
171 | 172 |
|
| 173 | + @pytest.mark.parametrize( |
| 174 | + 'storage_arg_for_change,storage_arg_for_deploy', |
| 175 | + [ |
| 176 | + ({'some-label': 'ebs,100G,1'}, {'some-label': {'count': 1, 'pool': 'ebs', 'size': 102400}}), |
| 177 | + ({'some-label': 'ebs,2.1G,3'}, {'some-label': {'count': 3, 'pool': 'ebs', 'size': 2150}}), |
| 178 | + ({'some-label': 'ebs,100G'}, {'some-label': {'count': 1, 'pool': 'ebs', 'size': 102400}}), |
| 179 | + ({'some-label': 'ebs,2'}, {'some-label': {'count': 2, 'pool': 'ebs'}}), |
| 180 | + ({'some-label': '200G,7'}, {'some-label': {'count': 7, 'size': 204800}}), |
| 181 | + ({'some-label': 'ebs'}, {'some-label': {'count': 1, 'pool': 'ebs'}}), |
| 182 | + ({'some-label': '10YB'}, {'some-label': {'count': 1, 'size': 11529215046068469760}}), |
| 183 | + ({'some-label': '1'}, {'some-label': {'count': 1}}), |
| 184 | + ({'some-label': '-1'}, {'some-label': {'count': 1}}), |
| 185 | + ({'some-label': ''}, {'some-label': {'count': 1}}), |
| 186 | + ( |
| 187 | + { |
| 188 | + 'some-label': '2.1G,3', |
| 189 | + 'data': '1MiB,70', |
| 190 | + 'logs': 'ebs,-1', |
| 191 | + }, |
| 192 | + { |
| 193 | + 'some-label': {'count': 3, 'size': 2150}, |
| 194 | + 'data': {'count': 70, 'size': 1}, |
| 195 | + 'logs': {'count': 1, 'pool': 'ebs'} |
| 196 | + }, |
| 197 | + ), |
| 198 | + ] |
| 199 | + ) |
| 200 | + async def test_run_with_storage_variations( |
| 201 | + self, |
| 202 | + storage_arg_for_change: Dict[str, str], |
| 203 | + storage_arg_for_deploy: Dict[str, Dict[str, Union[int, str]]], |
| 204 | + ): |
| 205 | + """Test that various valid storage constraints are parsed as expected before model._deploy is called. |
| 206 | +
|
| 207 | + Uses the mock call logic from test_run_with_charmhub_charm, which will run before this test. |
| 208 | + """ |
| 209 | + change = AddApplicationChange( |
| 210 | + 1, |
| 211 | + [], |
| 212 | + params={ |
| 213 | + "charm": "charm", |
| 214 | + "series": "series", |
| 215 | + "application": "application", |
| 216 | + "options": "options", |
| 217 | + "constraints": "constraints", |
| 218 | + "storage": storage_arg_for_change, |
| 219 | + "endpoint-bindings": "endpoint_bindings", |
| 220 | + "resources": "resources", |
| 221 | + "devices": "devices", |
| 222 | + "num-units": "num_units", |
| 223 | + "channel": "channel", |
| 224 | + }, |
| 225 | + ) |
| 226 | + # mock model |
| 227 | + model = Mock() |
| 228 | + model._deploy = mock.AsyncMock(return_value=None) |
| 229 | + model._add_charmhub_resources = mock.AsyncMock(return_value=["resource1"]) |
| 230 | + model.applications = {} |
| 231 | + # mock context |
| 232 | + context = Mock() |
| 233 | + context.resolve.return_value = "ch:charm1" |
| 234 | + context.origins = {"ch:charm1": Mock()} |
| 235 | + context.trusted = False |
| 236 | + context.model = model |
| 237 | + # mock info_func |
| 238 | + info_func = mock.AsyncMock(return_value=["12345", "name"]) |
| 239 | + # patch and call |
| 240 | + with patch.object(charmhub.CharmHub, 'get_charm_id', info_func): |
| 241 | + result = await change.run(context) |
| 242 | + assert result == "application" |
| 243 | + # asserts |
| 244 | + model._deploy.assert_called_once() |
| 245 | + model._deploy.assert_called_with( |
| 246 | + charm_url="ch:charm1", |
| 247 | + application="application", |
| 248 | + series="series", |
| 249 | + config="options", |
| 250 | + constraints="constraints", |
| 251 | + endpoint_bindings="endpoint_bindings", |
| 252 | + resources=["resource1"], |
| 253 | + storage=storage_arg_for_deploy, # we're testing this |
| 254 | + devices="devices", |
| 255 | + channel="channel", |
| 256 | + charm_origin=ANY, |
| 257 | + num_units="num_units", |
| 258 | + ) |
| 259 | + |
172 | 260 | async def test_run_with_charmhub_charm_no_channel(self): |
173 | 261 | """Test to verify if when the given channel is None, the channel defaults to "local/stable", which |
174 | 262 | is the default channel value for the Charm Hub |
|
0 commit comments