Ejemplo n.º 1
0
def debug_output_about_repo_examination(repo: BlueprintRepo,
                                        blueprint_name: str):
    if not repo.repo_has_blueprint(blueprint_name):
        logger.debug(
            f"Current repo does not contain a definition for the blueprint '{blueprint_name}'."
        )
    if repo.is_dirty():
        logger.debug("You have uncommitted changes")
    if repo.untracked_files:
        logger.debug(
            "Untracked files detected - only staged or committed files will be used when testing local changes"
        )
    if not repo.current_branch_exists_on_remote():
        logger.debug("Your current local branch doesn't exist on remote")
        # raise BadBlueprintRepo("Your current local branch doesn't exist on remote")
    if not repo.is_current_branch_synced():
        logger.debug("Your local branch is not synced with remote")
Ejemplo n.º 2
0
def examine_blueprint_working_branch(repo: BlueprintRepo, blueprint_name: str) -> None:
    if repo.is_repo_detached():
        raise BadBlueprintRepo("Repo's HEAD is in detached state")

    if not repo.repo_has_blueprint(blueprint_name):
        logger.debug(f"Current repo does not contain a definition for the blueprint '{blueprint_name}'.")

    if repo.is_dirty():
        logger.debug("You have uncommitted changes")

    if repo.untracked_files:
        logger.debug(
            "Untracked files detected - only staged or committed files will be used when testing local changes"
        )

    if not repo.current_branch_exists_on_remote():
        logger.debug("Your current local branch doesn't exist on remote")
        # raise BadBlueprintRepo("Your current local branch doesn't exist on remote")

    if not repo.is_current_branch_synced():
        logger.debug("Your local branch is not synced with remote")
    return
