def validate(self): if not isinstance(self.client, yapconf.etcd_client.Client): raise YapconfSourceError( 'Invalid source (%s). Client must be supplied and must be of ' 'type %s. Got type: %s' % (self.label, type(yapconf.etcd_client.Client), type( self.client)))
def spawn_watcher(self, label, target=None, eternal=False): """Spawns a config watcher in a separate daemon thread. If a particular config value changes, and the item has a ``watch_target`` defined, then that method will be called. If a ``target`` is passed in, then it will call the ``target`` anytime the config changes. Args: label (str): Should match a label added through ``add_source`` target (func): Should be a function that takes two arguments, the old configuration and the new configuration. eternal (bool): Determines if watcher threads should be restarted if they die. Returns: The thread that was spawned. """ if label not in self._sources: raise YapconfSourceError( "Cannot watch %s no source named %s" % (label, label) ) current_config = self._sources[label].get_data() handler = ConfigChangeHandler(current_config, self, target) return self._sources[label].watch(handler, eternal)
def validate(self): if (yapconf.kubernetes_client and not isinstance( self.client, yapconf.kubernetes_client.CoreV1Api)): raise YapconfSourceError( 'Invalid source (%s). Client must be supplied and must be of ' 'type %s. Got type: %s' % (self.label, type( yapconf.kubernetes_client.CoreV1Api), type(self.client))) if self.config_type == 'yaml' and not yapconf.yaml_support: raise YapconfSourceError( 'Kubernetes config source specified that the configmap ' 'contained a yaml config. In order to support yaml loading, ' 'you will need to `pip install yapconf[yaml]`.') if self.config_type not in yapconf.FILE_TYPES: raise YapconfSourceError( 'Invalid config type specified for a kubernetes config. %s is ' 'not supported. Supported types are %s' % (self.name, yapconf.FILE_TYPES))
def _watch(self, handler, data): if self.filename: file_handler = FileHandler(filename=self.filename, handler=handler, file_type="json") observer = Observer() directory = os.path.dirname(self.filename) observer.schedule(file_handler, directory, recursive=False) observer.start() observer.join() else: raise YapconfSourceError( "Cannot watch a string json source. Strings are immutable.")
def _watch(self, handler, data): w = watch.Watch() for event in w.stream(self.client.list_namespaced_config_map, namespace=self.namespace): config_map = event["object"] if config_map.metadata.name != self.name: continue if event["type"] == "DELETED": raise YapconfSourceError( "Kubernetes config watcher died. The configmap %s was " "deleted." % self.name) if event["type"] == "MODIFIED": handler.handle_config_change(self.get_data())
def _watch(self, handler, data): w = watch.Watch() for event in w.stream(self.client.list_namespaced_config_map, namespace=self.namespace): config_map = event['object'] if config_map.metadata.name != self.name: continue if event['type'] == 'DELETED': raise YapconfSourceError( 'Kubernetes config watcher died. The configmap %s was ' 'deleted.' % self.name) if event['type'] == 'MODIFIED': handler.handle_config_change(self.get_data())
def on_deleted(self, event): raise YapconfSourceError( "While watching file %s the file was deleted. Aborting watch." % self._filename)
def validate(self): if self.spec is None: raise YapconfSourceError( "Invalid source (%s). No spec was provided for a CLI " "config source." % self.label)
def validate(self): if self.filename is None: raise YapconfSourceError( "Invalid source (%s). No filename was provided for a YAML " "config source." % self.label)
def validate(self): if self.data is None and self.filename is None: raise YapconfSourceError( "Invalid source (%s). No data or filename was provided for a " "JSON config source." % self.label)
def get_source(label, source_type, **kwargs): """Get a config source based on type and keyword args. This is meant to be used internally by the spec via ``add_source``. Args: label (str): The label for this source. source_type: The type of source. See ``yapconf.SUPPORTED_SOURCES`` Keyword Args: The keyword arguments are based on the source_type. Please see the documentation of the individual sources for a detailed list of all possible arguments. Returns (yapconf.sources.ConfigSource): A valid config source which can be used for generating an override. Raises: YapconfSourceError: If there is some kind of error with this source definition. """ if source_type not in yapconf.ALL_SUPPORTED_SOURCES: raise YapconfSourceError( "Invalid source type %s. Supported types are %s." % (source_type, yapconf.ALL_SUPPORTED_SOURCES)) if source_type not in yapconf.SUPPORTED_SOURCES: raise YapconfSourceError( 'Unsupported source type "%s". If you want to use this type, you ' "will need to install the correct client for it (try `pip install " "yapconf[%s]. Currently supported types are %s. All supported " "types are %s" % ( source_type, source_type, yapconf.SUPPORTED_SOURCES, yapconf.ALL_SUPPORTED_SOURCES, )) # We pop arguments from kwargs because the individual config sources # have better error messages if a keyword argument is missed. if source_type == "dict": return DictConfigSource(label, data=kwargs.get("data")) elif source_type == "json": return JsonConfigSource(label, **kwargs) elif source_type == "yaml": filename = kwargs.get("filename") if "filename" in kwargs: kwargs.pop("filename") return YamlConfigSource(label, filename, **kwargs) elif source_type == "environment": return EnvironmentConfigSource(label) elif source_type == "etcd": return EtcdConfigSource(label, kwargs.get("client"), kwargs.get("key", "/")) elif source_type == "kubernetes": name = kwargs.get("name") if "name" in kwargs: kwargs.pop("name") client = kwargs.get("client") if "client" in kwargs: kwargs.pop("client") return KubernetesConfigSource(label, client, name, **kwargs) elif source_type == "cli": return CliConfigSource(label, **kwargs) else: raise NotImplementedError("No implementation for source type %s" % source_type)
def validate(self): if not isinstance(self.data, dict): raise YapconfSourceError( "Invalid source provided. %s provided data but it was not a " "dictionary. Got: %s" % (self.label, self.data))