def test_http_lifecycle_wrapper_with_lifecycle(): runner_mock = mock.create_autospec(ThermosTaskRunner) mti = MesosTaskInstance(lifecycle=LifecycleConfig(http=HttpLifecycleConfig())) # pass-thru if no health port has been defined -- see comment in http_lifecycle.py regarding # the rationalization for this behavior. with make_mocks(mti, {}) as (runner_mock, runner_wrapper, wrapper_init): assert runner_mock is runner_wrapper assert wrapper_init.mock_calls == [] # wrap it once health is available and validate the constructor is called as expected with make_mocks(mti, {'health': 31337}) as (runner_mock, runner_wrapper, wrapper_init): assert isinstance(runner_wrapper, HttpLifecycleManager) assert wrapper_init.mock_calls == [ mock.call(runner_mock, 31337, [('/quitquitquit', Amount(5, Time.SECONDS)), ('/abortabortabort', Amount(5, Time.SECONDS))]) ] # Validate that we can override ports, endpoints, wait times mti = MesosTaskInstance(lifecycle=LifecycleConfig(http=HttpLifecycleConfig( port='http', graceful_shutdown_endpoint='/frankfrankfrank', shutdown_endpoint='/bobbobbob', graceful_shutdown_wait_secs=123, shutdown_wait_secs=456 ))) portmap = {'http': 12345, 'admin': 54321} with make_mocks(mti, portmap) as (runner_mock, runner_wrapper, wrapper_init): assert isinstance(runner_wrapper, HttpLifecycleManager) assert wrapper_init.mock_calls == [ mock.call(runner_mock, 12345, [('/frankfrankfrank', Amount(123, Time.SECONDS)), ('/bobbobbob', Amount(456, Time.SECONDS))]) ]
def test_http_lifecycle_wrapper_without_lifecycle(): mti_without_lifecycle = MesosTaskInstance() mti_without_http_lifecycle = MesosTaskInstance(lifecycle=LifecycleConfig()) runner_mock = mock.create_autospec(ThermosTaskRunner) assert HttpLifecycleManager.wrap(runner_mock, mti_without_lifecycle, {}) is runner_mock assert HttpLifecycleManager.wrap(runner_mock, mti_without_http_lifecycle, {}) is runner_mock
def task_instance_from_job(job, instance, hostname): instance_context = MesosContext(instance=instance, hostname=hostname) health_check_config = HealthCheckConfig() if job.has_health_check_config(): health_check_config = job.health_check_config() ti = MesosTaskInstance(task=job.task(), role=job.role(), health_check_config=health_check_config, instance=instance) if job.has_announce(): ti = ti(announce=job.announce()) if job.has_environment(): ti = ti(environment=job.environment()) if job.has_lifecycle(): ti = ti(lifecycle=job.lifecycle()) return ti.bind(mesos=instance_context)
def mesos_task_instance_from_assigned_task(assigned_task): """Deserialize MesosTaskInstance from an AssignedTask thrift.""" thermos_task = assigned_task.task.executorConfig.data if not thermos_task: raise TaskInfoError('Task did not have a thermos config!') try: json_blob = json.loads(thermos_task) except (TypeError, ValueError) as e: raise TaskInfoError('Could not deserialize thermos config: %s' % e) # TODO(wickman) Determine if there are any serialized MesosTaskInstances in the wild; # kill this code if not. if 'instance' in json_blob: return MesosTaskInstance.json_loads(thermos_task) # This is a MesosJob task_instance = task_instance_from_job( MesosJob.json_loads(thermos_task), assigned_task.instanceId) try: ThermosTaskValidator.assert_valid_task(task_instance.task()) ThermosTaskValidator.assert_all_refs_bound(task_instance) except ThermosTaskValidator.InvalidTaskError as e: raise UnexpectedUnboundRefsError('Got invalid task: %s' % e) task_instance, _ = task_instance.interpolate() return task_instance
def mesos_task_instance_from_assigned_task(assigned_task): """Deserialize MesosTaskInstance from an AssignedTask thrift.""" thermos_task = assigned_task.task.executorConfig.data if not thermos_task: raise TaskInfoError('Task did not have a thermos config!') try: json_blob = json.loads(thermos_task) except (TypeError, ValueError) as e: raise TaskInfoError('Could not deserialize thermos config: %s' % e) # TODO(wickman) Determine if there are any serialized MesosTaskInstances in the wild; # kill this code if not. if 'instance' in json_blob: return MesosTaskInstance.json_loads(thermos_task) # This is a MesosJob task_instance = task_instance_from_job(MesosJob.json_loads(thermos_task), assigned_task.instanceId, assigned_task.slaveHost) try: ThermosTaskValidator.assert_valid_task(task_instance.task()) ThermosTaskValidator.assert_all_refs_bound(task_instance) except ThermosTaskValidator.InvalidTaskError as e: raise UnexpectedUnboundRefsError('Got invalid task: %s' % e) task_instance, _ = task_instance.interpolate() return task_instance
def task_instance_from_job(job, instance): instance_context = MesosContext(instance=instance) # TODO(Sathya): Remove health_check_interval_secs references after deprecation cycle is complete. health_check_config = HealthCheckConfig() if job.has_health_check_interval_secs(): health_check_config = HealthCheckConfig(interval_secs=job.health_check_interval_secs().get()) elif job.has_health_check_config(): health_check_config = job.health_check_config() ti = MesosTaskInstance(task=job.task(), role=job.role(), health_check_interval_secs=health_check_config.interval_secs().get(), health_check_config=health_check_config, instance=instance) if job.has_announce(): ti = ti(announce=job.announce()) if job.has_environment(): ti = ti(environment=job.environment()) return ti.bind(mesos=instance_context).interpolate()
def task_instance_from_job(job, instance): instance_context = MesosContext(instance=instance) # TODO(Sathya): Remove health_check_interval_secs references after deprecation cycle is complete. health_check_config = HealthCheckConfig() if job.has_health_check_interval_secs(): health_check_config = HealthCheckConfig( interval_secs=job.health_check_interval_secs().get()) elif job.has_health_check_config(): health_check_config = job.health_check_config() ti = MesosTaskInstance( task=job.task(), role=job.role(), health_check_interval_secs=health_check_config.interval_secs().get(), health_check_config=health_check_config, instance=instance) if job.has_announce(): ti = ti(announce=job.announce()) if job.has_environment(): ti = ti(environment=job.environment()) return ti.bind(mesos=instance_context).interpolate()
def test_http_lifecycle_wraps_start_and_stop(): mti = MesosTaskInstance(lifecycle=LifecycleConfig(http=HttpLifecycleConfig())) runner_mock = mock.create_autospec(ThermosTaskRunner) with mock.patch.object(HttpLifecycleManager, '_terminate_http', return_value=None) as http_mock: runner_wrapper = HttpLifecycleManager.wrap(runner_mock, mti, {'health': 31337}) # ensure that start and stop are properly wrapped runner_wrapper.start(23.3) assert runner_mock.start.mock_calls == [mock.call(timeout=23.3)] # ensure that http teardown called when stopped runner_wrapper.stop(32.2) assert http_mock.mock_calls == [mock.call()] assert runner_mock.stop.mock_calls == [mock.call(timeout=32.2)]
def mesos_task_instance_from_assigned_task(assigned_task): """Deserialize MesosTaskInstance from an AssignedTask thrift.""" thermos_task = assigned_task.task.executorConfig.data if not thermos_task: raise ValueError('Task did not have a thermos config!') try: json_blob = json.loads(thermos_task) except (TypeError, ValueError) as e: raise ValueError('Could not deserialize thermos config: %s' % e) # As part of the transition for MESOS-2133, we can send either a MesosTaskInstance # or we can be sending a MesosJob. So handle both possible cases. Once everyone # is using MesosJob, then we can begin to leverage additional information that # becomes available such as cluster. if 'instance' in json_blob: return MesosTaskInstance.json_loads(thermos_task) # This is a MesosJob mti, refs = task_instance_from_job(MesosJob.json_loads(thermos_task), assigned_task.instanceId) unbound_refs = [] for ref in refs: # If the ref is {{thermos.task_id}} or a subscope of # {{thermos.ports}}, it currently gets bound by the Thermos Runner, # so we must leave them unbound. # # {{thermos.user}} is a legacy binding which we can safely ignore. # # TODO(wickman) These should be rewritten by the mesos client to use # %%style%% replacements in order to allow us to better type-check configs # client-side. if ref == Ref.from_address('thermos.task_id'): continue if Ref.subscope(Ref.from_address('thermos.ports'), ref): continue if ref == Ref.from_address('thermos.user'): continue else: unbound_refs.append(ref) if len(unbound_refs) != 0: raise ValueError('Unexpected unbound refs: %s' % ' '.join(map(str, unbound_refs))) return mti
task=TaskConfig(executorConfig=ExecutorConfig( name=AURORA_EXECUTOR_NAME, data=thermos_config.json_dumps()), job=JobKey(role=role, environment='env', name='name')), assignedPorts=assigned_ports, **kw) td = mesos_pb2.TaskInfo() td.task_id.value = task_id td.name = thermos_config.task().name().get() td.data = serialize(at) return td BASE_MTI = MesosTaskInstance(instance=0, role=getpass.getuser()) BASE_TASK = Task(resources=Resources(cpu=1.0, ram=16 * MB, disk=32 * MB)) HELLO_WORLD_TASK_ID = 'hello_world-001' HELLO_WORLD = BASE_TASK(name='hello_world', processes=[ Process(name='hello_world_{{thermos.task_id}}', cmdline='echo hello world') ]) HELLO_WORLD_MTI = BASE_MTI(task=HELLO_WORLD) SLEEP60 = BASE_TASK(processes=[Process(name='sleep60', cmdline='sleep 60')]) SLEEP2 = BASE_TASK(processes=[Process(name='sleep2', cmdline='sleep 2')]) SLEEP60_MTI = BASE_MTI(task=SLEEP60) MESOS_JOB = MesosJob(
from twitter.common.quantity import Amount, Time from apache.aurora.config.schema.base import MB, MesosTaskInstance, Process, Resources, Task from apache.aurora.executor.common.sandbox import DirectorySandbox from apache.aurora.executor.http_lifecycle import HttpLifecycleManager from apache.aurora.executor.thermos_task_runner import ThermosTaskRunner from apache.thermos.common.statuses import (INTERNAL_ERROR, INVALID_TASK, TERMINAL_TASK, UNKNOWN_ERROR, UNKNOWN_USER) from gen.apache.thermos.ttypes import TaskState TASK = MesosTaskInstance( instance=0, role=getpass.getuser(), task=Task( resources=Resources(cpu=1.0, ram=16 * MB, disk=32 * MB), name='hello_world', processes=[Process(name='hello_world', cmdline='{{command}}')], )) class TestThermosTaskRunnerIntegration(object): PEX_PATH = None LOG_DIR = None @classmethod def setup_class(cls): cls.LOG_DIR = tempfile.mkdtemp() LogOptions.set_log_dir(cls.LOG_DIR) LogOptions.set_disk_log_level('DEBUG') log.init('executor_logger')
import getpass from apache.aurora.config.schema.base import ( MB, DefaultLifecycleConfig, MesosJob, MesosTaskInstance, Process, Resources, Task ) BASE_MTI = MesosTaskInstance( instance=0, lifecycle=DefaultLifecycleConfig, role=getpass.getuser(), ) BASE_TASK = Task(resources=Resources(cpu=1.0, ram=16 * MB, disk=32 * MB)) HELLO_WORLD_TASK_ID = 'hello_world-001' HELLO_WORLD = BASE_TASK( name='hello_world', processes=[Process(name='hello_world_{{thermos.task_id}}', cmdline='echo hello world')]) HELLO_WORLD_MTI = BASE_MTI(task=HELLO_WORLD) SLEEP60 = BASE_TASK(processes=[Process(name='sleep60', cmdline='sleep 60')]) SLEEP2 = BASE_TASK(processes=[Process(name='sleep2', cmdline='sleep 2')]) SLEEP60_MTI = BASE_MTI(task=SLEEP60) MESOS_JOB = MesosJob(