def test_simple_successful_create_job(self):
    """Run a test of the "create" command against a mocked-out API:
    Verifies that the creation command sends the right API RPCs, and performs the correct
    tests on the result."""

    # We'll patch out create_context, which will give us a fake context
    # object, and everything can be stubbed through that.
    mock_context = FakeAuroraCommandContext()
    with patch('twitter.aurora.client.cli.jobs.Job.create_context', return_value=mock_context):
      # After making the client, create sets up a job monitor.
      # The monitor uses TaskQuery to get the tasks. It's called at least twice:once before
      # the job is created, and once after. So we need to set up mocks for the query results.
      mock_query = self.create_mock_query()
      mock_context.add_expected_status_query_result(
        self.create_mock_status_query_result(ScheduleStatus.INIT))
      mock_context.add_expected_status_query_result(
        self.create_mock_status_query_result(ScheduleStatus.RUNNING))
      api = mock_context.get_api('west')
      api.create_job.return_value = self.get_createjob_response()

      # This is the real test: invoke create as if it had been called by the command line.
      with temporary_file() as fp:
        fp.write(self.get_valid_config())
        fp.flush()
        cmd = AuroraCommandLine()
        cmd.execute(['job', 'create', '--wait_until=RUNNING', 'west/mchucarroll/test/hello',
            fp.name])

      # Now check that the right API calls got made.
      # Check that create_job was called exactly once, with an AuroraConfig parameter.
      self.assert_create_job_called(api)
      self.assert_scheduler_called(api, mock_query, 2)
  def test_create_job_failed(self):
    """Run a test of the "create" command against a mocked-out API:
    this time, make the monitor check status several times before successful completion.
    """
    mock_context = FakeAuroraCommandContext()
    with patch('twitter.aurora.client.cli.jobs.Job.create_context', return_value=mock_context):
      mock_context.add_expected_status_query_result(
          self.create_mock_status_query_result(ScheduleStatus.INIT))
      api = mock_context.get_api('west')
      api.create_job.return_value = self.get_failed_createjob_response()
      # This is the real test: invoke create as if it had been called by the command line.
      with temporary_file() as fp:
        fp.write(self.get_valid_config())
        fp.flush()
        cmd = AuroraCommandLine()
        result = cmd.execute(['job', 'create', '--wait_until=RUNNING',
            'west/mchucarroll/test/hello', fp.name])
        assert result == EXIT_NETWORK_ERROR

      # Now check that the right API calls got made.
      # Check that create_job was called exactly once, with an AuroraConfig parameter.
      self.assert_create_job_called(api)

      # getTasksStatus was called once, before the create_job
      assert api.scheduler.getTasksStatus.call_count == 1
  def test_create_job_failed_invalid_config(self):
    """Run a test of the "create" command against a mocked-out API, with a configuration
    containing a syntax error"""
    mock_context = FakeAuroraCommandContext()
    with patch('twitter.aurora.client.cli.jobs.Job.create_context', return_value=mock_context):
      with temporary_file() as fp:
        fp.write(self.get_invalid_config('invalid_clause=oops'))
        fp.flush()
        cmd = AuroraCommandLine()
        result = cmd.execute(['job', 'create', '--wait_until=RUNNING',
            'west/mchucarroll/test/hello', fp.name])
        assert result == EXIT_INVALID_CONFIGURATION

      # Now check that the right API calls got made.
      # Check that create_job was not called.
      api = mock_context.get_api('west')
      assert api.create_job.call_count == 0
      assert api.scheduler.getTasksStatus.call_count == 0
 def test_kill_job_with_instances_deep_api(self):
   """Test kill client-side API logic."""
   mock_context = FakeAuroraCommandContext()
   (mock_api, mock_scheduler) = self.setup_mock_api()
   with contextlib.nested(
       patch('twitter.aurora.client.api.SchedulerProxy', return_value=mock_scheduler),
       patch('twitter.aurora.client.factory.CLUSTERS', new=self.TEST_CLUSTERS)):
     mock_scheduler.killTasks.return_value = self.get_kill_job_response()
     with temporary_file() as fp:
       fp.write(self.get_valid_config())
       fp.flush()
       cmd = AuroraCommandLine()
       cmd.execute(['job', 'kill', '--config=%s' % fp.name, '--instances=0,2,4-6',
          'west/mchucarroll/test/hello'])
     # Now check that the right API calls got made.
     assert mock_scheduler.killTasks.call_count == 1
     mock_scheduler.killTasks.assert_called_with(
       TaskQuery(jobName='hello', environment='test', instanceIds=frozenset([0, 2, 4, 5, 6]),
           owner=Identity(role='mchucarroll')), None)
  def test_kill_job_with_instances(self):
    """Test kill client-side API logic."""
    mock_context = FakeAuroraCommandContext()
    with contextlib.nested(
        patch('twitter.aurora.client.cli.jobs.Job.create_context', return_value=mock_context),
        patch('twitter.aurora.client.factory.CLUSTERS', new=self.TEST_CLUSTERS)):
      api = mock_context.get_api('west')
      api.kill_job.return_value = self.get_kill_job_response()
      with temporary_file() as fp:
        fp.write(self.get_valid_config())
        fp.flush()
        cmd = AuroraCommandLine()
        cmd.execute(['job', 'kill', '--config=%s' % fp.name, '--instances=0,2,4-6',
           'west/mchucarroll/test/hello'])

      # Now check that the right API calls got made.
      assert api.kill_job.call_count == 1
      api.kill_job.assert_called_with(AuroraJobKey.from_path('west/mchucarroll/test/hello'),
          [0, 2, 4, 5, 6])
 def test_create_job_delayed(self):
   """Run a test of the "create" command against a mocked-out API:
   this time, make the monitor check status several times before successful completion.
   """
   mock_context = FakeAuroraCommandContext()
   with contextlib.nested(
       patch('time.sleep'),
       patch('twitter.aurora.client.cli.jobs.Job.create_context', return_value=mock_context)):
     mock_query = self.create_mock_query()
     for result in [ScheduleStatus.INIT, ScheduleStatus.PENDING, ScheduleStatus.PENDING,
         ScheduleStatus.RUNNING, ScheduleStatus.FINISHED]:
       mock_context.add_expected_status_query_result(self.create_mock_status_query_result(result))
     api = mock_context.get_api('west')
     api.create_job.return_value = self.get_createjob_response()
     with temporary_file() as fp:
       fp.write(self.get_valid_config())
       fp.flush()
       cmd = AuroraCommandLine()
       cmd.execute(['job', 'create', '--wait_until=RUNNING', 'west/mchucarroll/test/hello',
           fp.name])
       # Now check that the right API calls got made.
       # Check that create_job was called exactly once, with an AuroraConfig parameter.
       self.assert_create_job_called(api)
       self.assert_scheduler_called(api, mock_query, 4)