Giter Site home page Giter Site logo

paritytech / zombienet Goto Github PK

View Code? Open in Web Editor NEW
147.0 5.0 85.0 13.74 MB

A cli tool to easily spawn ephemeral Polkadot/Substrate networks and perform tests against them.

Home Page: https://paritytech.github.io/zombienet/

License: GNU General Public License v3.0

JavaScript 2.32% TypeScript 75.59% Dockerfile 1.57% Shell 3.15% Rust 12.28% Python 2.46% Nix 1.88% Go 0.74%
substrate testing-tools kubernetes polkadot

zombienet's Introduction

ci GitLab Status

Zombienet

A cli tool to easily spawn ephemeral Polkadot/Substrate networks and perform tests against them.

โš ๏ธ ๐Ÿšง Under Active Development ๐Ÿšง โš ๏ธ

This project is still in early stage and very much a work in progress. More features will be added, docs may be missing or outdated and api/config may change.

NOTE: polkadot-collator has recently been renamed polkadot-parachain.


What is Zombienet?

Zombienet aims to be a testing framework for Substrate based blockchains, providing a simple cli tool that allows users to spawn and test ephemeral networks. The assertions used in the tests can include on-chain storage, metrics, logs and custom javascript scripts that interact with the chain. To make it easy to define those, zombienet has a natural language built-in allowing developers to write tests as smooth as possible.

Internally zombienet is a javascript library, designed to run on Node.js and support different backend providers to run the nodes, at this moment kubernetes, podman and native are supported.

Usage

Zombienet releases are available in github. Each one provides an executable for both linux and macos created with pkg and allows to run zombienet cli without having Node.js installed but each provider defines its own requirements (e.g. k8s, podman).

Note: Currently, it is only possible to use podman for Zombienet users on Linux machines. Although podman comes with support for macOS, it is done using an internal VM and the Zombienet provider code expects podman to be running natively.

Status

At the moment Zombienet only works with local chains (e.g. rococo-local, polkadot-local, etc).

Requirements by provider

With kubernetes

Zombienet should work with any k8s cluster (e.g GKE, docker-desktop, kind) but you need to have kubectl installed to interact with your cluster.

Also, you need permission to create resources (e.g namespaces, pods and cronJobs) in the target cluster.

Using Zombienet GKE cluster (internally).

Zombienet project has it's own k8s cluster in GCP, to use it please ping Javier(@javier:matrix.parity.io) in element to gain access and steps to use.

With Podman

Zombienet supports Podman rootless as provider, you only need to have podman installed in your environment to use and either set in the network file or with the --provider flag in the cli. Podman for zombienet is currently only supported for Linux machines. This is mostly related to paths and directories used by store configuration (chain-spec) and the data directory.

With Native

Zombienet native provider allows you to run the nodes as a local process in your environment. You only need to have the binaries used in your network (e.g polkadot or polkadot-parachain). To use it either set in the network file or with the --provider flag in the cli.

NOTE: The native provider only uses the command config for nodes/collators, both relative and absolute paths are supported. You can use default_command config to set the binary to spawn all the nodes in the relay chain.

Alternative: You can set the command to the binary directly if is available in your PATH.

Features by provider

kubernetes

With k8s zombienet use "Prometheus operator" (if it is available) to offload the monitoring/visibility layer, so only the network's pods are deployed by zombienet.

Podman

With podman zombienet deploys a couple of extra pods to add a layer of monitoring/visibility to the running network. In particular pods for prometheus, tempo and grafana are deployed. Also, grafana is configured to have prometheus and tempo as datasource.

To access those services you can find the url in the output of zombinet:

  Monitor: prometheus - url: http://127.0.0.1:34123

  Monitor: tempo - url: http://127.0.0.1:34125

  Monitor: grafana - url: http://127.0.0.1:41461

Note: Grafana is deployed with the default admin access.

Once the network is stopped, by ctrl+c on a running spawn or by finishing the test, these pods are removed with the rest of the pods launched by zombienet.

Native

Native provider doesn't run any extra layer/process at the moment.


Cli usage

For this example we will use the macos version of the executable

โฏ ./zombienet-macos
Usage: zombienet [options] [command]

Options:
  -c, --spawn-concurrency <concurrency>  Number of concurrent spawning process to launch, default is 1
  -p, --provider <provider>              Override provider to use (choices: "podman", "kubernetes", "native")
                                         default: kubernetes
  -l, --logType <logType>                Type of logging on the console - defaults to 'table' (choices: "table", "text", "silent")
  -d, --dir <path>                       Directory path for placing the network files instead of random temp one (e.g. -d /home/user/my-zombienet)
  -f, --force                            Force override all prompt commands
  -m, --monitor                          Start as monitor, do not auto cleanup network
  -h, --help                             display help for command

Commands:
  spawn <networkConfig> [creds]  Spawn the network defined in the config
  test <testFile>                Run tests on the network defined
  version                        Prints zombienet version
  help [command]                 display help for command

Configuration files and examples

Spawning

One of the goals of zombienet is to easily spawn ephemeral networks, providing a simple but powerful cli that allows you to declare the desired network in toml or json format. You can check the definition spec to view the available options.

A minimal configuration example with two validators and one parachain:

[settings]
timeout = 1000

[relaychain]
default_image = "paritypr/polkadot-debug:master"
chain = "rococo-local"

  [[relaychain.nodes]]
  name = "alice"

  [[relaychain.nodes]]
  name = "bob"

[[parachains]]
id = 100

  [parachains.collator]
  name = "collator01"
  image = "paritypr/colander:master"
  command = "adder-collator"

Then you can spawn the network by running the following command:

โฏ ./zombienet-macos spawn --provider native examples/0001-small-network.toml

Note that the command expects two binaries polkadot and adder-collator to be installed on your system. See further down for how to get them.

You can follow the output of the steps to spawn the network and once the network is launched a message with the nodes information like this one is shown

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                                                       Network launched ๐Ÿš€๐Ÿš€                                                  โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Namespace               โ”‚ zombie-72a1e2ffad0ad73167061bbd560e0766                                                            โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Provider                โ”‚ native                                                                                             โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                         Node Information                                                     โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Name                    โ”‚ alice                                                                                              โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Direct Link             โ”‚ https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:45589#/explorer                                   โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Prometheus Link         โ”‚ http://127.0.0.1:44107/metrics                                                                     โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Log Cmd                 โ”‚ tail -f  /tmp/zombie-85391d4649f2829bb26b30d6c0328bcb_-15819-BNFoSs5qusWH/alice.log                โ”‚ 
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                         Node Information                                                     โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Name                    โ”‚ bob                                                                                                โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Direct Link             โ”‚ https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:46459#/explorer                                   โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Prometheus Link         โ”‚ http://127.0.0.1:43831/metrics                                                                     โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Log Cmd                 โ”‚ tail -f  /tmp/zombie-85391d4649f2829bb26b30d6c0328bcb_-15819-BNFoSs5qusWH/bob.log                  โ”‚ 
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                                                         Node Information                                                     โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Name                    โ”‚ collator01                                                                                         โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Direct Link             โ”‚ https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:42607#/explorer                                   โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Prometheus Link         โ”‚ http://127.0.0.1:38281/metrics                                                                     โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Log Cmd                 โ”‚ tail -f  /tmp/zombie-85391d4649f2829bb26b30d6c0328bcb_-15819-BNFoSs5qusWH/collator01.log           โ”‚ 
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Parachain ID            โ”‚ 100                                                                                                โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”‚ ChainSpec Path          โ”‚ /tmp/zombie-85391d4649f2829bb26b30d6c0328bcb_-15819-BNFoSs5qusWH/rococo-local-100.json             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Both the prometheus and the node links are accessible in your local machine to get the metrics or connect to the node.

