Document how the Chaos scenario is set up
What does this MR do and why?
Closes #691 (closed)
The Chaos section of docs/what_tests_can_be_run.md did not explain how the proxy fits in, which is what the review of gitlab!98019 (closed) asked for, and it had three mistakes:
- It named the scenario
Test::Instance::Chaos. That class does not exist, so the documented command fails withuninitialized constant Gitlab::QA::Scenario::Test::Instance::Chaos. The scenario isTest::Integration::Chaos. - Its example passed no release, while
performrequires one (CE,EEor an image address). - It said the scenario runs only the tests tagged
:chaos. The scenario inherits@tag = nilfromTest::Integration::Praefect, so it runsTest::Instance::Allwith no:chaosfilter unless you pass-- --tag chaos, which is what theee:chaosCI job did until it was removed in 30d11584 (March 2023).
I rewrote the section from the code:
- How the scenario is set up: the
chaosToxiproxy container and its API port, thePOST /populaterequest and why it is sent from a container on the network, a table of the five proxies with where each one forwards, thechaos.testaddresses and ports the scenario sets, and what is meant to run after that. - Writing a chaos test: the existing sample, plus what
toxicandapplydo and where to point the Toxiproxy client from the host and from the GitLab QA container. - Current status: while checking each step against
master(d18bf530) I found that the scenario no longer runs, so the page now says so.
That last part is where I would like a maintainer's view:
Test::Integration::Chaos#performcallsrun_gitaly_cluster, which the scenario lost when Gitaly and Praefect moved into components (f66dd679, December 2022). It now raisesNoMethodErrorright after it starts the Toxiproxy container, and removes that container again.- The addresses it sets (
@praefect_addr = "chaos.test"and the rest) are no longer read. GitLab, Praefect and Gitaly take theirs fromComponent::GitalyCluster::GitalyClusterConfig, which derives them from the node names and keeps Gitaly on port 8075, while the three Gitaly proxies forward to 8076, 8077 and 8078. - The QA suite in gitlab-org/gitlab has no tests tagged
:chaosand no Toxiproxy dependency. gitlab!98019 (closed), which proposed the first tests, was closed without being merged.
I kept this MR to documentation, as the issue asks, and wrote down the state as it is so that nobody follows the example and wonders why it fails. If you would rather fix the scenario or remove it, I am happy to do either in a separate MR, but I did not want to make that call in a docs change.
!1464 (merged) edits other sections of the same file and says it left the Chaos section to this issue. The two branches merge without conflicts (git merge-tree against its head 8c60d365).
Screenshots or screen recordings
Not applicable, documentation only. The runs behind every statement in the new section are below.
The documented command, and the scenario under its real name (Ruby 3.3.7, master at d18bf530)
gitlab-qa Test::Instance::Chaos:
/src/lib/gitlab/qa/runner.rb:93:in `run': uninitialized constant Gitlab::QA::Scenario::Test::Instance::Chaos (NameError)gitlab-qa Test::Integration::Chaos EE, with QA_DOCKER_NETWORK=w6chaos so that the run did not create a test network on my machine:
INFO -- Shell command: `docker run -d --name chaos --network w6chaos --publish 8474:8474 ghcr.io/shopify/toxiproxy:2.5.0`
INFO -- Shell command: `docker run --network w6chaos --rm curlimages/curl:7.85.0 -i -s -X POST http://chaos:8474/populate -H 'Content-Type: application/json' -d '[{"name":"postgres","listen":"[::]:5432","upstream":"postgres.test:5432","enabled":true},{"name":"praefect","listen":"[::]:2305","upstream":"praefect.test:2305","enabled":true},{"name":"gitaly1","listen":"[::]:8076","upstream":"gitaly1.test:8076","enabled":true},{"name":"gitaly2","listen":"[::]:8077","upstream":"gitaly2.test:8077","enabled":true},{"name":"gitaly3","listen":"[::]:8078","upstream":"gitaly3.test:8078","enabled":true}]'
INFO -- Shell command: `docker ps -f name=chaos`
INFO -- Shell command: `docker rm -f chaos`
/src/lib/gitlab/qa/scenario/test/integration/chaos.rb:25:in `perform': undefined method `run_gitaly_cluster' for an instance of Gitlab::QA::Scenario::Test::Integration::Chaos (NoMethodError)The upstream hosts stay on .test although the network was w6chaos.
What the scenario object holds, and what the containers would be configured with
perform arity: [[:req, :release], [:rest, :rspec_args]]
scenario responds to run_gitaly_cluster: false
component responds to run_gitaly_cluster: true
@tag: nil; @spec_suite: "Test::Instance::All"; @env: {:QA_PRAEFECT_REPOSITORY_STORAGE=>"default"}
config used for omnibus: praefect_addr=praefect.test praefect_port=2305 database=postgres.test:5432 primary=gitaly1.test:8075 secondary=gitaly2.test:8075 tertiary=gitaly3.test:8075
ivars set by Chaos#initialize: @praefect_addr="chaos.test" @database_addr="chaos.test" @primary_node_addr="chaos.test" @primary_node_port=8076
omnibus gitaly_address line: 'gitaly_address' => "tcp://praefect.test:2305",
component config: praefect=praefect.test:2305 database=postgres.test:5432 gitaly ports=[8075, 8075, 8075]
praefect omnibus: host: 'postgres.test', | 'address': 'tcp://gitaly1.test:8075', | 'address': 'tcp://gitaly2.test:8075', | 'address': 'tcp://gitaly3.test:8075',
gitaly default port: 8075The first config is the scenario's own, which writes the GitLab Omnibus configuration; the second is the one Component::GitalyCluster uses for Praefect and the Gitaly nodes.
The proxies and the Toxiproxy client example, against the container the component starts
I started only Component::Chaos (Gitlab::QA::Component::Chaos.new.start) and left it running.
From the host, through the published port:
$ curl -s localhost:8474/proxies | jq -c 'to_entries[] | {name: .key, listen: .value.listen, upstream: .value.upstream}'
{"name":"gitaly1","listen":"[::]:8076","upstream":"gitaly1.test:8076"}
{"name":"gitaly2","listen":"[::]:8077","upstream":"gitaly2.test:8077"}
{"name":"gitaly3","listen":"[::]:8078","upstream":"gitaly3.test:8078"}
{"name":"postgres","listen":"[::]:5432","upstream":"postgres.test:5432"}
{"name":"praefect","listen":"[::]:2305","upstream":"praefect.test:2305"}From a container on the same network, with the toxiproxy gem (2.0.2), Toxiproxy.host = 'http://chaos.w6chaos:8474' and the toxic from the sample:
toxics on gitaly1 before: []
toxics on gitaly1 inside apply: [["latency", "downstream", {"latency"=>30000, "jitter"=>0}]]
toxics on gitaly1 after: []With no host set, the client used http://127.0.0.1:8474 and listed the same five proxies from the host. A container on a user-defined network resolved <container>.<network> (here chaos.w6chaos), which is what chaos.test relies on.
The POST /populate in the scenario run reached the container by name (http://chaos:8474), which is the address the page now gives the client. I ran the same client script with Toxiproxy.host = 'http://chaos:8474' from a container on another throwaway network, w6chaos2, and checked which names resolve there:
client 2.0.2, uri http://chaos:8474
toxics on gitaly1 before: []
toxics on gitaly1 inside apply: [["latency", "downstream", {"latency"=>30000, "jitter"=>0}]]
toxics on gitaly1 after: []
chaos: resolves
chaos.w6chaos2: resolves
chaos.test: does not resolvechaos.test resolves only when the network is named test, so the page uses the container name. In the client source (2.0.2), toxic is alias_method :toxic, :downstream, and ToxicCollection#apply destroys the toxics in an ensure.
How to set up and validate locally
- Check out this branch and run
bundle install. - Run the old command,
bundle exec exe/gitlab-qa Test::Instance::Chaos, and see theNameError. - Run
bundle exec exe/gitlab-qa Test::Integration::Chaos EE. It pullsghcr.io/shopify/toxiproxy:2.5.0andcurlimages/curl:7.85.0, creates thetestDocker network if it is missing (the network stays afterwards), starts thechaoscontainer with port 8474 published, populates it, removes it and stops with theNoMethodErrorabove. - To check the proxy table and the client example, start only the component with
bundle exec ruby -Ilib -e "require 'gitlab/qa'; Gitlab::QA::Component::Chaos.new.start", then runcurl -s localhost:8474/proxies. Remove it afterwards withdocker rm -f chaos. - To see the addresses the containers would get, run
bundle exec ruby -Ilib -e "require 'gitlab/qa'; c = Gitlab::QA::Scenario::Test::Integration::Chaos.new.config; p [c.praefect_addr, c.database_node_addr, c.primary_node_addr, c.primary_node_port]", which prints["praefect.test", "postgres.test", "gitaly1.test", 8075].
I also ran the project's CI checks on the branch with Ruby 3.3.7: bundle exec rubocop (154 files, no offenses) and bundle exec rspec (446 examples, 0 failures). Neither reads the docs, but both pass.
MR acceptance checklist
This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
- Commits include
Changelog:trailer - I have evaluated the MR acceptance checklist for this MR.