def list_interfaces(call=None, kwargs=None): # pylint: disable=unused-argument ''' Create a network interface ''' global netconn # pylint: disable=global-statement,invalid-name if not netconn: netconn = get_conn(NetworkManagementClient, NetworkManagementClientConfiguration) if kwargs is None: kwargs = {} if kwargs.get('resource_group') is None: kwargs['resource_group'] = config.get_cloud_config_value( 'resource_group', {}, __opts__, search_global=True) region = get_location() bank = 'cloud/metadata/azurearm/{0}'.format(region) interfaces = cache.cache(bank, 'network_interfaces', netconn.network_interfaces.list, loop_fun=make_safe, expire=config.get_cloud_config_value( 'expire_interface_cache', get_configured_provider(), __opts__, search_global=False, default=86400, ), resource_group_name=kwargs['resource_group']) return interfaces
def list_resource_groups(conn=None, call=None): # pylint: disable=unused-argument ''' List resource groups associated with the account ''' if call == 'action': raise SaltCloudSystemExit( 'The list_hosted_services function must be called with ' '-f or --function') global resconn # pylint: disable=global-statement,invalid-name if not resconn: resconn = get_conn(ResourceManagementClient, ResourceManagementClientConfiguration) ret = {} region = get_location() bank = 'cloud/metadata/azurearm/{0}'.format(region) groups = cache.cache(bank, 'resource_groups', resconn.resource_groups.list, loop_fun=object_to_dict, expire=config.get_cloud_config_value( 'expire_group_cache', get_configured_provider(), __opts__, search_global=False, default=86400, )) for group in groups: ret[group['name']] = group return ret
def list_networks(call=None, kwargs=None): # pylint: disable=unused-argument ''' List virtual networks ''' if call == 'action': raise SaltCloudSystemExit( 'The avail_sizes function must be called with ' '-f or --function, or with the --list-sizes option') global netconn # pylint: disable=global-statement,invalid-name if not netconn: netconn = get_conn(NetworkManagementClient, NetworkManagementClientConfiguration) region = get_location() bank = 'cloud/metadata/azurearm/{0}/virtual_networks'.format(region) if kwargs is None: kwargs = {} if 'group' in kwargs: groups = [kwargs['group']] else: groups = list_resource_groups() ret = {} for group in groups: try: networks = cache.cache( bank, group, netconn.virtual_networks.list, loop_fun=make_safe, expire=config.get_cloud_config_value( 'expire_network_cache', get_configured_provider(), __opts__, search_global=False, default=86400, ), resource_group_name=group, ) except CloudError: networks = {} for vnet in networks: ret[vnet['name']] = make_safe(vnet) ret[vnet['name']]['subnets'] = list_subnets(kwargs={ 'group': group, 'network': vnet['name'] }) return ret
def list_subnets(call=None, kwargs=None): # pylint: disable=unused-argument ''' List subnets in a virtual network ''' if call == 'action': raise SaltCloudSystemExit( 'The avail_sizes function must be called with ' '-f or --function, or with the --list-sizes option') global netconn # pylint: disable=global-statement,invalid-name if not netconn: netconn = get_conn(NetworkManagementClient, NetworkManagementClientConfiguration) if 'group' not in kwargs: raise SaltCloudSystemExit( 'A resource_group must be specified as "group"') if 'network' not in kwargs: raise SaltCloudSystemExit('A "network" must be specified using') region = get_location() bank = 'cloud/metadata/azurearm/{0}/{1}'.format(region, kwargs['network']) ret = {} try: subnets = cache.cache( bank, 'subnets', netconn.subnets.list, loop_fun=make_safe, expire=config.get_cloud_config_value( 'expire_subnet_cache', get_configured_provider(), __opts__, search_global=False, default=86400, ), resource_group_name=kwargs['group'], virtual_network_name=kwargs['network'], ) except CloudError: return ret for subnet in subnets: ret[subnet['name']] = subnet subnet['resource_group'] = kwargs['group'] #subnet['ip_configurations'] = list_ip_configurations(kwargs=subnet) return ret
def list_security_rules(call=None, kwargs=None): # pylint: disable=unused-argument ''' Lits network security rules ''' global netconn # pylint: disable=global-statement,invalid-name if not netconn: netconn = get_conn(NetworkManagementClient, NetworkManagementClientConfiguration) if kwargs is None: kwargs = {} if kwargs.get('resource_group') is None: kwargs['resource_group'] = config.get_cloud_config_value( 'resource_group', {}, __opts__, search_global=True) if kwargs.get('security_group') is None: kwargs['security_group'] = config.get_cloud_config_value( 'security_group', {}, __opts__, search_global=True) region = get_location() bank = 'cloud/metadata/azurearm/{0}'.format(region) security_rules = cache.cache( bank, 'security_rules', netconn.security_rules.list, loop_fun=make_safe, expire=config.get_cloud_config_value( 'expire_security_rule_cache', get_configured_provider(), __opts__, search_global=False, default=86400, ), resource_group_name=kwargs['resource_group'], network_security_group_name=kwargs['security_group'], ) ret = {} for group in security_rules: ret[group['name']] = group return ret
def run_common_cache_tests(subtests, cache): bank = "fnord/kevin/stuart" # ^^^^ This bank can be just fnord, or fnord/foo, or any mildly reasonable # or possibly unreasonably nested names. # # No. Seriously. Try import string; bank = '/'.join(string.ascii_letters) # - it works! # import string; bank = "/".join(string.ascii_letters) good_key = "roscivs" bad_key = "monkey" with subtests.test("non-existent bank should be empty on cache start"): assert not cache.contains(bank=bank) assert cache.list(bank=bank) == [] with subtests.test("after storing key in bank it should be in cache list"): cache.store(bank=bank, key=good_key, data=b"\x01\x04\x05fnordy data") assert cache.list(bank) == [good_key] with subtests.test("after storing value, it should be fetchable"): expected_data = "trombone pleasantry" cache.store(bank=bank, key=good_key, data=expected_data) assert cache.fetch(bank=bank, key=good_key) == expected_data with subtests.test("bad key should still be absent from cache"): assert cache.fetch(bank=bank, key=bad_key) == {} with subtests.test("storing new value should update it"): # Double check that the data was still the old stuff old_data = expected_data assert cache.fetch(bank=bank, key=good_key) == old_data new_data = "stromboli" cache.store(bank=bank, key=good_key, data=new_data) assert cache.fetch(bank=bank, key=good_key) == new_data with subtests.test("storing complex object works"): new_thing = { "some": "data", 42: "wheee", "some other": {"sub": {"objects": "here"}}, } cache.store(bank=bank, key=good_key, data=new_thing) actual_thing = cache.fetch(bank=bank, key=good_key) if isinstance(cache, salt.cache.MemCache): # MemCache should actually store the object - everything else # should create a copy of it. assert actual_thing is new_thing else: assert actual_thing is not new_thing assert actual_thing == new_thing with subtests.test("contains returns true if key in bank"): assert cache.contains(bank=bank, key=good_key) with subtests.test("contains returns true if bank exists and key is None"): assert cache.contains(bank=bank, key=None) with subtests.test( "contains returns False when bank not in cache and/or key not in bank" ): assert not cache.contains(bank=bank, key=bad_key) assert not cache.contains(bank="nonexistent", key=good_key) assert not cache.contains(bank="nonexistent", key=bad_key) assert not cache.contains(bank="nonexistent", key=None) with subtests.test("flushing nonexistent key should not remove other keys"): cache.flush(bank=bank, key=bad_key) assert cache.contains(bank=bank, key=good_key) with subtests.test( "flushing existing key should not remove bank if no more keys exist" ): pytest.skip( "This is impossible with redis. Should we make localfs behave the same way?" ) cache.flush(bank=bank, key=good_key) assert cache.contains(bank=bank) assert cache.list(bank=bank) == [] with subtests.test( "after existing key is flushed updated should not return a timestamp for that key" ): cache.store(bank=bank, key=good_key, data="fnord") cache.flush(bank=bank, key=good_key) timestamp = cache.updated(bank=bank, key=good_key) assert timestamp is None with subtests.test( "after flushing bank containing a good key, updated should not return a timestamp for that key" ): cache.store(bank=bank, key=good_key, data="fnord") cache.flush(bank=bank, key=None) timestamp = cache.updated(bank=bank, key=good_key) assert timestamp is None with subtests.test("flushing bank with None as key should remove bank"): cache.flush(bank=bank, key=None) assert not cache.contains(bank=bank) with subtests.test("Exception should happen when flushing None bank"): # This bit is maybe an accidental API, but currently there is no # protection at least with the localfs cache when bank is None. If # bank is None we try to `os.path.normpath` the bank, which explodes # and is at least the current behavior. If we want to change that # this test should change. Or be removed altogether. # TODO: this should actually not raise. Not sure if there's a test that we can do here... or just call the code which will fail if there's actually an exception. -W. Werner, 2021-09-28 pytest.skip( "Skipping for now - etcd, redis, and mysql do not raise. Should ensure all backends behave consistently" ) with pytest.raises(Exception): cache.flush(bank=None, key=None) with subtests.test("Updated for non-existent key should return None"): timestamp = cache.updated(bank="nonexistent", key="whatever") assert timestamp is None with subtests.test("Updated for key should return a reasonable time"): before_storage = int(time.time()) cache.store(bank="fnord", key="updated test part 2", data="fnord") after_storage = int(time.time()) timestamp = cache.updated(bank="fnord", key="updated test part 2") assert before_storage <= timestamp <= after_storage with subtests.test( "If the module raises SaltCacheError then it should make it out of updated" ): with patch.dict( cache.modules._dict, {"{}.updated".format(cache.driver): MagicMock(side_effect=SaltCacheError)}, ), pytest.raises(SaltCacheError): cache.updated(bank="kaboom", key="oops") with subtests.test( "cache.cache right after a value is cached should not update the cache" ): expected_value = "some cool value yo" cache.store(bank=bank, key=good_key, data=expected_value) result = cache.cache( bank=bank, key=good_key, fun=lambda **kwargs: "bad bad value no good", value="some other value?", loop_fun=lambda x: "super very no good bad", ) fetch_result = cache.fetch(bank=bank, key=good_key) assert result == fetch_result == expected_value with subtests.test( "cache.cache should update the value with the result of fun when value was updated longer than expiration", ), patch( "salt.cache.Cache.updated", return_value=42, # Dec 31, 1969... time to update the cache! autospec=True, ): expected_value = "this is the return value woo woo woo" cache.store(bank=bank, key=good_key, data="not this value") cache_result = cache.cache( bank=bank, key=good_key, fun=lambda *args, **kwargs: expected_value ) fetch_result = cache.fetch(bank=bank, key=good_key) assert cache_result == fetch_result == expected_value with subtests.test( "cache.cache should update the value with all of the outputs from loop_fun if loop_fun was provided", ), patch( "salt.cache.Cache.updated", return_value=42, autospec=True, ): expected_value = "SOME HUGE STRING OKAY?" cache.store(bank=bank, key=good_key, data="nope, not me") cache_result = cache.cache( bank=bank, key=good_key, fun=lambda **kwargs: "some huge string okay?", loop_fun=str.upper, ) fetch_result = cache.fetch(bank=bank, key=good_key) assert cache_result == fetch_result assert "".join(fetch_result) == expected_value with subtests.test( "cache.cache should update the value if the stored value is empty but present and expiry is way in the future" ), patch( "salt.cache.Cache.updated", return_value=time.time() * 2, autospec=True, ): # Unclear if this was intended behavior: currently any falsey data will # be updated by cache.cache. If this is incorrect, this test should # be updated or removed. expected_data = "some random string whatever" for empty in ("", (), [], {}, 0, 0.0, False, None): with subtests.test(empty=empty): cache.store( bank=bank, key=good_key, data=empty ) # empty chairs and empty data cache_result = cache.cache( bank=bank, key=good_key, fun=lambda **kwargs: expected_data ) fetch_result = cache.fetch(bank=bank, key=good_key) assert cache_result == fetch_result == expected_data with subtests.test("cache.cache should store a value if it does not exist"): expected_result = "some result plz" cache.flush(bank=bank, key=None) assert cache.fetch(bank=bank, key=good_key) == {} cache_result = cache.cache( bank=bank, key=good_key, fun=lambda **kwargs: expected_result ) fetch_result = cache.fetch(bank=bank, key=good_key) assert cache_result == fetch_result assert fetch_result == expected_result assert cache_result == fetch_result == expected_result