Beispiel #1
0
    def test_repeat_scheduling(self):
        self.mock_result.stdout = 'Maybe Certbot got updated'
        subdomain1 = Subdomain('unknown-1', 'unit.test')
        subdomain2 = Subdomain('unknown-2', 'unit.test')

        self.assertTrue(self.manager.needs_update(subdomain1))
        result = self.manager.update(subdomain1)
        self.assertEqual(result, 'Unknown')

        self.assertTrue(self.manager.needs_update(subdomain2))
        result = self.manager.update(subdomain2)
        self.assertEqual(result, 'Unknown')

        self.assertFalse(self.manager.needs_update(subdomain1))
        self.assertFalse(self.manager.needs_update(subdomain2))

        self.manager.last_run[subdomain1.full] = datetime.now() - timedelta(
            seconds=6 * 60 * 60)

        self.assertFalse(self.manager.needs_update(subdomain1))
        self.assertFalse(self.manager.needs_update(subdomain2))

        self.manager.last_run[subdomain1.full] = datetime.now() - timedelta(
            days=0.5, seconds=30)

        self.assertTrue(self.manager.needs_update(subdomain1))
        result = self.manager.update(subdomain1)
        self.assertEqual(result, 'Unknown')

        self.assertFalse(self.manager.needs_update(subdomain1))
Beispiel #2
0
    def _to_subdomain(self, name):
        if name == self.default_domain:
            return Subdomain('', self.default_domain)

        elif name.endswith(self.default_domain):
            return Subdomain(name.replace('.%s' % self.default_domain, ''), self.default_domain)

        else:
            return Subdomain(name, self.default_domain)
Beispiel #3
0
    def test_update(self):
        self.cf.zones.dns_records.base = 'sample.com'
        self.cf.zones.items.append({'id': 'abcd1234', 'name': 'sample.com'})

        result = self.manager.update(Subdomain('mock', 'sample.com'),
                                     '8.8.4.4')

        self.assertEqual('OK, created [8.8.4.4]', result)

        result = self.manager.update(Subdomain('mock', 'sample.com'),
                                     '8.8.8.8')

        self.assertEqual('OK, updated [8.8.8.8]', result)
Beispiel #4
0
    def test_new_certificate(self):
        self.mock_result.stdout = 'Congratulations! It worked!'
        self.mock_result.stderr = 'Obtaining a new certificate'

        result = self.manager.update(Subdomain('new-domain', 'unit.test'))

        self.assertEqual(result, 'OK, new certificate')

        self.assertIn('certbot certonly -n --keep',
                      ' '.join(self.mock_result.args))
        self.assertIn('-d new-domain.unit.test',
                      ' '.join(self.mock_result.args))
        self.assertIn('--email [email protected]',
                      ' '.join(self.mock_result.args))
        self.assertIn('--dns-cloudflare', ' '.join(self.mock_result.args))
        self.assertIn('--dns-cloudflare-credentials .cloudflare.ini',
                      ' '.join(self.mock_result.args))
        self.assertIn('--dns-cloudflare-propagation-seconds 30',
                      ' '.join(self.mock_result.args))

        self.assertIn(('timeout', 120), self.mock_result.kwargs.items())
        self.assertIn(('stdout', subprocess.PIPE),
                      self.mock_result.kwargs.items())
        self.assertIn(('stderr', subprocess.PIPE),
                      self.mock_result.kwargs.items())

        self.assertNotIn('--staging', self.mock_result.args)
Beispiel #5
0
    def test_unknown_result(self):
        self.mock_result.stdout = 'Maybe Certbot got updated'

        result = self.manager.update(Subdomain('unknown', 'unit.test'))

        self.assertEqual(result, 'Unknown')
        self.assertIn('-d unknown.unit.test', ' '.join(self.mock_result.args))
    def test_give_up_retries(self):
        self.client.response = {'ok': False, 'headers': {'Retry-After': '3'}}

        # slack_message.time.sleep = lambda x: x
        slack_message.threading.Timer = MockTimer

        message = '`[DNS update]` *give.up.update.test* : Failing'

        with self.assertLogs('slack-notification', 'DEBUG') as logs:
            self.manager.dns_updated(Subdomain('give.up', 'update.test'),
                                     'Failing')

        self.client.assert_call('chat.postMessage',
                                channel='unittest',
                                text=message,
                                as_user=False,
                                username='******')

        self.assertEqual(len(logs.output), 4)

        for idx in range(3):
            self.assertEqual(
                logs.output[idx],
                'DEBUG:slack-notification:Retrying Slack message after 3 seconds'
            )

        self.assertEqual(
            logs.output[3],
            'ERROR:slack-notification:Giving up on Slack message: %s' %
            message)