Using env variables in network config

Zombienet can also make replacements in the network config using environment variables. To define a replacement you need to use the {{ENV_VAR_NAME}} syntax.

For example, from the previous example but using env variables could be:

[relaychain]
default_image = "{{ZOMBIENET_INTEGRATION_TEST_IMAGE}}"
chain = "rococo-local"

  [[relaychain.nodes]]
  name = "alice"

  [[relaychain.nodes]]
  name = "bob"

[[parachains]]
id = 100
add_to_genesis = false

  [parachains.collator]
  name = "collator01"
  image = "{{COL_IMAGE}}"
  command = "adder-collator"

Then you can export the needed values before you run the command to spawn the network again:

โฏ export ZOMBIENET_INTEGRATION_TEST_IMAGE=docker.io/paritypr/polkadot-debug:master
โฏ export COL_IMAGE=docker.io/paritypr/colander:master

./zombienet-macos spawn examples/0001-small-network.toml
Teardown

You can teardown the network (and cleanup the used resources) by terminating the process (ctrl+c).


Testing

The other goal of zombienet is to provide a way to perform test/assertions against the spawned network, using a set of natural language expressions that allow you to make assertions based on metrics, logs and some built-in function that query the network using polkadot.js. Those assertions should be defined in a .zndsl test, and the dsl (Domain Specific Language) and format is documented in here.

The following is a small example to spawn a network (using the previous simple network definition) and assert that:

  • Both nodes are running
  • The defined parachain is registered
  • The defined parachain is producing blocks and produced at least 10 within 200 seconds.
Description: Simple Network Smoke Test
Network: ./0001-small-network.toml
Creds: config

alice: is up
bob: is up
alice: parachain 100 is registered within 225 seconds
alice: parachain 100 block height is at least 10 within 200 seconds

Other examples are provided in the examples directory.


Development

Requirements

  • Node.js if you are not using the self contained linux or macos releases.
  • Kubernetes cluster to use kubernetes target (kubectl command installed).
  • Podman to use podman target.

Installation

You need first to clone this repository and run:

โฏ cd zombienet/javascript
โฏ npm i && npm run build

Download and install needed artifacts (optional)

For an easier and faster setup of your local environment, run:

โฏ cd zombinet/javascript
โฏ npm i && npm run zombie -- setup <binaries>

This allows to use the setup script, making everything ready for a ZombieNet dev environment.

You can use the following arguments:

--help shows the different options and commands for using the Zombienet CLI. --binaries or -b: enables providing the binaries that you want to be downloaded and installed during the setup. Possible options: all, polkadot, polkadot-parachain. Note: Downloading polkadot will automatically download also the binaries of polkadot-prepare-worker, polkadot-execute-worker. Since Polkadot v1.0 all 3 binaries are needed for the node to run as a validator; For example:

โฏ cd zombinet/javascript
โฏ npm i && npm run zombie -- setup polkadot polkadot-parachain

Note: If you are using macOS please clone the polkadot-sdk repo and run it locally. At the moment there is no polkadot binary for MacOs.

The command above will retrieve the binaries provided and try to download and prepare those binaries for usage. At the end of the download, the setup script will provide a command to run in your local environment in order to add the directory where the binaries were downloaded in your $PATH var, for example:

Please add the dir to your $PATH by running the command: export PATH=/home/<user>/zombienet/dist:$PATH

Build adder-collator (needed for running examples with native provider)

You can build it from source like this

โฏ git clone [email protected]:paritytech/polkadot-sdk.git
โฏ cd polkadot-sdk
โฏ cargo build --profile testnet -p test-parachain-adder-collator
โฏ export PATH=$(pwd)/target/testnet:$PATH

Using Zombienet

With the above steps completed, the zombienet CLI is ready to run:

โฏ cd zombinet/javascript
โฏ npm run zombie

Usage: zombienet [options] [command]

Options:
  -c, --spawn-concurrency <concurrency>    Number of concurrent spawning process to launch, default is 1
  -p, --provider <provider>                Override provider to use (choices: "podman", "kubernetes", "native")
  -l, --logType <logType>                  Type of logging - defaults to 'table' (choices: "table", "text", "silent")
  -d, --dir <path>                         Directory path for placing the network files instead of random temp one 
                                           (e.g. -d /home/user/my-zombienet)
  -f, --force                              Force override all prompt commands
  -h, --help                               display help for command

Commands:
  spawn [options] <networkConfig> [creds]  Spawn the network defined in the config
  test <testFile> [runningNetworkSpec]     Run tests on the network defined
  setup [options] <binaries...>            Setup is meant for downloading and making dev environment of ZombieNet ready
  convert <filePath>                       Convert is meant for transforming a (now deprecated) polkadot-launch configuration to zombienet configuration
  version                                  Prints zombienet version
  help [command]                           display help for command

With nix run nix run github:paritytech/zombienet or add inputs.zombienet.url = "github:paritytech/zombienet"; to flake.

Projects using Zombienet

Below can be found some of the projects that are currently using Zombienet as integration or as a testing framework:

In Parity:

In the Polkadot ecosystem:

Acknowledgement

This project takes inspiration and some patterns from polkadot-launch and simnet.

zombienet's People

Contributors

alvicsam avatar bkchr avatar cuteolaf avatar dastanbeksamatov avatar davxy avatar dependabot[bot] avatar dzmitry-lahoda avatar emamihe avatar forgetso avatar gioyik avatar l0r1s avatar mergify[bot] avatar michalkucharczyk avatar mrcnski avatar muctepdayh16 avatar mutantcornholio avatar nvengal avatar oleg-plakida avatar omahs avatar pepoviola avatar rgoulter avatar samelamin avatar sandreim avatar sergejparity avatar skunert avatar svyatonik avatar tobbelobb avatar wirednkod avatar zdave-parity avatar zombienet-push-commit-bot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

zombienet's Issues

Provide loki url

Currently zombie-${key} is shown as the podname, I'd love to have a directly valid url that has already the relevant query integrated to see the logs of this pod

Use full metric names to make assertions

We need to remove the logic that remove the prefix and also the well known metrics. Also, update the test used in the ci to use the full name of the metric.

Example

   1) alice: reports polkadot_pvf_preparation_time_bucket{le="1"} is at least 1
    โœ” alice: reports pvf_preparation_time_bucket{le="1"} is at least 1 (224ms)

