-
Notifications
You must be signed in to change notification settings - Fork 15
Add PBM and PMM user configuration for config servers #1165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
8e66cad
5e72703
24d0eda
ca026c1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -140,6 +140,74 @@ docker compose -f docker-compose-sharded-with-pmm.yaml exec -T rscfg01 mongo --q | |
| EOF | ||
| sleep 60 | ||
| echo | ||
| echo "configuring root user on primary rscfg01 configserver replicaset" | ||
| docker compose -f docker-compose-sharded-with-pmm.yaml exec -T rscfg01 mongo --quiet << EOF | ||
| db.getSiblingDB("admin").createUser({ user: "root", pwd: "root", roles: [ "root", "userAdminAnyDatabase", "clusterAdmin" ] }); | ||
| EOF | ||
| echo | ||
| echo "configuring pbm and pmm roles on configserver replicaset rscfg" | ||
| docker compose -f docker-compose-sharded-with-pmm.yaml exec -T rscfg01 mongo "mongodb://root:root@localhost/?replicaSet=rscfg" --quiet << EOF | ||
| db.getSiblingDB("admin").createRole({ | ||
| "role": "pbmAnyAction", | ||
| "privileges": [{ | ||
| "resource": { "anyResource": true }, | ||
| "actions": [ "anyAction" ] | ||
| }], | ||
| "roles": [] | ||
| }); | ||
| db.getSiblingDB("admin").createRole({ | ||
| role: "explainRole", | ||
| privileges: [{ | ||
| resource: { | ||
| db: "", | ||
| collection: "" | ||
| }, | ||
| actions: [ | ||
| "listIndexes", | ||
| "listCollections", | ||
| "dbStats", | ||
| "dbHash", | ||
| "collStats", | ||
| "find" | ||
| ] | ||
| }], | ||
| roles:[] | ||
| }); | ||
| EOF | ||
| echo | ||
| echo "creating pbm user for configserver replicaset rscfg" | ||
| docker compose -f docker-compose-sharded-with-pmm.yaml exec -T rscfg01 mongo "mongodb://root:root@localhost/?replicaSet=rscfg" --quiet << EOF | ||
| db.getSiblingDB("admin").createUser({ | ||
| user: "${pbm_user}", | ||
| pwd: "${pbm_pass}", | ||
| "roles" : [ | ||
| { "db" : "admin", "role" : "readWrite", "collection": "" }, | ||
| { "db" : "admin", "role" : "backup" }, | ||
| { "db" : "admin", "role" : "clusterMonitor" }, | ||
| { "db" : "admin", "role" : "restore" }, | ||
| { "db" : "admin", "role" : "pbmAnyAction" } | ||
| ] | ||
| }); | ||
| EOF | ||
| echo | ||
| echo "creating pmm user for configserver replicaset rscfg" | ||
| docker compose -f docker-compose-sharded-with-pmm.yaml exec -T rscfg01 mongo "mongodb://root:root@localhost/?replicaSet=rscfg" --quiet << EOF | ||
| db.getSiblingDB("admin").createUser({ | ||
| user: "${pmm_user}", | ||
| pwd: "${pmm_pass}", | ||
| roles: [ | ||
| { role: "explainRole", db: "admin" }, | ||
| { role: "clusterMonitor", db: "admin" }, | ||
| { role: "read", db: "local" }, | ||
| { "db" : "admin", "role" : "readWrite", "collection": "" }, | ||
| { "db" : "admin", "role" : "backup" }, | ||
| { "db" : "admin", "role" : "clusterMonitor" }, | ||
| { "db" : "admin", "role" : "restore" }, | ||
| { "db" : "admin", "role" : "pbmAnyAction" } | ||
| ] | ||
| }); | ||
| EOF | ||
| echo | ||
| echo "adding shards and creating global mongo user" | ||
| docker compose -f docker-compose-sharded-with-pmm.yaml exec -T mongos mongo --quiet << EOF | ||
| db.getSiblingDB("admin").createUser({ user: "root", pwd: "root", roles: [ "root", "userAdminAnyDatabase", "clusterAdmin" ] }); | ||
|
|
@@ -241,6 +309,34 @@ docker compose -f docker-compose-sharded-with-pmm.yaml exec -T rscfg01 pmm-admin | |
|
|
||
| echo "adding some data" | ||
| docker compose -f docker-compose-sharded-with-pmm.yaml exec -T mongos mgodatagen -f /etc/datagen/sharded.json --uri=mongodb://root:root@127.0.0.1:27017 | ||
|
|
||
| echo "writing chunk-activity generator so the chunk-move/split dashboards keep getting data" | ||
| docker compose -f docker-compose-sharded-with-pmm.yaml exec -T mongos tee /tmp/keep_chunks_moving.js > /dev/null << 'JSEOF' | ||
| var shards = db.getSiblingDB("config").shards.find().toArray().map(function (s) { return s._id; }); | ||
| var ins = db.getSiblingDB("test").test.insertOne({ ts: new Date() }); | ||
| shards.forEach(function (target) { | ||
| try { | ||
| sh.moveChunk("test.test", { _id: ins.insertedId }, target); | ||
| } catch (e) { | ||
| print("moveChunk to " + target + " failed, skipping: " + e); | ||
| } | ||
| }); | ||
| try { | ||
| sh.splitFind("test.test", { _id: ins.insertedId }); | ||
|
Comment on lines
+316
to
+325
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/usr/bin/env bash
set -euo pipefail
found=0
while IFS= read -r config; do
found=1
echo "== $config =="
rg -n -C 6 'test|collection|namespace|shard|key|_id' "$config"
done < <(fd -i -t f 'sharded\.json$')
if [ "$found" -eq 0 ]; then
echo "No sharded.json file found" >&2
exit 1
fiRepository: percona/pmm-qa Length of output: 204 🏁 Script executed: set -euo pipefail
printf '%s\n' '== candidate files =='
fd -i -t f 'sharded\.json$|start-sharded-with-pmm\.sh$|datagen' . || true
printf '%s\n' '== relevant references =='
rg -n -C 8 'sharded\.json|test\.test|moveChunk|splitFind|shardCollection|shardKey|_id' qa-integration .github 2>/dev/null || trueRepository: percona/pmm-qa Length of output: 50371 🏁 Script executed: set -euo pipefail
printf '%s\n' '== sharded.json =='
cat -n qa-integration/pmm_psmdb-pbm_setup/conf/datagen/sharded.json
printf '%s\n' '== generator and surrounding setup =='
sed -n '295,345p' qa-integration/pmm_psmdb-pbm_setup/start-sharded-with-pmm.sh
printf '%s\n' '== compose image and datagen mounts =='
rg -n -C 5 'mongos:|mongo:|mgodatagen|datagen|image:' qa-integration/pmm_psmdb-pbm_setup/docker-compose-sharded-with-pmm.yamlRepository: percona/pmm-qa Length of output: 7934 🏁 Script executed: set -euo pipefail
printf '%s\n' '== image definition =='
cat -n qa-integration/pmm_psmdb-pbm_setup/Dockerfile
printf '%s\n' '== mongo shell references =='
rg -n -C 6 'mongo(shell)?|mongos|MONGO|PSMDB|percona-server-mongodb|mongodb-org|mgodatagen' qa-integration/pmm_psmdb-pbm_setup --glob '!*.json'
printf '%s\n' '== repository metadata for image version =='
rg -n -C 4 'REPO|PSMDB|MONGODB|VERSION|TAG' qa-integration/pmm_psmdb-pbm_setup/{Dockerfile,docker-compose-sharded-with-pmm.yaml,.env,Makefile} 2>/dev/null || trueRepository: percona/pmm-qa Length of output: 50371 🌐 Web query:
💡 Result: In MongoDB 8.0, both sh.moveChunk and sh.splitFind are available as helper methods in mongosh [1][2][3]. sh.moveChunk The signature for this method is sh.moveChunk(namespace, query, destination) [4]. - namespace (string): The full namespace (database.collection) of the sharded collection [4]. - query (document): An equality match on the shard key used to identify the chunk to move [4]. - destination (string): The ID of the recipient shard [4]. This method wraps the moveChunk database command [4]. It is not suitable for hashed shard keys when using the query parameter; for hashed shard keys, users should instead utilize the moveChunk command directly with the bounds field [4][5]. sh.splitFind The signature for this method is sh.splitFind(namespace, query) [6]. - namespace (string): The full namespace of the sharded collection [6][7]. - query (document): A query that identifies the shard key value within the chunk to be split [6][7]. This method splits the identified chunk at its median point, resulting in two roughly equal chunks [6][3]. It wraps the split database command [6][8]. General Note MongoDB documentation emphasizes that in most production environments, automatic chunk management (balancing and splitting) should be left to the built-in system processes rather than manual intervention via these helpers [4][6][7]. Furthermore, while these helpers provide convenience in mongosh, they may not return the same comprehensive information as the underlying database commands [5][8]. Citations:
🌐 Web query:
💡 Result: The sh.splitFind method is not directly supported for splitting chunks in a collection partitioned using a hashed shard key [1][2][3][4]. In MongoDB, while sh.splitFind and sh.splitAt are convenient helpers for manual chunk splitting, they are designed to work with range-based sharding [5][6][7]. For collections using a hashed shard key, you must use the underlying split database command with the bounds parameter [1][2][3][4]. The bounds parameter requires an array containing two documents that specify the exact lower and upper shard-key values of the chunk you intend to split [1][2][3][4]. These values must match the minimum and maximum boundaries of an existing chunk, which can be identified using sh.status [1][2][3][4]. Example of splitting a hashed chunk via the database command: db.adminCommand({ split: "database.collection", bounds: [ { hashed_shard_key: NumberLong("-5838464104018346494") }, { hashed_shard_key: NumberLong("-5557153028469814163") } ] }) [1][2][3][4] Because hashed values are represented as 64-bit integers, you must use the NumberLong type when specifying these bounds [1][2][3][4]. Citations:
Use a range-based shard key for 🤖 Prompt for AI Agents |
||
| } catch (e) { | ||
| print("splitFind failed, skipping: " + e); | ||
| } | ||
| JSEOF | ||
| docker compose -f docker-compose-sharded-with-pmm.yaml exec -T mongos tee /tmp/keep_chunks_moving.sh > /dev/null << 'SHEOF' | ||
| #!/bin/bash | ||
| while true; do | ||
| mongo "mongodb://root:root@localhost" --quiet /tmp/keep_chunks_moving.js > /tmp/keep_chunks_moving.log 2>&1 | ||
| sleep 240 | ||
| done | ||
| SHEOF | ||
| echo "starting background chunk-activity generator" | ||
| docker compose -f docker-compose-sharded-with-pmm.yaml exec -d mongos bash /tmp/keep_chunks_moving.sh | ||
|
Comment on lines
+314
to
+338
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win Use a private temporary directory for generator state. Lines [314], [330], and [333] use predictable paths under 🧰 Tools🪛 ast-grep (0.45.1)[warning] 329-329: Writing to or reading from a hardcoded, predictable path under /tmp is vulnerable to symlink and TOCTOU attacks: a local attacker can pre-create the file (or a symlink pointing elsewhere) and hijack or corrupt the contents. Generate a unique, unpredictable temporary file with mktemp instead, e.g. (predictable-tmp-file-bash) [warning] 337-337: Writing to or reading from a hardcoded, predictable path under /tmp is vulnerable to symlink and TOCTOU attacks: a local attacker can pre-create the file (or a symlink pointing elsewhere) and hijack or corrupt the contents. Generate a unique, unpredictable temporary file with mktemp instead, e.g. (predictable-tmp-file-bash) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||
|
|
||
| tests=${TESTS:-yes} | ||
| if [ $tests != "no" ]; then | ||
| echo "running tests" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -145,6 +145,74 @@ docker compose -f docker-compose-sharded.yaml exec -T rscfg01 mongo --quiet << E | |
| EOF | ||
| sleep 60 | ||
| echo | ||
| echo "configuring root user on primary rscfg01 configserver replicaset" | ||
| docker compose -f docker-compose-sharded.yaml exec -T rscfg01 mongo --quiet << EOF | ||
| db.getSiblingDB("admin").createUser({ user: "root", pwd: "root", roles: [ "root", "userAdminAnyDatabase", "clusterAdmin" ] }); | ||
| EOF | ||
| echo | ||
| echo "configuring pbm and pmm roles on configserver replicaset rscfg" | ||
| docker compose -f docker-compose-sharded.yaml exec -T rscfg01 mongo "mongodb://root:root@localhost/?replicaSet=rscfg" --quiet << EOF | ||
| db.getSiblingDB("admin").createRole({ | ||
| "role": "pbmAnyAction", | ||
| "privileges": [{ | ||
| "resource": { "anyResource": true }, | ||
| "actions": [ "anyAction" ] | ||
| }], | ||
| "roles": [] | ||
| }); | ||
| db.getSiblingDB("admin").createRole({ | ||
| role: "explainRole", | ||
| privileges: [{ | ||
| resource: { | ||
| db: "", | ||
| collection: "" | ||
| }, | ||
| actions: [ | ||
| "listIndexes", | ||
| "listCollections", | ||
| "dbStats", | ||
| "dbHash", | ||
| "collStats", | ||
| "find" | ||
| ] | ||
| }], | ||
| roles:[] | ||
| }); | ||
| EOF | ||
| echo | ||
| echo "creating pbm user for configserver replicaset rscfg" | ||
| docker compose -f docker-compose-sharded.yaml exec -T rscfg01 mongo "mongodb://root:root@localhost/?replicaSet=rscfg" --quiet << EOF | ||
| db.getSiblingDB("admin").createUser({ | ||
| user: "${pbm_user}", | ||
| pwd: "${pbm_pass}", | ||
| "roles" : [ | ||
| { "db" : "admin", "role" : "readWrite", "collection": "" }, | ||
| { "db" : "admin", "role" : "backup" }, | ||
| { "db" : "admin", "role" : "clusterMonitor" }, | ||
| { "db" : "admin", "role" : "restore" }, | ||
| { "db" : "admin", "role" : "pbmAnyAction" } | ||
| ] | ||
| }); | ||
| EOF | ||
| echo | ||
| echo "creating pmm user for configserver replicaset rscfg" | ||
| docker compose -f docker-compose-sharded.yaml exec -T rscfg01 mongo "mongodb://root:root@localhost/?replicaSet=rscfg" --quiet << EOF | ||
| db.getSiblingDB("admin").createUser({ | ||
| user: "${pmm_mongo_user}", | ||
| pwd: "${pmm_mongo_user_pass}", | ||
| roles: [ | ||
| { role: "explainRole", db: "admin" }, | ||
| { role: "clusterMonitor", db: "admin" }, | ||
| { role: "read", db: "local" }, | ||
| { "db" : "admin", "role" : "readWrite", "collection": "" }, | ||
| { "db" : "admin", "role" : "backup" }, | ||
| { "db" : "admin", "role" : "clusterMonitor" }, | ||
| { "db" : "admin", "role" : "restore" }, | ||
| { "db" : "admin", "role" : "pbmAnyAction" } | ||
| ] | ||
| }); | ||
| EOF | ||
| echo | ||
| echo "adding shards and creating global mongo user" | ||
| docker compose -f docker-compose-sharded.yaml exec -T mongos mongo --quiet << EOF | ||
| db.getSiblingDB("admin").createUser({ user: "root", pwd: "root", roles: [ "root", "userAdminAnyDatabase", "clusterAdmin" ] }); | ||
|
|
@@ -246,6 +314,34 @@ docker compose -f docker-compose-sharded.yaml exec -T rscfg01 pmm-admin add mong | |
|
|
||
| echo "adding some data" | ||
| docker compose -f docker-compose-sharded.yaml exec -T mongos mgodatagen -f /etc/datagen/sharded.json --uri=mongodb://root:root@127.0.0.1:27017 | ||
|
|
||
| echo "writing chunk-activity generator so the chunk-move/split dashboards keep getting data" | ||
| docker compose -f docker-compose-sharded.yaml exec -T mongos tee /tmp/keep_chunks_moving.js > /dev/null << 'JSEOF' | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- target script context ---'
sed -n '290,355p' qa-integration/pmm_psmdb-pbm_setup/start-sharded.sh
printf '%s\n' '--- all generated-path references ---'
rg -n -C 3 'keep_chunks_moving|docker compose.*mongos|JSEOF' qa-integration/pmm_psmdb-pbm_setup/start-sharded.sh
printf '%s\n' '--- container user and compose mounts ---'
sed -n '1,180p' qa-integration/pmm_psmdb-pbm_setup/docker-compose-sharded.yaml
printf '%s\n' '--- repository guidance files ---'
find . -maxdepth 3 -type f \( -iname 'README*' -o -iname '*CONTRIBUTING*' -o -iname '*GUIDELINE*' \) -printRepository: percona/pmm-qa Length of output: 12651 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- relevant compose services ---'
rg -n -A35 -B8 '^[[:space:]]+mongos:|^[[:space:]]+test:' qa-integration/pmm_psmdb-pbm_setup/docker-compose-sharded.yaml
printf '%s\n' '--- setup documentation ---'
sed -n '1,220p' qa-integration/pmm_psmdb-pbm_setup/readme.md
printf '%s\n' '--- image and privilege declarations ---'
rg -n -C 3 'FROM|USER|privileged|volumes:|mongos|test' qa-integration/pmm_psmdb-pbm_setup/Dockerfile qa-integration/pmm_psmdb-pbm_setup/docker-compose-sharded.yaml
printf '%s\n' '--- script lifecycle and cleanup ---'
sed -n '1,90p' qa-integration/pmm_psmdb-pbm_setup/start-sharded.sh
sed -n '343,390p' qa-integration/pmm_psmdb-pbm_setup/start-sharded.shRepository: percona/pmm-qa Length of output: 44242 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- test image capabilities and Docker access ---'
sed -n '1,220p' qa-integration/pmm_psmdb-pbm_setup/Dockerfile-testinfra
rg -n -C 4 'docker|exec|mongos|keep_chunks|/tmp' qa-integration/pmm_psmdb-pbm_setup/test qa-integration/pmm_psmdb-pbm_setup/*.sh
printf '%s\n' '--- image user declarations ---'
rg -n '^[[:space:]]*USER[[:space:]]|^[[:space:]]*ENTRYPOINT|^[[:space:]]*CMD' qa-integration/pmm_psmdb-pbm_setup/Dockerfile qa-integration/pmm_psmdb-pbm_setup/Dockerfile-testinfra || true
printf '%s\n' '--- deterministic path and symlink check ---'
python3 - <<'PY'
from pathlib import Path
script = Path("qa-integration/pmm_psmdb-pbm_setup/start-sharded.sh").read_text()
compose = Path("qa-integration/pmm_psmdb-pbm_setup/docker-compose-sharded.yaml").read_text()
paths = ["/tmp/keep_chunks_moving.js", "/tmp/keep_chunks_moving.sh", "/tmp/keep_chunks_moving.log"]
print("generated_paths:", paths)
print("all_paths_in_script:", all(p in script for p in paths))
print("mongos_service_privileged:", " mongos:" in compose and " privileged: true" in compose[compose.index(" mongos:"):])
mongos = compose[compose.index(" mongos:"):compose.index(" minio:")]
print("mongos_has_tmp_mount:", "/tmp" in mongos)
print("mongos_has_user_override:", any(line.lstrip().startswith("user:") for line in mongos.splitlines()))
# Demonstrate the relevant filesystem property without touching repository files.
import tempfile, os
with tempfile.TemporaryDirectory() as d:
target = Path(d) / "target"
link = Path(d) / "fixed-name"
target.write_text("original")
link.symlink_to(target)
with link.open("w") as f:
f.write("overwritten")
print("ordinary_writer_follows_precreated_symlink:", target.read_text() == "overwritten")
PYRepository: percona/pmm-qa Length of output: 50370 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- focused verifier output ---'
python3 - <<'PY'
from pathlib import Path
script = Path("qa-integration/pmm_psmdb-pbm_setup/start-sharded.sh").read_text()
compose = Path("qa-integration/pmm_psmdb-pbm_setup/docker-compose-sharded.yaml").read_text()
paths = ["/tmp/keep_chunks_moving.js", "/tmp/keep_chunks_moving.sh", "/tmp/keep_chunks_moving.log"]
mongos = compose[compose.index(" mongos:"):compose.index(" minio:")]
print("generated_paths:", all(p in script for p in paths))
print("mongos_privileged:", " privileged: true" in mongos)
print("mongos_tmp_mount:", "/tmp" in mongos)
print("mongos_user_override:", any(x.lstrip().startswith("user:") for x in mongos.splitlines()))
import tempfile
with tempfile.TemporaryDirectory() as d:
target, link = Path(d)/"target", Path(d)/"fixed-name"
target.write_text("original")
link.symlink_to(target)
link.write_text("overwritten")
print("writer_follows_precreated_symlink:", target.read_text() == "overwritten")
PY
printf '%s\n' '--- test sources with Docker or container access ---'
find qa-integration/pmm_psmdb-pbm_setup/test -maxdepth 2 -type f -print
rg -n -C 2 --glob '*.py' 'docker|Docker|exec|mongos|/tmp|subprocess' qa-integration/pmm_psmdb-pbm_setup/test || trueRepository: percona/pmm-qa Length of output: 3831 Use a private temporary directory for the generator files. 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||
| var shards = db.getSiblingDB("config").shards.find().toArray().map(function (s) { return s._id; }); | ||
| var ins = db.getSiblingDB("test").test.insertOne({ ts: new Date() }); | ||
| shards.forEach(function (target) { | ||
| try { | ||
| sh.moveChunk("test.test", { _id: ins.insertedId }, target); | ||
| } catch (e) { | ||
| print("moveChunk to " + target + " failed, skipping: " + e); | ||
| } | ||
| }); | ||
| try { | ||
| sh.splitFind("test.test", { _id: ins.insertedId }); | ||
| } catch (e) { | ||
| print("splitFind failed, skipping: " + e); | ||
| } | ||
|
Comment on lines
+329
to
+333
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- target context ---'
sed -n '300,350p' qa-integration/pmm_psmdb-pbm_setup/start-sharded.sh
printf '%s\n' '--- shard-key and split-related references ---'
rg -n -C 3 'splitFind|split|shardCollection|shard key|shardKey|hashed|test\.test' qa-integration/pmm_psmdb-pbm_setup
printf '%s\n' '--- MongoDB image/version declarations ---'
rg -n -i 'mongo.*(image|version)|mongodb|percona-server-mongodb|psmdb' qa-integration/pmm_psmdb-pbm_setup .github docker-compose*.yml 2>/dev/null | head -200Repository: percona/pmm-qa Length of output: 35832 🌐 Web query:
💡 Result: In MongoDB, for collections using a hashed shard key, you should not use sh.splitFind to manually split chunks [1][2]. The split command requires the bounds parameter to split chunks in hashed sharded collections, rather than the find parameter used by sh.splitFind [1][2]. The reasons and behavior are as follows: 1. Parameter Mismatch: The sh.splitFind method wraps the split database command using the find parameter [3][4]. However, the documentation for the split command explicitly states that you must use the bounds parameter for collections partitioned using a hashed shard key [1][2]. 2. Bounds Requirement: The bounds parameter requires an array containing two documents that specify the exact minimum and maximum shard-key values of the existing chunk you intend to split [1][2]. These values must match the current chunk's boundaries, which can be identified using sh.status [1][2]. 3. Median Splitting: When the bounds parameter is used correctly, MongoDB splits the chunk along its median [1][2]. The split command cannot use the find or middle parameters for hashed shard keys because hashed shards rely on specific, pre-defined chunk ranges rather than the query-based discovery used by sh.splitFind [1][2]. Attempting to use sh.splitFind on a hashed sharded collection may fail or behave unexpectedly because it is designed for range-based sharding where the query can identify a document within a chunk to determine the split point, which is not applicable to the distribution logic of hashed shard keys [3][1]. To manually split a hashed chunk, you should invoke the split command directly via db.adminCommand using the bounds option [1][2]. Citations:
🏁 Script executed: #!/bin/bash
set -eu
python3 - <<'PY'
import json
from pathlib import Path
setup = Path("qa-integration/pmm_psmdb-pbm_setup/start-sharded.sh").read_text()
config = json.loads(Path("qa-integration/pmm_psmdb-pbm_setup/conf/datagen/sharded.json").read_text())
collection = config["collections"][0]
shard_config = collection["shardConfig"]
key = shard_config["key"]
print("collection:", f'{shard_config["shardCollection"]}')
print("shard_key:", key)
print("insert_target_present:", 'getSiblingDB("test").test.insertOne' in setup)
print("splitFind_present:", 'sh.splitFind("test.test", { _id: ins.insertedId })' in setup)
print("catch_logs_and_skips:", 'print("splitFind failed, skipping: " + e);' in setup)
print("hashed_id_for_test.test:", shard_config["shardCollection"] == "test.test" and key == {"_id": "hashed"})
PYRepository: percona/pmm-qa Length of output: 285 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- sharded data generator ---'
cat -n qa-integration/pmm_psmdb-pbm_setup/conf/datagen/sharded.json
printf '%s\n' '--- focused consistency check ---'
python3 - <<'PY'
import json
from pathlib import Path
setup = Path("qa-integration/pmm_psmdb-pbm_setup/start-sharded.sh").read_text()
data = json.loads(Path("qa-integration/pmm_psmdb-pbm_setup/conf/datagen/sharded.json").read_text())
matches = []
for item in data:
shard_config = item.get("shardConfig", {})
if shard_config.get("shardCollection") == "test.test":
matches.append((item.get("collection"), shard_config.get("key")))
print("test.test shard configuration:", matches)
print("insert_target_present:", 'getSiblingDB("test").test.insertOne' in setup)
print("splitFind_present:", 'sh.splitFind("test.test", { _id: ins.insertedId })' in setup)
print("failure_is_swallowed:", 'print("splitFind failed, skipping: " + e);' in setup)
PYRepository: percona/pmm-qa Length of output: 1163 Use bounds for the hashed-key split.
🤖 Prompt for AI AgentsSource: MCP tools |
||
| JSEOF | ||
| docker compose -f docker-compose-sharded.yaml exec -T mongos tee /tmp/keep_chunks_moving.sh > /dev/null << 'SHEOF' | ||
| #!/bin/bash | ||
| while true; do | ||
| mongo "mongodb://root:root@localhost" --quiet /tmp/keep_chunks_moving.js > /tmp/keep_chunks_moving.log 2>&1 | ||
| sleep 240 | ||
| done | ||
| SHEOF | ||
| echo "starting background chunk-activity generator" | ||
| docker compose -f docker-compose-sharded.yaml exec -d mongos bash /tmp/keep_chunks_moving.sh | ||
|
Comment on lines
+342
to
+343
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win Install cleanup before launching the detached loop. The loop starts before the tests, but cleanup runs only after the tests complete. With 🧰 Tools🪛 ast-grep (0.45.1)[warning] 342-342: Writing to or reading from a hardcoded, predictable path under /tmp is vulnerable to symlink and TOCTOU attacks: a local attacker can pre-create the file (or a symlink pointing elsewhere) and hijack or corrupt the contents. Generate a unique, unpredictable temporary file with mktemp instead, e.g. (predictable-tmp-file-bash) 🤖 Prompt for AI Agents |
||
|
|
||
| tests=${TESTS:-yes} | ||
| if [ $tests != "no" ]; then | ||
| echo "running tests" | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.