Exemple #1
0
def _wait_for_pg(
    timeout_secs: int,
    query: str,
    dbname: str,
    port: int,
    host: str,
    user: str,
    password: str,
    print_result: bool,
    expected: Union[Iterable[Any], Literal["any"]],
) -> None:
    """Wait for a pg-compatible database (includes materialized)"""
    args = f"dbname={dbname} host={host} port={port} user={user} password={password}"
    ui.progress(f"waiting for {args} to handle {query!r}", "C")
    error = None
    for remaining in ui.timeout_loop(timeout_secs):
        try:
            conn = pg8000.connect(
                database=dbname,
                host=host,
                port=port,
                user=user,
                password=password,
                timeout=1,
            )
            # The default (autocommit = false) wraps everything in a transaction.
            conn.autocommit = True
            cur = conn.cursor()
            cur.execute(query)
            if expected == "any" and cur.rowcount == -1:
                ui.progress("success!", finish=True)
                return
            result = list(cur.fetchall())
            if expected == "any" or result == expected:
                if print_result:
                    say(f"query result: {result}")
                else:
                    ui.progress("success!", finish=True)
                return
            else:
                say(
                    f"host={host} port={port} did not return rows matching {expected} got: {result}"
                )
        except Exception as e:
            ui.progress(" " + str(int(remaining)))
            error = e
    ui.progress(finish=True)
    raise UIError(f"never got correct result for {args}: {error}")
Exemple #2
0
 def run(self, comp: Composition, workflow: Workflow) -> None:
     pattern = f"{comp.name}_{self._container}"
     ui.progress(f"Ensuring {self._container} stays up ", "C")
     for i in range(self._uptime_secs, 0, -1):
         time.sleep(1)
         try:
             stdout = spawn.capture(["docker", "ps", "--format={{.Names}}"],
                                    unicode=True)
         except subprocess.CalledProcessError as e:
             raise Failed(f"{e.stdout}")
         found = False
         for line in stdout.splitlines():
             if line.startswith(pattern):
                 found = True
                 break
         if not found:
             print(f"failed! {pattern} logs follow:")
             print_docker_logs(pattern, 10)
             raise Failed(f"container {self._container} stopped running!")
         ui.progress(f" {i}")
     print()
Exemple #3
0
def wait_for_mysql(timeout_secs: int, user: str, passwd: str, host: str,
                   port: int) -> None:
    args = f"mysql user={user} host={host} port={port}"
    ui.progress(f"waitng for {args}", "C")
    error = None
    for _ in ui.timeout_loop(timeout_secs):
        try:
            conn = pymysql.connect(user=user,
                                   passwd=passwd,
                                   host=host,
                                   port=port)
            with conn.cursor() as cur:
                cur.execute("SELECT 1")
                result = cur.fetchone()
            if result == (1, ):
                print(f"success!")
                return
            else:
                print(f"weird, {args} did not return 1: {result}")
        except Exception as e:
            ui.progress(".")
            error = e
    ui.progress(finish=True)

    raise Failed(f"Never got correct result for {args}: {error}")
Exemple #4
0
 def run(self, comp: Composition, workflow: Workflow) -> None:
     ui.progress(
         f"waiting for {self._host}:{self._port}",
         "C",
     )
     for remaining in ui.timeout_loop(self._timeout_secs):
         cmd = f"docker run --rm -t --network {comp.name}_default ubuntu:bionic-20200403".split(
         )
         cmd.extend([
             "timeout",
             str(self._timeout_secs),
             "bash",
             "-c",
             f"cat < /dev/null > /dev/tcp/{self._host}/{self._port}",
         ])
         try:
             spawn.capture(cmd, unicode=True, stderr_too=True)
         except subprocess.CalledProcessError as e:
             ui.log_in_automation(
                 "wait-for-tcp ({}:{}): error running {}: {}, stdout:\n{}\nstderr:\n{}"
                 .format(
                     self._host,
                     self._port,
                     ui.shell_quote(cmd),
                     e,
                     e.stdout,
                     e.stderr,
                 ))
             ui.progress(" {}".format(int(remaining)))
         else:
             ui.progress(" success!", finish=True)
             return
     raise Failed(f"Unable to connect to {self._host}:{self._port}")
Exemple #5
0
    def run(self, workflow: Workflow) -> None:
        ui.progress(f"waiting for {self._host}:{self._port}", "C")
        for remaining in ui.timeout_loop(self._timeout_secs):
            cmd = f"docker run --rm -t --network {workflow.composition.name}_default ubuntu:bionic-20200403".split()

            try:
                executed = _check_tcp(
                    cmd[:], self._host, self._port, self._timeout_secs
                )
            except subprocess.CalledProcessError as e:
                ui.progress(" {}".format(int(remaining)))
            else:
                ui.progress(" success!", finish=True)
                return

            for dep in self._dependencies:
                host, port = dep["host"], dep["port"]
                try:
                    _check_tcp(
                        cmd[:], host, port, self._timeout_secs, kind="dependency "
                    )
                except subprocess.CalledProcessError as e:
                    message = f"Dependency is down {host}:{port}"
                    if "hint" in dep:
                        message += f"\n    hint: {dep['hint']}"
                    raise errors.Failed(message)

        raise errors.Failed(f"Unable to connect to {self._host}:{self._port}")
