예제 #1
0
 def test_cannot_infer_git_provider_from_url(self):
     with pytest.raises(GitOpsException) as ex:
         create_git(
             tmp_dir="TMP_DIR",
             username="******",
             password="******",
             git_user="******",
             git_email="GIT_EMAIL",
             organisation="ORG",
             repository_name="REPO",
             git_provider=None,
             git_provider_url="some.unknown-url.com",
         )
     self.assertEqual("Please provide --git-provider", str(ex.value))
예제 #2
0
 def test_unknown_git_provider(self):
     with pytest.raises(GitOpsException) as ex:
         create_git(
             tmp_dir="TMP_DIR",
             username="******",
             password="******",
             git_user="******",
             git_email="GIT_EMAIL",
             organisation="ORG",
             repository_name="REPO",
             git_provider="unknown",  # <- unknown
             git_provider_url="GIT_PROVIDER_URL",
         )
     self.assertEqual("Git provider 'unknown' is not supported.",
                      str(ex.value))
예제 #3
0
 def test_bitbucket_server_missing_git_provider_url(self):
     with pytest.raises(GitOpsException) as ex:
         create_git(
             tmp_dir="TMP_DIR",
             username="******",
             password="******",
             git_user="******",
             git_email="GIT_EMAIL",
             organisation="ORG",
             repository_name="REPO",
             git_provider="bitbucket-server",
             git_provider_url=None,  # <- missing
         )
     self.assertEqual(
         "Please provide --git-provider-url for bitbucket-server",
         str(ex.value))
예제 #4
0
    def test_bitbucket_server(self, mock_bitbucket_git_util_constructor):
        mock_bitbucket_git_util = MagicMock()
        mock_bitbucket_git_util_constructor.return_value = mock_bitbucket_git_util

        git = create_git(
            tmp_dir="TMP_DIR",
            username="******",
            password="******",
            git_user="******",
            git_email="GIT_EMAIL",
            organisation="ORG",
            repository_name="REPO",
            git_provider="bitbucket-server",
            git_provider_url="GIT_PROVIDER_URL",
        )

        self.assertEqual(git, mock_bitbucket_git_util)
        mock_bitbucket_git_util_constructor.assert_called_with(
            tmp_dir="TMP_DIR",
            username="******",
            password="******",
            git_user="******",
            git_email="GIT_EMAIL",
            organisation="ORG",
            repository_name="REPO",
            git_provider_url="GIT_PROVIDER_URL",
        )
예제 #5
0
    def test_github_via_git_provider_url(self,
                                         mock_github_git_util_constructor):
        mock_github_git_util = MagicMock()
        mock_github_git_util_constructor.return_value = mock_github_git_util

        git = create_git(
            tmp_dir="TMP_DIR",
            username="******",
            password="******",
            git_user="******",
            git_email="GIT_EMAIL",
            organisation="ORG",
            repository_name="REPO",
            git_provider=None,
            git_provider_url="www.github.com",
        )

        self.assertEqual(git, mock_github_git_util)
        mock_github_git_util_constructor.assert_called_with(
            tmp_dir="TMP_DIR",
            username="******",
            password="******",
            git_user="******",
            git_email="GIT_EMAIL",
            organisation="ORG",
            repository_name="REPO",
        )
예제 #6
0
def sync_apps_command(
    command,
    username,
    password,
    git_user,
    git_email,
    root_organisation,
    root_repository_name,
    organisation,
    repository_name,
    git_provider,
    git_provider_url,
):
    assert command == "sync-apps"

    apps_tmp_dir = create_tmp_dir()
    root_tmp_dir = create_tmp_dir()

    try:
        apps_git = create_git(
            username,
            password,
            git_user,
            git_email,
            organisation,
            repository_name,
            git_provider,
            git_provider_url,
            apps_tmp_dir,
        )
        root_git = create_git(
            username,
            password,
            git_user,
            git_email,
            root_organisation,
            root_repository_name,
            git_provider,
            git_provider_url,
            root_tmp_dir,
        )

        __sync_apps(apps_git, root_git)
    finally:
        delete_tmp_dir(apps_tmp_dir)
        delete_tmp_dir(root_tmp_dir)
예제 #7
0
def deploy_command(
    command,
    file,
    values,
    username,
    password,
    git_user,
    git_email,
    create_pr,
    auto_merge,
    single_commit,
    organisation,
    repository_name,
    git_provider,
    git_provider_url,
    commit_message=None,
):
    assert command == "deploy"

    tmp_dir = create_tmp_dir()

    try:
        git = create_git(
            username,
            password,
            git_user,
            git_email,
            organisation,
            repository_name,
            git_provider,
            git_provider_url,
            tmp_dir,
        )
        git.checkout("master")
        logging.info("Master checkout successful")

        config_branch = f"gitopscli-deploy-{str(uuid.uuid4())[:8]}" if create_pr else "master"

        if create_pr:
            git.new_branch(config_branch)
            logging.info("Created branch %s", config_branch)

        updated_values = __update_values(git, file, values, single_commit,
                                         commit_message)
        if not updated_values:
            logging.info("All values already up-to-date. I'm done here")
            return

        git.push(config_branch)
        logging.info("Pushed branch %s", config_branch)
    finally:
        delete_tmp_dir(tmp_dir)

    if create_pr:
        __create_pr(git, config_branch, file, updated_values, auto_merge)
