Source code for feast.config

#
#  Copyright 2019 The Feast Authors
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      https://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
#

from os.path import expanduser, join
import logging
import os
import sys
from typing import Dict
from urllib.parse import urlparse
from urllib.parse import ParseResult

import toml

_logger = logging.getLogger(__name__)

feast_configuration_properties = {"core_url": "URL", "serving_url": "URL"}

CONFIGURATION_FILE_DIR = os.environ.get("FEAST_CONFIG", ".feast")
CONFIGURATION_FILE_NAME = "config.toml"


def _get_or_create_config() -> Dict:
    """Get user configuration file or create it and return"""

    user_config_file_dir, user_config_file_path = _get_config_file_locations()
    user_config_file_dir = user_config_file_dir.rstrip("/") + "/"
    if not os.path.exists(os.path.dirname(user_config_file_dir)):
        os.makedirs(os.path.dirname(user_config_file_dir))

    if not os.path.isfile(user_config_file_path):
        _save_config(user_config_file_path, _props_to_dict())

    try:
        return toml.load(user_config_file_path)
    except FileNotFoundError:
        _logger.error(
            "Could not find Feast configuration file " + user_config_file_path
        )
        sys.exit(1)
    except toml.decoder.TomlDecodeError:
        _logger.error(
            "Could not decode Feast configuration file " + user_config_file_path
        )
        sys.exit(1)
    except Exception as e:
        _logger.error(e)
        sys.exit(1)


[docs]def set_property(prop: str, value: str): """ Sets a single property in the Feast users local configuration file Args: prop: Feast property name value: Feast property value """ if _is_valid_property(prop, value): active_feast_config = _get_or_create_config() active_feast_config[prop] = value _, user_config_file_path = _get_config_file_locations() _save_config(user_config_file_path, active_feast_config) print("Updated property [%s]" % prop) else: _logger.error("Invalid property selected") sys.exit(1)
[docs]def get_config_property_or_fail(prop: str, force_config: Dict[str, str] = None) -> str: """ Gets a single property in the users configuration Args: prop: Property to retrieve force_config: Configuration dictionary containing properties that should be overridden. This will take precedence over file based properties. Returns: Returns a string property """ if ( isinstance(force_config, dict) and prop in force_config and force_config[prop] is not None ): return force_config[prop] active_feast_config = _get_or_create_config() if _is_valid_property(prop, active_feast_config[prop]): return active_feast_config[prop] _logger.error("Could not load Feast property from configuration: %s" % prop) sys.exit(1)
def _props_to_dict() -> Dict[str, str]: """Create empty dictionary of all Feast properties""" prop_dict = {} for prop in feast_configuration_properties: prop_dict[prop] = "" return prop_dict def _is_valid_property(prop: str, value: str) -> bool: """ Validates both a Feast property as well as value Args: prop: Feast property name value: Feast property value Returns: Returns True if property and value are valid """ if prop not in feast_configuration_properties: _logger.error("You are trying to set an invalid property") sys.exit(1) prop_type = feast_configuration_properties[prop] if prop_type == "URL": if "//" not in value: value = "%s%s" % ("grpc://", value) parsed_value = urlparse(value) # type: ParseResult if parsed_value.netloc: return True _logger.error("The property you are trying to set could not be identified") sys.exit(1) def _save_config(user_config_file_path: str, config_string: Dict[str, str]): """ Saves Feast configuration Args: user_config_file_path: Local file system path to save configuration config_string: Contents in dictionary format to save to path """ try: with open(user_config_file_path, "w+") as f: toml.dump(config_string, f) except Exception as e: _logger.error("Could not update configuration file for Feast") print(e) sys.exit(1) def _get_config_file_locations() -> (str, str): """Gets the local user configuration directory and file path""" user_config_file_dir = join(expanduser("~"), CONFIGURATION_FILE_DIR) user_config_file_path = join(user_config_file_dir, CONFIGURATION_FILE_NAME) return user_config_file_dir, user_config_file_path