blob: ee0030012d6511ec70ed0ceb0640fd37c628af77 [file] [log] [blame]
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from pystachio import Ref
from pystachio.matcher import Any, Matcher
from twitter.common.contextutil import temporary_file
from apache.aurora.client import binding_helper
from apache.aurora.client.binding_helper import BindingHelper, CachingBindingHelper
from apache.aurora.config import AuroraConfig
GENERIC_CONFIG = """
main_job = Job(
name = 'hello_world',
environment = 'prod',
cluster = 'derp',
task = Task(
name = 'main',
processes = [
Process(name='hello_one', cmdline='{{uncached[hello]}} {{cached[hello]}}'),
Process(name='hello_two', cmdline='{{uncached[hello]}} {{cached[hello]}}')
],
resources = Resources(cpu = 0.1, ram = 64 * MB, disk = 64 * MB),
)
)
jobs = [
main_job(role = 'john_doe'),
main_job(role = 'jane_doe'),
]
"""
class UncachedHelper(BindingHelper):
@property
def name(self):
return 'uncached'
@property
def matcher(self):
return Matcher('uncached')[Any]
def __init__(self):
self.binds = 0
super(UncachedHelper, self).__init__()
def bind(self, config, match, env, binding_dict):
# TODO(wickman) You should be able to take a match tuple + matcher
# object and return the ref.
self.binds += 1
ref = Ref.from_address('%s[%s]' % match)
config.bind({ref: 'U(%s)' % match[1]})
class CachedHelper(CachingBindingHelper):
@property
def name(self):
return 'cached'
@property
def matcher(self):
return Matcher('cached')[Any]
def __init__(self):
self.binds, self.uncached_binds = 0, 0
super(CachedHelper, self).__init__()
def bind(self, *args, **kw):
self.binds += 1
super(CachedHelper, self).bind(*args, **kw)
def uncached_bind(self, config, match, env, binding_dict):
self.uncached_binds += 1
ref = Ref.from_address('%s[%s]' % match)
binding = {ref: 'C(%s)' % match[1]}
config.bind(binding)
return binding
def write_and_load_config(role):
with temporary_file() as fp:
fp.write(GENERIC_CONFIG)
fp.flush()
return AuroraConfig.load(fp.name, name='hello_world', select_role=role)
def test_registry():
binding_helper.unregister_all()
assert len(binding_helper._BINDING_HELPERS) == 0
BindingHelper.register(UncachedHelper())
assert len(binding_helper._BINDING_HELPERS) == 1
BindingHelper.register(CachedHelper())
assert len(binding_helper._BINDING_HELPERS) == 2
binding_helper.unregister_all()
assert len(binding_helper._BINDING_HELPERS) == 0
def test_helper_types():
binding_helper.unregister_all()
BindingHelper.register(UncachedHelper())
BindingHelper.register(CachedHelper())
uncached_helper = binding_helper._BINDING_HELPERS[0]
cached_helper = binding_helper._BINDING_HELPERS[1]
def smoke_test():
cfg = write_and_load_config(role='john_doe')
binding_helper.apply_all(cfg)
assert cfg.task(0).processes()[0].cmdline().get() == 'U(hello) C(hello)'
assert cfg.task(0).processes()[1].cmdline().get() == 'U(hello) C(hello)'
# initially everything uncached (also -- multiple symbols result in a single bind)
smoke_test()
assert uncached_helper.binds == 1
assert cached_helper.binds == 1
assert cached_helper.uncached_binds == 1
# cached helper is warm, should no longer have uncached binds
smoke_test()
assert uncached_helper.binds == 2
assert cached_helper.binds == 2
assert cached_helper.uncached_binds == 1
# flush cache and validate miss
binding_helper.clear_binding_caches()
smoke_test()
assert uncached_helper.binds == 3
assert cached_helper.binds == 3
assert cached_helper.uncached_binds == 2