예제 #8
0
def create_pr_preview_command(
    command,
    pr_id,
    parent_id,
    username,
    password,
    git_user,
    git_email,
    organisation,
    repository_name,
    git_provider,
    git_provider_url,
):
    assert command == "create-pr-preview"

    apps_tmp_dir = create_tmp_dir()

    try:
        apps_git = create_git(
            username,
            password,
            git_user,
            git_email,
            organisation,
            repository_name,
            git_provider,
            git_provider_url,
            apps_tmp_dir,
        )

        pr_branch = apps_git.get_pull_request_branch(pr_id)

        apps_git.checkout(pr_branch)
        logging.info("App repo PR branch %s checkout successful", pr_branch)
        git_hash = apps_git.get_last_commit_hash()
        create_preview_command(
            command,
            username,
            password,
            git_user,
            git_email,
            organisation,
            repository_name,
            git_provider,
            git_provider_url,
            git_hash,
            pr_branch,  # <- preview_id
            __create_deployment_already_up_to_date_callback(parent_id, pr_id),
            __create_deployment_exist_callback(parent_id, pr_id, pr_branch),
            __create_deployment_new_callback(parent_id, pr_id, pr_branch),
        )
    finally:
        delete_tmp_dir(apps_tmp_dir)
예제 #9
0
def pr_comment_command(
    command,
    text,
    username,
    password,
    parent_id,
    pr_id,
    organisation,
    repository_name,
    git_provider,
    git_provider_url,
):
    assert command == "add-pr-comment"
    apps_git = create_git(
        username,
        password,
        None,
        None,
        organisation,
        repository_name,
        git_provider,
        git_provider_url,
        None,
    )
    if parent_id:
        logging.info(
            "Creating comment for PR %s as reply to comment %s with content: %s",
            pr_id,
            parent_id,
            text,
        )
    else:
        logging.info(
            "Creating comment for PR %s with content: %s",
            pr_id,
            text,
        )
    apps_git.add_pull_request_comment(pr_id, text, parent_id)
예제 #10
0
def delete_preview_command(
    command,
    username,
    password,
    git_user,
    git_email,
    organisation,
    repository_name,
    git_provider,
    git_provider_url,
    preview_id,
):

    assert command is not None

    apps_tmp_dir = create_tmp_dir()
    root_tmp_dir = create_tmp_dir()

    try:
        apps_git = create_git(
            username,
            password,
            git_user,
            git_email,
            organisation,
            repository_name,
            git_provider,
            git_provider_url,
            apps_tmp_dir,
        )

        apps_git.checkout("master")
        logging.info("App repo branch master checkout successful")
        try:
            gitops_config = GitOpsConfig(
                apps_git.get_full_file_path(".gitops.config.yaml"))
        except FileNotFoundError as ex:
            raise GitOpsException(f"Couldn't find .gitops.config.yaml") from ex
        logging.info("Read GitOpsConfig: %s", gitops_config)

        root_git = create_git(
            username,
            password,
            git_user,
            git_email,
            gitops_config.team_config_org,
            gitops_config.team_config_repo,
            git_provider,
            git_provider_url,
            root_tmp_dir,
        )
        root_git.checkout("master")
        logging.info("Config repo branch master checkout successful")
        config_branch = "master"
        hashed_preview_id = hashlib.sha256(
            preview_id.encode("utf-8")).hexdigest()[:8]
        preview_folder_name = gitops_config.application_name + "-" + hashed_preview_id + "-preview"
        logging.info("Preview folder name: %s", preview_folder_name)
        branch_preview_env_exists = os.path.exists(
            root_git.get_full_file_path(preview_folder_name))
        logging.info("Is preview env already existing for branch? %s",
                     branch_preview_env_exists)
        if branch_preview_env_exists:
            shutil.rmtree(root_git.get_full_file_path(preview_folder_name),
                          ignore_errors=True)
        else:
            raise GitOpsException(
                f"There was no preview with name: {preview_folder_name}")
        root_git.commit(
            f"Delete preview environment for '{gitops_config.application_name}' and preview id '{preview_id}'."
        )
        root_git.push(config_branch)
        logging.info("Pushed branch %s", config_branch)

    finally:
        delete_tmp_dir(apps_tmp_dir)
        delete_tmp_dir(root_tmp_dir)