Beispiel #7
0
    def test_not_yet_due_for_renewal(self):
        self.mock_result.stdout = 'The certificate is not yet due for renewal, skipping.'

        result = self.manager.update(Subdomain('still-valid', 'unit.test'))

        self.assertEqual(result, 'Not yet due for renewal')
        self.assertIn('-d still-valid.unit.test',
                      ' '.join(self.mock_result.args))
    def test_failing_swarm_mode(self):
        self.client.swarm_mode = True
        self.manager.label_name = 'test.failing'

        self.manager.ssl_updated(Subdomain('swarm'), 'Failed')
        self.assertIsNone(self.client.service)

        docker_signal.get_current_container_id = lambda: None

        self.manager.ssl_updated(Subdomain('swarm'), 'OK')
        self.assertIsNone(self.client.service)

        docker_signal.get_current_container_id = lambda: 'c-self'

        self.manager.ssl_updated(Subdomain('swarm'), 'OK')
        self.assertIsNone(self.client.service)

        self.client.items.append(MockContainer('c-self', 'own-container'))

        self.manager.ssl_updated(Subdomain('swarm'), 'OK')
        self.assertIsNone(self.client.service)

        self.client.items[0].image = 'test/image'
        self.client.tasks.append({
            'DesiredState': 'shutdown',
            'Status': {
                'State': 'failed'
            }
        })

        self.client.service_logs[:] = ['failed to send signal']

        with self.assertLogs('docker-signal', level='INFO') as logs:
            self.manager.ssl_updated(Subdomain('swarm'), 'OK')

        self.assertEqual(len(logs.output), 2)
        self.assertEqual(
            logs.output[0],
            'INFO:docker-signal:Signalled containers with label %s - result: %s'
            % ('test.failing', 'failed'))
        self.assertEqual(
            logs.output[1],
            'INFO:docker-signal:Signal logs: %s' % 'failed to send signal')

        self.assertIsNotNone(self.client.service)
Beispiel #9
0
    def test_existing_certificate(self):
        self.mock_result.stdout = 'Congratulations! It worked!'
        self.mock_result.stderr = 'Renewing an existing certificate'

        result = self.manager.update(Subdomain('existing-domain', 'unit.test'))

        self.assertEqual(result, 'OK, renewed')
        self.assertIn('-d existing-domain.unit.test',
                      ' '.join(self.mock_result.args))
    def test_update_non_swarm(self):
        self.client.swarm_mode = False
        self.client.items.extend([
            MockContainer('c1', 'container-term', {'test.label': 'TERM'}),
            MockContainer('c2', 'container-kill', {'test.label': 'KILL'})
        ])

        self.manager.ssl_updated(Subdomain('test'), 'OK')

        self.assertEqual(self.client.items[0].killed_with, 'TERM')
        self.assertEqual(self.client.items[1].killed_with, 'KILL')
    def test_update_swarm_mode(self):
        self.client.swarm_mode = True

        container = MockContainer('c-self', 'test-automation-container')
        container.image = 'domain/automation'
        container.log_driver = 'custom'
        container.log_config = {'x-opt': 'abcd'}

        self.client.items.append(container)
        self.client.tasks.append({
            'DesiredState': 'running',
            'Status': {
                'State': 'running'
            }
        })

        docker_signal.get_current_container_id = lambda: 'c-self'

        def mock_sleep(seconds):
            # change the task state instead
            self.client.tasks[0]['DesiredState'] = 'shutdown'
            self.client.tasks[0]['Status']['State'] = 'complete'

        docker_signal.time.sleep = mock_sleep

        self.manager.label_name = 'test.label'

        with self.assertLogs('docker-signal', level='INFO') as logs:
            self.manager.ssl_updated(Subdomain('swarm'), 'OK')

        self.assertIsNotNone(self.client.service)
        self.assertEqual(self.client.service.image, 'domain/automation')
        self.assertEqual(self.client.service.command[-2:],
                         ['--label', 'test.label'])
        self.assertIn('domain-automation-', self.client.service.name)
        self.assertGreater(len(self.client.service.env), 0)
        self.assertIn('PYTHONPATH=', self.client.service.env[0])
        self.assertEqual(self.client.service.log_driver, 'custom')
        self.assertEqual(self.client.service.log_driver_options,
                         {'x-opt': 'abcd'})
        self.assertEqual(self.client.service.mode.mode, 'global')
        self.assertEqual(self.client.service.restart_policy['Condition'],
                         'none')
        self.assertEqual(self.client.service.restart_policy['MaxAttempts'], 0)
        self.assertTrue(self.client.service.removed)

        self.assertEqual(len(logs.output), 2)
        self.assertEqual(
            logs.output[0],
            'INFO:docker-signal:Signalled containers with label %s - result: %s'
            % ('test.label', 'complete'))
        self.assertEqual(
            logs.output[1],
            'INFO:docker-signal:Signal logs: %s' % 'output-1\noutput-2')
