Example #1
0
    def test_sync_apps_missing_bootstrap_element_in_bootstrap_yaml(self):
        self.yaml_file_load_mock.side_effect = lambda file_path: {
            "/tmp/root-config-repo/bootstrap/values.yaml": {
            },  # empty bootstrap yaml
        }[file_path]

        args = SyncAppsCommand.Args(
            username="******",
            password="******",
            git_user="******",
            git_email="GIT_EMAIL",
            root_organisation="ROOT_ORGA",
            root_repository_name="ROOT_REPO",
            organisation="TEAM_ORGA",
            repository_name="TEAM_REPO",
            git_provider=GitProvider.GITHUB,
            git_provider_url=None,
        )
        try:
            SyncAppsCommand(ARGS).execute()
            self.fail()
        except GitOpsException as ex:
            self.assertEqual(
                "Cannot find key 'bootstrap' in 'bootstrap/values.yaml'",
                str(ex))
Example #2
0
    def test_sync_apps_app_name_collission(self):
        self.yaml_file_load_mock.side_effect = lambda file_path: {
            "/tmp/root-config-repo/bootstrap/values.yaml": {
                "bootstrap": [{
                    "name": "team-non-prod"
                }, {
                    "name": "other-team-non-prod"
                }],
            },
            "/tmp/root-config-repo/apps/team-non-prod.yaml": {
                "repository": "https://team.config.repo.git",
                "applications": {
                    "some-other-app-1": None
                },
            },
            "/tmp/root-config-repo/apps/other-team-non-prod.yaml": {
                "repository": "https://other-team.config.repo.git",
                "applications": {
                    "my-app": None
                },  # the other-team already has an app named "my-app"
            },
        }[file_path]

        try:
            SyncAppsCommand(ARGS).execute()
            self.fail()
        except GitOpsException as ex:
            self.assertEqual(
                "Application 'my-app' already exists in a different repository",
                str(ex))
Example #3
0
 def test_sync_apps_happy_flow(self):
     SyncAppsCommand(ARGS).execute()
     assert self.mock_manager.method_calls == [
         call.GitRepoApiFactory.create(ARGS, "TEAM_ORGA", "TEAM_REPO",),
         call.GitRepoApiFactory.create(ARGS, "ROOT_ORGA", "ROOT_REPO",),
         call.GitRepo(self.team_config_git_repo_api_mock),
         call.GitRepo(self.root_config_git_repo_api_mock),
         call.GitRepo_team.get_clone_url(),
         call.logging.info("Team config repository: %s", "https://team.config.repo.git"),
         call.GitRepo_root.get_clone_url(),
         call.logging.info("Root config repository: %s", "https://root.config.repo.git"),
         call.GitRepo_team.clone(),
         call.GitRepo_team.get_full_file_path("."),
         call.os.listdir("/tmp/team-config-repo/."),
         call.os.path.join("/tmp/team-config-repo/.", "my-app"),
         call.os.path.isdir("/tmp/team-config-repo/./my-app"),
         call.logging.info("Found %s app(s) in apps repository: %s", 1, "my-app"),
         call.logging.info("Searching apps repository in root repository's 'apps/' directory..."),
         call.GitRepo_root.clone(),
         call.GitRepo_root.get_full_file_path("bootstrap/values.yaml"),
         call.yaml_file_load("/tmp/root-config-repo/bootstrap/values.yaml"),
         call.GitRepo_team.get_clone_url(),
         call.logging.info("Analyzing %s in root repository", "apps/team-non-prod.yaml"),
         call.GitRepo_root.get_full_file_path("apps/team-non-prod.yaml"),
         call.yaml_file_load("/tmp/root-config-repo/apps/team-non-prod.yaml"),
         call.logging.info("Found apps repository in %s", "apps/team-non-prod.yaml"),
         call.logging.info("Analyzing %s in root repository", "apps/other-team-non-prod.yaml"),
         call.GitRepo_root.get_full_file_path("apps/other-team-non-prod.yaml"),
         call.yaml_file_load("/tmp/root-config-repo/apps/other-team-non-prod.yaml"),
         call.logging.info("Sync applications in root repository's %s.", "apps/team-non-prod.yaml"),
         call.merge_yaml_element("/tmp/root-config-repo/apps/team-non-prod.yaml", "applications", {"my-app": {}}),
         call.GitRepo_team.get_author_from_last_commit(),
         call.GitRepo_root.commit("GIT_USER", "GIT_EMAIL", "author updated apps/team-non-prod.yaml"),
         call.GitRepo_root.push(),
     ]
