Пример #1
0
    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)
Пример #2
0
    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)
Пример #3
0
    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)
Пример #4
0
    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'))
Пример #5
0
    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'))
Пример #6
0
    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)
Пример #7
0
    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'))
Пример #8
0
    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
Пример #9
0
    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()
Пример #10
0
    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())
Пример #11
0
    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)
Пример #12
0
    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)
Пример #13
0
    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')
Пример #14
0
    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
Пример #15
0
    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())
Пример #16
0
    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)
Пример #17
0
 def setUp(self):
     super(DockerComposeTests, self).setUp()
     self.app = pygen.PyGen(
         template=relative_path('templates/mockserver.conf.json'))
Пример #18
0
    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)