Beispiel #12
0
    def test_current_ip(self):
        self.cf.zones.items.append({'id': 'abcd1234', 'name': 'sample.com'})
        self.cf.zones.dns_records.records['abcd1234'] = [{
            'zone_id': 'abcd1234',
            'type': 'A',
            'name': 'test.sample.com',
            'content': '9.9.9.9'
        }]

        address = self.manager.get_current_ip(Subdomain('test', 'sample.com'))

        self.assertIsNotNone(address)
        self.assertEqual(address, '9.9.9.9')
    def test_dns_update(self):
        message = '`[DNS update]` *dns.update.test* : OK, test'

        with self.assertLogs('slack-notification', 'DEBUG') as logs:
            self.manager.dns_updated(Subdomain('dns', 'update.test'),
                                     'OK, test')

        self.client.assert_call('chat.postMessage',
                                channel='unittest',
                                text=message,
                                as_user=False,
                                username='******')

        self.assertEqual(len(logs.output), 1)
        self.assertEqual(
            logs.output[0],
            'INFO:slack-notification:Slack message sent: %s' % message)
    def test_retry_once(self):
        original_send_message = self.manager.send_message

        def send_message(*args, **kwargs):
            if kwargs.get('retry', 1) > 1:
                self.client.response = {'ok': True}
            else:
                self.client.response = {
                    'ok': False,
                    'headers': {
                        'Retry-After': '12'
                    }
                }

            original_send_message(*args, **kwargs)

        self.manager.send_message = send_message

        # slack_message.time.sleep = lambda x: x
        slack_message.threading.Timer = MockTimer

        message = '`[DNS update]` *retry.update.test* : With retries'

        with self.assertLogs('slack-notification', 'DEBUG') as logs:
            self.manager.dns_updated(Subdomain('retry', 'update.test'),
                                     'With retries')

        self.client.assert_call('chat.postMessage',
                                channel='unittest',
                                text=message,
                                as_user=False,
                                username='******')

        self.assertEqual(len(logs.output), 2)
        self.assertEqual(
            logs.output[0],
            'DEBUG:slack-notification:Retrying Slack message after 12 seconds')
        self.assertEqual(
            logs.output[1],
            'INFO:slack-notification:Slack message sent: %s' % message)
Beispiel #15
0
    def test_failing_certbot(self):
        self.mock_result.returncode = 1

        result = self.manager.update(Subdomain('failing.unit.test'))

        self.assertEqual(result, 'Failed with exit code: 1')
Beispiel #16
0
    def test_use_staging_servers(self):
        self.manager.use_staging = True

        self.manager.update(Subdomain('staging', 'unit.test'))

        self.assertIn('--staging', self.mock_result.args)
    def test_skip_ssl_notification(self):
        self.manager.ssl_updated(Subdomain('skip', 'cert.renewal'),
                                 SSLManager.RESULT_NOT_YET_DUE_FOR_RENEWAL)

        self.assertIsNone(self.client.last_call)