Esempio n. 1
0
def read(config_values):
    """Reads an ordered list of configuration values and deep merge the values in reverse order."""
    if not config_values:
        raise RheaError('Cannot read config_value: `{}`'.format(config_values))

    config_values = to_list(config_values)

    config = {}
    for config_value in config_values:
        if not isinstance(config_value, (Mapping, six.string_types)):
            raise RheaError(
                "Expects Mapping, string, or list of Mapping/string instances, "
                "received {} instead".format(type(config_value)))

        if isinstance(config_value, Mapping):
            config_results = config_value
        elif os.path.isfile(config_value):
            config_results = _read_from_file(config_value)
        else:
            # try reading a stream of yaml or json
            try:
                config_results = _read_from_stream(config_value)
            except ScannerError:
                raise RheaError('Received non valid yaml stream: `{}`'.format(
                    config_value))

        if config_results and isinstance(config_results, Mapping):
            config = deep_update(config, config_results)
        else:
            raise RheaError(
                'Cannot read config_value: `{}`'.format(config_value))

    return config
Esempio n. 2
0
    def _get_typed_list_value(self,
                              key,
                              target_type,
                              type_convert,
                              is_optional=False,
                              is_secret=False,
                              is_local=False,
                              default=None,
                              options=None):
        """
        Return the value corresponding to the key converted first to list
        than each element to the given type.

        Args:
            key: the dict key.
            target_type: The type we expect the variable or key to be in.
            type_convert: A lambda expression that converts the key to the desired type.
            is_optional: To raise an error if key was not found.
            is_secret: If the key is a secret.
            is_local: If the key is a local to this service.
            default: default value if is_optional is True.
            options: list/tuple if provided, the value must be one of these values.
        """

        value = self._get_typed_value(key=key,
                                      target_type=list,
                                      type_convert=json.loads,
                                      is_optional=is_optional,
                                      is_secret=is_secret,
                                      is_local=is_local,
                                      default=default,
                                      options=options)

        if not value:
            return default

        raise_type = 'dict' if target_type == Mapping else target_type

        if not isinstance(value, list):
            raise RheaError("Cannot convert value `{}` (key: `{}`) "
                            "to `{}`".format(value, key, raise_type))
        # If we are here the value must be a list
        result = []
        for v in value:
            if isinstance(v, six.string_types):
                try:
                    result.append(type_convert(v))
                except ValueError:
                    raise RheaError(
                        "Cannot convert value `{}` (found in list key: `{}`) "
                        "to `{}`".format(v, key, raise_type))
            elif isinstance(v, target_type):
                result.append(v)

            else:
                raise RheaError(
                    "Cannot convert value `{}` (found in list key: `{}`) "
                    "to `{}`".format(v, key, raise_type))
        return result
Esempio n. 3
0
def _read_from_json(f_path, is_stream=False):
    if is_stream:
        try:
            return json.loads(f_path)
        except ValueError as e:
            raise RheaError(e)
    try:
        return json.loads(open(f_path).read())
    except ValueError as e:
        raise RheaError(e)
Esempio n. 4
0
def parse_gcs_path(gcs_path):
    """
    Parses and validates a google cloud storage url.

    Returns:
        tuple(bucket_name, blob).
    """
    parsed_url = urllib.parse.urlparse(gcs_path)
    if not parsed_url.netloc:
        raise RheaError('Received an invalid GCS url `{}`'.format(gcs_path))
    if parsed_url.scheme != 'gs':
        raise RheaError('Received an invalid url GCS `{}`'.format(gcs_path))
    blob = parsed_url.path.lstrip('/')
    return GCSSpec(parsed_url.netloc, blob)
