mirror of
https://github.com/outbackdingo/patroni.git
synced 2026-08-25 14:53:37 +00:00
Enforce data-type checks for step matcher
and increase default timeout for patroni start
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import os.path
|
||||
import os
|
||||
import psycopg2
|
||||
import requests
|
||||
import subprocess
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
import yaml
|
||||
@@ -50,7 +50,7 @@ class PatroniController(object):
|
||||
return None
|
||||
return content.strip()
|
||||
|
||||
def start(self, pg_name, max_wait_limit=15, tags=None):
|
||||
def start(self, pg_name, max_wait_limit=20, tags=None):
|
||||
if not self._is_running(pg_name):
|
||||
if pg_name in self._processes:
|
||||
del self._processes[pg_name]
|
||||
|
||||
@@ -4,22 +4,22 @@ from behave import step, then
|
||||
from time import sleep, time
|
||||
|
||||
|
||||
@step('I start {name}')
|
||||
@step('I start {name:w}')
|
||||
def start_patroni(context, name):
|
||||
return context.pctl.start(name)
|
||||
|
||||
|
||||
@step('I shut down {name}')
|
||||
@step('I shut down {name:w}')
|
||||
def stop_patroni(context, name):
|
||||
return context.pctl.stop(name)
|
||||
|
||||
|
||||
@step('I kill {name}')
|
||||
@step('I kill {name:w}')
|
||||
def kill_patroni(context, name):
|
||||
return context.pctl.stop(name, kill=True)
|
||||
|
||||
|
||||
@step('I add the table {table_name} to {pg_name}')
|
||||
@step('I add the table {table_name:w} to {pg_name:w}')
|
||||
def add_table(context, table_name, pg_name):
|
||||
# parse the configuration file and get the port
|
||||
try:
|
||||
@@ -28,7 +28,7 @@ def add_table(context, table_name, pg_name):
|
||||
assert False, "Error creating table {0} on {1}: {2}".format(table_name, pg_name, e)
|
||||
|
||||
|
||||
@then('Table {table_name} is present on {pg_name} after {max_replication_delay} seconds')
|
||||
@then('Table {table_name:w} is present on {pg_name:w} after {max_replication_delay:d} seconds')
|
||||
def table_is_present_on(context, table_name, pg_name, max_replication_delay):
|
||||
for _ in range(int(max_replication_delay)):
|
||||
if context.pctl.query(pg_name, "SELECT 1 FROM {0}".format(table_name), fail_ok=True) is not None:
|
||||
@@ -39,15 +39,15 @@ def table_is_present_on(context, table_name, pg_name, max_replication_delay):
|
||||
"Table {0} is not present on {1} after {2} seconds".format(table_name, pg_name, max_replication_delay)
|
||||
|
||||
|
||||
@then('{pg_name} role is the {pg_role} after {max_promotion_timeout} seconds')
|
||||
@then('{pg_name:w} role is the {pg_role:w} after {max_promotion_timeout:d} seconds')
|
||||
def check_role(context, pg_name, pg_role, max_promotion_timeout):
|
||||
if not context.pctl.check_role_has_changed_to(pg_name, pg_role, timeout=int(max_promotion_timeout)):
|
||||
assert False,\
|
||||
"{0} role didn't change to {1} after {2} seconds".format(pg_name, pg_role, max_promotion_timeout)
|
||||
|
||||
|
||||
@step('replication works from {master} to {replica} after {time_limit} seconds')
|
||||
@then('replication works from {master} to {replica} after {time_limit} seconds')
|
||||
@step('replication works from {master:w} to {replica:w} after {time_limit:d} seconds')
|
||||
@then('replication works from {master:w} to {replica:w} after {time_limit:d} seconds')
|
||||
def replication_works(context, master, replica, time_limit):
|
||||
context.execute_steps(u"""
|
||||
When I add the table test_{0} to {1}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
from behave import step, then
|
||||
|
||||
|
||||
@step('I configure and start {name} with a tag {tag_name} {tag_value}')
|
||||
@step('I configure and start {name:w} with a tag {tag_name:w} {tag_value:w}')
|
||||
def start_patroni_with_a_name_value_tag(context, name, tag_name, tag_value):
|
||||
return context.pctl.start(name, tags={tag_name: tag_value})
|
||||
|
||||
|
||||
@then('There is a label with "{content}" in {name} data directory')
|
||||
@then('There is a label with "{content:w}" in {name:w} data directory')
|
||||
def check_label(context, content, name):
|
||||
label = context.pctl.read_label(name)
|
||||
assert label == content, "{0} is not equal to {1}".format(label, content)
|
||||
|
||||
|
||||
@step('I create label with "{content}" in {name} data directory')
|
||||
@step('I create label with "{content:w}" in {name:w} data directory')
|
||||
def write_label(context, content, name):
|
||||
context.pctl.write_label(name, content)
|
||||
|
||||
@@ -1,9 +1,23 @@
|
||||
import time
|
||||
import parse
|
||||
import pytz
|
||||
import requests
|
||||
import time
|
||||
|
||||
from behave import register_type, step, then
|
||||
from datetime import datetime, timedelta
|
||||
from behave import step, then
|
||||
|
||||
|
||||
@parse.with_pattern(r'https?://(?:\w|\.|:|/)+')
|
||||
def parse_url(text):
|
||||
return text
|
||||
|
||||
|
||||
@parse.with_pattern(r'(?:\w+=(?:\w|\.|:|-|\+|\s)+,?)+')
|
||||
def parse_data(text):
|
||||
return text
|
||||
|
||||
|
||||
register_type(url=parse_url, data=parse_data)
|
||||
|
||||
|
||||
# there is no way we can find out if the node has already
|
||||
@@ -11,8 +25,8 @@ from behave import step, then
|
||||
# just rely on the database availability, since there is
|
||||
# a short gap between the time PostgreSQL becomes available
|
||||
# and Patroni assuming the leader role.
|
||||
@step('{name} is a leader after {time_limit} seconds')
|
||||
@then('{name} is a leader after {time_limit} seconds')
|
||||
@step('{name:w} is a leader after {time_limit:d} seconds')
|
||||
@then('{name:w} is a leader after {time_limit:d} seconds')
|
||||
def is_a_leader(context, name, time_limit):
|
||||
max_time = time.time() + int(time_limit)
|
||||
while (context.etcd_ctl.query("leader") != name):
|
||||
@@ -21,12 +35,12 @@ def is_a_leader(context, name, time_limit):
|
||||
assert False, "{0} is not a leader in etcd after {1} seconds".format(name, time_limit)
|
||||
|
||||
|
||||
@step('I sleep for {value} seconds')
|
||||
@step('I sleep for {value:d} seconds')
|
||||
def sleep_for_n_seconds(context, value):
|
||||
time.sleep(int(value))
|
||||
|
||||
|
||||
@step('I issue a GET request to {url}')
|
||||
@step('I issue a GET request to {url:url}')
|
||||
def do_get(context, url):
|
||||
try:
|
||||
r = requests.get(url)
|
||||
@@ -41,12 +55,12 @@ def do_get(context, url):
|
||||
context.response = r.content.decode('utf-8')
|
||||
|
||||
|
||||
@step('I issue an empty POST request to {url}')
|
||||
@step('I issue an empty POST request to {url:url}')
|
||||
def do_post_empty(context, url):
|
||||
do_post(context, url, None)
|
||||
|
||||
|
||||
@step('I issue a POST request to {url} with {data}')
|
||||
@step('I issue a POST request to {url:url} with {data:data}')
|
||||
def do_post(context, url, data):
|
||||
post_data = {}
|
||||
if data:
|
||||
@@ -68,7 +82,7 @@ def do_post(context, url, data):
|
||||
context.response = r.content.decode('utf-8')
|
||||
|
||||
|
||||
@then('I receive a response {component} {data}')
|
||||
@then('I receive a response {component:w} {data}')
|
||||
def check_response(context, component, data):
|
||||
if component == 'code':
|
||||
assert context.status_code == int(data),\
|
||||
@@ -80,8 +94,8 @@ def check_response(context, component, data):
|
||||
assert context.response[component] == data, "{0} does not contain {1}".format(component, data)
|
||||
|
||||
|
||||
@step('I issue a scheduled failover at {at_url} from {from_host} to {to_host} in {in_seconds} seconds')
|
||||
def scheduld_failover(context, at_url, from_host, to_host, in_seconds):
|
||||
context.execute_steps("""
|
||||
@step('I issue a scheduled failover at {at_url:url} from {from_host:w} to {to_host:w} in {in_seconds:d} seconds')
|
||||
def scheduled_failover(context, at_url, from_host, to_host, in_seconds):
|
||||
context.execute_steps(u"""
|
||||
Given I issue a POST request to {0}/failover with leader={1},candidate={2},scheduled_at={3}
|
||||
""".format(at_url, from_host, to_host, datetime.now(pytz.utc) + timedelta(seconds=int(in_seconds))))
|
||||
|
||||
Reference in New Issue
Block a user