コード例 #1
0
class TestSetupChronosJob:

    fake_docker_image = 'test_docker:1.0'
    fake_client = mock.MagicMock()

    fake_service = 'test_service'
    fake_instance = 'test'
    fake_cluster = 'fake_test_cluster'
    fake_config_dict = {
        'name': 'test_service test gitsha config',
        'description': 'This is a test Chronos job.',
        'command': '/bin/sleep 40',
        'bounce_method': 'graceful',
        'epsilon': 'PT30M',
        'retries': 5,
        'owner': '*****@*****.**',
        'async': False,
        'cpus': 5.5,
        'mem': 1024.4,
        'disk': 2048.5,
        'disabled': 'true',
        'schedule': 'R/2015-03-25T19:36:35Z/PT5M',
        'schedule_time_zone': 'Zulu',
    }
    fake_branch_dict = {
        'docker_image': f'paasta-{fake_service}-{fake_cluster}',
        'git_sha': 'fake_sha',
        'force_bounce': None,
        'desired_state': 'start',
    }
    fake_chronos_job_config = chronos_tools.ChronosJobConfig(
        service=fake_service,
        cluster=fake_cluster,
        instance=fake_instance,
        config_dict=fake_config_dict,
        branch_dict=fake_branch_dict,
    )

    fake_docker_registry = 'remote_registry.com'
    fake_args = mock.MagicMock(
        service_instance=compose_job_id(fake_service, fake_instance),
        soa_dir='no_more',
        verbose=False,
    )

    def test_config_with_historical_stats(self):
        with mock.patch(
                'paasta_tools.setup_chronos_job.chronos_tools.lookup_chronos_jobs',
                autospec=True,
        ) as mock_lookup_chronos_jobs:
            ret = [{
                'lastSuccess': '2017-04-01T00:00:00Z',
                'lastError': '2017-04-02T00:00:00Z',
                'successCount': 1,
                'errorCount': 1,
            }]
            mock_lookup_chronos_jobs.return_value = ret
            init_config = {
                'name': 'foo bar',
            }
            expected_merge = {
                'name': 'foo bar',
                'lastSuccess': '2017-04-01T00:00:00Z',
                'lastError': '2017-04-02T00:00:00Z',
                'successCount': 1,
                'errorCount': 1,
            }
            actual = setup_chronos_job.config_with_historical_stats(
                chronos_client=mock.Mock(),
                service='foo',
                instance='bar',
                job_config=init_config,
            )
            assert actual == expected_merge

    def test_config_with_historical_stats_no_existing(self):
        with mock.patch(
                'paasta_tools.setup_chronos_job.chronos_tools.lookup_chronos_jobs',
                autospec=True,
        ) as mock_lookup_chronos_jobs:
            ret = []
            mock_lookup_chronos_jobs.return_value = ret
            init_config = {
                'name': 'foo bar',
            }
            expected_merge = {
                'name': 'foo bar',
            }
            actual = setup_chronos_job.config_with_historical_stats(
                chronos_client=mock.Mock(),
                service='foo',
                instance='bar',
                job_config=init_config,
            )
            assert actual == expected_merge

    def test_main_success(self):
        expected_status = 0
        expected_output = 'it_is_finished'
        fake_complete_job_config = {'foo': 'bar'}
        with mock.patch(
                'paasta_tools.setup_chronos_job.parse_args',
                return_value=self.fake_args,
                autospec=True,
        ) as parse_args_patch, mock.patch(
                'paasta_tools.chronos_tools.load_chronos_config',
                autospec=True,
        ) as load_chronos_config_patch, mock.patch(
                'paasta_tools.chronos_tools.get_chronos_client',
                return_value=self.fake_client,
                autospec=True,
        ) as get_client_patch, mock.patch(
                'paasta_tools.chronos_tools.create_complete_config',
                return_value=fake_complete_job_config,
                autospec=True,
        ), mock.patch(
                'paasta_tools.setup_chronos_job.setup_job',
                return_value=(expected_status, expected_output),
                autospec=True,
        ) as setup_job_patch, mock.patch(
                'paasta_tools.setup_chronos_job.send_event',
                autospec=True,
        ) as send_event_patch, mock.patch(
                'paasta_tools.setup_chronos_job.load_system_paasta_config',
                autospec=True,
        ) as load_system_paasta_config_patch, mock.patch(
                'sys.exit',
                autospec=True,
        ) as sys_exit_patch:
            load_system_paasta_config_patch.return_value.get_cluster = mock.MagicMock(
                return_value=self.fake_cluster)
            setup_chronos_job.main()

            parse_args_patch.assert_called_once_with()
            get_client_patch.assert_called_once_with(
                load_chronos_config_patch.return_value)
            setup_job_patch.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                complete_job_config=fake_complete_job_config,
                client=self.fake_client,
                cluster=self.fake_cluster,
            )
            send_event_patch.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                soa_dir=self.fake_args.soa_dir,
                status=expected_status,
                output=expected_output,
            )
            sys_exit_patch.assert_called_once_with(0)

    def test_main_no_deployments(self):
        with mock.patch(
                'paasta_tools.setup_chronos_job.parse_args',
                return_value=self.fake_args,
                autospec=True,
        ), mock.patch(
                'paasta_tools.chronos_tools.load_chronos_config',
                autospec=True,
        ), mock.patch(
                'paasta_tools.chronos_tools.get_chronos_client',
                return_value=self.fake_client,
                autospec=True,
        ), mock.patch(
                'paasta_tools.chronos_tools.create_complete_config',
                return_value={},
                autospec=True,
                side_effect=NoDeploymentsAvailable,
        ), mock.patch(
                'paasta_tools.setup_chronos_job.setup_job',
                return_value=(0, 'it_is_finished'),
                autospec=True,
        ), mock.patch(
                'paasta_tools.setup_chronos_job.load_system_paasta_config',
                autospec=True,
        ) as load_system_paasta_config_patch, mock.patch(
                'paasta_tools.setup_chronos_job.send_event',
                autospec=True,
        ):
            load_system_paasta_config_patch.return_value.get_cluster = mock.MagicMock(
                return_value=self.fake_cluster)
            with raises(SystemExit) as excinfo:
                setup_chronos_job.main()
            assert excinfo.value.code == 0

    def test_main_bad_chronos_job_config_notifies_user(self):
        with mock.patch(
                'paasta_tools.setup_chronos_job.parse_args',
                return_value=self.fake_args,
                autospec=True,
        ), mock.patch(
                'paasta_tools.chronos_tools.load_chronos_config',
                autospec=True,
        ), mock.patch(
                'paasta_tools.chronos_tools.get_chronos_client',
                return_value=self.fake_client,
                autospec=True,
        ), mock.patch(
                'paasta_tools.chronos_tools.create_complete_config',
                autospec=True,
                side_effect=NoConfigurationForServiceError(
                    'test bad configuration'),
        ), mock.patch(
                'paasta_tools.setup_chronos_job.setup_job',
                return_value=(0, 'it_is_finished'),
                autospec=True,
        ), mock.patch(
                'paasta_tools.setup_chronos_job.load_system_paasta_config',
                autospec=True,
        ) as load_system_paasta_config_patch, mock.patch(
                'paasta_tools.setup_chronos_job.send_event',
                autospec=True,
        ) as send_event_patch:
            load_system_paasta_config_patch.return_value.get_cluster = mock.MagicMock(
                return_value=self.fake_cluster)
            with raises(SystemExit) as excinfo:
                setup_chronos_job.main()
            assert excinfo.value.code == 0
            expected_error_msg = (
                "Could not read chronos configuration file for %s in cluster %s\nError was: test bad configuration"
                % (compose_job_id(self.fake_service,
                                  self.fake_instance), self.fake_cluster))
            send_event_patch.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                soa_dir=self.fake_args.soa_dir,
                status=Status.CRITICAL,
                output=expected_error_msg,
            )

    def test_setup_job_new_app_with_no_previous_jobs(self):
        fake_existing_jobs = []
        with mock.patch(
                'paasta_tools.setup_chronos_job.bounce_chronos_job',
                autospec=True,
                return_value=(0, 'ok'),
        ) as mock_bounce_chronos_job, mock.patch(
                'paasta_tools.chronos_tools.lookup_chronos_jobs',
                autospec=True,
        ), mock.patch(
                'paasta_tools.chronos_tools.sort_jobs',
                autospec=True,
                return_value=fake_existing_jobs,
        ), mock.patch(
                'paasta_tools.utils.load_system_paasta_config',
                autospec=True,
        ), mock.patch(
                'paasta_tools.chronos_tools.load_system_paasta_config',
                autospec=True,
        ) as load_system_paasta_config_patch, mock.patch(
                'paasta_tools.chronos_tools.load_chronos_job_config',
                autospec=True,
                return_value=self.fake_chronos_job_config,
        ):
            load_system_paasta_config_patch.return_value.get_cluster.return_value = self.fake_cluster
            load_system_paasta_config_patch.return_value.get_volumes.return_value = []
            load_system_paasta_config_patch.return_value.get_deploy_whitelist.return_value = None
            load_system_paasta_config_patch.return_value.get_dockercfg_location.return_value = \
                'file:///root/.dockercfg'
            complete_config = chronos_tools.create_complete_config(
                service=self.fake_service,
                job_name=self.fake_instance,
                soa_dir=self.fake_args.soa_dir,
            )
            actual = setup_chronos_job.setup_job(
                service=self.fake_service,
                instance=self.fake_instance,
                complete_job_config=complete_config,
                client=self.fake_client,
                cluster=self.fake_cluster,
            )
            mock_bounce_chronos_job.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                job_to_update=complete_config,
                client=self.fake_client,
            )
            assert actual == mock_bounce_chronos_job.return_value

    def test_setup_job_with_previously_enabled_job(self):
        fake_existing_job = {
            'name': 'fake_job',
            'disabled': False,
        }
        with mock.patch(
                'paasta_tools.setup_chronos_job.bounce_chronos_job',
                autospec=True,
                return_value=(0, 'ok'),
        ) as mock_bounce_chronos_job, mock.patch(
                'paasta_tools.chronos_tools.lookup_chronos_jobs',
                autospec=True,
        ) as mock_lookup_chronos_jobs, mock.patch(
                'paasta_tools.chronos_tools.sort_jobs',
                autospec=True,
                return_value=[fake_existing_job],
        ), mock.patch(
                'paasta_tools.utils.load_system_paasta_config',
                autospec=True,
        ), mock.patch(
                'paasta_tools.chronos_tools.load_system_paasta_config',
                autospec=True,
        ) as load_system_paasta_config_patch, mock.patch(
                'paasta_tools.chronos_tools.load_chronos_job_config',
                autospec=True,
                return_value=self.fake_chronos_job_config,
        ):
            load_system_paasta_config_patch.return_value.get_cluster.return_value = self.fake_cluster
            load_system_paasta_config_patch.return_value.get_volumes.return_value = []
            load_system_paasta_config_patch.return_value.get_deploy_whitelist.return_value = None
            load_system_paasta_config_patch.return_value.get_dockercfg_location.return_value = \
                "file:///root/.dockercfg"
            complete_config = chronos_tools.create_complete_config(
                service=self.fake_service,
                job_name=self.fake_instance,
                soa_dir=self.fake_args.soa_dir,
            )
            actual = setup_chronos_job.setup_job(
                service=self.fake_service,
                instance=self.fake_instance,
                complete_job_config=complete_config,
                client=self.fake_client,
                cluster=self.fake_cluster,
            )
            mock_bounce_chronos_job.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                job_to_update=complete_config,
                client=self.fake_client,
            )
            assert mock_lookup_chronos_jobs.called
            assert actual == mock_bounce_chronos_job.return_value

    def test_setup_job_does_nothing_with_only_existing_app(self):
        fake_existing_job = copy.deepcopy(self.fake_config_dict)
        with mock.patch(
                'paasta_tools.setup_chronos_job.bounce_chronos_job',
                autospec=True,
                return_value=(0, 'ok'),
        ) as mock_bounce_chronos_job, mock.patch(
                'paasta_tools.chronos_tools.lookup_chronos_jobs',
                autospec=True,
                return_value=[fake_existing_job],
        ) as mock_lookup_chronos_jobs, mock.patch(
                'paasta_tools.chronos_tools.load_system_paasta_config',
                autospec=True,
        ) as load_system_paasta_config_patch, mock.patch(
                'paasta_tools.chronos_tools.load_chronos_job_config',
                autospec=True,
                return_value=self.fake_chronos_job_config,
        ):
            load_system_paasta_config_patch.return_value.get_cluster.return_value = self.fake_cluster
            complete_config = copy.deepcopy(self.fake_config_dict)
            # Force the complete_config's name to match the return value of
            # lookup_chronos_jobs to simulate that they have the same name
            complete_config["name"] = fake_existing_job["name"]
            actual = setup_chronos_job.setup_job(
                service=self.fake_service,
                instance=self.fake_instance,
                complete_job_config=complete_config,
                client=self.fake_client,
                cluster=self.fake_cluster,
            )
            mock_bounce_chronos_job.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                job_to_update=None,
                client=self.fake_client,
            )
            assert mock_lookup_chronos_jobs.called
            assert actual == mock_bounce_chronos_job.return_value

    def test_send_event(self):
        fake_status = '42'
        fake_output = 'something went wrong'
        fake_soa_dir = ''
        expected_check_name = 'setup_chronos_job.%s' % compose_job_id(
            self.fake_service, self.fake_instance)
        with mock.patch(
                "paasta_tools.monitoring_tools.send_event",
                autospec=True,
        ) as mock_send_event, mock.patch(
                "paasta_tools.chronos_tools.load_chronos_job_config",
                autospec=True,
        ) as mock_load_chronos_job_config, mock.patch(
                "paasta_tools.setup_chronos_job.load_system_paasta_config",
                autospec=True,
        ) as mock_load_system_paasta_config:
            mock_load_system_paasta_config.return_value.get_cluster = mock.Mock(
                return_value='fake_cluster')
            mock_load_chronos_job_config.return_value.get_monitoring.return_value = {}

            setup_chronos_job.send_event(
                service=self.fake_service,
                instance=self.fake_instance,
                soa_dir=fake_soa_dir,
                status=fake_status,
                output=fake_output,
            )
            mock_send_event.assert_called_once_with(
                service=self.fake_service,
                check_name=expected_check_name,
                overrides={
                    'alert_after': '10m',
                    'check_every': '10s'
                },
                status=fake_status,
                output=fake_output,
                soa_dir=fake_soa_dir,
            )
            mock_load_chronos_job_config.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=mock_load_system_paasta_config.return_value.
                get_cluster.return_value,
                soa_dir=fake_soa_dir,
                load_deployments=False,
            )

    def test_bounce_chronos_job_takes_actions(self):
        fake_job_to_update = {'name': 'job_to_update'}
        with mock.patch(
                "paasta_tools.setup_chronos_job._log",
                autospec=True,
        ) as mock_log, mock.patch(
                "paasta_tools.chronos_tools.update_job",
                autospec=True,
        ) as mock_update_job:
            setup_chronos_job.bounce_chronos_job(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                job_to_update=fake_job_to_update,
                client=self.fake_client,
            )
            mock_log.assert_any_call(
                line=mock.ANY,
                level='debug',
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                component='deploy',
                service=self.fake_service,
            )
            mock_log.assert_any_call(
                line="Updated Chronos job: job_to_update",
                level='event',
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                component='deploy',
                service=self.fake_service,
            )
            mock_update_job.assert_called_once_with(job=fake_job_to_update,
                                                    client=self.fake_client)

    def test_bounce_chronos_job_doesnt_log_when_nothing_to_do(self):
        with mock.patch(
                "paasta_tools.setup_chronos_job._log",
                autospec=True,
        ) as mock_log, mock.patch(
                "paasta_tools.chronos_tools.update_job",
                autospec=True,
        ) as mock_update_job:
            setup_chronos_job.bounce_chronos_job(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                job_to_update=None,
                client=self.fake_client,
            )
            assert not mock_log.called
            assert not mock_update_job.called