We should support polkadot_pvf_preparation_time_bucket{le="1"} and drop pvf_preparation_time_bucket{le="1"}.

Prometheus histogram matcher

Something like alice: reports histogram pvf_execution_time has at last X samples in buckets ["0.2", "1.0", "3.0"] IMO provides enough flexibility.

[Docs] Improve docs with examples/use cases

Improve docs with:

spawn

  • Steps to run locally.
  • Steps to run in zombienet cluster (including auth with gcloud).
  • Simple use case (2 validators / 1 parachain).
  • Wococo use case.
  • Overrides example.
  • Provide a chain-spec file.
  • Register parachain.

test

  • metrics assertion
  • commands

Integrate chain state / RPC queries into the test spec

Currently we rely entirely on prometheus metrics for asserts.

This will soon be insufficient for more involved test cases, hence we need a way to introspect the chain state.

We should start with subscribing to chain events Event.

[bug] dup bootnodes

set add_to_bootnodes = true in both generate dup bootnodes for bob.

[relaychain]
default_image = "docker.io/paritypr/synth-wave:4131-0.9.12-ccd09bbf-29a1ac18"
chain = "rococo-local"
command = "polkadot"

  [[relaychain.nodes]]
  name = "alice"
  validator = true
  extra_args = [ "--alice", "-lparachain=debug" ]
  add_to_bootnodes = true

  [[relaychain.nodes]]
  name = "bob"
  validator = true
  extra_args = [ "--bob", "-lparachain=debug" ]
  add_to_bootnodes = true

Add timestamps on test progress output

Currently it is hard to reason about how the test is going in terms of latency. It would be useful to have each line of output be prefixed with the timestamp.

getMetric() results in retries (up to cmd timeout) when metric is undefined

This happens when matching for 0 values eve: reports parachain_candidate_dispute_concluded{validity="invalid"} is 0 within 200 seconds. The metric with that label is not present because there were no disputes concluded invalid.

Many retries:
zombie::network-node fetching metrics - q: 106 time: Fri Feb 04 2022 10:41:33 GMT+0000 (Coordinated Universal Time) +1s zombie::network-node current value: undefined for metric parachain_candidate_dispute_concluded{validity="invalid"}, keep trying... +41ms

Proposed solution: treat undefined as 0.

`jaeger` spans

As an additional mean of information input, we could also use the existing jaeger-Span annotations, mapped to prometheus metrics. https://github.com/paritytech/dot-jaeger already did this successfully to a smaller extent.

Must be integrated into the test definition as well.

[overrides] do we need `remote_name`

Is not useful when the name of the binary is the same we want to override. e.g.

  [[relaychain.nodes]]
  name = "alice"
  extra_args = [ "--alice" ]
    [[relaychain.nodes.overrides]]
    local_path = "/local/path/to/polkadot"
    remote_name = "polkadot"

but is useful when is different, e.g

  [[relaychain.nodes]]
  name = "alice"
  extra_args = [ "--alice" ]
    [[relaychain.nodes.overrides]]
    local_path = "../bye"
    remote_name = "polkadot" 

We could make remote_name optional to make the config more clear.

Parachain chainspec Path does not exist

When running zombienet for @substrate/connect for a scenario where parachain is used, the outcome JSON used in the tests does not contain the chainspec of the parachain, which based on the API of substrate/connect is essential in order to connect with the light client.
The chainspec at the moment is provided as:

{
  "chainSpecPath": "/tmp/zombie-0f364056fe48d2d37b9c79e6f374504b_-70536-6qZpufzfhHyo/wococo-local.json",
  "relay": [
    {
     ...
     "paras": {
          "100": { 
               ...

I would suggest to include the parachain spec as:

{
  "chainSpecPath": "/tmp/zombie-0f364056fe48d2d37b9c79e6f374504b_-70536-6qZpufzfhHyo/wococo-local.json",
  "relay": [
    {
     ...
     "paras": {
          "100": {
               "chainSpecPath": "/tmp/zombie-0f364056fe48d2d37b9c79e6f374504b_-70536-6qZpufzfhHyo/wococo-local-parachain.json", 
               ...

cc @pepoviola

Sporadic stalls

Sporadically tests fail to launch, this is very intermittent.

Allow local execution

Currently it is required to have access to a kubernetes cluster, with binary overrides and the smoke tests, it's often faster + easier to run them locally via means of podman.

Suggestion:

Introduce a abstraction to use podman in place of kubernetes.

[Edited] Improve error log description - Global upload appears to start before upload of override binary

cat ./zombienet_tests/parachains/0001-parachains-smoke-test.toml 
[settings]
timeout = 1000

[relaychain]
default_image = "{{ZOMBIENET_INTEGRATION_TEST_IMAGE}}"
chain = "rococo-local"
command = "polkadot"

  [[relaychain.nodes]]
  name = "alice"
  extra_args = [ "--alice" ]

  [[relaychain.nodes.env]]
  name = "RUST_LOG"
  value = "parachain=debug"

  [[relaychain.nodes.overrides]]
  local_path = "/media/supersonic1t/projects/parity/polkadot/target/release/polkadot"
  remote_name = "wonderland"

  [[relaychain.nodes]]
  name = "bob"
  extra_args = [ "--bob" ]

  [[relaychain.nodes.env]]
  name = "RUST_LOG"
  value = "parachain=debug"

  [[relaychain.nodes.overrides]]
  local_path = "/media/supersonic1t/projects/parity/polkadot/target/release/polkadot"
  remote_name = "builder"

[[parachains]]
id = 100
addToGenesis = false

  [parachains.collator]
  name = "collator01"
  image = "{{COL_IMAGE}}"
  command = "/usr/local/bin/adder-collator"

[types.Header]
number = "u64"
parent_hash = "Hash"
post_state = "Hash"

DEBUG=zombie* node ../zombienet/dist/cli.js test ./zombienet_tests/parachains/0001-parachains-smoke-test.feature | tee log2.txt 2>&1  


  ( Smoke Test )
	 Launching network... this can take a while.
  zombie {
  zombie     "relaychain": {
  zombie         "defaultImage": "docker.io/paritypr/synth-wave:4555-0.9.13-acbc33c-e60ff27f",
  zombie         "nodes": [
  zombie             {
  zombie                 "name": "alice",
  zombie                 "command": "polkadot",
  zombie                 "image": "docker.io/paritypr/synth-wave:4555-0.9.13-acbc33c-e60ff27f",
  zombie                 "wsPort": 9933,
  zombie                 "port": 30333,
  zombie                 "chain": "rococo-local",
  zombie                 "args": [
  zombie                     "--alice"
  zombie                 ],
  zombie                 "env": [
  zombie                     {
  zombie                         "name": "COLORBT_SHOW_HIDDEN",
  zombie                         "value": "1"
  zombie                     },
  zombie                     {
  zombie                         "name": "RUST_BACKTRACE",
  zombie                         "value": "FULL"
  zombie                     },
  zombie                     {
  zombie                         "name": "RUST_LOG",
  zombie                         "value": "parachain=debug"
  zombie                     }
  zombie                 ],
  zombie                 "bootnodes": [
  zombie                     "/dns/bootnode/tcp/30333/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp"
  zombie                 ],
  zombie                 "telemetryUrl": "",
  zombie                 "telemetry": false,
  zombie                 "prometheus": false,
  zombie                 "overrides": [
  zombie                     {
  zombie                         "local_path": "/media/supersonic1t/projects/parity/polkadot/target/release/polkadot",
  zombie                         "remote_name": "wonderland"
  zombie                     }
  zombie                 ]
  zombie             },
  zombie             {
  zombie                 "name": "bob",
  zombie                 "command": "polkadot",
  zombie                 "image": "docker.io/paritypr/synth-wave:4555-0.9.13-acbc33c-e60ff27f",
  zombie                 "wsPort": 9933,
  zombie                 "port": 30333,
  zombie                 "chain": "rococo-local",
  zombie                 "args": [
  zombie                     "--bob"
  zombie                 ],
  zombie                 "env": [
  zombie                     {
  zombie                         "name": "COLORBT_SHOW_HIDDEN",
  zombie                         "value": "1"
  zombie                     },
  zombie                     {
  zombie                         "name": "RUST_BACKTRACE",
  zombie                         "value": "FULL"
  zombie                     },
  zombie                     {
  zombie                         "name": "RUST_LOG",
  zombie                         "value": "parachain=debug"
  zombie                     }
  zombie                 ],
  zombie                 "bootnodes": [
  zombie                     "/dns/bootnode/tcp/30333/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp"
  zombie                 ],
  zombie                 "telemetryUrl": "",
  zombie                 "telemetry": false,
  zombie                 "prometheus": false,
  zombie                 "overrides": [
  zombie                     {
  zombie                         "local_path": "/media/supersonic1t/projects/parity/polkadot/target/release/polkadot",
  zombie                         "remote_name": "builder"
  zombie                     }
  zombie                 ]
  zombie             }
  zombie         ],
  zombie         "chain": "rococo-local",
  zombie         "overrides": [],
  zombie         "chainSpecCommand": "polkadot build-spec --chain rococo-local --disable-default-bootnode"
  zombie     },
  zombie     "parachains": [
  zombie         {
  zombie             "id": 100,
  zombie             "addToGenesis": false,
  zombie             "collator": {
  zombie                 "name": "collator",
  zombie                 "command": "/usr/local/bin/adder-collator",
  zombie                 "image": "docker.io/paritypr/colander:4555-acbc33c9",
  zombie                 "chain": "rococo-local",
  zombie                 "args": [],
  zombie                 "env": [],
  zombie                 "bootnodes": [
  zombie                     "/dns/bootnode/tcp/30333/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp"
  zombie                 ],
  zombie                 "substrateRole": "collator"
  zombie             },
  zombie             "genesisWasmGenerator": "/usr/local/bin/adder-collator export-genesis-wasm > /cfg/genesis-wasm",
  zombie             "genesisStateGenerator": "/usr/local/bin/adder-collator export-genesis-state > /cfg/genesis-state"
  zombie         }
  zombie     ],
  zombie     "settings": {
  zombie         "timeout": 1000
  zombie     },
  zombie     "types": {
  zombie         "Header": {
  zombie             "number": "u64",
  zombie             "parent_hash": "Hash",
  zombie             "post_state": "Hash"
  zombie         }
  zombie     }
  zombie } +0ms
  zombie 	 Temp Dir: /tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9 +3ms
	 Launching network under namespace: zombie-a54d098ddd6929d09a3209048a68ffbd
  zombie 	 Launching network under namespace: zombie-a54d098ddd6929d09a3209048a68ffbd +0ms
  zombie::kube::client {
  zombie::kube::client   apiVersion: 'v1',
  zombie::kube::client   kind: 'Namespace',
  zombie::kube::client   metadata: { name: 'zombie-a54d098ddd6929d09a3209048a68ffbd' }
  zombie::kube::client } +0ms
  zombie Creating bootnode and backchannel services +651ms
  zombie::kube::client launching temp pod with image docker.io/paritypr/synth-wave:4555-0.9.13-acbc33c-e60ff27f +4s
  zombie::kube::client command: bash -c polkadot build-spec --chain rococo-local --disable-default-bootnode > /cfg/rococo-local.json && until [ -f /tmp/finished.txt ]; do echo waiting for copy files to finish; sleep 1; done; echo copy files has finished +0ms
  zombie::kube::client {
  zombie::kube::client   apiVersion: 'v1',
  zombie::kube::client   kind: 'Pod',
  zombie::kube::client   metadata: {
  zombie::kube::client     name: 'temp',
  zombie::kube::client     labels: {
  zombie::kube::client       role: 'full-node',
  zombie::kube::client       app: 'zombienet',
  zombie::kube::client       'app.kubernetes.io/name': 'zombie-a54d098ddd6929d09a3209048a68ffbd',
  zombie::kube::client       'app.kubernetes.io/instance': 'temp'
  zombie::kube::client     },
  zombie::kube::client     annotations: { 'prometheus.io/scrape': 'true', 'prometheus.io/port': '9615' }
  zombie::kube::client   },
  zombie::kube::client   spec: {
  zombie::kube::client     hostname: 'temp',
  zombie::kube::client     containers: [ [Object] ],
  zombie::kube::client     initContainers: [ [Object] ],
  zombie::kube::client     restartPolicy: 'OnFailure',
  zombie::kube::client     volumes: [ [Object] ]
  zombie::kube::client   }
  zombie::kube::client } +364ms
  zombie::kube::client copyFileToPod [
  'cp',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/finished.txt',
  'temp:/tmp/finished.txt',
  '-c',
  'transfer-files-container'
] +3s
  zombie::kube::client { exitCode: 0, stdout: '' } +651ms
  zombie::kube::client temp pod is ready! +4s
  zombie::kube::chain-spec copy file from pod +0ms
  zombie::kube::client copyFileFromPod [
  'cp',
  'temp:/cfg/rococo-local.json',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/rococo-local.json',
  '-c',
  'temp'
] +1ms
  zombie::kube::client { exitCode: 0, stdout: "tar: Removing leading `/' from member names" } +2s
  zombie::kube::client copyFileToPod [
  'cp',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/finished.txt',
  'temp:/tmp/finished.txt',
  '-c',
  'temp'
] +1ms
  zombie::kube::client { exitCode: 0, stdout: '' } +625ms

๐Ÿงน Starting with a fresh authority set...
  ๐Ÿ‘ค Added Genesis Authority alice - 5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY
  ๐Ÿ‘ค Added Genesis Authority bob - 5HpG9w8EBLe5XCrbczpwq5TSXvedjrBGCwqxK1iQ7qUsSWFc
launching temp-collator pod with image docker.io/paritypr/colander:4555-acbc33c9
command: bash -c /usr/local/bin/adder-collator export-genesis-state > /cfg/genesis-state && /usr/local/bin/adder-collator export-genesis-wasm > /cfg/genesis-wasm && until [ -f /tmp/finished.txt ]; do echo waiting for copy files to finish; sleep 1; done; echo copy files has finished
  zombie::kube::client {
  zombie::kube::client   apiVersion: 'v1',
  zombie::kube::client   kind: 'Pod',
  zombie::kube::client   metadata: {
  zombie::kube::client     name: 'temp-collator',
  zombie::kube::client     labels: {
  zombie::kube::client       role: 'full-node',
  zombie::kube::client       app: 'zombienet',
  zombie::kube::client       'app.kubernetes.io/name': 'zombie-a54d098ddd6929d09a3209048a68ffbd',
  zombie::kube::client       'app.kubernetes.io/instance': 'temp-collator'
  zombie::kube::client     },
  zombie::kube::client     annotations: { 'prometheus.io/scrape': 'true', 'prometheus.io/port': '9615' }
  zombie::kube::client   },
  zombie::kube::client   spec: {
  zombie::kube::client     hostname: 'temp-collator',
  zombie::kube::client     containers: [ [Object] ],
  zombie::kube::client     initContainers: [ [Object] ],
  zombie::kube::client     restartPolicy: 'OnFailure',
  zombie::kube::client     volumes: [ [Object] ]
  zombie::kube::client   }
  zombie::kube::client } +802ms
  zombie::kube::client copyFileToPod [
  'cp',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/finished.txt',
  'temp-collator:/tmp/finished.txt',
  '-c',
  'transfer-files-container'
] +4s
  zombie::kube::client { exitCode: 0, stdout: '' } +635ms
  zombie::kube::client copyFileFromPod [
  'cp',
  'temp-collator:/cfg/genesis-state',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/100/genesis-state'
] +7s
  zombie::kube::client { exitCode: 0, stdout: '' } +395ms
  zombie::kube::client copyFileFromPod [
  'cp',
  'temp-collator:/cfg/genesis-wasm',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/100/genesis-wasm'
] +0ms
  zombie::kube::client { exitCode: 0, stdout: "tar: Removing leading `/' from member names" } +412ms
  zombie::kube::client copyFileToPod [
  'cp',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/finished.txt',
  'temp-collator:/tmp/finished.txt'
] +0ms
  zombie::kube::client { exitCode: 0, stdout: '' } +598ms
  zombie::kube::client launching temp-1 pod with image docker.io/paritypr/synth-wave:4555-0.9.13-acbc33c-e60ff27f +2ms
  zombie::kube::client command: bash -c polkadot build-spec --chain /cfg/rococo-local.json --disable-default-bootnode  --raw > /cfg/rococo-local-raw.json && until [ -f /tmp/finished.txt ]; do echo waiting for copy files to finish; sleep 1; done; echo copy files has finished +0ms
  zombie::kube::client {
  zombie::kube::client   apiVersion: 'v1',
  zombie::kube::client   kind: 'Pod',
  zombie::kube::client   metadata: {
  zombie::kube::client     name: 'temp-1',
  zombie::kube::client     labels: {
  zombie::kube::client       role: 'full-node',
  zombie::kube::client       app: 'zombienet',
  zombie::kube::client       'app.kubernetes.io/name': 'zombie-a54d098ddd6929d09a3209048a68ffbd',
  zombie::kube::client       'app.kubernetes.io/instance': 'temp-1'
  zombie::kube::client     },
  zombie::kube::client     annotations: { 'prometheus.io/scrape': 'true', 'prometheus.io/port': '9615' }
  zombie::kube::client   },
  zombie::kube::client   spec: {
  zombie::kube::client     hostname: 'temp-1',
  zombie::kube::client     containers: [ [Object] ],
  zombie::kube::client     initContainers: [ [Object] ],
  zombie::kube::client     restartPolicy: 'OnFailure',
  zombie::kube::client     volumes: [ [Object] ]
  zombie::kube::client   }
  zombie::kube::client } +395ms
  zombie::kube::client copyFileToPod [
  'cp',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/rococo-local.json',
  'temp-1:/cfg/rococo-local.json',
  '-c',
  'transfer-files-container'
] +4s
  zombie::kube::client { exitCode: 0, stdout: '' } +4s
  zombie::kube::client copyFileToPod [
  'cp',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/finished.txt',
  'temp-1:/tmp/finished.txt',
  '-c',
  'transfer-files-container'
] +1ms
  zombie::kube::client { exitCode: 0, stdout: '' } +670ms
  zombie::kube::client temp-1 pod is ready! +4s
  zombie::kube::chain-spec Getting the raw chain spec file from pod to the local environment. +28s
  zombie::kube::client copyFileFromPod [
  'cp',
  'temp-1:/cfg/rococo-local-raw.json',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/rococo-local.json',
  '-c',
  'temp-1'
] +0ms
  zombie::kube::client { exitCode: 0, stdout: "tar: Removing leading `/' from member names" } +2s
  zombie::kube::client copyFileToPod [
  'cp',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/finished.txt',
  'temp-1:/tmp/finished.txt',
  '-c',
  'temp-1'
] +3ms
  zombie::kube::client { exitCode: 0, stdout: '' } +521ms
  zombie Chain name: Rococo Local Testnet +43s
  zombie::kube::client launching bootnode pod with image docker.io/paritypr/synth-wave:4555-0.9.13-acbc33c-e60ff27f +1ms
  zombie::kube::client command: /cfg/zombie-wrapper.sh polkadot --chain /cfg/rococo-local.json --name bootnode --rpc-cors all --node-key 0000000000000000000000000000000000000000000000000000000000000001 --ws-external --rpc-external --listen-addr /ip4/0.0.0.0/tcp/30333 --no-mdns --no-telemetry +0ms
  zombie::kube::client {
  zombie::kube::client   apiVersion: 'v1',
  zombie::kube::client   kind: 'Pod',
  zombie::kube::client   metadata: {
  zombie::kube::client     name: 'bootnode',
  zombie::kube::client     labels: {
  zombie::kube::client       'app.kubernetes.io/name': 'zombie-a54d098ddd6929d09a3209048a68ffbd',
  zombie::kube::client       'app.kubernetes.io/instance': 'bootnode',
  zombie::kube::client       role: 'bootnode',
  zombie::kube::client       app: 'zombienet'
  zombie::kube::client     }
  zombie::kube::client   },
  zombie::kube::client   spec: {
  zombie::kube::client     hostname: 'bootnode',
  zombie::kube::client     containers: [ [Object] ],
  zombie::kube::client     initContainers: [ [Object] ],
  zombie::kube::client     restartPolicy: 'OnFailure',
  zombie::kube::client     volumes: [ [Object] ]
  zombie::kube::client   }
  zombie::kube::client } +404ms
  zombie::kube::client copyFileToPod [
  'cp',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/rococo-local.json',
  'bootnode:/cfg/rococo-local.json',
  '-c',
  'transfer-files-container'
] +4s
  zombie::kube::client { exitCode: 0, stdout: '' } +5s
  zombie::kube::client copyFileToPod [
  'cp',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/zombie-wrapper.sh',
  'bootnode:/cfg/zombie-wrapper.sh',
  '-c',
  'transfer-files-container'
] +0ms
  zombie::kube::client { exitCode: 0, stdout: '' } +651ms
  zombie::kube::client copyFileToPod [
  'cp',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/finished.txt',
  'bootnode:/tmp/finished.txt',
  '-c',
  'transfer-files-container'
] +1ms
  zombie::kube::client { exitCode: 0, stdout: '' } +651ms
  zombie::kube::client bootnode pod is ready! +4s
  zombie::port-forwarder stdout: Forwarding from 127.0.0.1:35777 -> 9944
  zombie::port-forwarder Forwarding from [::1]:35777 -> 9944
  zombie::port-forwarder  +0ms
  zombie::port-forwarder stdout: Forwarding from 127.0.0.1:41501 -> 9615
  zombie::port-forwarder Forwarding from [::1]:41501 -> 9615
  zombie::port-forwarder  +333ms
  zombie creating node: alice +21s
  zombie::kube::client launching alice pod with image docker.io/paritypr/synth-wave:4555-0.9.13-acbc33c-e60ff27f +6s
  zombie::kube::client command: /cfg/zombie-wrapper.sh polkadot --chain /cfg/rococo-local.json --name alice --rpc-cors all --alice --no-mdns --no-telemetry --bootnodes /dns/10.24.2.56/tcp/30333/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp +0ms
  zombie::kube::client {
  zombie::kube::client   apiVersion: 'v1',
  zombie::kube::client   kind: 'Pod',
  zombie::kube::client   metadata: {
  zombie::kube::client     name: 'alice',
  zombie::kube::client     labels: {
  zombie::kube::client       role: 'full-node',
  zombie::kube::client       app: 'zombienet',
  zombie::kube::client       'app.kubernetes.io/name': 'zombie-a54d098ddd6929d09a3209048a68ffbd',
  zombie::kube::client       'app.kubernetes.io/instance': 'alice'
  zombie::kube::client     },
  zombie::kube::client     annotations: { 'prometheus.io/scrape': 'true', 'prometheus.io/port': '9615' }
  zombie::kube::client   },
  zombie::kube::client   spec: {
  zombie::kube::client     hostname: 'alice',
  zombie::kube::client     containers: [ [Object] ],
  zombie::kube::client     initContainers: [ [Object] ],
  zombie::kube::client     restartPolicy: 'OnFailure',
  zombie::kube::client     volumes: [ [Object] ]
  zombie::kube::client   }
  zombie::kube::client } +369ms
  zombie::kube::client copyFileToPod [
  'cp',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/rococo-local.json',
  'alice:/cfg/rococo-local.json',
  '-c',
  'transfer-files-container'
] +4s
  zombie::kube::client { exitCode: 0, stdout: '' } +4s
  zombie::kube::client copyFileToPod [
  'cp',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/zombie-wrapper.sh',
  'alice:/cfg/zombie-wrapper.sh',
  '-c',
  'transfer-files-container'
] +1ms
  zombie::kube::client { exitCode: 0, stdout: '' } +664ms
  zombie::kube::client copyFileToPod [
  'cp',
  '/media/supersonic1t/projects/parity/polkadot/target/release/polkadot',
  'alice:/cfg/wonderland',
  '-c',
  'transfer-files-container'
] +0ms
  zombie::kube::client { exitCode: 0, stdout: '' } +6m
  zombie::kube::client copyFileToPod [
  'cp',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/finished.txt',
  'alice:/tmp/finished.txt',
  '-c',
  'transfer-files-container'
] +0ms
  zombie::kube::client { exitCode: 0, stdout: '' } +544ms
  zombie::kube::client alice pod is ready! +3s
  zombie::port-forwarder stdout: Forwarding from 127.0.0.1:32993 -> 9944
  zombie::port-forwarder Forwarding from [::1]:32993 -> 9944
  zombie::port-forwarder  +6m
  zombie::port-forwarder stdout: Forwarding from 127.0.0.1:39755 -> 9615
  zombie::port-forwarder Forwarding from [::1]:39755 -> 9615
  zombie::port-forwarder  +226ms
  zombie creating node: bob +6m
  zombie::kube::client launching bob pod with image docker.io/paritypr/synth-wave:4555-0.9.13-acbc33c-e60ff27f +457ms
  zombie::kube::client command: /cfg/zombie-wrapper.sh polkadot --chain /cfg/rococo-local.json --name bob --rpc-cors all --bob --no-mdns --no-telemetry --bootnodes /dns/10.24.2.56/tcp/30333/p2p/12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp +0ms
  zombie::kube::client {
  zombie::kube::client   apiVersion: 'v1',
  zombie::kube::client   kind: 'Pod',
  zombie::kube::client   metadata: {
  zombie::kube::client     name: 'bob',
  zombie::kube::client     labels: {
  zombie::kube::client       role: 'full-node',
  zombie::kube::client       app: 'zombienet',
  zombie::kube::client       'app.kubernetes.io/name': 'zombie-a54d098ddd6929d09a3209048a68ffbd',
  zombie::kube::client       'app.kubernetes.io/instance': 'bob'
  zombie::kube::client     },
  zombie::kube::client     annotations: { 'prometheus.io/scrape': 'true', 'prometheus.io/port': '9615' }
  zombie::kube::client   },
  zombie::kube::client   spec: {
  zombie::kube::client     hostname: 'bob',
  zombie::kube::client     containers: [ [Object] ],
  zombie::kube::client     initContainers: [ [Object] ],
  zombie::kube::client     restartPolicy: 'OnFailure',
  zombie::kube::client     volumes: [ [Object] ]
  zombie::kube::client   }
  zombie::kube::client } +358ms
  zombie::kube::client copyFileToPod [
  'cp',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/rococo-local.json',
  'bob:/cfg/rococo-local.json',
  '-c',
  'transfer-files-container'
] +3s
  zombie::kube::client { exitCode: 0, stdout: '' } +4s
  zombie::kube::client copyFileToPod [
  'cp',
  '/tmp/zombie-a54d098ddd6929d09a3209048a68ffbd_-3202409-arhLjcKHwch9/zombie-wrapper.sh',
  'bob:/cfg/zombie-wrapper.sh',
  '-c',
  'transfer-files-container'
] +1ms
  zombie::kube::client { exitCode: 0, stdout: '' } +476ms
  zombie::kube::client copyFileToPod [
  'cp',
  '/media/supersonic1t/projects/parity/polkadot/target/release/polkadot',
  'bob:/cfg/wonderland',
  '-c',
  'transfer-files-container'
] +0ms
  zombie::kube::client { exitCode: 0, stdout: '' } +6m
  zombie::kube::client copyFileToPod [
  'cp',
  '/media/supersonic1t/projects/parity/polkadot/target/release/polkadot',
  'bob:/cfg/builder',
  '-c',
  'transfer-files-container'
] +0ms
uncaughtException
Error: GLOBAL TIMEOUT (1000 secs) 
    at Timeout._onTimeout (/media/supersonic1t/projects/parity/zombienet/dist/orchestrator.js:49:27)
    at listOnTimeout (node:internal/timers:557:17)
    at processTimers (node:internal/timers:500:7)
Error: GLOBAL TIMEOUT (1000 secs) 
    at Timeout._onTimeout (/media/supersonic1t/projects/parity/zombienet/dist/orchestrator.js:49:27)
    at listOnTimeout (node:internal/timers:557:17)
    at processTimers (node:internal/timers:500:7)

Test hangs (intermitent)

Seen this happening for paritytech/polkadot#4859
Hanged CI job: https://gitlab.parity.io/parity/polkadot/-/jobs/1374388

IIRC I have observed the hang locally but ruled it out at the time because I had my own set of changes. Not sure what's going on, but the parachains seem to be making progress and test is running - https://grafana.parity-mgmt.parity.io/explore?orgId=1&left=%5B%22now-3h%22,%22now%22,%22loki.parity-zombienet%22,%7B%22expr%22:%22%7Bpod%3D%5C%22zombie-6c8c8f76a0cc482932c2e418659f4fe4%2Falice%5C%22%7D%20%7C~%20%5C%22included%5C%22%22,%22refId%22:%22A%22,%22range%22:true%7D%5D

Unable to use multiple threads for starting up native(local) tests.

I'm getting this an error during initialization when building the chain spec:

'Command failed with exit code 1: /bin/bash -c ../polkadot/target/testnet/polkadot build-spec --chain /tmp/zombie-ed5b6f5519f111a43b207dc01e282ae1_-1183183-foPqTJ0Wokh4/rococo-local-plain.json --disable-default-bootnode  --raw > /tmp/zombie-ed5b6f5519f111a43b207dc01e282ae1_-1183183-foPqTJ0Wokh4/rococo-local-raw.json',

Reason:

"Thread 'main' panicked at 'empty validation code is not allowed in genesis', /home/sandreim/polkadot/runtime/parachains/src/paras/mod.rs:688\n" +

Looking at /tmp/zombie-ed5b6f5519f111a43b207dc01e282ae1_-1183183-foPqTJ0Wokh4/rococo-local-plain.json, some paras are missing their code and genesis state hash. This is probably a race condition during initialization. As a fix, maybe we can start the additional threads after we finish initialization.

Config:

[settings]
timeout = 1000

# [relaychain.genesis.runtime.runtime_genesis_config.configuration.config]
#   max_validators_per_core = 2
#   needed_approvals = 2

[relaychain]
default_image = "{{ZOMBIENET_INTEGRATION_TEST_IMAGE}}"
chain = "rococo-local"
chain_spec_command = "../polkadot/target/testnet/polkadot build-spec --chain rococo-local --disable-default-bootnode"
default_command = "../polkadot/target/testnet/polkadot"

[relaychain.default_resources]
limits = { memory = "4G", cpu = "2" }
requests = { memory = "2G", cpu = "1" }

  [[relaychain.nodes]]
  image = "{{MALUS_IMAGE}}"
  name = "alice"
  command = "../polkadot/target/testnet/malus dispute-ancestor --fake-validation backing-and-approval-valid"
  extra_args = [ "--alice", "-lparachain=debug" ]

  [[relaychain.nodes]]
  image = "{{MALUS_IMAGE}}"
  name = "bob"
  command = "../polkadot/target/testnet/malus dispute-ancestor --fake-validation backing-and-approval-valid"
  extra_args = [ "--bob", "-lparachain=debug"]
  
  [[relaychain.nodes]]
  image = "{{MALUS_IMAGE}}"
  name = "charlie"
  command = "../polkadot/target/testnet/malus dispute-ancestor --fake-validation backing-and-approval-valid"
  extra_args = [ "--charlie", "-lparachain=debug" ]

  [[relaychain.nodes]]
  name = "dave"
  extra_args = [ "--dave", "-lparachain=debug"]

  [[relaychain.nodes]]
  name = "ferdie"
  extra_args = [ "--ferdie", "-lparachain=debug" ]

  [[relaychain.nodes]]
  name = "eve"
  extra_args = [ "--eve", "-lparachain=debug"]

  [[relaychain.nodes]]
  name = "one"
  extra_args = [ "--one", "-lparachain=debug" ]

  [[relaychain.nodes]]
  name = "two"
  extra_args = [ "--two", "-lparachain=debug"]

[[parachains]]
id = 2000
addToGenesis = true
genesis_state_generator = "../polkadot/target/testnet/undying-collator export-genesis-state --pov-size=100000 --pvf-complexity=1"

  [parachains.collator]
  image = "{{COL_IMAGE}}"
  name = "collator01"
  command = "../polkadot/target/testnet/undying-collator"
  args = ["-lparachain=debug", "--pov-size=100000", "--pvf-complexity=1", "--parachain-id=2000"]

[[parachains]]
id = 2001
addToGenesis = true
genesis_state_generator = "../polkadot/target/testnet/undying-collator export-genesis-state --pov-size=100000 --pvf-complexity=2"

  [parachains.collator]
  image = "{{COL_IMAGE}}"
  name = "collator02"
  command = "../polkadot/target/testnet/undying-collator"
  args = ["-lparachain=debug", "--pov-size=100000", "--parachain-id=2001", "--pvf-complexity=2"]

[[parachains]]
id = 2002
addToGenesis = true
genesis_state_generator = "../polkadot/target/testnet/undying-collator export-genesis-state --pov-size=100000 --pvf-complexity=10"

  [parachains.collator]
  image = "{{COL_IMAGE}}"
  name = "collator03"
  command = "../polkadot/target/testnet/undying-collator"
  args = ["-lparachain=debug", "--pov-size=100000", "--parachain-id=2002", "--pvf-complexity=10"]

[[parachains]]
id = 2003
addToGenesis = true
genesis_state_generator = "../polkadot/target/testnet/undying-collator export-genesis-state --pov-size=20000 --pvf-complexity=1000"

  [parachains.collator]
  image = "{{COL_IMAGE}}"
  name = "collator04"
  command = "../polkadot/target/testnet/undying-collator"
  args = ["-lparachain=debug", "--pov-size=20000", "--parachain-id=2003", "--pvf-complexity=1000"]

[types.Header]
number = "u64"
parent_hash = "Hash"
post_state = "Hash"

Error logs formatting

Currently the visual discrimination between deliberate the error log and the backtrace is not very visible.

Suggestion:

Add color + boldness.

Include external toml

It would be helpful to have some sort of include(external_toml) functionality, so we can dedup these (and possible other test code):

[types.Header]
number = "u64"
parent_hash = "Hash"
post_state = "Hash"

Show progress bar for long running operations

It's sometimes not clear if zombienet stalled (i.e. a kubernetes issue, inet issue) or if a long running op is inprogress.

Prime example:

  • [override] with local_path, that uploads a 200mb binary

extrinsic-based tests

Recently we started the Ecosystem Performance Benchmarks initiative. The idea came from a call the Ecosystem Success team had with @bkchr and some teams (Acala, Astar, Enjin and Moonbeam) to discuss many topics around Parachain Performance.

The goal of this effort is to aggregate tests from the Polkadot Ecosystem into a single repository, where we can share insights into extrinsics performance.

However, after reading the Test DSL specs, I'm unsure if the DSL currently allows for the kind of testing we wanted to do. So I'm writing this issue to clarify: would it be possible for us to use zombienet to compose batch extrinsic calls and collect data from their execution? Or is that something zombienet is just not meant to do?

Metric matching consistency

Currently, we have these interfaces to parse/assert metrics:

  • natural language to query metrics (for example block height, or peer count) - Alice: reports peers count is at least 1 within 150 seconds
  • query by name - alice: reports pvf_preparation_time_bucket{le="10"} is 1

This provides a sugary syntax for the tests as in you write less, but behind the scenes the metric prefixes (substrate, polkadot) are being prepended to the metric names based on naming logic inside zombienet.

We should follow the pattern in Polkadot/Substrate so that we explicitly define the metrics and not rely on any prefixes that are added later. It will make tests more explicit and decouples the zombienet implementation from the Polkadot/Substrate metrics.

[bug] wrong collator command

without args = ["-lparachain=debug"] for cumulus collators the cmd generated is wrong.

[[parachains]]
id = 100
cumulus_based = true

  [parachains.collator]
  name = "collator1"
  image = "docker.io/paritypr/colander:4131-ccd09bbf"
  command = "polkadot-collator"

Failed to apply changes to genesis config

This specific conf fails:

[relaychain.genesis.runtime.runtime_genesis_config.configuration.config]
  max_validators_per_core = 2
  needed_approvals = 2

Result:

                 โš™ Updating Relay Chain Genesis Configuration
TypeError: Cannot convert object to primitive value
    at /home/sandreim/zombienet/dist/chain-spec.js:212:118
    at Array.forEach (<anonymous>)
    at findAndReplaceConfig (/home/sandreim/zombienet/dist/chain-spec.js:201:23)
    at /home/sandreim/zombienet/dist/chain-spec.js:138:13
    at Generator.next (<anonymous>)
    at /home/sandreim/zombienet/dist/chain-spec.js:8:71
    at new Promise (<anonymous>)
    at __awaiter (/home/sandreim/zombienet/dist/chain-spec.js:4:12)
    at changeGenesisConfig (/home/sandreim/zombienet/dist/chain-spec.js:132:12)
    at Object.<anonymous> (/home/sandreim/zombienet/dist/orchestrator.js:114:64)

Avoid duplicate upload

When specifying override binaries, often one uses the same binary multiple times. Deduplication should be handled at the client side.

High scale testing MVP

We're looking at writing an integration test suite that focuses on performance testing, more specifically on a list of key indicators that are covered in paritytech/polkadot-sdk#874. The current design of Zombienet for configuration and DSL make it an easy to write tests for single digit sized networks and provides very explicit primitives for testing metrics and logs (alice: parachain 100 block height is at least 10 within 200 seconds). I'll focus on what I think we need to implement to make writing tests easy for test scenarios of an order of magnitude larger at least.

I'm breaking down everything down into two: Test configuration and the DSL.

Test configuration

In the context of higher scale, the goal is to enable the configuration to be defined in bulk, such that we don't need to talk about individual validators and their configuration (binary and args), which is cumbersome for 100 validators for example.

Where we are at

  • The validator nodes we can spawn is currently constrained by the built in identities we can use: Alice, Bob, Charlie, Dave, Ferdie, One, Two
  • All relay chain nodes need to defined individually under the relaychain section.
  • Parachains and collators need to be individually defined

Where we want to be

  • We can create as many authority key pairs as we want and include them in the genesis block so we can spawn as many validators.
  • We can define relay chain nodes in bulk by using a three step approach:
    • Total validator count is specified in the DSL file and not in the configuration file. The idea here is that by doing so, we can reuse a configuration file for different sized networks. That would require that we will use percentages to define group sizes rather than a value. Doing so might require us to have a different way of asserting metrics, that uses a percentile based approach as well (P50, P90, P99, etc).More details on how we can test metric values in this scenario can be found in the following DSL section.
    • A relay chain node configuration which specifies the binary, args
    • A relay chain node group which defines how many nodes are to be spawned in that group and which node configuration to use. We can specify either number of nodes or percentage of the total nodes

Test scenario (DSL)

The goal is to enable writing test assertions that looks at groups of validators rather than only one.

Where we are at

  • metrics and logs can be asserted using a natural language which includes a node target, a condition and a timeout.
  • code upgrades can be triggered
  • backchannel functionality can pull information from inside the nodes ? (haven't actually tried this)
  • external custom javascript scripts can be run in the context of a validator connections (scripts implement connect/run callbacks)

Where we want to be

  • Separate DSL sections with initialization/sanitiy checks
  • Ability to write loops, such that we don't duplicate test code.
  • Use a catch all matcher: All is up
  • Use a validator group matching of metrics - ValidatorGroup1: parachain 100 block height is at least 10 within 300 seconds
  • Use percentage based assertion of metrics - ValidatorGroup1(P90): reports polkadot_parachain_disputes_finality_lag is at most 1 within 300 seconds. This example will ensure at least 90% of all validators report dispute_finality lag being 1 block.
  • Logs also have the same matching features as metrics
  • Js scripts improvements - we could embed JS directly in the test file to make things more readable, but we would want to keep external support as well, but maybe as dependencies to a test file rather than a line in the test file. Some overall context at the test level (basically support for test global variables that include the network topology, enable RPC calls, logs, metrics clients and user defined variables) and Zombienet API accesses. This would reduce the need to make the natural language more complicated by implementing things that can be easily done in Javascript.
  • I'm on the fence about if and how backchannel related features would work in this scenario. Would be great to hear some input on this from @pepoviola

Issues and other improvements

I've stumbled upon some issues or missing functionality:

  • I could not match on any collator metrics or logs. The node name is collator01, but the actual name that I must reference in the test is collator01-1, but still fails
  • My test failed to parse alice: reports polkadot_pvf_preparation_time_bucket{le="1"} is at least 1
  • Full metrics parsing support - working with histograms requires inspecting two buckets and diffing as these are cumulative. Would be great to not have to do this by hand.
  • Ability to spawn nodes in parallel, rather then doing it sequentially . This would speed up test rampup time (the time it takes for everybody to "be up" and start the actual test (especially for higher scale tests).

CI integration

It doesn't seem to be a good idea to have these tests run as part of the per PR pipeline, because of the long duration and high cost of scaling the kubernetes. My proposal is to run a subset of small scale variants of the tests on the PR pipeline and run the high scale tests at release checkpoints or on a need to basis.

That being said, it looks like a lot of work, and at the same time we want to run these high scale tests sooner rather than later. My proposal is to build this incrementally starting with what I consider to be the MVP:

  • Add support to scale validators and collators/parachains (#78) - this should include ability to generate as many authority key pairs as needed, grouping.
  • Full metrics support (includes resolving some of issues described above) along with group matching.
  • Group log matching support
  • Javascript improvements described above
  • CI: Separate PR and Release pipelines

Link to a branch with a sample test and some comments to add more context: TBD.

Node companion pod support

This is needed to allow custom tools to be used in a zombienet test for native and k8s.

  • Short term: prometheus metrics and health check support (my-companion-0: is up)
  • Longer term: backchannel integration if anything is needed .

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.