Esempio n. 5
0
    def _get_typed_value(self,
                         key,
                         target_type,
                         type_convert,
                         is_optional=False,
                         is_secret=False,
                         is_local=False,
                         default=None,
                         options=None):
        """
        Return the value corresponding to the key converted to the given type.

        Args:
            key: the dict key.
            target_type: The type we expect the variable or key to be in.
            type_convert: A lambda expression that converts the key to the desired type.
            is_optional: To raise an error if key was not found.
            is_secret: If the key is a secret.
            is_local: If the key is a local to this service.
            default: default value if is_optional is True.
            options: list/tuple if provided, the value must be one of these values.

        Returns:
            The corresponding value of the key converted.
        """
        try:
            value = self._get(key)
        except KeyError:
            if not is_optional:
                raise RheaError(
                    'No value was provided for the non optional key `{}`.'.
                    format(key))
            return default

        if isinstance(value, six.string_types):
            try:
                self._add_key(key, is_secret=is_secret, is_local=is_local)
                self._check_options(key=key, value=value, options=options)
                return type_convert(value)
            except ValueError:
                raise RheaError("Cannot convert value `{}` (key: `{}`) "
                                "to `{}`".format(value, key, target_type))

        if isinstance(value, target_type):
            self._add_key(key, is_secret=is_secret, is_local=is_local)
            self._check_options(key=key, value=value, options=options)
            return value
        raise RheaError("Cannot convert value `{}` (key: `{}`) "
                        "to `{}`".format(value, key, target_type))
Esempio n. 6
0
def parse_uri_spec(uri_spec):
    parts = uri_spec.split('@')
    if len(parts) != 2:
        raise RheaError(
            'Received invalid uri_spec `{}`. '
            'The uri must be in the format `user:pass@host`'.format(uri_spec))

    user_pass, host = parts
    user_pass = user_pass.split(':')
    if len(user_pass) != 2:
        raise RheaError(
            'Received invalid uri_spec `{}`. `user:host` is not conform.'
            'The uri must be in the format `user:pass@host`'.format(uri_spec))

    return UriSpec(user=user_pass[0], password=user_pass[1], host=host)
Esempio n. 7
0
 def convert_to_dict(x):
     x = json.loads(x)
     if not isinstance(x, Mapping):
         raise RheaError(
             "Cannot convert value `{}` (key: `{}`) to `dict`".format(
                 x, key))
     return x
Esempio n. 8
0
def _read_from_yml(f_path, is_stream=False):
    try:
        if is_stream:
            return yaml.safe_load(f_path)
        with open(f_path) as f:
            return yaml.safe_load(f)
    except (ScannerError, ParserError):
        raise RheaError('Received non valid yaml: `{}`'.format(f_path))
Esempio n. 9
0
 def check_type(self):
     type_check = (self.config_type is None
                   and not isinstance(self.value,
                                      (Mapping, six.string_types)))
     if type_check:
         raise RheaError(
             "Expects Mapping, string, or list of Mapping/string instances, "
             "received {} instead".format(type(self.value)))
Esempio n. 10
0
def parse_auth_spec(auth_spec):
    user_pass = auth_spec.split(':')
    if len(user_pass) != 2:
        raise RheaError(
            'Received invalid uri_spec `{}`. `user:host` is not conform.'
            'The uri must be in the format `user:pass`'.format(auth_spec))

    return AuthSpec(user=user_pass[0], password=user_pass[1])
Esempio n. 11
0
def _read_from_file(f_path, file_type):
    _, ext = os.path.splitext(f_path)
    if ext in ('.yml', '.yaml') or file_type in ('.yml', '.yaml'):
        return _read_from_yml(f_path)
    elif ext == '.json' or file_type == '.json':
        return _read_from_json(f_path)
    raise RheaError(
        "Expects a file with extension: `.yml`, `.yaml`, or `json`, "
        "received instead `{}`".format(ext))
Esempio n. 12
0
    def get_dict(self,
                 key,
                 is_list=False,
                 is_optional=False,
                 is_secret=False,
                 is_local=False,
                 default=None,
                 options=None):
        """
        Get a the value corresponding to the key and converts it to `dict`.

        Args:
            key: the dict key.
            is_list: If this is one element or a list of elements.
            is_optional: To raise an error if key was not found.
            is_secret: If the key is a secret.
            is_local: If the key is a local to this service.
            default: default value if is_optional is True.
            options: list/tuple if provided, the value must be one of these values.

        Returns:
            `str`: value corresponding to the key.
        """
        def convert_to_dict(x):
            x = json.loads(x)
            if not isinstance(x, Mapping):
                raise RheaError(
                    "Cannot convert value `{}` (key: `{}`) to `dict`".format(
                        x, key))
            return x

        if is_list:
            return self._get_typed_list_value(key=key,
                                              target_type=Mapping,
                                              type_convert=convert_to_dict,
                                              is_optional=is_optional,
                                              is_secret=is_secret,
                                              is_local=is_local,
                                              default=default,
                                              options=options)
        value = self._get_typed_value(key=key,
                                      target_type=Mapping,
                                      type_convert=convert_to_dict,
                                      is_optional=is_optional,
                                      is_secret=is_secret,
                                      is_local=is_local,
                                      default=default,
                                      options=options)

        if not value:
            return default

        if not isinstance(value, Mapping):
            raise RheaError("Cannot convert value `{}` (key: `{}`) "
                            "to `dict`".format(value, key))
        return value
