def test_does_not_replace_unchanged_content(self): self.app = pygen.PyGen(target=self.target_path, interval=[0], template="""# {% for container in containers %} __{{ container.name }}__ {% endfor %}""") original_signal_func = self.app.timer.function def counting_signal(*args, **kwargs): self.count_signal_calls += 1 original_signal_func(*args, **kwargs) self.app.timer.function = counting_signal self.start_container() self.assertEqual(0, self.count_signal_calls) self.app.update_target() self.assertEqual(1, self.count_signal_calls) self.app.update_target() self.assertEqual(1, self.count_signal_calls) self.app.update_target() self.assertEqual(1, self.count_signal_calls)
def test_swarm_manager(self): self.app = pygen.PyGen( template='#', swarm_manager=True, workers=['localhost'], signal=[('remote-signal', 'USR1')], interval=[0] ) self.worker = Worker('localhost') self.worker.start() self.worker.send_update('testing') response = requests.get('http://localhost:9413/metrics') self.assertEqual(response.status_code, 200) metrics = response.text self.assertIn('pygen_worker_request_count{client=', metrics) self.assertIn('pygen_worker_send_count{target=', metrics) self.assertIn('pygen_manager_request_count{client=', metrics) self.assertIn('pygen_manager_send_count{target=', metrics) self.assertIn('pygen_signal_action_seconds_count{' 'signal="USR1",target="remote-signal"} ', metrics) self.assertIn('pygen_signal_action_seconds_sum{' 'signal="USR1",target="remote-signal"} ', metrics)
def test_updates_target(self): self.app = pygen.PyGen(target=self.target_path, interval=[0], template="""# {% for container in containers %} __{{ container.name }}__ {% endfor %}""") c1 = self.start_container() self.app.update_target() content = self.read_contents() self.assertIn('__%s__' % c1.name, content) c2 = self.start_container() self.app.update_target() content = self.read_contents() self.assertIn('__%s__' % c1.name, content) self.assertIn('__%s__' % c2.name, content) c1.stop() self.app.update_target() content = self.read_contents() self.assertNotIn('__%s__' % c1.name, content) self.assertIn('__%s__' % c2.name, content)
def test_template_from_absolute_file(self): app = pygen.PyGen( template=os.path.abspath(relative_path('templates/hello.txt'))) self.assertIsNotNone(app.template) self.assertEqual('Hello world!', app.template.render(name='world')) self.assertEqual('Hello Jinja2!', app.template.render(name='Jinja2'))
def test_template_from_url(self): url = 'https://raw.githubusercontent.com/rycus86/docker-pygen/master/tests/templates/hello.txt' app = pygen.PyGen(template=url) self.assertIsNotNone(app.template) self.assertEqual('Hello world!', app.template.render(name='world')) self.assertEqual('Hello Jinja2!', app.template.render(name='Jinja2'))
def test_generate_with_groups(self): self.start_container(environment=['GENERATOR=pygen'], labels={ 'instance': '001', 'application': 'web' }) self.start_container(environment=['GENERATOR=pygen'], labels={ 'instance': '002', 'application': 'web' }) self.start_container(environment=['GENERATOR=pygen'], labels={ 'instance': '003', 'application': 'db' }) self.app = pygen.PyGen(template="""# {% for key, containers in containers|groupby('labels.application') %} group: {{ key }} {% for container in containers %} instance: {{ container.labels.instance }} {% endfor %} {% endfor %}""") content = self.app.generate() self.assertIn('group: web', content) self.assertIn('group: db', content) for num in range(1, 4): self.assertIn('instance: %03d' % num, content)
def test_inline_template(self): app = pygen.PyGen( template='#{{ who }} {{ what }} use inline templates') self.assertIsNotNone(app.template) self.assertEqual('You can use inline templates', app.template.render(who='You', what='can')) self.assertEqual('I could use inline templates', app.template.render(who='I', what='could'))
def setUp(self): self.generate_count = 0 self.app = pygen.PyGen(template='#', swarm_manager=True) def counting_generate(): self.generate_count += 1 return 'Generated %d times' % self.generate_count self.app.generate = counting_generate
def setUp(self): self.manager = pygen.PyGen(template='#', interval=[0], swarm_manager=True, workers=['localhost']) self.worker = swarm_worker.Worker('localhost') self.worker.start() self.assertIsNotNone(self.manager.swarm_manager) self.to_restore = dict()
def test_lazy_in_templates(self): app = pygen.PyGen( template='#{% for c in all_containers %}' '{{ all_containers|length }}{{ c.name }}' '-{% set first = all_containers|first %}{{ first.id }}' '{% endfor %}') def mock_containers(*args, **kwargs): return [{'name': 'mocked', 'id': 12}] app.api.containers = mock_containers self.assertEqual('1mocked-12', app.generate())
def test_intervals(self): self.assertRaises(pygen.PyGenException, pygen.PyGen, template='#', interval=[1, 2, 3]) self.assertRaises(pygen.PyGenException, pygen.PyGen, template='#', interval=[2, 1]) app = pygen.PyGen(template='#', interval=[12, 40]) self.assertEqual(app.timer.min_interval, 12) self.assertEqual(app.timer.max_interval, 40)
def test_generate(self): test_container = self.start_container(environment=['GENERATOR=pygen']) self.app = pygen.PyGen(template="""# {% for container in containers %} running: {{ container.name }} ID={{ container.short_id }} {% for key, value in container.env.items() %} env: {{ key }}=>{{ value }} {% endfor %} {% endfor %}""") content = self.app.generate() self.assertIn('running: %s' % test_container.name, content) self.assertIn('ID=%s' % test_container.short_id, content) self.assertIn('env: GENERATOR=>pygen', content)
def test_read_config(self): app = pygen.PyGen( template='#c1={{ read_config("PYGEN_TEST_KEY") }} ' 'c2={{ read_config("PYGEN_CONF", "/tmp/pygen-conf-test") }} ' 'cd={{ read_config("PYGEN_DEFAULT", default="DefaultValue") }}') try: os.environ['PYGEN_TEST_KEY'] = 'from-env' with open('/tmp/pygen-conf-test', 'w') as config_file: config_file.write('PYGEN_CONF=from-file') content = app.generate() self.assertIn('c1=from-env', content) self.assertIn('c2=from-file', content) self.assertIn('cd=DefaultValue', content) finally: del os.environ['PYGEN_TEST_KEY'] if os.path.exists('/tmp/pygen-conf-test'): os.remove('/tmp/pygen-conf-test')
def test_watch(self): self.app = pygen.PyGen(target=self.target_path, interval=[0], template="""# {% for container in containers %} __{{ container.name }}__{{ container.health }}__ {% endfor %}""") original_signal_func = self.app.timer.function def counting_signal(*args, **kwargs): self.count_signal_calls += 1 original_signal_func(*args, **kwargs) self.app.timer.function = counting_signal self.assertEqual(0, self.count_signal_calls) def run(_flags): since = datetime.utcnow() while _flags['run']: until = datetime.utcnow() + timedelta(seconds=1) self.app.watch(since=since, until=until) since = until - timedelta(seconds=1) flags = {'run': True} try: thread = threading.Thread(target=run, args=(flags, )) thread.start() self.assertEqual(0, self.count_signal_calls) c1 = self.start_container(healthcheck={ 'Test': ['CMD-SHELL', 'exit 0'], 'Interval': 500000000 }) time.sleep(1.2) self.assertSignalHasCalled(times=2) # start + healthy self.assertIn('__%s__' % c1.name, self.read_contents()) c2 = self.start_container() time.sleep(1.2) self.assertSignalHasCalled(times=3) self.assertIn('__%s__' % c1.name, self.read_contents()) self.assertIn('__%s__' % c2.name, self.read_contents()) c1.stop() time.sleep(1.2) self.assertSignalHasCalled(times=4) self.assertNotIn('__%s__' % c1.name, self.read_contents()) self.assertIn('__%s__' % c2.name, self.read_contents()) flags['run'] = False thread.join() self.assertSignalHasCalled(times=4) except: flags['run'] = False raise
def test_own_container_id(self): app = pygen.PyGen(template='#cid={{ own_container_id }}') container_id = docker_helper.get_current_container_id() self.assertEqual('cid=%s' % container_id, app.generate())
def test_nginx_template(self): self.start_container(name='pygen-test-nginx-1', labels={'virtual-host': 'test.site.com'}, ports={8080: None}) self.start_container(name='pygen-test-nginx-2', labels={'virtual-host': 'test.site.com'}, ports={8080: None}) self.start_container(name='pygen-test-nginx-3', labels={'virtual-host': 'www.site.com'}, ports={8080: None}) self.start_container(name='pygen-test-nginx-4', labels={ 'virtual-host': 'api.site.com', 'context-path': '/rest' }, ports={5000: None}) self.start_container(name='pygen-test-nginx-5', labels={ 'virtual-host': 'api.site.com', 'context-path': '/stream' }, ports={5000: None}) self.start_container(name='pygen-test-nginx-6', labels={ 'virtual-host': 'api.site.com', 'context-path': '/no-port-exposed' }) self.start_container(name='pygen-test-nginx-7', labels={'context-path': '/no-virtual-host'}, ports={9001: None}) self.app = pygen.PyGen( template=self.relative('templates/nginx.example')) content = self.app.generate() # pygen-test-nginx-1 : test.site.com/ 8080 self.assertIn('# pygen-test-nginx-1', content) # pygen-test-nginx-2 : test.site.com/ 8080 self.assertIn('# pygen-test-nginx-2', content) # pygen-test-nginx-3 : www.site.com/ 8080 self.assertIn('# pygen-test-nginx-3', content) # pygen-test-nginx-4 : api.site.com/rest 5000 self.assertIn('# pygen-test-nginx-4', content) # pygen-test-nginx-5 : api.site.com/stream 5000 self.assertIn('# pygen-test-nginx-5', content) # pygen-test-nginx-6 : - /no-port-exposed self.assertNotIn('pygen-test-nginx-6', content) # pygen-test-nginx-7 : - /no-virtual-host 9001 self.assertNotIn('pygen-test-nginx-7', content) for upstream in ('test.site.com___', 'www.site.com___', 'api.site.com___rest', 'api.site.com___stream'): self.assertIn('upstream %s ' % upstream, content) self.assertIn('proxy_pass http://%s;' % upstream, content) self.assertNotIn('upstream api.site.com___ ', content) self.assertIn('location / ', content) self.assertIn('location /rest ', content) self.assertIn('location /stream ', content) for num in range(1, 6): container = self.docker_client.containers.get( 'pygen-test-nginx-%d' % num) ip_address = next( iter(container.attrs['NetworkSettings'] ['Networks'].values())).get('IPAddress') port = next( iter(container.attrs['Config'].get( 'ExposedPorts', dict()).keys())).split('/')[0] self.assertIn('server %s:%s;' % (ip_address, port), content)
def setUp(self): super(DockerComposeTests, self).setUp() self.app = pygen.PyGen( template=relative_path('templates/mockserver.conf.json'))
def test_available_metrics(self): self.app = pygen.PyGen( template='#', restart=['sample-restart'], signal=[('sample-signal', 'HUP'), ('sample-interrupt', 'INT')], interval=[0] ) self.app.update_target() self.app.update_target() response = requests.get('http://localhost:9413/metrics') self.assertEqual(response.status_code, 200) metrics = response.text # process / platform self.assertIn('python_info{', metrics) self.assertIn('process_start_time_seconds ', metrics) # app info self.assertIn('pygen_app_info{version=', metrics) self.assertIn('pygen_app_built_at ', metrics) # pygen self.assertIn('pygen_generation_seconds_count ', metrics) self.assertIn('pygen_generation_seconds_sum ', metrics) self.assertIn('pygen_target_update_seconds_count ', metrics) self.assertIn('pygen_target_update_seconds_sum ', metrics) # actions self.assertIn('pygen_restart_action_seconds_count{' 'target="sample-restart"} ', metrics) self.assertIn('pygen_restart_action_seconds_sum{' 'target="sample-restart"} ', metrics) self.assertIn('pygen_signal_action_seconds_count{' 'signal="HUP",target="sample-signal"} ', metrics) self.assertIn('pygen_signal_action_seconds_sum{' 'signal="HUP",target="sample-signal"} ', metrics) self.assertIn('pygen_signal_action_seconds_count{' 'signal="INT",target="sample-interrupt"} ', metrics) self.assertIn('pygen_signal_action_seconds_sum{' 'signal="INT",target="sample-interrupt"} ', metrics) self.assertIn('pygen_action_execution_strategy_seconds_count{' 'strategy="local"} ', metrics) self.assertIn('pygen_action_execution_strategy_seconds_sum{' 'strategy="local"} ', metrics) # api self.assertIn('pygen_api_containers_seconds_count{list_all="0"} ', metrics) self.assertIn('pygen_api_containers_seconds_sum{list_all="0"} ', metrics) self.assertIn('pygen_api_containers_seconds_bucket{le="0.25",list_all="0"} ', metrics) self.assertIn('pygen_api_services_seconds_count{desired_state="running"} ', metrics) self.assertIn('pygen_api_services_seconds_sum{desired_state="running"} ', metrics) self.assertIn('pygen_api_services_seconds_bucket{desired_state="running",le="0.25"} ', metrics) self.assertIn('pygen_api_nodes_seconds_count ', metrics) self.assertIn('pygen_api_nodes_seconds_sum ', metrics) self.assertIn('pygen_api_nodes_seconds_bucket{le="0.25"} ', metrics)