1from __future__ import absolute_import, division, print_function 2 3__metaclass__ = type 4 5import sys 6 7import pytest 8 9from ansible.playbook.task import Task 10 11from ansible_collections.sensu.sensu_go.plugins.module_utils import ( 12 bonsai, errors, 13) 14from ansible_collections.sensu.sensu_go.plugins.action import bonsai_asset 15 16pytestmark = pytest.mark.skipif( 17 sys.version_info < (2, 7), reason="requires python2.7 or higher" 18) 19 20 21class TestValidate: 22 @pytest.mark.parametrize("name,args,required,typ", [ 23 # Required values must match the selected type. 24 ("a", dict(a=3), True, int), 25 ("a", dict(a=3.3), True, float), 26 ("a", dict(a="b"), True, str), 27 ("a", dict(a=[]), True, list), 28 ("a", dict(a={}), True, dict), 29 # Optional values are not checked for type-correctness if they are 30 # missing. 31 ("a", dict(), False, int), 32 ("a", dict(), False, float), 33 ("a", dict(), False, str), 34 ("a", dict(), False, list), 35 ("a", dict(), False, dict), 36 ]) 37 def test_valid_values(self, name, args, required, typ): 38 bonsai_asset.validate(name, args, required, typ) 39 40 def test_missing_required(self): 41 with pytest.raises(errors.Error, match="required"): 42 bonsai_asset.validate("a", {}, True, str) 43 44 def test_invalid_type(self): 45 with pytest.raises(errors.Error, match="should"): 46 bonsai_asset.validate("a", dict(a=3), True, str) 47 48 def test_invalid_type_for_optional_value(self): 49 with pytest.raises(errors.Error, match="should"): 50 bonsai_asset.validate("a", dict(a=3), False, dict) 51 52 53class TestValidateArguments: 54 def test_valid_minimal_args(self): 55 bonsai_asset.ActionModule.validate_arguments(dict( 56 name="abc", version="1.2.3", 57 )) 58 59 def test_valid_all_args(self): 60 bonsai_asset.ActionModule.validate_arguments(dict( 61 name="abc", version="1.2.3", rename="def", 62 labels={}, annotations={}, 63 )) 64 65 def test_valid_unicode_strings_python2(self): 66 bonsai_asset.ActionModule.validate_arguments(dict( 67 name=u"abc", version=u"1.2.3", rename=u"def", 68 labels={}, annotations={}, 69 )) 70 71 def test_invalid_name(self): 72 with pytest.raises(errors.Error, match="name"): 73 bonsai_asset.ActionModule.validate_arguments(dict( 74 name=1.234, version="1.2.3", 75 )) 76 77 def test_missing_name(self): 78 with pytest.raises(errors.Error, match="name"): 79 bonsai_asset.ActionModule.validate_arguments(dict( 80 version="1.2.3", 81 )) 82 83 def test_invalid_version(self): 84 with pytest.raises(errors.Error, match="version"): 85 bonsai_asset.ActionModule.validate_arguments(dict( 86 name="abc", version=1.2, 87 )) 88 89 def test_missing_version(self): 90 with pytest.raises(errors.Error, match="version"): 91 bonsai_asset.ActionModule.validate_arguments(dict( 92 name="abc", 93 )) 94 95 def test_invalid_rename(self): 96 with pytest.raises(errors.Error, match="rename"): 97 bonsai_asset.ActionModule.validate_arguments(dict( 98 name="abc", version="1.2.3", rename=1, 99 )) 100 101 def test_invalid_labels(self): 102 with pytest.raises(errors.Error, match="labels"): 103 bonsai_asset.ActionModule.validate_arguments(dict( 104 name="abc", version="1.2.3", labels=1, 105 )) 106 107 def test_invalid_annotations(self): 108 with pytest.raises(errors.Error, match="annotations"): 109 bonsai_asset.ActionModule.validate_arguments(dict( 110 name="abc", version="1.2.3", annotations=1, 111 )) 112 113 114class TestBuildAssetArgs: 115 def test_no_additional_metadata(self, mocker): 116 bonsai_params = mocker.patch.object(bonsai, "get_asset_parameters") 117 bonsai_params.return_value = dict( 118 builds=[], labels=None, annotations=None, 119 ) 120 121 result = bonsai_asset.ActionModule.build_asset_args(dict( 122 name="test/asset", 123 version="1.2.3", 124 )) 125 126 assert result == dict( 127 name="test/asset", 128 state="present", 129 builds=[], 130 ) 131 132 def test_bonsai_metadata_only(self, mocker): 133 bonsai_params = mocker.patch.object(bonsai, "get_asset_parameters") 134 bonsai_params.return_value = dict( 135 builds=[], labels=dict(a="b"), annotations=dict(c="d"), 136 ) 137 138 result = bonsai_asset.ActionModule.build_asset_args(dict( 139 name="test/asset", 140 version="1.2.3", 141 )) 142 143 assert result == dict( 144 name="test/asset", 145 state="present", 146 builds=[], 147 annotations=dict(c="d"), 148 labels=dict(a="b"), 149 ) 150 151 def test_user_metadata_only(self, mocker): 152 bonsai_params = mocker.patch.object(bonsai, "get_asset_parameters") 153 bonsai_params.return_value = dict( 154 builds=[1, 2, 3], labels=None, annotations=None, 155 ) 156 157 result = bonsai_asset.ActionModule.build_asset_args(dict( 158 name="test/asset", 159 version="1.2.3", 160 labels=dict(my="label"), 161 annotations=dict(my="annotation"), 162 )) 163 164 assert result == dict( 165 name="test/asset", 166 state="present", 167 builds=[1, 2, 3], 168 annotations=dict(my="annotation"), 169 labels=dict(my="label"), 170 ) 171 172 def test_mixed_metadata(self, mocker): 173 bonsai_params = mocker.patch.object(bonsai, "get_asset_parameters") 174 bonsai_params.return_value = dict( 175 builds=[], labels=dict(my="x", a="b"), annotations=dict(my="c"), 176 ) 177 178 result = bonsai_asset.ActionModule.build_asset_args(dict( 179 name="test/asset", 180 version="1.2.3", 181 labels=dict(my="label"), 182 annotations=dict(my="annotation"), 183 )) 184 185 assert result == dict( 186 name="test/asset", 187 state="present", 188 builds=[], 189 annotations=dict(my="annotation"), 190 labels=dict(my="label", a="b"), 191 ) 192 193 def test_rename(self, mocker): 194 bonsai_params = mocker.patch.object(bonsai, "get_asset_parameters") 195 bonsai_params.return_value = dict( 196 builds=[], labels=None, annotations=None, 197 ) 198 199 result = bonsai_asset.ActionModule.build_asset_args(dict( 200 name="test/asset", 201 version="1.2.3", 202 rename="my-asset", 203 )) 204 205 assert result == dict( 206 name="my-asset", 207 state="present", 208 builds=[], 209 ) 210 211 def test_auth_passthrough(self, mocker): 212 bonsai_params = mocker.patch.object(bonsai, "get_asset_parameters") 213 bonsai_params.return_value = dict( 214 builds=[], labels=None, annotations=None, 215 ) 216 217 result = bonsai_asset.ActionModule.build_asset_args(dict( 218 auth=dict(url="http://localhost:1234"), 219 name="test/asset", 220 version="1.2.3", 221 )) 222 223 assert result == dict( 224 auth=dict(url="http://localhost:1234"), 225 name="test/asset", 226 state="present", 227 builds=[], 228 ) 229 230 def test_namespace_passthrough(self, mocker): 231 bonsai_params = mocker.patch.object(bonsai, "get_asset_parameters") 232 bonsai_params.return_value = dict( 233 builds=[], labels=None, annotations=None, 234 ) 235 236 result = bonsai_asset.ActionModule.build_asset_args(dict( 237 namespace='default', 238 name="test/asset", 239 version="1.2.3", 240 )) 241 242 assert result == dict( 243 name="test/asset", 244 namespace='default', 245 state="present", 246 builds=[], 247 ) 248 249 def test_fail_bonsai(self, mocker): 250 bonsai_params = mocker.patch.object(bonsai, "get_asset_parameters") 251 bonsai_params.side_effect = errors.BonsaiError("Bonsai bad") 252 253 with pytest.raises(errors.Error, match="Bonsai bad"): 254 bonsai_asset.ActionModule.build_asset_args(dict( 255 name="test/asset", 256 version="1.2.3", 257 )) 258 259 bonsai_params.assert_called_with("test/asset", "1.2.3") 260 261 262class TestRun: 263 def test_success(self, mocker): 264 bonsai_params = mocker.patch.object(bonsai, "get_asset_parameters") 265 bonsai_params.return_value = dict( 266 builds=[], labels=None, annotations=None, 267 ) 268 task = mocker.MagicMock(Task, async_val=0, args=dict( 269 name="test/asset", 270 version="1.2.3", 271 )) 272 action = bonsai_asset.ActionModule( 273 task, mocker.MagicMock(), mocker.MagicMock(), loader=None, 274 templar=None, shared_loader_obj=None, 275 ) 276 action._execute_module = mocker.MagicMock(return_value=dict(a=3)) 277 278 result = action.run() 279 280 assert result == dict(a=3) 281 282 def test_fail(self, mocker): 283 bonsai_params = mocker.patch.object(bonsai, "get_asset_parameters") 284 bonsai_params.return_value = dict( 285 builds=[], labels=None, annotations=None, 286 ) 287 task = mocker.MagicMock(Task, async_val=0, args=dict( 288 name="test/asset", 289 )) 290 action = bonsai_asset.ActionModule( 291 task, mocker.MagicMock(), mocker.MagicMock(), loader=None, 292 templar=None, shared_loader_obj=None, 293 ) 294 action._execute_module = mocker.MagicMock(return_value=dict(a=3)) 295 296 result = action.run() 297 298 assert result["failed"] is True 299