Esempio n. 13
0
def read(config_values):
    """Reads an ordered list of configuration values and deep merge the values in reverse order."""
    if not config_values:
        raise RheaError('Cannot read config_value: `{}`'.format(config_values))

    config_values = to_list(config_values)

    config = {}
    for config_value in config_values:
        config_value = ConfigSpec.get_from(value=config_value)
        config_value.check_type()
        config_results = config_value.read()
        if config_results and isinstance(config_results, Mapping):
            config = deep_update(config, config_results)
        elif config_value.check_if_exists:
            raise RheaError(
                'Cannot read config_value: `{}`'.format(config_value))

    return config
Esempio n. 14
0
 def read(self):
     if isinstance(self.value, Mapping):
         config_results = self.value
     elif os.path.isfile(self.value):
         config_results = _read_from_file(self.value, self.config_type)
     else:
         # try reading a stream of yaml or json
         try:
             config_results = _read_from_stream(self.value)
         except (ScannerError, ParserError):
             raise RheaError('Received non valid yaml stream: `{}`'.format(
                 self.value))
     return config_results
Esempio n. 15
0
def parse_s3_path(s3_path):
    """
    Parses and validates an S3 url.

    Returns:
         tuple(bucket_name, key).
    """
    parsed_url = urllib.parse.urlparse(s3_path)
    if not parsed_url.netloc:
        raise RheaError('Received an invalid S3 url `{}`'.format(s3_path))
    else:
        bucket_name = parsed_url.netloc
        key = parsed_url.path.strip('/')
        return S3Spec(bucket_name, key)
Esempio n. 16
0
def parse_wasbs_path(wasbs_path):
    parsed_url = urllib.parse.urlparse(wasbs_path)
    match = re.match("([^@]+)@([^.]+)\\.blob\\.core\\.windows\\.net",
                     parsed_url.netloc)
    if match is None:
        raise RheaError(
            'wasbs url must be of the form <container>@<account>.blob.core.windows.net'
        )

    container = match.group(1)
    storage_account = match.group(2)
    path = parsed_url.path
    if path.startswith('/'):
        path = path[1:]
    return WasbsSpec(container, storage_account, path)
Esempio n. 17
0
    def get_dict_of_dicts(self,
                          key,
                          is_optional=False,
                          is_secret=False,
                          is_local=False,
                          default=None,
                          options=None):
        """
        Get a the value corresponding to the key and converts it to `dict`.

        Add an extra validation that all keys have a dict as values.

        Args:
            key: the dict key.
            is_optional: To raise an error if key was not found.
            is_secret: If the key is a secret.
            is_local: If the key is a local to this service.
            default: default value if is_optional is True.
            options: list/tuple if provided, the value must be one of these values.

        Returns:
            `str`: value corresponding to the key.
        """
        value = self.get_dict(
            key=key,
            is_optional=is_optional,
            is_secret=is_secret,
            is_local=is_local,
            default=default,
            options=options,
        )
        if not value:
            return default

        for k in value:
            if not isinstance(value[k], Mapping):
                raise RheaError(
                    "`{}` must be an object. "
                    "Received a non valid configuration for key `{}`.".format(
                        value[k], key))

        return value
Esempio n. 18
0
def _check_options(key, value, options):
    if options and value not in options:
        raise RheaError('The value `{}` provided for key `{}` '
                        'is not one of the possible values.'.format(
                            value, key))