def test_get_region(self, environment_variables, input_mock):
     """Test our logic for rules is correct"""
     input_mock.return_value = "us-east-1"
     environment_variables.return_value = None
     all_input = UserInput(False)
     self.assertIsNone(all_input.get_region())
     self.assertEqual("us-east-1", self.user_input.get_region())
    def __init__(self, config_file, select_all, auto_overwrite=False):

        self.user_input = UserInput(not select_all)
        self.config_file = config_file
        self.current_config = ConfigParser(self.config_file)
        self.current_config.parse_valid_config()
        self.auto_overwrite = auto_overwrite
 def __init__(self, interactive, config_file):
     self.user_input = UserInput(interactive)
     self.configs = {}
     self.config_file = config_file
     self.rule_discoverer = RuleDiscoverer()
     self.template_env = Environment(
         loader=PackageLoader("reflex_cli", "templates"),
         autoescape=select_autoescape(["jinja2"]),
     )
    def test_collect_default_email(self, input_mock):
        """Test our logic for rules is correct"""
        input_mock.return_value = "*****@*****.**"
        select_all_input = UserInput(False)
        self.assertEqual("*****@*****.**",
                         select_all_input.collect_default_email())

        no_select_all_input = UserInput(True)
        self.assertEqual("*****@*****.**",
                         no_select_all_input.collect_default_email())
 def setUp(self):
     self.user_input = UserInput(True)
class UserInputTestCase(unittest.TestCase):
    """Test class for the environment context of our CLI tool."""
    def setUp(self):
        self.user_input = UserInput(True)

    @patch("reflex_cli.user_input.UserInput.get_input")
    def test_collect_default_email(self, input_mock):
        """Test our logic for rules is correct"""
        input_mock.return_value = "*****@*****.**"
        select_all_input = UserInput(False)
        self.assertEqual("*****@*****.**",
                         select_all_input.collect_default_email())

        no_select_all_input = UserInput(True)
        self.assertEqual("*****@*****.**",
                         no_select_all_input.collect_default_email())

    @patch("reflex_cli.user_input.UserInput.get_input")
    def test_verify_rule(self, input_mock):
        """Test our logic for rules is correct"""
        input_mock.return_value = "y"
        test = MagicMock()
        test.name = "example"
        test.version = "example"
        self.assertTrue(self.user_input.verify_rule(test))

    @patch("reflex_cli.user_input.UserInput.verify_rule")
    def test_get_rule_input(self, input_mock):
        """Test our logic for rules is correct"""
        input_mock.return_value = True
        test = MagicMock()
        test.name = "example"
        test.version = None

        self.assertEqual([], self.user_input.get_rule_input([test]))

        test2 = MagicMock()
        test2.name = "first"
        test2.version = "example"
        test2.configurables = None

        self.assertEqual(
            [{
                "first": {
                    "version": "example"
                }
            }],
            self.user_input.get_rule_input([test2]),
        )

        test3 = MagicMock()
        test3.name = "first"
        test3.version = "example"
        test3.configurables = ["mode"]

        self.assertEqual(
            [{
                "first": {
                    "version": "example",
                    "configuration": {
                        "mode": ""
                    }
                }
            }],
            self.user_input.get_rule_input([test3]),
        )

        test4 = MagicMock()
        test4.name = "first"
        test4.version = "example"
        test4.configurables = [{"mode": "detect"}]

        self.assertEqual(
            [{
                "first": {
                    "version": "example",
                    "configuration": {
                        "mode": "detect"
                    },
                }
            }],
            self.user_input.get_rule_input([test4]),
        )

    @patch("reflex_cli.user_input.UserInput.get_input")
    def test_get_backend_key_values(self, input_mock):
        """Test our logic for rules is correct"""
        input_mock.return_value = "N"
        key_values = self.user_input.collect_backend_key_values()
        self.assertEqual(key_values, [{"N": "N"}])

    @patch("reflex_cli.user_input.UserInput.get_input")
    @patch("reflex_cli.user_input.UserInput.collect_backend_key_values")
    def test_get_backend_config(self, key_values, input_mock):
        """Test our logic for rules is correct"""
        input_mock.return_value = "y"
        key_values.return_value = [{"bucket": "s3-bucket"}]
        backend_config = self.user_input.get_backend_configuration()
        self.assertEqual(backend_config, {"y": [{"bucket": "s3-bucket"}]})

    @patch("reflex_cli.user_input.UserInput.get_input")
    @patch("os.environ.get")
    def test_get_region(self, environment_variables, input_mock):
        """Test our logic for rules is correct"""
        input_mock.return_value = "us-east-1"
        environment_variables.return_value = None
        all_input = UserInput(False)
        self.assertIsNone(all_input.get_region())
        self.assertEqual("us-east-1", self.user_input.get_region())

    @patch("reflex_cli.user_input.UserInput.get_input")
    @patch("reflex_cli.user_input.UserInput.ask_to_overwrite")
    def test_verify_upgrade_interested(self, overwrite_mock, input_mock):
        """Test our logic for rules is correct"""
        overwrite_mock.return_value = True
        all_input = UserInput(False)
        self.assertTrue(all_input.verify_upgrade_interest())
 def test_verify_upgrade_interested(self, overwrite_mock, input_mock):
     """Test our logic for rules is correct"""
     overwrite_mock.return_value = True
     all_input = UserInput(False)
     self.assertTrue(all_input.verify_upgrade_interest())