예제 #11
0
def delete_pr_preview_command(
    command,
    branch,
    username,
    password,
    git_user,
    git_email,
    organisation,
    repository_name,
    git_provider,
    git_provider_url,
):
    assert command == "delete-pr-preview"

    apps_tmp_dir = create_tmp_dir()
    root_tmp_dir = create_tmp_dir()

    try:
        apps_git = create_git(
            username,
            password,
            git_user,
            git_email,
            organisation,
            repository_name,
            git_provider,
            git_provider_url,
            apps_tmp_dir,
        )

        app_master_branch_name = "master"
        apps_git.checkout(app_master_branch_name)
        logging.info("App repo branch %s checkout successful",
                     app_master_branch_name)
        try:
            gitops_config = GitOpsConfig(
                apps_git.get_full_file_path(".gitops.config.yaml"))
        except FileNotFoundError as ex:
            raise GitOpsException(f"Couldn't find .gitops.config.yaml") from ex
        logging.info("Read GitOpsConfig: %s", gitops_config)

        root_git = create_git(
            username,
            password,
            git_user,
            git_email,
            gitops_config.team_config_org,
            gitops_config.team_config_repo,
            git_provider,
            git_provider_url,
            root_tmp_dir,
        )
        root_git.checkout("master")
        logging.info("Config repo branch master checkout successful")

        delete_preview_command(
            command,
            username,
            password,
            git_user,
            git_email,
            organisation,
            repository_name,
            git_provider,
            git_provider_url,
            branch,
        )

    finally:
        delete_tmp_dir(apps_tmp_dir)
        delete_tmp_dir(root_tmp_dir)
예제 #12
0
def create_preview_command(
    command,
    username,
    password,
    git_user,
    git_email,
    organisation,
    repository_name,
    git_provider,
    git_provider_url,
    git_hash,
    preview_id,
    deployment_already_up_to_date_callback=None,
    deployment_exists_callback=None,
    deployment_new_callback=None,
):

    assert command is not None

    apps_tmp_dir = create_tmp_dir()
    root_tmp_dir = create_tmp_dir()

    try:
        apps_git = create_git(
            username,
            password,
            git_user,
            git_email,
            organisation,
            repository_name,
            git_provider,
            git_provider_url,
            apps_tmp_dir,
        )

        apps_git.checkout(git_hash)
        logging.info("App repo git hash %s checkout successful", git_hash)
        try:
            gitops_config = GitOpsConfig(
                apps_git.get_full_file_path(".gitops.config.yaml"))
        except FileNotFoundError as ex:
            raise GitOpsException(f"Couldn't find .gitops.config.yaml") from ex
        logging.info("Read .gitops.config.yaml: %s", gitops_config)

        root_git = create_git(
            username,
            password,
            git_user,
            git_email,
            gitops_config.team_config_org,
            gitops_config.team_config_repo,
            git_provider,
            git_provider_url,
            root_tmp_dir,
        )
        root_git.checkout("master")
        logging.info("Config repo branch master checkout successful")

        preview_template_folder_name = ".preview-templates/" + gitops_config.application_name
        if os.path.isdir(
                root_git.get_full_file_path(preview_template_folder_name)):
            logging.info("Using the preview template folder: %s",
                         preview_template_folder_name)
        else:
            raise GitOpsException(
                f"The preview template folder does not exist: {preview_template_folder_name}"
            )

        hashed_preview_id = hashlib.sha256(
            preview_id.encode("utf-8")).hexdigest()[:8]
        new_preview_folder_name = gitops_config.application_name + "-" + hashed_preview_id + "-preview"
        logging.info("New folder for preview: %s", new_preview_folder_name)
        preview_env_already_exist = os.path.isdir(
            root_git.get_full_file_path(new_preview_folder_name))
        logging.info("Is preview env already existing? %s",
                     preview_env_already_exist)
        if not preview_env_already_exist:
            __create_new_preview_env(
                git_hash,
                new_preview_folder_name,
                preview_template_folder_name,
                root_git,
                gitops_config.application_name,
            )
        logging.info("Using image tag from git hash: %s", git_hash)
        route_host = None
        value_replaced = False
        for replacement in gitops_config.replacements:
            route_host, value_replaced = __replace_value(
                gitops_config,
                git_hash,
                new_preview_folder_name,
                replacement,
                root_git,
                route_host,
                hashed_preview_id,
                value_replaced,
            )
        if not value_replaced:
            logging.info(
                "The image tag %s has already been deployed. Doing nothing.",
                git_hash)
            if deployment_already_up_to_date_callback:
                deployment_already_up_to_date_callback(apps_git, git_hash)
            return

        root_git.commit(
            f"Update preview environment for '{gitops_config.application_name}' and git hash '{git_hash}'."
        )
        root_git.push("master")
        logging.info("Pushed branch master")

        if preview_env_already_exist:
            if deployment_exists_callback:
                deployment_exists_callback(apps_git, gitops_config, route_host)
        else:
            if deployment_new_callback:
                deployment_new_callback(apps_git, gitops_config, route_host)
    finally:
        delete_tmp_dir(apps_tmp_dir)
        delete_tmp_dir(root_tmp_dir)