def test_shove_instances(self): instance1 = ShoveInstanceFactory.create(hostname='foo', active=True) instance2 = ShoveInstanceFactory.create(hostname='bar', active=True) ShoveInstanceFactory.create(hostname='baz', active=False) command = ScheduledCommandFactory(hostnames='foo,bar,baz') assert_equal(set(command.shove_instances), set([instance1, instance2]))
def test_run(self): instance1 = ShoveInstanceFactory.create(hostname='foo', active=True) instance2 = ShoveInstanceFactory.create(hostname='bar', active=True) command = ScheduledCommandFactory(command='asdf', hostnames='foo,bar') command.project.send_command = Mock() with patch('captain.projects.models.timezone') as mock_timezone: now = aware_datetime(2014, 1, 1, 1, 1, 1) mock_timezone.now.return_value = now command.run() assert_equal(command.last_run, now) command.project.send_command.assert_called_with(None, 'asdf', CONTAINS(instance1, instance2))
def test_clean_hostnames(self): """ The cleaned hostname value should be a comma-separated list of hostnames of the selected ShoveInstances. """ project = ProjectFactory.create() instance1 = ShoveInstanceFactory.create(hostname='foo.bar') instance2 = ShoveInstanceFactory.create(hostname='baz.biff') project.shove_instances.add(instance1) project.shove_instances.add(instance2) form = CreateScheduledCommandForm({ 'command': 'test', 'hostnames': [instance1.pk, instance2.pk], }, project=project) form.is_valid() hostnames = form.cleaned_data['hostnames'].split(',') assert_equal(set(hostnames), set(['foo.bar', 'baz.biff']))
def test_inactive_thread_mark_inactive_shoves(self): """ mark_inactive_shoves should find any ShoveInstances with a last_heartbeat older than the HEARTBEAT_INACTIVE_DELAY setting and mark them as inactive. """ up_to_date_instance = ShoveInstanceFactory.create( last_heartbeat=aware_datetime(2014, 1, 1, 10, 0, 0), active=True) out_of_date_instance = ShoveInstanceFactory.create( last_heartbeat=aware_datetime(2014, 1, 1, 9, 30, 0), active=True) thread = monitor_shove_instances.MarkInactiveShoveInstancesThread() with self.settings(HEARTBEAT_INACTIVE_DELAY=10*60): with patch.object(monitor_shove_instances, 'timezone') as mock_timezone: mock_timezone.now.return_value = aware_datetime(2014, 1, 1, 10, 5, 0) thread.mark_inactive_shoves() assert_equal(ShoveInstance.objects.get(pk=up_to_date_instance.pk).active, True) assert_equal(ShoveInstance.objects.get(pk=out_of_date_instance.pk).active, False)
def test_send_command(self): project = ProjectFactory.create(project_name='myproject') instance = ShoveInstanceFactory.create(active=True, routing_key='route') project.shove_instances.add(instance) sent_command = SentCommandFactory.create(command='asdf') with patch('captain.projects.models.shove') as shove: log = instance.send_command(project, sent_command) shove.send_command.assert_called_with('route', 'myproject', 'asdf', log.pk) assert_equal(log.shove_instance, instance) assert_equal(log.sent_command, sent_command)
def test_non_whitespace_command(self): """If a command has non-whitespace characters, the form should be valid.""" project = ProjectFactory.create() shove_instance = ShoveInstanceFactory.create() project.shove_instances.add(shove_instance) form_data = { 'command': ' whitespace but not blank ', 'shove_instances': [shove_instance.pk] } form = RunCommandForm(form_data, project=project) assert_true(form.is_valid())
def test_handle_heartbeat_remove_projects(self): """Remove any old projects not in the project_names list.""" instance = ShoveInstanceFactory.create(routing_key='asdf') project1 = ProjectFactory.create(project_name='foo') project2 = ProjectFactory.create(project_name='bar') instance.projects.add(project1) monitor_shove_instances.handle_heartbeat_event({ 'routing_key': 'asdf', 'hostname': 'paranoia.local', 'project_names': 'bar,baz', }) instance = ShoveInstance.objects.get(routing_key='asdf') assert_equal(list(instance.projects.all()), [project2])
def test_valid_command(self, get_object): """ If the user submits a valid command, send it to shove and redirect back to the project. """ # Mock send_command on the project returned by get_object to inject it into the view. self.project.send_command = Mock() get_object.return_value = self.project instance1, instance2 = ShoveInstanceFactory.create_batch(2, active=True) self.project.shove_instances.add(instance1, instance2) user = self._login_user(True) response = self._run_command(command='blah', shove_instances=[instance1.pk, instance2.pk]) self.assertRedirects(response, self.project.get_absolute_url()) self.project.send_command.assert_called_once_with(user, 'blah', CONTAINS(instance1, instance2))
def test_handle_heartbeat_existing_shove_instance(self): """ If a shove instance for the given routing key already exists, update it with the latest hostname and projects. """ instance = ShoveInstanceFactory.create(routing_key='asdf', hostname='old.local') project1 = ProjectFactory.create(project_name='foo') monitor_shove_instances.handle_heartbeat_event({ 'routing_key': 'asdf', 'hostname': 'paranoia.local', 'project_names': 'foo', }) instance = ShoveInstance.objects.get(pk=instance.pk) assert_equal(instance.hostname, 'paranoia.local') assert_equal(list(instance.projects.all()), [project1])
def test_send_command_no_user(self): """ If None is passed in as the user, do not perform any permission checks and run the command. """ project = ProjectFactory.create(project_name='blah') instance = ShoveInstanceFactory.create(active=True) project.shove_instances.add(instance) with patch.object(ShoveInstance, 'send_command', autospec=True) as send_command: sent_command = project.send_command(None, 'asdf', [instance]) send_command.assert_called_with(instance, project, sent_command) assert_equal(sent_command.project, project) assert_equal(sent_command.user, None) assert_equal(sent_command.command, 'asdf')
def test_whitespace_command(self): """If a command consists only of whitespace, the form should be invalid.""" project = ProjectFactory.create() shove_instance = ShoveInstanceFactory.create() project.shove_instances.add(shove_instance) form = RunCommandForm({'command': ' ', 'shove_instances': [shove_instance.pk]}, project=project) assert_false(form.is_valid()) form = RunCommandForm({'command': '\t\t', 'shove_instances': [shove_instance.pk]}, project=project) assert_false(form.is_valid()) form = RunCommandForm({'command': '\n\n\n\n', 'shove_instances': [shove_instance.pk]}, project=project) assert_false(form.is_valid())
def test_send_command_has_permission(self): """ If the user has permission to run a command for this project, send the command to shove and create a sent command for it. """ user = UserFactory.create() project = ProjectFactory.create(project_name='blah') assign_perm('can_run_commands', user, project) instance1, instance2 = ShoveInstanceFactory.create_batch(2, active=True) project.shove_instances.add(instance1, instance2) with patch.object(ShoveInstance, 'send_command', autospec=True) as send_command: sent_command = project.send_command(user, 'asdf', [instance1, instance2]) send_command.assert_has_calls([call(instance1, project, sent_command), call(instance2, project, sent_command)], any_order=True) assert_equal(sent_command.project, project) assert_equal(sent_command.user, user) assert_equal(sent_command.command, 'asdf')
def test_send_command_inactive_shoves(self): """ If any of the shove instances given are not in the set of active shove instances for this project, raise a ValueError. """ user = UserFactory.create() project = ProjectFactory.create() assign_perm('can_run_commands', user, project) instance1, instance2 = ShoveInstanceFactory.create_batch(2, active=True) project.shove_instances.add(instance1) with assert_raises(ValueError): project.send_command(user, 'asdf', [instance1, instance2]) # Now try with an inactive instance that is part of the # project's instances. instance2.active = False instance2.save() project.shove_instances.add(instance2) with assert_raises(ValueError): project.send_command(user, 'asdf', [instance1, instance2])
def setUp(self): self.project = ProjectFactory.create() self.shove_instances = ShoveInstanceFactory.create_batch(2) self.project.shove_instances.add(*self.shove_instances) self.url = reverse('projects.details.schedule', args=(self.project.pk,))