class ConfigVersionUpdater:
    """Checks remote sources for newer rule releases"""
    def __init__(self, config_file, select_all, auto_overwrite=False):

        self.user_input = UserInput(not select_all)
        self.config_file = config_file
        self.current_config = ConfigParser(self.config_file)
        self.current_config.parse_valid_config()
        self.auto_overwrite = auto_overwrite

    def gather_latest_remote_versions(self):
        """Reaches out to urls to get tag information per rule."""
        manifest_rules = RuleDiscoverer().collect_rules()
        remote_versions = {}
        for rule in self.current_config.rule_list:
            if not rule.is_custom:
                cleaned_rule_name = f"reflex-aws-{rule.name}"
                for manifest_rule in manifest_rules:
                    if manifest_rule.name == cleaned_rule_name:
                        remote_versions[rule.name] = manifest_rule.version
            else:
                LOGGER.debug("Rule: %s has remote: %s", rule, rule.remote_url)
                remote_versions[
                    rule.name] = ReflexGithub().get_remote_latest_version(
                        ReflexGithub.get_repo_format(rule.remote_url))
            LOGGER.debug("Rule has remote version: %s",
                         remote_versions[rule.name])
        return remote_versions

    def upgrade_engine_version(self):
        """Checks for the latest engine version"""
        engine_data = RuleDiscoverer().collect_engine()
        engine_version = engine_data["reflex-engine"]["version"]
        self.current_config.raw_configuration[
            "engine_version"] = engine_version

    def _find_rule_value(self, rule_name, key):
        for rule in self.current_config.raw_configuration["rules"]["aws"]:
            if rule.get(rule_name):
                return rule.get(rule_name).get(key)
        return None

    def _set_rule_value(self, rule_name, key, value):
        """Overwrites existing key with value."""
        for rule in self.current_config.raw_configuration["rules"]["aws"]:
            if rule.get(rule_name):
                rule[rule_name][key] = value

    def compare_current_rule_versions(self):
        """Iterates over all rules and compares rules with remote versions."""
        LOGGER.debug("Comparing current rule versions.")
        update_requested = False
        remote_versions = self.gather_latest_remote_versions()

        for rule in self.current_config.rule_list:
            current_version = self._find_rule_value(rule.name, "version")
            remote_version = remote_versions[rule.name]
            if not remote_version:
                LOGGER.debug("No release information for %s. Skipping!",
                             rule.name)
                continue
            if current_version != remote_version:
                LOGGER.info(
                    "%s (current version: %s) has new release: %s.",
                    rule.name,
                    current_version,
                    remote_version,
                )
                if self.user_input.verify_upgrade_interest():
                    update_requested = True
                    self._set_rule_value(rule.name, "version", remote_version)
        return update_requested

    def compare_current_rule_version(self, rule_name):
        """ Check single rule version and compare it to remote version."""
        LOGGER.debug("Comparing current rule version.")
        update_requested = False
        remote_versions = self.gather_latest_remote_versions()

        rule_found = False

        for rule in self.current_config.rule_list:
            if rule.name == rule_name:

                rule_found = True

                current_version = self._find_rule_value(rule.name, "version")
                remote_version = remote_versions[rule.name]
                if not remote_version:
                    LOGGER.info("No release information for %s. Skipping!",
                                rule.name)

                    return update_requested

                if current_version != remote_version:
                    LOGGER.info(
                        "%s (current version: %s) has new release: %s.",
                        rule.name,
                        current_version,
                        remote_version,
                    )
                    if self.user_input.verify_upgrade_interest():
                        update_requested = True
                        self._set_rule_value(rule.name, "version",
                                             remote_version)

                    return update_requested

                LOGGER.info("%s rule does not have a new release.", rule.name)

                return update_requested
        if not rule_found:
            LOGGER.info(
                "Rule with name %s does not exist, please check the spelling.",
                rule_name,
            )
        return update_requested

    def overwrite_reflex_config(self):
        """If any upgrades possible, overwrite current reflex config."""
        initializer = ReflexInitializer(False, self.config_file,
                                        self.auto_overwrite)
        initializer.config_file = self.config_file
        initializer.configs = self.current_config.raw_configuration
        initializer.write_config_file()
