def lint_deprecated_runtime_value(): cluster_names = get_cluster_names('service') for application_name, cluster_name in cluster_names: fingerprints = get_fingerprints( 'service', application_name, cluster_name) for fingerprint in fingerprints: data_path = combine( huskar_client.base_path, 'service', application_name, cluster_name, fingerprint) runtime_path = combine(data_path, 'runtime') try: runtime_data, _ = huskar_client.client.get(runtime_path) except NoNodeError: continue else: try: data, _ = huskar_client.client.get(data_path) except NoNodeError: pass else: try: data = json.loads(data) except (ValueError, TypeError): pass else: if isinstance(data, dict) and 'state' in data: yield LintIssue( 'E-ZK001', runtime_path, runtime_data) continue yield LintIssue('E-ZK002', runtime_path, runtime_data)
def test_overall_switch(switch, node_dir, overall_node_dir): full_path = combine(node_dir, key) overall_full_path = combine(overall_node_dir, key) switch.client.call_client('create', overall_full_path, OFF, makepath=True, ephemeral=True) switch.start() gevent.sleep(1) @switch.bind(key) def switch_func(): switch_func.called = True switch_func.called = False switch_func() assert not switch.is_switched_on(key) assert not switch_func.called switch_func.called = False switch.client.call_client('create', full_path, ON, ephemeral=True) gevent.sleep(1) switch_func() assert switch.is_switched_on(key) assert switch_func.called
def _record_switch(self, service, cluster, nodes): path = self.service_instance_path(service, cluster) for n in nodes: watch_patch = combine(path, n) self.watched_service_nodes[(service, cluster)].append(watch_patch) self.watched_service_nodes_signals[(service, cluster)].append( (path, n)) self._connect_signal_by_basename_and_nodename( path, n, functools.partial( self._trigger_service, service, cluster, )) self.client.watch_key(watch_patch) service_cache = self.get_service_cache(service, cluster) changed = False for n in service_cache.keys(): if n not in nodes: if len(service_cache) >= self.min_server_num: # ensure the services num is no less than min server num # noqa self._disconnect_signal(combine(path, n)) service_cache.pop(n) changed = True if changed: self.trigger_service_list_change_signal(service, cluster)
def get_cluster_names(type_name): path = combine(huskar_client.base_path, type_name) application_names = huskar_client.client.get_children(path) for application_name in application_names: cluster_path = combine( huskar_client.base_path, type_name, application_name) cluster_names = huskar_client.client.get_children(cluster_path) for cluster_name in cluster_names: yield application_name, cluster_name
def _trigger_config(self, configs, path, name, value_state): name = decode_key(name) value, state = value_state if state.is_deleted: self.logger.info('node: %s removed', combine(path, name)) configs.pop(name, None) self.client.unwatch_key(combine(path, name)) else: self.logger.debug('config changed: %s', name) configs[name] = value self.notify_watchers(name, self.get)
def _register_config(self, nodes, base_path, configs): callback = functools.partial(self._trigger_config, configs) for raw_key in nodes: self._connect_signal_by_basename_and_nodename( base_path, raw_key, callback) self.client.watch_key(combine(base_path, raw_key)) for raw_key in set(configs): key = encode_key(raw_key) if key in nodes: continue self._disconnect_signal(combine(base_path, key)) self.client.unwatch_key(combine(base_path, key)) configs.pop(raw_key)
def _trigger_switch(self, switches, path, name, value_state): name = decode_key(name) value, state = value_state if state.is_deleted: self.logger.info('node: %s removed', combine(path, name)) self.client.unwatch_key(combine(path, name)) switches.pop(name, None) else: self.logger.debug('switch triggered: %s -> %s', name, value) try: switches[name] = {'value': float(value), 'path': path} except (TypeError, ValueError): self.logger.warning("wrong value type for switch %s: %s", name, value) self.notify_watchers(name, self.is_switched_on)
def _register_switch(self, path, nodes, switches): callback = functools.partial(self._trigger_switch, switches) for n in nodes: self._connect_signal_by_basename_and_nodename(path, n, callback) self.client.watch_key(combine(path, n)) for n in set(switches): s = switches[n] if not isinstance(s, dict): self.logger.warn("malformed data in switches: %s", switches) continue if path == s.get('path', None) and encode_key(n) not in nodes: self._disconnect_signal(combine(path, encode_key(n))) self.client.unwatch_key(combine(path, encode_key(n))) switches.pop(n)
def test_lazy_off(switch, node_dir): full_path = combine(node_dir, key) switch.lazy = False switch.client.call_client('create', full_path, OFF, ephemeral=True) assert not switch.started assert switch.is_switched_on(key) assert not switch.started
def test_switch_cache_consistency(Huskar, servers, cache_huskar, huskar, node_dir): full_path = combine(node_dir, key) cache_huskar.start() cache_huskar.switch.client.call_client('create', full_path, OFF, makepath=True) gevent.sleep(1) assert OFF == cache_huskar.client.call_client('get', full_path)[0] assert not cache_huskar.switch.is_switched_on(key) cache_huskar.stop() # stop huskar # change the value of key in zk huskar.client.call_client('set', full_path, ON) huskar.stop() # reconnect using cache h = Huskar(servers=servers, service='test_service', cluster='test_cluster', cache_dir=cache_huskar.cache_dir) h.start() gevent.sleep(1) # h = cache_huskar FIXME: uncomment this then test fails assert ON == h.client.call_client('get', full_path)[0] try: assert h.switch.is_switched_on(key) finally: h.client.call_client('delete', full_path) h.stop()
def test_default_value(switch, node_dir): full_path = combine(node_dir, 'func') switch.client.call_client('create', full_path, ON, ephemeral=True) @switch.bind(default=u'default') def func(): return u'value' assert func() == u'value' switch.client.call_client('set', full_path, OFF) gevent.sleep(1) assert func() == u'default' del func @switch.bind('func', default=list) def func2(): return [1] switch.client.call_client('set', full_path, ON) gevent.sleep(1) assert func2() == [1] switch.client.call_client('set', full_path, OFF) gevent.sleep(1) assert func2() == []
def lint_service_instance(): cluster_names = get_cluster_names('service') for application_name, cluster_name in cluster_names: fingerprints = get_fingerprints( 'service', application_name, cluster_name) for fingerprint in fingerprints: path = combine( huskar_client.base_path, 'service', application_name, cluster_name, fingerprint) try: data, _ = huskar_client.client.get(path) except NoNodeError: pass else: try: data = json.loads(data) except (ValueError, TypeError): yield LintIssue('E-ZK004', path, data) else: if (not isinstance(data, dict) or not data.get('ip') or not isinstance(data.get('port'), dict) or not isinstance(data['port'].get('main'), int) or data['port']['main'] <= 0): yield LintIssue('E-ZK004', path, data) elif 'meta' in data: meta = data['meta'] if (not isinstance(meta, dict) or not all(isinstance(v, unicode) for v in meta.values())): yield LintIssue('E-ZK004', path, data)
def test_lazy(switch, node_dir): full_path = combine(node_dir, key) switch.client.call_client('create', full_path, OFF, ephemeral=True) assert not switch.started while switch.is_switched_on(key): gevent.sleep(0.5) assert not switch.is_switched_on(key) assert switch.started
def test_slash_key(huskar, switch, base_path): huskar.client.call_client('create', combine( base_path, 'switch/test_service/test_cluster/%SLASH%'), OFF, ephemeral=True) switch.start() gevent.sleep(0.2) assert not switch.is_switched_on('/')
def stop(self): super(Config, self).stop() with self.lock: if self.started: self.started = False self.started_timeout.clear() self.ready.clear() self.client.unwatch_path(self.base_path) self.client.unwatch_path(self.overall_base_path) for name in self.configs: self.client.unwatch_key(combine(self.base_path, name)) for name in self.overall_configs: self.client.unwatch_key( combine(self.overall_base_path, name)) # close cache try: self.configs.close() self.overall_configs.close() except AttributeError: pass
def test_off(switch, node_dir): full_path = combine(node_dir, key) switch.client.call_client('create', full_path, OFF, ephemeral=True) @switch.bind(key) def switch_func(): switch_func.called = True switch_func.called = False gevent.sleep(1) switch_func() assert not switch_func.called assert not switch.is_switched_on(key)
def test_float(switch, node_dir): switch.start() gevent.sleep(1) full_path = combine(node_dir, key) switch.client.call_client('create', full_path, b'0.0000001', ephemeral=True) gevent.sleep(0.5) assert not switch.is_switched_on(key) switch.client.call_client('set', full_path, b'gibberis') gevent.sleep(0.5) assert not switch.is_switched_on(key)
def lint_cluster_link(): cluster_names = get_cluster_names('service') for application_name, cluster_name in cluster_names: cluster_path = combine( huskar_client.base_path, 'service', application_name, cluster_name) data, stat = huskar_client.client.get(cluster_path) if not data: continue try: data = json.loads(data) except (TypeError, ValueError): yield LintIssue('E-ZK003', cluster_path, data) else: if isinstance(data, dict): link = data.get('link', []) if isinstance(link, list) and (0 <= len(link) <= 1): continue yield LintIssue('E-ZK003', cluster_path, data)
def test_switch_cache(Huskar, cache_huskar, node_dir): full_path = combine(node_dir, key) switch = cache_huskar.switch switch.start() cache_huskar.client.call_client('create', full_path, OFF, makepath=True, ephemeral=True) gevent.sleep(1) assert not switch.is_switched_on(key) cache_huskar.client.stop() gevent.sleep(1) assert not switch.is_switched_on(key) # hot cache h = Huskar(service='test_service', servers='host_that_not_exists', cluster='test_cluster', lazy=True, cache_dir=cache_huskar.cache_dir) assert not h.switch.is_switched_on(key) # cold cache
def node_dir(huskar): return combine(huskar.base_path, huskar.switch.base_path)
def get_fingerprints(type_name, application_name, cluster_name): path = combine( huskar_client.base_path, type_name, application_name, cluster_name) return huskar_client.client.get_children(path)
def get_full_path(path): return combine(node_dir, path)
def overall_node_dir(huskar): return combine(huskar.base_path, huskar.switch.overall_base_path)
def get_full_overall_path(path): return combine(overall_node_dir, path)
def wrapped(data_type, key): cluster_name = 'test' return combine(BASE_PATH, data_type, test_application_name, cluster_name, key)
def get_full_name(self, name=None): return combine(self.base_path, name) if name else self.base_path
def _connect_signal_by_basename_and_nodename(self, path, name, callback): signal_name = combine(path, name) # path, name, value_state will be passed to callback _callback = functools.partial(callback, path, name) return self._connect_signal(signal_name, _callback)
def get_path(self, application, cluster, key=None): return combine(BASE_PATH, self.sub_domain, application, cluster, key)
def _disconnect_signal_by_path_name(self, path, name): signal_name = combine(path, name) self._disconnect_signal(signal_name)
def test_full_path(base_path, test_key): return combine(base_path, test_key)