Example #4
0
    def test_sync_apps_bootstrap_yaml_not_found(self):
        self.yaml_file_load_mock.side_effect = FileNotFoundError()

        try:
            SyncAppsCommand(ARGS).execute()
            self.fail()
        except GitOpsException as ex:
            self.assertEqual("File 'bootstrap/values.yaml' not found in root repository.", str(ex))
Example #5
0
    def test_sync_apps_invalid_bootstrap_entry_in_bootstrap_yaml(self):
        self.yaml_file_load_mock.side_effect = lambda file_path: {
            "/tmp/root-config-repo/bootstrap/values.yaml": {
                "bootstrap": [{"something": "invalid"}],  # bootstrap entry has no "name" property
            },
        }[file_path]

        try:
            SyncAppsCommand(ARGS).execute()
            self.fail()
        except GitOpsException as ex:
            self.assertEqual("Every bootstrap entry must have a 'name' property.", str(ex))
Example #6
0
    def test_sync_apps_missing_repository_element_in_team_yaml(self):
        self.yaml_file_load_mock.side_effect = lambda file_path: {
            "/tmp/root-config-repo/bootstrap/values.yaml": {"bootstrap": [{"name": "team-non-prod"}],},
            "/tmp/root-config-repo/apps/team-non-prod.yaml": {
                # missing: "repository": "https://team.config.repo.git",
                "applications": {},
            },
        }[file_path]

        try:
            SyncAppsCommand(ARGS).execute()
            self.fail()
        except GitOpsException as ex:
            self.assertEqual("Cannot find key 'repository' in 'apps/team-non-prod.yaml'", str(ex))
Example #7
0
    def test_sync_apps_undefined_team_repo(self):
        self.yaml_file_load_mock.side_effect = lambda file_path: {
            "/tmp/root-config-repo/bootstrap/values.yaml": {"bootstrap": [{"name": "other-team-non-prod"}],},
            "/tmp/root-config-repo/apps/other-team-non-prod.yaml": {
                "repository": "https://other-team.config.repo.git",  # there is no repo matching the command's team repo
                "applications": {},
            },
        }[file_path]

        try:
            SyncAppsCommand(ARGS).execute()
            self.fail()
        except GitOpsException as ex:
            self.assertEqual(
                "Couldn't find config file for apps repository in root repository's 'apps/' directory", str(ex)
            )
Example #8
0
    def test_sync_apps_team_yaml_not_found(self):
        def file_load_mock_side_effect(file_path):
            if file_path == "/tmp/root-config-repo/bootstrap/values.yaml":
                return {
                    "bootstrap": [{"name": "team-non-prod"}],
                }
            if file_path == "/tmp/root-config-repo/apps/team-non-prod.yaml":
                raise FileNotFoundError()
            raise Exception("test should not reach this")

        self.yaml_file_load_mock.side_effect = file_load_mock_side_effect

        try:
            SyncAppsCommand(ARGS).execute()
            self.fail()
        except GitOpsException as ex:
            self.assertEqual("File 'apps/team-non-prod.yaml' not found in root repository.", str(ex))