Exemple #6
0
def wait(
    condition: str, resource: str, timeout_secs: int = 300, context: str = "kind-kind"
) -> None:
    cmd = [
        "kubectl",
        "wait",
        "--for",
        condition,
        resource,
        "--timeout",
        f"{timeout_secs}s",
        "--context",
        context,
    ]
    ui.progress(f'waiting for {" ".join(cmd)} ... ')

    error = None
    for remaining in ui.timeout_loop(timeout_secs, tick=0.1):
        try:
            output = subprocess.check_output(cmd, stderr=subprocess.STDOUT).decode(
                "ascii"
            )
            # output is:
            # - an empty string when a 'delete' condition is satisfied
            # - 'condition met' for all other conditions
            if len(output) == 0 or "condition met" in output:
                ui.progress("success!", finish=True)
                return
        except subprocess.CalledProcessError as e:
            print(e, e.output)
            error = e

    ui.progress(finish=True)
    raise UIError(f"kubectl wait never returned 'condition met': {error}")
Exemple #7
0
def wait_for_pg(
    timeout_secs: int,
    query: str,
    dbname: str,
    port: int,
    host: str,
    print_result: bool,
    expected: Union[Iterable[Any], Literal["any"]],
) -> None:
    """Wait for a pg-compatible database (includes materialized)
    """
    args = f"dbname={dbname} host={host} port={port} user=ignored"
    ui.progress(f"waiting for {args} to handle {query!r}", "C")
    error = None
    if isinstance(expected, tuple):
        expected = list(expected)
    for remaining in ui.timeout_loop(timeout_secs):
        try:
            conn = pg8000.connect(database=dbname,
                                  host=host,
                                  port=port,
                                  user="******",
                                  timeout=1)
            cur = conn.cursor()
            cur.execute(query)
            result = cur.fetchall()
            found_result = False
            for row in result:
                if expected == "any" or list(row) == expected:
                    if not found_result:
                        found_result = True
                        ui.progress(" up and responding!", finish=True)
                        if print_result:
                            say("query result:")
                    if print_result:
                        print(" ".join([str(r) for r in row]))
            if found_result:
                return
            else:
                say(f"host={host} port={port} did not return any row matching {expected} got: {result}"
                    )
        except Exception as e:
            ui.progress(" " + str(int(remaining)))
            error = e
    ui.progress(finish=True)
    raise Failed(f"never got correct result for {args}: {error}")
Exemple #8
0
    def wait_for_tcp(
        self,
        *,
        host: str = "localhost",
        port: int,
        timeout_secs: int = 240,
    ) -> None:
        ui.progress(f"waiting for {host}:{port}", "C")
        for remaining in ui.timeout_loop(timeout_secs):
            cmd = f"docker run --rm -t --network {self.name}_default ubuntu:focal-20210723".split()

            try:
                _check_tcp(cmd[:], host, port, timeout_secs)
            except subprocess.CalledProcessError:
                ui.progress(" {}".format(int(remaining)))
            else:
                ui.progress(" success!", finish=True)
                return

        ui.progress(" error!", finish=True)
        raise UIError(f"unable to connect to {host}:{port}")
Exemple #9
0
 def wait_for_tcp(
     self,
     *,
     host: str = "localhost",
     port: Union[int, str],
     timeout_secs: int = 240,
 ) -> None:
     if isinstance(port, str):
         port = int(port.split(":")[0])
     ui.progress(f"waiting for {host}:{port}", "C")
     cmd = f"docker run --rm -t --network {self.name}_default ubuntu:focal-20210723".split()
     try:
         _check_tcp(cmd[:], host, port, timeout_secs)
     except subprocess.CalledProcessError:
         ui.progress(" error!", finish=True)
         raise UIError(f"unable to connect to {host}:{port}")
     else:
         ui.progress(" success!", finish=True)
Exemple #10
0
 def run(self, comp: Composition) -> None:
     ui.progress(
         f"waiting for {self._host}:{self._port}",
         "C",
     )
     for remaining in ui.timeout_loop(self._timeout_secs):
         cmd = f"docker run --rm -it --network {comp.name}_default ubuntu:bionic-20200403".split(
         )
         cmd.extend([
             "timeout",
             str(self._timeout_secs),
             "bash",
             "-c",
             f"cat < /dev/null > /dev/tcp/{self._host}/{self._port}",
         ])
         try:
             spawn.capture(cmd, unicode=True, stderr_too=True)
         except subprocess.CalledProcessError:
             ui.progress(" {}".format(int(remaining)))
         else:
             ui.progress(" success!", finish=True)
             return
     raise Failed(f"Unable to connect to {self._host}:{self._port}")
Exemple #11
0
 def run_for_duration(self, container_id: str) -> None:
     ui.progress(f"running for {self._duration} ", "C")
     for _ in ui.timeout_loop(self._duration):
         self.stop_and_start(container_id)
     ui.progress(finish=True)