コード例 #2
0
class TestMonitoring_Tools:

    general_page = True
    fake_general_service_config = {
        'team': 'general_test_team',
        'runbook': 'y/general_test_runbook',
        'tip': 'general_test_tip',
        'notification_email': 'general_test_notification_email',
        'page': general_page
    }

    empty_service_config = marathon_tools.MarathonServiceConfig(
        service='myservicename',
        cluster='mycluster',
        instance='myinstance',
        config_dict={},
        branch_dict={},
    )
    job_page = False
    fake_marathon_job_config = marathon_tools.MarathonServiceConfig(
        service='myservicename',
        cluster='myclustername',
        instance='myinstance',
        config_dict={
            'team': 'job_test_team',
            'runbook': 'y/job_test_runbook',
            'tip': 'job_test_tip',
            'notification_email': 'job_test_notification_email',
            'page': job_page
        },
        branch_dict={},
    )
    fake_chronos_job_config = chronos_tools.ChronosJobConfig(
        service='myservicename',
        cluster='myclustername',
        instance='myinstance',
        config_dict={
            'team': 'job_test_team',
            'runbook': 'y/job_test_runbook',
            'tip': 'job_test_tip',
            'notification_email': 'job_test_notification_email',
            'page': job_page
        },
        branch_dict={},
    )
    empty_job_config = {}
    monitor_page = True
    fake_monitor_config = {
        'team': 'monitor_test_team',
        'runbook': 'y/monitor_test_runbook',
        'tip': 'monitor_test_tip',
        'notification_email': 'monitor_test_notification_email',
        'page': monitor_page
    }
    empty_monitor_config = {}
    framework = 'fake_framework'
    overrides = {}
    instance = 'fake_instance'
    service = 'fake_service'
    soa_dir = '/fake/soa/dir'

    def test_get_team(self):
        with mock.patch(
                'paasta_tools.monitoring_tools.__get_monitoring_config_value',
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_team(self.overrides, self.service,
                                      self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                'team', self.overrides, self.service, self.soa_dir)

    def test_get_runbook(self):
        with mock.patch(
                'paasta_tools.monitoring_tools.__get_monitoring_config_value',
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_runbook(self.overrides, self.service,
                                         self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                'runbook', self.overrides, self.service, self.soa_dir)

    def test_get_tip(self):
        with mock.patch(
                'paasta_tools.monitoring_tools.__get_monitoring_config_value',
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_tip(self.overrides, self.service,
                                     self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                'tip', self.overrides, self.service, self.soa_dir)

    def test_get_notification_email(self):
        with mock.patch(
                'paasta_tools.monitoring_tools.__get_monitoring_config_value',
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_notification_email(self.overrides,
                                                    self.service, self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                'notification_email', self.overrides, self.service,
                self.soa_dir)

    def test_get_page(self):
        with mock.patch(
                'paasta_tools.monitoring_tools.__get_monitoring_config_value',
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_page(self.overrides, self.service,
                                      self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                'page', self.overrides, self.service, self.soa_dir)

    def test_get_alert_after(self):
        with mock.patch(
                'paasta_tools.monitoring_tools.__get_monitoring_config_value',
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_alert_after(self.overrides, self.service,
                                             self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                'alert_after', self.overrides, self.service, self.soa_dir)

    def test_get_realert_every(self):
        with mock.patch(
                'paasta_tools.monitoring_tools.__get_monitoring_config_value',
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_realert_every(self.overrides, self.service,
                                               self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                'realert_every', self.overrides, self.service, self.soa_dir)

    def test_get_check_every(self):
        with mock.patch(
                'paasta_tools.monitoring_tools.__get_monitoring_config_value',
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_check_every(self.overrides, self.service,
                                             self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                'check_every', self.overrides, self.service, self.soa_dir)

    def test_get_irc_channels(self):
        with mock.patch(
                'paasta_tools.monitoring_tools.__get_monitoring_config_value',
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_irc_channels(self.overrides, self.service,
                                              self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                'irc_channels', self.overrides, self.service, self.soa_dir)

    def test_get_dependencies(self):
        with mock.patch(
                'paasta_tools.monitoring_tools.__get_monitoring_config_value',
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_dependencies(self.overrides, self.service,
                                              self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                'dependencies', self.overrides, self.service, self.soa_dir)

    def test_get_ticket(self):
        with mock.patch(
                'paasta_tools.monitoring_tools.__get_monitoring_config_value',
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_ticket(self.overrides, self.service,
                                        self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                'ticket', self.overrides, self.service, self.soa_dir)

    def test_get_project(self):
        with mock.patch(
                'paasta_tools.monitoring_tools.__get_monitoring_config_value',
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_project(self.overrides, self.service,
                                         self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                'project', self.overrides, self.service, self.soa_dir)

    def test_get_monitoring_config_value_with_monitor_config(self):
        expected = 'monitor_test_team'
        with contextlib.nested(
                mock.patch(
                    'service_configuration_lib.read_service_configuration',
                    autospec=True,
                    return_value=self.fake_general_service_config),
                mock.patch(
                    'paasta_tools.monitoring_tools.read_monitoring_config',
                    autospec=True,
                    return_value=self.fake_monitor_config),
                mock.patch(
                    'paasta_tools.monitoring_tools.load_system_paasta_config',
                    autospec=True),
        ) as (
                service_configuration_lib_patch,
                read_monitoring_patch,
                load_system_paasta_config_patch,
        ):
            load_system_paasta_config_patch.return_value.get_cluster = mock.Mock(
                return_value='fake_cluster')
            actual = monitoring_tools.get_team(self.overrides, self.service,
                                               self.soa_dir)
            assert expected == actual
            service_configuration_lib_patch.assert_called_once_with(
                self.service, soa_dir=self.soa_dir)
            read_monitoring_patch.assert_called_once_with(self.service,
                                                          soa_dir=self.soa_dir)

    def test_get_monitoring_config_value_with_service_config(self):
        expected = 'general_test_team'
        with contextlib.nested(
                mock.patch(
                    'service_configuration_lib.read_service_configuration',
                    autospec=True,
                    return_value=self.fake_general_service_config),
                mock.patch(
                    'paasta_tools.monitoring_tools.read_monitoring_config',
                    autospec=True,
                    return_value=self.empty_monitor_config),
                mock.patch(
                    'paasta_tools.monitoring_tools.load_system_paasta_config',
                    autospec=True),
        ) as (
                service_configuration_lib_patch,
                read_monitoring_patch,
                load_system_paasta_config_patch,
        ):
            load_system_paasta_config_patch.return_value.get_cluster = mock.Mock(
                return_value='fake_cluster')
            actual = monitoring_tools.get_team(self.overrides, self.service,
                                               self.soa_dir)
            assert expected == actual
            service_configuration_lib_patch.assert_called_once_with(
                self.service, soa_dir=self.soa_dir)
            read_monitoring_patch.assert_called_once_with(self.service,
                                                          soa_dir=self.soa_dir)

    def test_get_monitoring_config_value_with_defaults(self):
        expected = None
        with contextlib.nested(
                mock.patch(
                    'service_configuration_lib.read_service_configuration',
                    autospec=True,
                    return_value=self.empty_job_config),
                mock.patch(
                    'paasta_tools.monitoring_tools.read_monitoring_config',
                    autospec=True,
                    return_value=self.empty_monitor_config),
                mock.patch(
                    'paasta_tools.monitoring_tools.load_system_paasta_config',
                    autospec=True),
        ) as (
                service_configuration_lib_patch,
                read_monitoring_patch,
                load_system_paasta_config_patch,
        ):
            load_system_paasta_config_patch.return_value.get_cluster = mock.Mock(
                return_value='fake_cluster')
            actual = monitoring_tools.get_team(self.overrides, self.service,
                                               self.soa_dir)
            assert expected == actual
            service_configuration_lib_patch.assert_called_once_with(
                self.service, soa_dir=self.soa_dir)
            read_monitoring_patch.assert_called_once_with(self.service,
                                                          soa_dir=self.soa_dir)

    def test_get_team_email_address_uses_override_if_specified(self):
        fake_email = 'fake_email'
        with contextlib.nested(
                mock.patch(
                    'paasta_tools.monitoring_tools.__get_monitoring_config_value',
                    autospec=True), ) as (mock_get_monitoring_config_value, ):
            mock_get_monitoring_config_value.return_value = 'fake_email'
            actual = monitoring_tools.get_team_email_address(
                'fake_service', {'notification_email': fake_email})
            assert actual == fake_email

    def test_get_team_email_address_uses_instance_config_if_specified(self):
        expected = 'fake_email'
        with contextlib.nested(
                mock.patch(
                    'paasta_tools.monitoring_tools.__get_monitoring_config_value',
                    autospec=True), ) as (mock_get_monitoring_config_value, ):
            mock_get_monitoring_config_value.return_value = 'fake_email'
            actual = monitoring_tools.get_team_email_address('fake_service')
            assert actual == expected

    def test_get_team_email_address_uses_team_data_as_last_resort(self):
        expected = 'team_data_email'
        with contextlib.nested(
                mock.patch(
                    'paasta_tools.monitoring_tools.__get_monitoring_config_value',
                    autospec=True),
                mock.patch('paasta_tools.monitoring_tools.get_sensu_team_data',
                           autospec=True),
                mock.patch('paasta_tools.monitoring_tools.get_team',
                           autospec=True),
        ) as (
                mock_get_monitoring_config_value,
                mock_get_sensu_team_data,
                mock_get_team,
        ):
            mock_get_team.return_value = 'test_team'
            mock_get_monitoring_config_value.return_value = False
            mock_get_sensu_team_data.return_value = {
                'notification_email': expected
            }
            actual = monitoring_tools.get_team_email_address('fake_service')
            assert actual == expected

    def test_get_team_email_address_returns_none_if_not_available(self):
        with contextlib.nested(
                mock.patch(
                    'paasta_tools.monitoring_tools.__get_monitoring_config_value',
                    autospec=True),
                mock.patch('paasta_tools.monitoring_tools.get_sensu_team_data',
                           autospec=True),
                mock.patch('paasta_tools.monitoring_tools.get_team',
                           autospec=True),
        ) as (
                mock_get_monitoring_config_value,
                mock_get_sensu_team_data,
                mock_get_team,
        ):
            mock_get_team.return_value = 'test_team'
            mock_get_monitoring_config_value.return_value = False
            mock_get_sensu_team_data.return_value = {}
            actual = monitoring_tools.get_team_email_address('fake_service')
            assert actual is None

    def test_send_event(self):
        fake_service = 'fake_service'
        fake_monitoring_overrides = {}
        fake_check_name = 'fake_check_name'
        fake_status = '42'
        fake_output = 'The http port is not open'
        fake_team = 'fake_team'
        fake_tip = 'fake_tip'
        fake_notification_email = 'fake@notify'
        fake_irc = '#fake'
        fake_soa_dir = '/fake/soa/dir'
        self.fake_cluster = 'fake_cluster'
        fake_sensu_host = 'fake_sensu_host'
        fake_sensu_port = 12345
        expected_runbook = 'http://y/paasta-troubleshooting'
        expected_check_name = fake_check_name
        expected_kwargs = {
            'tip': fake_tip,
            'notification_email': fake_notification_email,
            'irc_channels': fake_irc,
            'project': None,
            'ticket': False,
            'page': True,
            'alert_after': '5m',
            'check_every': '1m',
            'realert_every': -1,
            'source': 'paasta-fake_cluster',
            'ttl': None,
        }
        with contextlib.nested(
                mock.patch(
                    "paasta_tools.monitoring_tools.get_team",
                    return_value=fake_team,
                    autospec=True,
                ),
                mock.patch(
                    "paasta_tools.monitoring_tools.get_tip",
                    return_value=fake_tip,
                    autospec=True,
                ),
                mock.patch(
                    "paasta_tools.monitoring_tools.get_notification_email",
                    return_value=fake_notification_email,
                    autospec=True,
                ),
                mock.patch(
                    "paasta_tools.monitoring_tools.get_irc_channels",
                    return_value=fake_irc,
                    autospec=True,
                ),
                mock.patch(
                    "paasta_tools.monitoring_tools.get_ticket",
                    return_value=False,
                    autospec=True,
                ),
                mock.patch(
                    "paasta_tools.monitoring_tools.get_project",
                    return_value=None,
                    autospec=True,
                ),
                mock.patch(
                    "paasta_tools.monitoring_tools.get_page",
                    return_value=True,
                    autospec=True,
                ),
                mock.patch("pysensu_yelp.send_event", autospec=True),
                mock.patch(
                    'paasta_tools.monitoring_tools.load_system_paasta_config',
                    autospec=True),
        ) as (
                get_team_patch,
                get_tip_patch,
                get_notification_email_patch,
                get_irc_patch,
                get_ticket_patch,
                get_project_patch,
                get_page_patch,
                pysensu_yelp_send_event_patch,
                load_system_paasta_config_patch,
        ):
            load_system_paasta_config_patch.return_value.get_cluster = mock.Mock(
                return_value=self.fake_cluster)
            load_system_paasta_config_patch.return_value.get_sensu_host = mock.Mock(
                return_value=fake_sensu_host)
            load_system_paasta_config_patch.return_value.get_sensu_port = mock.Mock(
                return_value=fake_sensu_port)

            monitoring_tools.send_event(fake_service, fake_check_name,
                                        fake_monitoring_overrides, fake_status,
                                        fake_output, fake_soa_dir)

            get_team_patch.assert_called_once_with(
                fake_monitoring_overrides,
                fake_service,
                fake_soa_dir,
            )
            get_tip_patch.assert_called_once_with(fake_monitoring_overrides,
                                                  fake_service, fake_soa_dir)
            get_notification_email_patch.assert_called_once_with(
                fake_monitoring_overrides, fake_service, fake_soa_dir)
            get_irc_patch.assert_called_once_with(fake_monitoring_overrides,
                                                  fake_service, fake_soa_dir)
            get_page_patch.assert_called_once_with(fake_monitoring_overrides,
                                                   fake_service, fake_soa_dir)
            pysensu_yelp_send_event_patch.assert_called_once_with(
                expected_check_name,
                expected_runbook,
                fake_status,
                fake_output,
                fake_team,
                sensu_host=fake_sensu_host,
                sensu_port=fake_sensu_port,
                **expected_kwargs)
            load_system_paasta_config_patch.return_value.get_cluster.assert_called_once_with(
            )

    def test_send_event_sensu_host_is_None(self):
        fake_service = 'fake_service'
        fake_monitoring_overrides = {}
        fake_check_name = 'fake_check_name'
        fake_status = '42'
        fake_output = 'The http port is not open'
        fake_soa_dir = '/fake/soa/dir'
        self.fake_cluster = 'fake_cluster'
        fake_sensu_port = 12345

        with contextlib.nested(
                mock.patch("paasta_tools.monitoring_tools.get_team",
                           autospec=True),
                mock.patch("paasta_tools.monitoring_tools.get_tip",
                           autospec=True),
                mock.patch(
                    "paasta_tools.monitoring_tools.get_notification_email",
                    autospec=True),
                mock.patch("paasta_tools.monitoring_tools.get_irc_channels",
                           autospec=True),
                mock.patch("paasta_tools.monitoring_tools.get_ticket",
                           autospec=True),
                mock.patch("paasta_tools.monitoring_tools.get_project",
                           autospec=True),
                mock.patch("paasta_tools.monitoring_tools.get_page",
                           autospec=True),
                mock.patch("pysensu_yelp.send_event", autospec=True),
                mock.patch(
                    'paasta_tools.monitoring_tools.load_system_paasta_config',
                    autospec=True),
        ) as (
                get_team_patch,
                get_tip_patch,
                get_notification_email_patch,
                get_irc_patch,
                get_ticket_patch,
                get_project_patch,
                get_page_patch,
                pysensu_yelp_send_event_patch,
                load_system_paasta_config_patch,
        ):
            load_system_paasta_config_patch.return_value.get_sensu_host = mock.Mock(
                return_value=None)
            load_system_paasta_config_patch.return_value.get_sensu_port = mock.Mock(
                return_value=fake_sensu_port)

            monitoring_tools.send_event(fake_service, fake_check_name,
                                        fake_monitoring_overrides, fake_status,
                                        fake_output, fake_soa_dir)

            assert pysensu_yelp_send_event_patch.call_count == 0

    def test_read_monitoring_config(self):
        fake_name = 'partial'
        fake_fname = 'acronyms'
        fake_path = 'ever_patched'
        fake_soa_dir = '/nail/cte/oas'
        fake_dict = {'e': 'quail', 'v': 'snail'}
        with contextlib.nested(
                mock.patch('os.path.abspath',
                           autospec=True,
                           return_value=fake_path),
                mock.patch('os.path.join',
                           autospec=True,
                           return_value=fake_fname),
                mock.patch('service_configuration_lib.read_monitoring',
                           autospec=True,
                           return_value=fake_dict)) as (abspath_patch,
                                                        join_patch,
                                                        read_monitoring_patch):
            actual = monitoring_tools.read_monitoring_config(
                fake_name, fake_soa_dir)
            assert fake_dict == actual
            abspath_patch.assert_called_once_with(fake_soa_dir)
            join_patch.assert_called_once_with(fake_path, fake_name,
                                               'monitoring.yaml')
            read_monitoring_patch.assert_called_once_with(fake_fname)
コード例 #3
0
import sys

from behave import when, then

sys.path.append('../')
from paasta_tools import setup_chronos_job
from paasta_tools import chronos_tools

fake_service_name = 'test-service'
fake_instance_name = 'test-instance'
fake_job_id = 'fake_job_id'
fake_service_job_config = chronos_tools.ChronosJobConfig(
    fake_service_name,
    fake_instance_name,
    {},
    {
        'docker_image': 'test-image',
        'desired_state': 'start'
    },
)

# TODO DRY out in PAASTA-1174
fake_service_config = {
    "retries": 1,
    "container": {
        "image":
        "localhost/fake_docker_url",
        "type":
        "DOCKER",
        "network":
        "BRIDGE",
コード例 #4
0
class TestSetupChronosJob:
    @pytest.fixture(autouse=True)
    def mock_read_monitoring_config(self):
        with mock.patch(
                "paasta_tools.utils.get_pipeline_deploy_groups",
                mock.Mock(return_value=["fake_deploy_group"]),
                autospec=None,
        ) as f:
            yield f

    fake_docker_image = "test_docker:1.0"
    fake_client = mock.MagicMock()

    fake_service = "test_service"
    fake_instance = "test"
    fake_cluster = "fake_test_cluster"
    fake_config_dict = {
        "name": "test_service test gitsha config",
        "description": "This is a test Chronos job.",
        "command": "/bin/sleep 40",
        "bounce_method": "graceful",
        "epsilon": "PT30M",
        "retries": 5,
        "owner": "*****@*****.**",
        "async": False,
        "cpus": 5.5,
        "mem": 1024.4,
        "disk": 2048.5,
        "disabled": "true",
        "schedule": "R/2015-03-25T19:36:35Z/PT5M",
        "schedule_time_zone": "Zulu",
        "deploy_group": "fake_deploy_group",
    }
    fake_branch_dict = {
        "docker_image": f"paasta-{fake_service}-{fake_cluster}",
        "git_sha": "fake_sha",
        "force_bounce": None,
        "desired_state": "start",
    }
    fake_chronos_job_config = chronos_tools.ChronosJobConfig(
        service=fake_service,
        cluster=fake_cluster,
        instance=fake_instance,
        config_dict=fake_config_dict,
        branch_dict=fake_branch_dict,
    )

    fake_docker_registry = "remote_registry.com"
    fake_args = mock.MagicMock(
        service_instance=compose_job_id(fake_service, fake_instance),
        soa_dir="no_more",
        verbose=False,
    )

    def test_config_with_historical_stats(self):
        with mock.patch(
                "paasta_tools.setup_chronos_job.chronos_tools.lookup_chronos_jobs",
                autospec=True,
        ) as mock_lookup_chronos_jobs:
            ret = [{
                "lastSuccess": "2017-04-01T00:00:00Z",
                "lastError": "2017-04-02T00:00:00Z",
                "successCount": 1,
                "errorCount": 1,
            }]
            mock_lookup_chronos_jobs.return_value = ret
            init_config = {"name": "foo bar"}
            expected_merge = {
                "name": "foo bar",
                "lastSuccess": "2017-04-01T00:00:00Z",
                "lastError": "2017-04-02T00:00:00Z",
                "successCount": 1,
                "errorCount": 1,
            }
            actual = setup_chronos_job.config_with_historical_stats(
                chronos_client=mock.Mock(),
                service="foo",
                instance="bar",
                job_config=init_config,
            )
            assert actual == expected_merge

    def test_config_with_historical_stats_no_existing(self):
        with mock.patch(
                "paasta_tools.setup_chronos_job.chronos_tools.lookup_chronos_jobs",
                autospec=True,
        ) as mock_lookup_chronos_jobs:
            ret = []
            mock_lookup_chronos_jobs.return_value = ret
            init_config = {"name": "foo bar"}
            expected_merge = {"name": "foo bar"}
            actual = setup_chronos_job.config_with_historical_stats(
                chronos_client=mock.Mock(),
                service="foo",
                instance="bar",
                job_config=init_config,
            )
            assert actual == expected_merge

    def test_main_success(self):
        expected_status = 0
        expected_output = "it_is_finished"
        fake_complete_job_config = {"foo": "bar"}
        with mock.patch(
                "paasta_tools.setup_chronos_job.parse_args",
                return_value=self.fake_args,
                autospec=True,
        ) as parse_args_patch, mock.patch(
                "paasta_tools.chronos_tools.load_chronos_config", autospec=True
        ) as load_chronos_config_patch, mock.patch(
                "paasta_tools.chronos_tools.get_chronos_client",
                return_value=self.fake_client,
                autospec=True,
        ) as get_client_patch, mock.patch(
                "paasta_tools.chronos_tools.create_complete_config",
                return_value=fake_complete_job_config,
                autospec=True,
        ), mock.patch(
                "paasta_tools.setup_chronos_job.setup_job",
                return_value=(expected_status, expected_output),
                autospec=True,
        ) as setup_job_patch, mock.patch(
                "paasta_tools.setup_chronos_job.send_event", autospec=True
        ) as send_event_patch, mock.patch(
                "paasta_tools.setup_chronos_job.load_system_paasta_config",
                autospec=True) as load_system_paasta_config_patch, mock.patch(
                    "sys.exit", autospec=True) as sys_exit_patch:
            load_system_paasta_config_patch.return_value.get_cluster = mock.MagicMock(
                return_value=self.fake_cluster)
            setup_chronos_job.main()

            parse_args_patch.assert_called_once_with()
            get_client_patch.assert_called_once_with(
                load_chronos_config_patch.return_value)
            setup_job_patch.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                complete_job_config=fake_complete_job_config,
                client=self.fake_client,
                cluster=self.fake_cluster,
            )
            send_event_patch.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                soa_dir=self.fake_args.soa_dir,
                status=expected_status,
                output=expected_output,
            )
            sys_exit_patch.assert_called_once_with(0)

    def test_main_no_deployments(self):
        with mock.patch(
                "paasta_tools.setup_chronos_job.parse_args",
                return_value=self.fake_args,
                autospec=True,
        ), mock.patch(
                "paasta_tools.chronos_tools.load_chronos_config", autospec=True
        ), mock.patch(
                "paasta_tools.chronos_tools.get_chronos_client",
                return_value=self.fake_client,
                autospec=True,
        ), mock.patch(
                "paasta_tools.chronos_tools.create_complete_config",
                return_value={},
                autospec=True,
                side_effect=NoDeploymentsAvailable,
        ), mock.patch(
                "paasta_tools.setup_chronos_job.setup_job",
                return_value=(0, "it_is_finished"),
                autospec=True,
        ), mock.patch(
                "paasta_tools.setup_chronos_job.load_system_paasta_config",
                autospec=True) as load_system_paasta_config_patch, mock.patch(
                    "paasta_tools.setup_chronos_job.send_event",
                    autospec=True):
            load_system_paasta_config_patch.return_value.get_cluster = mock.MagicMock(
                return_value=self.fake_cluster)
            with raises(SystemExit) as excinfo:
                setup_chronos_job.main()
            assert excinfo.value.code == 0

    def test_main_bad_chronos_job_config_notifies_user(self):
        with mock.patch(
                "paasta_tools.setup_chronos_job.parse_args",
                return_value=self.fake_args,
                autospec=True,
        ), mock.patch(
                "paasta_tools.chronos_tools.load_chronos_config", autospec=True
        ), mock.patch(
                "paasta_tools.chronos_tools.get_chronos_client",
                return_value=self.fake_client,
                autospec=True,
        ), mock.patch(
                "paasta_tools.chronos_tools.create_complete_config",
                autospec=True,
                side_effect=NoConfigurationForServiceError(
                    "test bad configuration"),
        ), mock.patch(
                "paasta_tools.setup_chronos_job.setup_job",
                return_value=(0, "it_is_finished"),
                autospec=True,
        ), mock.patch(
                "paasta_tools.setup_chronos_job.load_system_paasta_config",
                autospec=True) as load_system_paasta_config_patch, mock.patch(
                    "paasta_tools.setup_chronos_job.send_event",
                    autospec=True) as send_event_patch:
            load_system_paasta_config_patch.return_value.get_cluster = mock.MagicMock(
                return_value=self.fake_cluster)
            with raises(SystemExit) as excinfo:
                setup_chronos_job.main()
            assert excinfo.value.code == 0
            expected_error_msg = (
                "Could not read chronos configuration file for %s in cluster %s\nError was: test bad configuration"
                % (
                    compose_job_id(self.fake_service, self.fake_instance),
                    self.fake_cluster,
                ))
            send_event_patch.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                soa_dir=self.fake_args.soa_dir,
                status=Status.CRITICAL,
                output=expected_error_msg,
            )

    def test_setup_job_new_app_with_no_previous_jobs(self):
        fake_existing_jobs = []
        with mock.patch(
                "paasta_tools.setup_chronos_job.bounce_chronos_job",
                autospec=True,
                return_value=(0, "ok"),
        ) as mock_bounce_chronos_job, mock.patch(
                "paasta_tools.chronos_tools.lookup_chronos_jobs",
                autospec=True), mock.patch(
                    "paasta_tools.chronos_tools.sort_jobs",
                    autospec=True,
                    return_value=fake_existing_jobs,
                ), mock.patch(
                    "paasta_tools.utils.load_system_paasta_config",
                    autospec=True), mock.patch(
                        "paasta_tools.chronos_tools.load_system_paasta_config",
                        autospec=True
                    ) as load_system_paasta_config_patch, mock.patch(
                        "paasta_tools.chronos_tools.load_chronos_job_config",
                        autospec=True,
                        return_value=self.fake_chronos_job_config,
                    ):
            load_system_paasta_config_patch.return_value.get_cluster.return_value = (
                self.fake_cluster)
            load_system_paasta_config_patch.return_value.get_volumes.return_value = []
            load_system_paasta_config_patch.return_value.get_deploy_whitelist.return_value = (
                None)
            load_system_paasta_config_patch.return_value.get_dockercfg_location.return_value = (
                "file:///root/.dockercfg")
            complete_config = chronos_tools.create_complete_config(
                service=self.fake_service,
                job_name=self.fake_instance,
                soa_dir=self.fake_args.soa_dir,
            )
            actual = setup_chronos_job.setup_job(
                service=self.fake_service,
                instance=self.fake_instance,
                complete_job_config=complete_config,
                client=self.fake_client,
                cluster=self.fake_cluster,
            )
            mock_bounce_chronos_job.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                job_to_update=complete_config,
                client=self.fake_client,
            )
            assert actual == mock_bounce_chronos_job.return_value

    def test_setup_job_with_previously_enabled_job(self):
        fake_existing_job = {"name": "fake_job", "disabled": False}
        with mock.patch(
                "paasta_tools.setup_chronos_job.bounce_chronos_job",
                autospec=True,
                return_value=(0, "ok"),
        ) as mock_bounce_chronos_job, mock.patch(
                "paasta_tools.chronos_tools.lookup_chronos_jobs",
                autospec=True) as mock_lookup_chronos_jobs, mock.patch(
                    "paasta_tools.chronos_tools.sort_jobs",
                    autospec=True,
                    return_value=[fake_existing_job],
                ), mock.patch(
                    "paasta_tools.utils.load_system_paasta_config",
                    autospec=True), mock.patch(
                        "paasta_tools.chronos_tools.load_system_paasta_config",
                        autospec=True
                    ) as load_system_paasta_config_patch, mock.patch(
                        "paasta_tools.chronos_tools.load_chronos_job_config",
                        autospec=True,
                        return_value=self.fake_chronos_job_config,
                    ):
            load_system_paasta_config_patch.return_value.get_cluster.return_value = (
                self.fake_cluster)
            load_system_paasta_config_patch.return_value.get_volumes.return_value = []
            load_system_paasta_config_patch.return_value.get_deploy_whitelist.return_value = (
                None)
            load_system_paasta_config_patch.return_value.get_dockercfg_location.return_value = (
                "file:///root/.dockercfg")
            complete_config = chronos_tools.create_complete_config(
                service=self.fake_service,
                job_name=self.fake_instance,
                soa_dir=self.fake_args.soa_dir,
            )
            actual = setup_chronos_job.setup_job(
                service=self.fake_service,
                instance=self.fake_instance,
                complete_job_config=complete_config,
                client=self.fake_client,
                cluster=self.fake_cluster,
            )
            mock_bounce_chronos_job.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                job_to_update=complete_config,
                client=self.fake_client,
            )
            assert mock_lookup_chronos_jobs.called
            assert actual == mock_bounce_chronos_job.return_value

    def test_setup_job_does_nothing_with_only_existing_app(self):
        fake_existing_job = copy.deepcopy(self.fake_config_dict)
        with mock.patch(
                "paasta_tools.setup_chronos_job.bounce_chronos_job",
                autospec=True,
                return_value=(0, "ok"),
        ) as mock_bounce_chronos_job, mock.patch(
                "paasta_tools.chronos_tools.lookup_chronos_jobs",
                autospec=True,
                return_value=[fake_existing_job],
        ) as mock_lookup_chronos_jobs, mock.patch(
                "paasta_tools.chronos_tools.load_system_paasta_config",
                autospec=True) as load_system_paasta_config_patch, mock.patch(
                    "paasta_tools.chronos_tools.load_chronos_job_config",
                    autospec=True,
                    return_value=self.fake_chronos_job_config,
                ):
            load_system_paasta_config_patch.return_value.get_cluster.return_value = (
                self.fake_cluster)
            complete_config = copy.deepcopy(self.fake_config_dict)
            # Force the complete_config's name to match the return value of
            # lookup_chronos_jobs to simulate that they have the same name
            complete_config["name"] = fake_existing_job["name"]
            actual = setup_chronos_job.setup_job(
                service=self.fake_service,
                instance=self.fake_instance,
                complete_job_config=complete_config,
                client=self.fake_client,
                cluster=self.fake_cluster,
            )
            mock_bounce_chronos_job.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                job_to_update=None,
                client=self.fake_client,
            )
            assert mock_lookup_chronos_jobs.called
            assert actual == mock_bounce_chronos_job.return_value

    def test_send_event(self):
        fake_status = "42"
        fake_output = "something went wrong"
        fake_soa_dir = ""
        expected_check_name = "setup_chronos_job.%s" % compose_job_id(
            self.fake_service, self.fake_instance)
        with mock.patch(
                "paasta_tools.monitoring_tools.send_event", autospec=True
        ) as mock_send_event, mock.patch(
                "paasta_tools.chronos_tools.load_chronos_job_config",
                autospec=True) as mock_load_chronos_job_config, mock.patch(
                    "paasta_tools.setup_chronos_job.load_system_paasta_config",
                    autospec=True) as mock_load_system_paasta_config:
            mock_load_system_paasta_config.return_value.get_cluster = mock.Mock(
                return_value="fake_cluster")
            mock_load_chronos_job_config.return_value.get_monitoring.return_value = {}

            setup_chronos_job.send_event(
                service=self.fake_service,
                instance=self.fake_instance,
                soa_dir=fake_soa_dir,
                status=fake_status,
                output=fake_output,
            )
            mock_send_event.assert_called_once_with(
                service=self.fake_service,
                check_name=expected_check_name,
                overrides={
                    "alert_after": "10m",
                    "check_every": "10s"
                },
                status=fake_status,
                output=fake_output,
                soa_dir=fake_soa_dir,
            )
            mock_load_chronos_job_config.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=mock_load_system_paasta_config.return_value.
                get_cluster.return_value,
                soa_dir=fake_soa_dir,
                load_deployments=False,
            )

    def test_bounce_chronos_job_takes_actions(self):
        fake_job_to_update = {"name": "job_to_update"}
        with mock.patch("paasta_tools.setup_chronos_job._log",
                        autospec=True) as mock_log, mock.patch(
                            "paasta_tools.chronos_tools.update_job",
                            autospec=True) as mock_update_job:
            setup_chronos_job.bounce_chronos_job(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                job_to_update=fake_job_to_update,
                client=self.fake_client,
            )
            mock_log.assert_any_call(
                line=mock.ANY,
                level="debug",
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                component="deploy",
                service=self.fake_service,
            )
            mock_log.assert_any_call(
                line="Updated Chronos job: job_to_update",
                level="event",
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                component="deploy",
                service=self.fake_service,
            )
            mock_update_job.assert_called_once_with(job=fake_job_to_update,
                                                    client=self.fake_client)

    def test_bounce_chronos_job_doesnt_log_when_nothing_to_do(self):
        with mock.patch("paasta_tools.setup_chronos_job._log",
                        autospec=True) as mock_log, mock.patch(
                            "paasta_tools.chronos_tools.update_job",
                            autospec=True) as mock_update_job:
            setup_chronos_job.bounce_chronos_job(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                job_to_update=None,
                client=self.fake_client,
            )
            assert not mock_log.called
            assert not mock_update_job.called
コード例 #5
0
class TestMonitoring_Tools:

    general_page = True
    fake_general_service_config = {
        "team": "general_test_team",
        "runbook": "y/general_test_runbook",
        "tip": "general_test_tip",
        "notification_email": "general_test_notification_email",
        "page": general_page,
    }

    empty_service_config = marathon_tools.MarathonServiceConfig(
        service="myservicename",
        cluster="mycluster",
        instance="myinstance",
        config_dict={},
        branch_dict=None,
    )
    job_page = False
    fake_marathon_job_config = marathon_tools.MarathonServiceConfig(
        service="myservicename",
        cluster="myclustername",
        instance="myinstance",
        config_dict={
            "team": "job_test_team",
            "runbook": "y/job_test_runbook",
            "tip": "job_test_tip",
            "notification_email": "job_test_notification_email",
            "page": job_page,
        },
        branch_dict=None,
    )
    fake_chronos_job_config = chronos_tools.ChronosJobConfig(
        service="myservicename",
        cluster="myclustername",
        instance="myinstance",
        config_dict={
            "team": "job_test_team",
            "runbook": "y/job_test_runbook",
            "tip": "job_test_tip",
            "notification_email": "job_test_notification_email",
            "page": job_page,
        },
        branch_dict=None,
    )
    empty_job_config = {}
    monitor_page = True
    fake_monitor_config = {
        "team": "monitor_test_team",
        "runbook": "y/monitor_test_runbook",
        "tip": "monitor_test_tip",
        "notification_email": "monitor_test_notification_email",
        "page": monitor_page,
    }
    empty_monitor_config = {}
    framework = "fake_framework"
    overrides = {}
    instance = "fake_instance"
    service = "fake_service"
    soa_dir = "/fake/soa/dir"

    def test_get_team(self):
        with mock.patch(
                "paasta_tools.monitoring_tools.__get_monitoring_config_value",
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_team(self.overrides, self.service,
                                      self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                "team", self.overrides, self.service, self.soa_dir)

    def test_get_runbook(self):
        with mock.patch(
                "paasta_tools.monitoring_tools.__get_monitoring_config_value",
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_runbook(self.overrides, self.service,
                                         self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                "runbook", self.overrides, self.service, self.soa_dir)

    def test_get_tip(self):
        with mock.patch(
                "paasta_tools.monitoring_tools.__get_monitoring_config_value",
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_tip(self.overrides, self.service,
                                     self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                "tip", self.overrides, self.service, self.soa_dir)

    def test_get_notification_email(self):
        with mock.patch(
                "paasta_tools.monitoring_tools.__get_monitoring_config_value",
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_notification_email(self.overrides,
                                                    self.service, self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                "notification_email", self.overrides, self.service,
                self.soa_dir)

    def test_get_page(self):
        with mock.patch(
                "paasta_tools.monitoring_tools.__get_monitoring_config_value",
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_page(self.overrides, self.service,
                                      self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                "page", self.overrides, self.service, self.soa_dir)

    def test_get_alert_after(self):
        with mock.patch(
                "paasta_tools.monitoring_tools.__get_monitoring_config_value",
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_alert_after(self.overrides, self.service,
                                             self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                "alert_after", self.overrides, self.service, self.soa_dir)

    def test_get_realert_every(self):
        with mock.patch(
                "paasta_tools.monitoring_tools.__get_monitoring_config_value",
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_defaults = mock.Mock()
            monitoring_tools.get_realert_every(self.overrides, self.service,
                                               self.soa_dir,
                                               monitoring_defaults)
            get_monitoring_config_value_patch.assert_called_once_with(
                "realert_every",
                self.overrides,
                self.service,
                self.soa_dir,
                monitoring_defaults,
            )

    def test_get_check_every(self):
        with mock.patch(
                "paasta_tools.monitoring_tools.__get_monitoring_config_value",
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_check_every(self.overrides, self.service,
                                             self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                "check_every", self.overrides, self.service, self.soa_dir)

    def test_get_irc_channels(self):
        with mock.patch(
                "paasta_tools.monitoring_tools.__get_monitoring_config_value",
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_irc_channels(self.overrides, self.service,
                                              self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                "irc_channels", self.overrides, self.service, self.soa_dir)

    def test_get_slack_channels(self):
        with mock.patch(
                "paasta_tools.monitoring_tools.__get_monitoring_config_value",
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_slack_channels(self.overrides, self.service,
                                                self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                "slack_channels", self.overrides, self.service, self.soa_dir)

    def test_get_dependencies(self):
        with mock.patch(
                "paasta_tools.monitoring_tools.__get_monitoring_config_value",
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_dependencies(self.overrides, self.service,
                                              self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                "dependencies", self.overrides, self.service, self.soa_dir)

    def test_get_ticket(self):
        with mock.patch(
                "paasta_tools.monitoring_tools.__get_monitoring_config_value",
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_ticket(self.overrides, self.service,
                                        self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                "ticket", self.overrides, self.service, self.soa_dir)

    def test_get_project(self):
        with mock.patch(
                "paasta_tools.monitoring_tools.__get_monitoring_config_value",
                autospec=True) as get_monitoring_config_value_patch:
            monitoring_tools.get_project(self.overrides, self.service,
                                         self.soa_dir)
            get_monitoring_config_value_patch.assert_called_once_with(
                "project", self.overrides, self.service, self.soa_dir)

    def test_get_monitoring_config_value_with_monitor_config(self):
        expected = "monitor_test_team"
        with mock.patch(
                "service_configuration_lib.read_service_configuration",
                autospec=True,
                return_value=self.fake_general_service_config,
        ) as service_configuration_lib_patch, mock.patch(
                "paasta_tools.monitoring_tools.read_monitoring_config",
                autospec=True,
                return_value=self.fake_monitor_config,
        ) as read_monitoring_patch, mock.patch(
                "paasta_tools.monitoring_tools.load_system_paasta_config",
                autospec=True) as load_system_paasta_config_patch:
            load_system_paasta_config_patch.return_value.get_cluster = mock.Mock(
                return_value="fake_cluster")
            actual = monitoring_tools.get_team(self.overrides, self.service,
                                               self.soa_dir)
            assert expected == actual
            service_configuration_lib_patch.assert_called_once_with(
                self.service, soa_dir=self.soa_dir)
            read_monitoring_patch.assert_called_once_with(self.service,
                                                          soa_dir=self.soa_dir)

    def test_get_monitoring_config_value_with_service_config(self):
        expected = "general_test_team"
        with mock.patch(
                "service_configuration_lib.read_service_configuration",
                autospec=True,
                return_value=self.fake_general_service_config,
        ) as service_configuration_lib_patch, mock.patch(
                "paasta_tools.monitoring_tools.read_monitoring_config",
                autospec=True,
                return_value=self.empty_monitor_config,
        ) as read_monitoring_patch, mock.patch(
                "paasta_tools.monitoring_tools.load_system_paasta_config",
                autospec=True) as load_system_paasta_config_patch:
            load_system_paasta_config_patch.return_value.get_cluster = mock.Mock(
                return_value="fake_cluster")
            actual = monitoring_tools.get_team(self.overrides, self.service,
                                               self.soa_dir)
            assert expected == actual
            service_configuration_lib_patch.assert_called_once_with(
                self.service, soa_dir=self.soa_dir)
            read_monitoring_patch.assert_called_once_with(self.service,
                                                          soa_dir=self.soa_dir)

    def test_get_monitoring_config_value_with_defaults(self):
        expected = None
        with mock.patch(
                "service_configuration_lib.read_service_configuration",
                autospec=True,
                return_value=self.empty_job_config,
        ) as service_configuration_lib_patch, mock.patch(
                "paasta_tools.monitoring_tools.read_monitoring_config",
                autospec=True,
                return_value=self.empty_monitor_config,
        ) as read_monitoring_patch, mock.patch(
                "paasta_tools.monitoring_tools.load_system_paasta_config",
                autospec=True) as load_system_paasta_config_patch:
            load_system_paasta_config_patch.return_value.get_cluster = mock.Mock(
                return_value="fake_cluster")
            actual = monitoring_tools.get_team(self.overrides, self.service,
                                               self.soa_dir)
            assert expected == actual
            service_configuration_lib_patch.assert_called_once_with(
                self.service, soa_dir=self.soa_dir)
            read_monitoring_patch.assert_called_once_with(self.service,
                                                          soa_dir=self.soa_dir)

    def test_send_event(self):
        fake_service = "fake_service"
        fake_monitoring_overrides = {}
        fake_check_name = "fake_check_name"
        fake_status = "42"
        fake_output = "The http port is not open"
        fake_team = "fake_team"
        fake_tip = "fake_tip"
        fake_notification_email = "fake@notify"
        fake_irc = "#fake"
        fake_slack = "#fake_slack"
        fake_soa_dir = "/fake/soa/dir"
        self.fake_cluster = "fake_cluster"
        fake_sensu_host = "fake_sensu_host"
        fake_sensu_port = 12345
        expected_runbook = "http://y/paasta-troubleshooting"
        expected_check_name = fake_check_name
        expected_kwargs = {
            "name": expected_check_name,
            "runbook": expected_runbook,
            "status": fake_status,
            "output": fake_output,
            "team": fake_team,
            "page": True,
            "tip": fake_tip,
            "notification_email": fake_notification_email,
            "check_every": "1m",
            "realert_every": -1,
            "alert_after": "5m",
            "irc_channels": fake_irc,
            "slack_channels": fake_slack,
            "ticket": False,
            "project": None,
            "priority": None,
            "source": "paasta-fake_cluster",
            "tags": [],
            "ttl": None,
            "sensu_host": fake_sensu_host,
            "sensu_port": fake_sensu_port,
            "component": None,
            "description": None,
        }
        with mock.patch(
                "paasta_tools.monitoring_tools.get_team",
                return_value=fake_team,
                autospec=True,
        ) as get_team_patch, mock.patch(
                "paasta_tools.monitoring_tools.get_tip",
                return_value=fake_tip,
                autospec=True,
        ) as get_tip_patch, mock.patch(
                "paasta_tools.monitoring_tools.get_notification_email",
                return_value=fake_notification_email,
                autospec=True,
        ) as get_notification_email_patch, mock.patch(
                "paasta_tools.monitoring_tools.get_irc_channels",
                return_value=fake_irc,
                autospec=True,
        ) as get_irc_patch, mock.patch(
                "paasta_tools.monitoring_tools.get_slack_channels",
                return_value=fake_slack,
                autospec=True,
        ) as get_slack_patch, mock.patch(
                "paasta_tools.monitoring_tools.get_ticket",
                return_value=False,
                autospec=True,
        ), mock.patch(
                "paasta_tools.monitoring_tools.get_project",
                return_value=None,
                autospec=True,
        ), mock.patch(
                "paasta_tools.monitoring_tools.get_page",
                return_value=True,
                autospec=True) as get_page_patch, mock.patch(
                    "paasta_tools.monitoring_tools.get_priority",
                    return_value=None,
                    autospec=True,
                ), mock.patch(
                    "paasta_tools.monitoring_tools.get_tags",
                    return_value=[],
                    autospec=True
                ), mock.patch(
                    "paasta_tools.monitoring_tools.get_component",
                    return_value=None,
                    autospec=True,
                ), mock.patch(
                    "paasta_tools.monitoring_tools.get_description",
                    return_value=None,
                    autospec=True,
                ), mock.patch(
                    "pysensu_yelp.send_event", autospec=True
                ) as pysensu_yelp_send_event_patch, mock.patch(
                    "paasta_tools.monitoring_tools.load_system_paasta_config",
                    autospec=True) as load_system_paasta_config_patch:
            load_system_paasta_config_patch.return_value.get_cluster = mock.Mock(
                return_value=self.fake_cluster)
            load_system_paasta_config_patch.return_value.get_sensu_host = mock.Mock(
                return_value=fake_sensu_host)
            load_system_paasta_config_patch.return_value.get_sensu_port = mock.Mock(
                return_value=fake_sensu_port)

            monitoring_tools.send_event(
                fake_service,
                fake_check_name,
                fake_monitoring_overrides,
                fake_status,
                fake_output,
                fake_soa_dir,
            )

            get_team_patch.assert_called_once_with(fake_monitoring_overrides,
                                                   fake_service, fake_soa_dir)
            get_tip_patch.assert_called_once_with(fake_monitoring_overrides,
                                                  fake_service, fake_soa_dir)
            get_notification_email_patch.assert_called_once_with(
                fake_monitoring_overrides, fake_service, fake_soa_dir)
            get_irc_patch.assert_called_once_with(fake_monitoring_overrides,
                                                  fake_service, fake_soa_dir)
            get_slack_patch.assert_called_once_with(fake_monitoring_overrides,
                                                    fake_service, fake_soa_dir)
            get_page_patch.assert_called_once_with(fake_monitoring_overrides,
                                                   fake_service, fake_soa_dir)
            pysensu_yelp_send_event_patch.assert_called_once_with(
                **expected_kwargs)
            load_system_paasta_config_patch.return_value.get_cluster.assert_called_once_with(
            )

    def test_send_event_sensu_host_is_None(self):
        fake_service = "fake_service"
        fake_monitoring_overrides = {}
        fake_check_name = "fake_check_name"
        fake_status = "42"
        fake_output = "The http port is not open"
        fake_soa_dir = "/fake/soa/dir"
        self.fake_cluster = "fake_cluster"
        fake_sensu_port = 12345

        with mock.patch(
                "paasta_tools.monitoring_tools.get_team", autospec=True
        ), mock.patch(
                "paasta_tools.monitoring_tools.get_tip", autospec=True
        ), mock.patch(
                "paasta_tools.monitoring_tools.get_notification_email",
                autospec=True), mock.patch(
                    "paasta_tools.monitoring_tools.get_irc_channels",
                    autospec=True
                ), mock.patch(
                    "paasta_tools.monitoring_tools.get_ticket", autospec=True
                ), mock.patch(
                    "paasta_tools.monitoring_tools.get_project", autospec=True
                ), mock.patch(
                    "paasta_tools.monitoring_tools.get_page", autospec=True
                ), mock.patch(
                    "pysensu_yelp.send_event", autospec=True
                ) as pysensu_yelp_send_event_patch, mock.patch(
                    "paasta_tools.monitoring_tools.load_system_paasta_config",
                    autospec=True) as load_system_paasta_config_patch:
            load_system_paasta_config_patch.return_value.get_sensu_host = mock.Mock(
                return_value=None)
            load_system_paasta_config_patch.return_value.get_sensu_port = mock.Mock(
                return_value=fake_sensu_port)

            monitoring_tools.send_event(
                fake_service,
                fake_check_name,
                fake_monitoring_overrides,
                fake_status,
                fake_output,
                fake_soa_dir,
            )

            assert pysensu_yelp_send_event_patch.call_count == 0

    def test_read_monitoring_config(self):
        fake_name = "partial"
        fake_fname = "acronyms"
        fake_path = "ever_patched"
        fake_soa_dir = "/nail/cte/oas"
        fake_dict = {"e": "quail", "v": "snail"}
        with mock.patch("os.path.abspath",
                        autospec=True,
                        return_value=fake_path) as abspath_patch, mock.patch(
                            "os.path.join",
                            autospec=True,
                            return_value=fake_fname) as join_patch, mock.patch(
                                "service_configuration_lib.read_monitoring",
                                autospec=True,
                                return_value=fake_dict,
                            ) as read_monitoring_patch:
            actual = monitoring_tools.read_monitoring_config(
                fake_name, fake_soa_dir)
            assert fake_dict == actual
            abspath_patch.assert_called_once_with(fake_soa_dir)
            join_patch.assert_called_once_with(fake_path, fake_name,
                                               "monitoring.yaml")
            read_monitoring_patch.assert_called_once_with(fake_fname)
コード例 #6
0
class TestSetupChronosJob:

    fake_docker_image = 'test_docker:1.0'
    fake_client = mock.MagicMock()

    fake_service = 'test_service'
    fake_instance = 'test'
    fake_cluster = 'fake_test_cluster'
    fake_config_dict = {
        'name': 'test_service test gitsha config',
        'description': 'This is a test Chronos job.',
        'command': '/bin/sleep 40',
        'bounce_method': 'graceful',
        'epsilon': 'PT30M',
        'retries': 5,
        'owner': '*****@*****.**',
        'async': False,
        'cpus': 5.5,
        'mem': 1024.4,
        'disk': 2048.5,
        'disabled': 'true',
        'schedule': 'R/2015-03-25T19:36:35Z/PT5M',
        'schedule_time_zone': 'Zulu',
    }
    fake_branch_dict = {
        'docker_image': 'paasta-%s-%s' % (fake_service, fake_cluster),
    }
    fake_chronos_job_config = chronos_tools.ChronosJobConfig(
        fake_service, fake_instance, fake_config_dict, fake_branch_dict)

    fake_docker_registry = 'remote_registry.com'
    fake_args = mock.MagicMock(
        service_instance=compose_job_id(fake_service, fake_instance),
        soa_dir='no_more',
        verbose=False,
    )

    def test_main_success(self):
        expected_status = 0
        expected_output = 'it_is_finished'
        fake_complete_job_config = {'foo': 'bar'}
        with contextlib.nested(
                mock.patch('setup_chronos_job.parse_args',
                           return_value=self.fake_args,
                           autospec=True),
                mock.patch('paasta_tools.chronos_tools.load_chronos_config',
                           autospec=True),
                mock.patch('paasta_tools.chronos_tools.get_chronos_client',
                           return_value=self.fake_client,
                           autospec=True),
                mock.patch(
                    'paasta_tools.chronos_tools.load_chronos_job_config',
                    return_value=self.fake_chronos_job_config,
                    autospec=True),
                mock.patch('paasta_tools.chronos_tools.create_complete_config',
                           return_value=fake_complete_job_config,
                           autospec=True),
                mock.patch('setup_chronos_job.setup_job',
                           return_value=(expected_status, expected_output),
                           autospec=True),
                mock.patch('setup_chronos_job.send_event', autospec=True),
                mock.patch('setup_chronos_job.load_system_paasta_config',
                           autospec=True),
                mock.patch('sys.exit', autospec=True),
        ) as (
                parse_args_patch,
                load_chronos_config_patch,
                get_client_patch,
                load_chronos_job_config_patch,
                create_complete_config_patch,
                setup_job_patch,
                send_event_patch,
                load_system_paasta_config_patch,
                sys_exit_patch,
        ):
            load_system_paasta_config_patch.return_value.get_cluster = mock.MagicMock(
                return_value=self.fake_cluster)
            setup_chronos_job.main()

            parse_args_patch.assert_called_once_with()
            get_client_patch.assert_called_once_with(
                load_chronos_config_patch.return_value)
            load_chronos_job_config_patch.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                soa_dir=self.fake_args.soa_dir,
            )
            setup_job_patch.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                chronos_job_config=self.fake_chronos_job_config,
                complete_job_config=fake_complete_job_config,
                client=self.fake_client,
                cluster=self.fake_cluster,
            )
            send_event_patch.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                soa_dir=self.fake_args.soa_dir,
                status=expected_status,
                output=expected_output,
            )
            sys_exit_patch.assert_called_once_with(0)

    def test_main_no_deployments(self):
        with contextlib.nested(
                mock.patch('setup_chronos_job.parse_args',
                           return_value=self.fake_args,
                           autospec=True),
                mock.patch('paasta_tools.chronos_tools.load_chronos_config',
                           autospec=True),
                mock.patch('paasta_tools.chronos_tools.get_chronos_client',
                           return_value=self.fake_client,
                           autospec=True),
                mock.patch(
                    'paasta_tools.chronos_tools.load_chronos_job_config',
                    return_value=self.fake_chronos_job_config,
                    autospec=True,
                    side_effect=NoDeploymentsAvailable),
                mock.patch('setup_chronos_job.setup_job',
                           return_value=(0, 'it_is_finished'),
                           autospec=True),
                mock.patch('setup_chronos_job.load_system_paasta_config',
                           autospec=True),
                mock.patch('setup_chronos_job.send_event', autospec=True),
        ) as (parse_args_patch, load_chronos_config_patch, get_client_patch,
              load_chronos_job_config_patch, setup_job_patch,
              load_system_paasta_config_patch, send_event_patch):
            load_system_paasta_config_patch.return_value.get_cluster = mock.MagicMock(
                return_value=self.fake_cluster)
            with raises(SystemExit) as excinfo:
                setup_chronos_job.main()
            assert excinfo.value.code == 0

    def test_main_bad_chronos_job_config_notifies_user(self):
        with contextlib.nested(
                mock.patch('setup_chronos_job.parse_args',
                           return_value=self.fake_args,
                           autospec=True),
                mock.patch('paasta_tools.chronos_tools.load_chronos_config',
                           autospec=True),
                mock.patch('paasta_tools.chronos_tools.get_chronos_client',
                           return_value=self.fake_client,
                           autospec=True),
                mock.patch(
                    'paasta_tools.chronos_tools.load_chronos_job_config',
                    return_value=self.fake_chronos_job_config,
                    autospec=True,
                    side_effect=chronos_tools.InvalidChronosConfigError(
                        'test bad configuration')),
                mock.patch('setup_chronos_job.setup_job',
                           return_value=(0, 'it_is_finished'),
                           autospec=True),
                mock.patch('setup_chronos_job.load_system_paasta_config',
                           autospec=True),
                mock.patch('setup_chronos_job.send_event', autospec=True),
        ) as (
                parse_args_patch,
                load_chronos_config_patch,
                get_client_patch,
                load_chronos_job_config_patch,
                setup_job_patch,
                load_system_paasta_config_patch,
                send_event_patch,
        ):
            load_system_paasta_config_patch.return_value.get_cluster = mock.MagicMock(
                return_value=self.fake_cluster)
            with raises(SystemExit) as excinfo:
                setup_chronos_job.main()
            assert excinfo.value.code == 0
            expected_error_msg = (
                "Could not read chronos configuration file for %s in cluster %s\nError was: test bad configuration"
                % (compose_job_id(self.fake_service,
                                  self.fake_instance), self.fake_cluster))
            send_event_patch.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                soa_dir=self.fake_args.soa_dir,
                status=Status.CRITICAL,
                output=expected_error_msg)

    def test_setup_job_new_app_with_no_previous_jobs(self):
        fake_existing_jobs = []
        with contextlib.nested(
                mock.patch('setup_chronos_job.bounce_chronos_job',
                           autospec=True,
                           return_value=(0, 'ok')),
                mock.patch('paasta_tools.chronos_tools.lookup_chronos_jobs',
                           autospec=True),
                mock.patch('paasta_tools.chronos_tools.sort_jobs',
                           autospec=True,
                           return_value=fake_existing_jobs),
                mock.patch(
                    'paasta_tools.chronos_tools.load_system_paasta_config',
                    autospec=True),
                mock.patch(
                    'paasta_tools.chronos_tools.load_chronos_job_config',
                    autospec=True,
                    return_value=self.fake_chronos_job_config),
        ) as (
                mock_bounce_chronos_job,
                lookup_chronos_jobs_patch,
                sort_jobs_patch,
                load_system_paasta_config_patch,
                load_chronos_job_config_patch,
        ):
            load_system_paasta_config_patch.return_value.get_cluster.return_value = self.fake_cluster
            complete_config = chronos_tools.create_complete_config(
                service=self.fake_service,
                job_name=self.fake_instance,
                soa_dir=self.fake_args.soa_dir)
            actual = setup_chronos_job.setup_job(
                service=self.fake_service,
                instance=self.fake_instance,
                chronos_job_config=self.fake_chronos_job_config,
                complete_job_config=complete_config,
                client=self.fake_client,
                cluster=self.fake_cluster,
            )
            mock_bounce_chronos_job.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                jobs_to_delete=[],
                jobs_to_disable=[],
                job_to_create=complete_config,
                client=self.fake_client,
            )
            assert actual == mock_bounce_chronos_job.return_value

    def test_setup_job_with_previously_enabled_job(self):
        fake_existing_job = {
            'name': 'fake_job',
            'disabled': False,
        }
        with contextlib.nested(
                mock.patch('setup_chronos_job.bounce_chronos_job',
                           autospec=True,
                           return_value=(0, 'ok')),
                mock.patch('paasta_tools.chronos_tools.lookup_chronos_jobs',
                           autospec=True),
                mock.patch('paasta_tools.chronos_tools.sort_jobs',
                           autospec=True,
                           return_value=[fake_existing_job]),
                mock.patch(
                    'paasta_tools.chronos_tools.load_system_paasta_config',
                    autospec=True),
                mock.patch(
                    'paasta_tools.chronos_tools.load_chronos_job_config',
                    autospec=True,
                    return_value=self.fake_chronos_job_config),
        ) as (
                mock_bounce_chronos_job,
                mock_lookup_chronos_jobs,
                mock_sort_jobs,
                load_system_paasta_config_patch,
                load_chronos_job_config_patch,
        ):
            load_system_paasta_config_patch.return_value.get_cluster.return_value = self.fake_cluster
            complete_config = chronos_tools.create_complete_config(
                service=self.fake_service,
                job_name=self.fake_instance,
                soa_dir=self.fake_args.soa_dir)
            actual = setup_chronos_job.setup_job(
                service=self.fake_service,
                instance=self.fake_instance,
                chronos_job_config=self.fake_chronos_job_config,
                complete_job_config=complete_config,
                client=self.fake_client,
                cluster=self.fake_cluster,
            )
            mock_bounce_chronos_job.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                jobs_to_delete=[],
                jobs_to_disable=[fake_existing_job],
                job_to_create=complete_config,
                client=self.fake_client,
            )
            assert mock_lookup_chronos_jobs.called
            assert actual == mock_bounce_chronos_job.return_value

    def test_setup_job_does_nothing_with_only_existing_app(self):
        fake_existing_job = self.fake_config_dict
        with contextlib.nested(
                mock.patch('setup_chronos_job.bounce_chronos_job',
                           autospec=True,
                           return_value=(0, 'ok')),
                mock.patch('paasta_tools.chronos_tools.lookup_chronos_jobs',
                           autospec=True),
                mock.patch('paasta_tools.chronos_tools.sort_jobs',
                           autospec=True,
                           return_value=[fake_existing_job]),
                mock.patch(
                    'paasta_tools.chronos_tools.load_system_paasta_config',
                    autospec=True),
                mock.patch(
                    'paasta_tools.chronos_tools.load_chronos_job_config',
                    autospec=True,
                    return_value=self.fake_chronos_job_config),
        ) as (
                mock_bounce_chronos_job,
                mock_lookup_chronos_jobs,
                mock_sort_jobs,
                load_system_paasta_config_patch,
                load_chronos_job_config_patch,
        ):
            load_system_paasta_config_patch.return_value.get_cluster.return_value = self.fake_cluster
            complete_config = chronos_tools.create_complete_config(
                service=self.fake_service,
                job_name=self.fake_instance,
                soa_dir=self.fake_args.soa_dir)
            # Force the complete_config's name to match the return value of
            # lookup_chronos_jobs to simulate that they have the same name
            complete_config["name"] = fake_existing_job["name"]
            actual = setup_chronos_job.setup_job(
                service=self.fake_service,
                instance=self.fake_instance,
                chronos_job_config=self.fake_chronos_job_config,
                complete_job_config=complete_config,
                client=self.fake_client,
                cluster=self.fake_cluster,
            )
            mock_bounce_chronos_job.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                jobs_to_delete=[],
                jobs_to_disable=[],
                job_to_create=None,
                client=self.fake_client,
            )
            assert mock_lookup_chronos_jobs.called
            assert actual == mock_bounce_chronos_job.return_value

    def test_send_event(self):
        fake_status = '42'
        fake_output = 'something went wrong'
        fake_soa_dir = ''
        expected_check_name = 'setup_chronos_job.%s' % compose_job_id(
            self.fake_service, self.fake_instance)
        with contextlib.nested(
                mock.patch("paasta_tools.monitoring_tools.send_event",
                           autospec=True),
                mock.patch(
                    "paasta_tools.chronos_tools.load_chronos_job_config",
                    autospec=True),
                mock.patch("setup_chronos_job.load_system_paasta_config",
                           autospec=True),
        ) as (
                mock_send_event,
                mock_load_chronos_job_config,
                mock_load_system_paasta_config,
        ):
            mock_load_system_paasta_config.return_value.get_cluster = mock.Mock(
                return_value='fake_cluster')
            mock_load_chronos_job_config.return_value.get_monitoring.return_value = {}

            setup_chronos_job.send_event(
                service=self.fake_service,
                instance=self.fake_instance,
                soa_dir=fake_soa_dir,
                status=fake_status,
                output=fake_output,
            )
            mock_send_event.assert_called_once_with(
                service=self.fake_service,
                check_name=expected_check_name,
                overrides={
                    'alert_after': '10m',
                    'check_every': '10s'
                },
                status=fake_status,
                output=fake_output,
                soa_dir=fake_soa_dir)
            mock_load_chronos_job_config.assert_called_once_with(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=mock_load_system_paasta_config.return_value.
                get_cluster.return_value,
                soa_dir=fake_soa_dir,
            )

    def test_bounce_chronos_job_takes_actions(self):
        fake_jobs_to_disable = [{'name': 'job_to_disable'}]
        fake_jobs_to_delete = [{'name': 'job_to_delete'}]
        fake_job_to_create = {'name': 'job_to_create'}
        with contextlib.nested(
                mock.patch("setup_chronos_job._log", autospec=True),
                mock.patch("paasta_tools.chronos_tools.disable_job",
                           autospec=True),
                mock.patch("paasta_tools.chronos_tools.delete_job",
                           autospec=True),
                mock.patch("paasta_tools.chronos_tools.create_job",
                           autospec=True),
        ) as (
                mock_log,
                mock_disable_job,
                mock_delete_job,
                mock_create_job,
        ):
            setup_chronos_job.bounce_chronos_job(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                jobs_to_disable=fake_jobs_to_disable,
                jobs_to_delete=fake_jobs_to_delete,
                job_to_create=fake_job_to_create,
                client=self.fake_client,
            )
            mock_log.assert_any_call(
                line=mock.ANY,
                level='debug',
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                component='deploy',
                service=self.fake_service,
            )
            mock_log.assert_any_call(
                line="Created new Chronos job: job_to_create",
                level='event',
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                component='deploy',
                service=self.fake_service,
            )
            mock_disable_job.assert_called_once_with(
                job=fake_jobs_to_disable[0], client=self.fake_client)
            mock_delete_job.assert_called_once_with(job=fake_jobs_to_delete[0],
                                                    client=self.fake_client)
            mock_create_job.assert_called_once_with(job=fake_job_to_create,
                                                    client=self.fake_client)

    def test_bounce_chronos_job_doesnt_log_when_nothing_to_do(self):
        fake_jobs_to_disable = []
        fake_jobs_to_delete = []
        fake_job_to_create = []
        with contextlib.nested(
                mock.patch("setup_chronos_job._log", autospec=True),
                mock.patch("paasta_tools.chronos_tools.disable_job",
                           autospec=True),
                mock.patch("paasta_tools.chronos_tools.delete_job",
                           autospec=True),
                mock.patch("paasta_tools.chronos_tools.create_job",
                           autospec=True),
        ) as (
                mock_log,
                mock_disable_job,
                mock_delete_job,
                mock_create_job,
        ):
            setup_chronos_job.bounce_chronos_job(
                service=self.fake_service,
                instance=self.fake_instance,
                cluster=self.fake_cluster,
                jobs_to_disable=fake_jobs_to_disable,
                jobs_to_delete=fake_jobs_to_delete,
                job_to_create=fake_job_to_create,
                client=self.fake_client,
            )
            assert not mock_log.called
            assert not mock_disable_job.called
            assert not mock_delete_job.called
            assert not mock_create_job.called