Example #9
0
    def test_sync_apps_already_up_to_date(self):
        self.yaml_file_load_mock.side_effect = lambda file_path: {
            "/tmp/root-config-repo/bootstrap/values.yaml": {
                "bootstrap": [{"name": "team-non-prod"}, {"name": "other-team-non-prod"}],
            },
            "/tmp/root-config-repo/apps/team-non-prod.yaml": {
                "repository": "https://team.config.repo.git",
                "applications": {"my-app": None},  # my-app already exists
            },
            "/tmp/root-config-repo/apps/other-team-non-prod.yaml": {
                "repository": "https://other-team.config.repo.git",
                "applications": {},
            },
        }[file_path]

        SyncAppsCommand(ARGS).execute()
        assert self.mock_manager.method_calls == [
            call.GitRepoApiFactory.create(ARGS, "TEAM_ORGA", "TEAM_REPO",),
            call.GitRepoApiFactory.create(ARGS, "ROOT_ORGA", "ROOT_REPO",),
            call.GitRepo(self.team_config_git_repo_api_mock),
            call.GitRepo(self.root_config_git_repo_api_mock),
            call.GitRepo_team.get_clone_url(),
            call.logging.info("Team config repository: %s", "https://team.config.repo.git"),
            call.GitRepo_root.get_clone_url(),
            call.logging.info("Root config repository: %s", "https://root.config.repo.git"),
            call.GitRepo_team.clone(),
            call.GitRepo_team.get_full_file_path("."),
            call.os.listdir("/tmp/team-config-repo/."),
            call.os.path.join("/tmp/team-config-repo/.", "my-app"),
            call.os.path.isdir("/tmp/team-config-repo/./my-app"),
            call.logging.info("Found %s app(s) in apps repository: %s", 1, "my-app"),
            call.logging.info("Searching apps repository in root repository's 'apps/' directory..."),
            call.GitRepo_root.clone(),
            call.GitRepo_root.get_full_file_path("bootstrap/values.yaml"),
            call.yaml_file_load("/tmp/root-config-repo/bootstrap/values.yaml"),
            call.GitRepo_team.get_clone_url(),
            call.logging.info("Analyzing %s in root repository", "apps/team-non-prod.yaml"),
            call.GitRepo_root.get_full_file_path("apps/team-non-prod.yaml"),
            call.yaml_file_load("/tmp/root-config-repo/apps/team-non-prod.yaml"),
            call.logging.info("Found apps repository in %s", "apps/team-non-prod.yaml"),
            call.logging.info("Analyzing %s in root repository", "apps/other-team-non-prod.yaml"),
            call.GitRepo_root.get_full_file_path("apps/other-team-non-prod.yaml"),
            call.yaml_file_load("/tmp/root-config-repo/apps/other-team-non-prod.yaml"),
            call.logging.info("Root repository already up-to-date. I'm done here."),
        ]
Example #10
0
import logging
import os
import unittest
from unittest.mock import call
from gitopscli.git_api import GitProvider, GitRepo, GitRepoApi, GitRepoApiFactory
from gitopscli.commands.sync_apps import SyncAppsCommand
from gitopscli.io_api.yaml_util import merge_yaml_element, yaml_file_load
from gitopscli.gitops_exception import GitOpsException
from .mock_mixin import MockMixin

ARGS = SyncAppsCommand.Args(
    username="******",
    password="******",
    git_user="******",
    git_email="GIT_EMAIL",
    root_organisation="ROOT_ORGA",
    root_repository_name="ROOT_REPO",
    organisation="TEAM_ORGA",
    repository_name="TEAM_REPO",
    git_provider=GitProvider.GITHUB,
    git_provider_url=None,
)


class SyncAppsCommandTest(MockMixin, unittest.TestCase):
    def setUp(self):
        self.init_mock_manager(SyncAppsCommand)

        self.os_mock = self.monkey_patch(os)
        self.os_mock.path.isdir.return_value = True
        self.os_mock.path.join.side_effect = os.path.join
        self.os_mock.listdir.return_value = ["my-app"]