Ejemplo n.º 3
0
class TestBlueprintRepo(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        super(TestBlueprintRepo, cls).setUpClass()
        cls.git_repo_url = "https://github.com/QualiSystemsLab/colony-demo-space.git"

    def setUp(self):
        self.test_dir = tempfile.mkdtemp()
        Repo.clone_from(self.git_repo_url, self.test_dir)
        self.bp_repo = BlueprintRepo(self.test_dir)

    def test_blueprint_repo_has_blueprints(self):
        bp_list = self.bp_repo.blueprints
        self.assertTrue(len(bp_list))

    def test_has_non_existing_blueprint(self):
        fake_bp = "MyTestBp"
        self.assertFalse(self.bp_repo.repo_has_blueprint(fake_bp))

    def test_has_blueprint(self):
        bp_name = "promotions-manager-all-aws"
        self.assertTrue(self.bp_repo.repo_has_blueprint(bp_name))

    def test_create_repo_from_non_git_dir(self):
        with tempfile.TemporaryDirectory() as wrong_dir:
            self.assertRaises(BadBlueprintRepo, BlueprintRepo, wrong_dir)

    def test_raise_on_bare_repo(self):
        with tempfile.TemporaryDirectory() as wrong_dir:
            Repo.init(wrong_dir, bare=True)
            self.assertRaises(BadBlueprintRepo, BlueprintRepo, wrong_dir)

    def test_raise_on_repo_without_blueprints_dir(self):
        with tempfile.TemporaryDirectory() as temp_dir:
            Repo.init(temp_dir)
            self.assertRaises(BadBlueprintRepo, BlueprintRepo, temp_dir)

    def test_raise_on_repo_without_remotes(self):
        with tempfile.TemporaryDirectory() as temp_dir:
            Repo.init(temp_dir)
            os.mkdir(f"{temp_dir}/blueprints")
            self.assertRaises(BadBlueprintRepo, BlueprintRepo, temp_dir)

    def test_has_remote_branch(self):
        self.assertTrue(self.bp_repo.current_branch_exists_on_remote())

    def test_no_branch_on_remote(self):
        local_branch = "my_super_branch"
        new_branch = self.bp_repo.create_head(local_branch)
        assert self.bp_repo.active_branch != new_branch
        new_branch.checkout()
        self.assertFalse(self.bp_repo.current_branch_exists_on_remote())

    def test_is_synced(self):
        self.assertTrue(self.bp_repo.is_current_branch_synced())

    def test_repo_not_synced(self):
        index = self.bp_repo.index

        new_file_path = os.path.join(self.test_dir, "new-file-name")
        open(new_file_path, "w").close()
        index.add([new_file_path])

        author = Actor("An author", "*****@*****.**")
        committer = Actor("A committer", "*****@*****.**")

        index.commit("my commit message", author=author, committer=committer)
        self.assertFalse(self.bp_repo.is_current_branch_synced())

    def tearDown(self):
        # Close the file, the directory will be removed after the test
        shutil.rmtree(self.test_dir)
Ejemplo n.º 4
0
    def do_start(self):
        blueprint_name = self.args["<blueprint_name>"]
        branch = self.args.get("--branch")
        commit = self.args.get("--commit")
        name = self.args["--name"]
        timeout = self.args["--wait"]

        if timeout is not None:
            try:
                timeout = int(timeout)
            except ValueError:
                raise DocoptExit("Timeout must be a number")

            if timeout < 0:
                raise DocoptExit("Timeout must be positive")

        try:
            duration = int(self.args["--duration"] or 120)
            if duration <= 0:
                raise DocoptExit("Duration must be positive")

        except ValueError:
            raise DocoptExit("Duration must be a number")

        if commit and branch is None:
            raise DocoptExit("Since commit is specified, branch is required")

        inputs = parse_comma_separated_string(self.args["--inputs"])
        artifacts = parse_comma_separated_string(self.args["--artifacts"])

        repo, working_branch, temp_working_branch, stashed_flag, success = figure_out_branches(
            branch, blueprint_name)

        if not success:
            return self.error("Unable to start Sandbox")

        # TODO(ddovbii): This obtaining default values magic must be refactored
        logger.debug(
            "Trying to obtain default values for artifacts and inputs from local git blueprint repo"
        )
        try:
            repo = BlueprintRepo(os.getcwd())
            if not repo.is_current_branch_synced():
                logger.debug(
                    "Skipping obtaining values since local branch is not synced with remote"
                )
            else:
                for art_name, art_path in repo.get_blueprint_artifacts(
                        blueprint_name).items():
                    if art_name not in artifacts and art_path is not None:
                        logger.debug(
                            f"Artifact `{art_name}` has been set with default path `{art_path}`"
                        )
                        artifacts[art_name] = art_path

                for input_name, input_value in repo.get_blueprint_default_inputs(
                        blueprint_name).items():
                    if input_name not in inputs and input_value is not None:
                        logger.debug(
                            f"Parameter `{input_name}` has been set with default value `{input_value}`"
                        )
                        inputs[input_name] = input_value

        except Exception as e:
            logger.debug(f"Unable to obtain default values. Details: {e}")

        branch_to_be_used = temp_working_branch or working_branch

        if name is None:
            suffix = datetime.datetime.now().strftime("%b%d-%H:%M:%S")
            branch_name_or_type = ""
            if working_branch:
                branch_name_or_type = working_branch + "-"
            if temp_working_branch:
                branch_name_or_type = "localchanges-"
            name = f"{blueprint_name}-{branch_name_or_type}{suffix}"

        try:
            sandbox_id = self.manager.start(name, blueprint_name, duration,
                                            branch_to_be_used, commit,
                                            artifacts, inputs)
            BaseCommand.action_announcement("Starting sandbox")
            BaseCommand.important_value("Id: ", sandbox_id)
            BaseCommand.url(
                prefix_message="URL: ",
                message=self.manager.get_sandbox_ui_link(sandbox_id))

        except Exception as e:
            logger.exception(e, exc_info=False)
            sandbox_id = None
            if temp_working_branch.startswith(UNCOMMITTED_BRANCH_NAME):
                revert_from_temp_branch(repo, working_branch, stashed_flag)
                delete_temp_branch(repo, temp_working_branch)
            return self.die()

        # todo: I think the below can be simplified and refactored
        if timeout is None:
            revert_wait_and_delete_temp_branch(self.manager, blueprint_name,
                                               repo, sandbox_id, stashed_flag,
                                               temp_working_branch,
                                               working_branch)
            return self.success("The Sandbox was created")

        else:
            start_time = datetime.datetime.now()

            logger.debug(f"Waiting for the Sandbox {sandbox_id} to start...")
            # Waiting loop
            while (datetime.datetime.now() -
                   start_time).seconds < timeout * 60:
                sandbox = self.manager.get(sandbox_id)
                status = getattr(sandbox, "sandbox_status")
                if status == "Active":
                    revert_and_delete_temp_branch(repo, working_branch,
                                                  temp_working_branch,
                                                  stashed_flag)
                    return self.success(sandbox_id)

                elif status == "Launching":
                    progress = getattr(sandbox, "launching_progress")
                    for check_points, properties in progress.items():
                        logger.debug(f"{check_points}: {properties['status']}")
                    time.sleep(30)

                else:
                    revert_and_delete_temp_branch(repo, working_branch,
                                                  temp_working_branch,
                                                  stashed_flag)
                    return self.die(
                        f"The Sandbox {sandbox_id} has started. Current state is: {status}"
                    )

            # timeout exceeded
            logger.error(
                f"Sandbox {sandbox_id} was not active after the provided timeout of {timeout} minutes"
            )
            revert_and_delete_temp_branch(repo, working_branch,
                                          temp_working_branch, stashed_flag)
            return self.die()