class ReflexInitializer:
    """Creates assets required to build a reflex deployment."""

    def __init__(self, interactive, config_file, auto_overwrite=False):
        self.user_input = UserInput(interactive)
        self.configs = {}
        self.config_file = config_file
        self.auto_overwrite = auto_overwrite
        self.rule_discoverer = RuleDiscoverer()
        self.template_env = Environment(
            loader=PackageLoader("reflex_cli", "templates"),
            autoescape=select_autoescape(["jinja2"]),
        )

    def query_possible_rules(self):
        """Iterates over templates and gets confirmation per rule."""
        discovered_rules = self.rule_discoverer.collect_rules()
        raw_rules = self.user_input.get_rule_input(discovered_rules)
        LOGGER.debug("Rules selected for config: %s", raw_rules)
        possible_rules = sorted(
            self.strip_rule_common_names(raw_rules), key=lambda d: list(d.keys())
        )
        return possible_rules

    @staticmethod
    def strip_rule_common_names(rule_array):
        """Takes in array of rules and strips out common repo prefix."""
        stripped_array = []
        for rule in rule_array:
            rule_key = list(rule.keys())[0]
            stripped_key = rule_key.replace(REFLEX_PREFIX, "")
            new_rule = {stripped_key: rule[rule_key]}
            stripped_array.append(new_rule)
        return stripped_array

    @staticmethod
    def get_reflex_version():
        """Looks at package version of CLI to determine reflex version."""
        package_object = pkg_resources.require("reflex-cli")[0]
        LOGGER.debug("Reflex version found as: %s", package_object.version)
        return package_object.version

    def get_engine_version(self):
        """Pulls the engine version information from discoverer."""
        engine_dictionary = self.rule_discoverer.collect_engine()
        return engine_dictionary["reflex-engine"]["version"]

    def set_global_values(self):
        """Sets values for common configurations across guardrails."""
        global_dict = {}
        global_dict["default_email"] = self.user_input.collect_default_email()
        return global_dict

    def determine_config_values(self):  # pragma: no cover
        """Outlines keys of config file and gathers values."""
        self.configs["cli_version"] = self.get_reflex_version()
        self.configs["engine_version"] = self.get_engine_version()
        self.configs["globals"] = self.set_global_values()
        self.configs["providers"] = [{"aws": {"region": self.user_input.get_region()}}]
        self.configs["backend"] = self.user_input.get_backend_configuration()
        self.configs["rules"] = {"aws": self.query_possible_rules()}

    def render_template(self):  # pragma: no cover
        """Renders jinja2 template with yaml dumps."""
        version_dump = yaml.dump({"cli_version": ("%s" % self.configs["cli_version"])})
        engine_dump = yaml.dump(
            {"engine_version": ("%s" % self.configs["engine_version"])}
        )
        globals_dump = yaml.dump({"globals": self.configs["globals"]})
        providers_dump = yaml.dump({"providers": self.configs["providers"]})
        rules_dump = yaml.dump({"rules": self.configs["rules"]})
        backend_dump = yaml.dump({"backend": self.configs["backend"]})

        template = self.template_env.get_template("reflex.yaml.jinja2")
        rendered_template = template.render(
            global_configs=globals_dump,
            providers=providers_dump,
            backend=backend_dump,
            rules=rules_dump,
            version=version_dump,
            engine=engine_dump,
        )
        LOGGER.debug("Config template rendered as: %s", rendered_template)
        return rendered_template

    def write_config_file(self):  # pragma: no cover
        """Opens config file, dumps dict as yaml."""
        LOGGER.debug("Writing config file to: %s", self.config_file)
        if os.path.exists(self.config_file) and not self.auto_overwrite:
            write_file = self.user_input.ask_to_overwrite(self.config_file)
        else:
            write_file = True
        if write_file:
            with open(self.config_file, "w") as config_file:
                config_file.write(self.render_template())
    def __init__(self, config_file, select_all):

        self.user_input = UserInput(not select_all)
        self.config_file = config_file
        self.current_config = ConfigParser(self.config_file)
        self.current_config.parse_valid_config()