summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/require_api_version.js
blob: 640a149adab83ae2c077b84270ef2c1532f401db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/**
 * Tests the "requireApiVersion" mongod/mongos parameter.
 *
 * This test is incompatible with parallel and passthrough suites; concurrent jobs fail while
 * requireApiVersion is true.
 *
 * @tags: [
 *   requires_journaling,
 *   requires_replication,
 *   requires_transactions,
 * ]
 */

(function() {
"use strict";

function runTest(db, supportsTransctions, isMongos, writeConcern = {}, secondaries = []) {
    assert.commandWorked(db.runCommand({setParameter: 1, requireApiVersion: true}));
    for (const secondary of secondaries) {
        assert.commandWorked(secondary.adminCommand({setParameter: 1, requireApiVersion: true}));
    }

    assert.commandFailedWithCode(db.runCommand({ping: 1}), 498870, "command without apiVersion");
    assert.commandWorked(db.runCommand({ping: 1, apiVersion: "1"}));
    assert.commandFailed(db.runCommand({ping: 1, apiVersion: "not a real API version"}));

    // Create a collection and do some writes with writeConcern majority.
    const collName = "testColl";
    assert.commandWorked(db.runCommand({create: collName, apiVersion: "1", writeConcern}));
    assert.commandWorked(db.runCommand(
        {insert: collName, documents: [{a: 1, b: 2}], apiVersion: "1", writeConcern}));

    // User management commands loop back into the system so make sure they set apiVersion
    // internally
    assert.commandWorked(db.adminCommand(
        {createRole: 'testRole', apiVersion: "1", writeConcern, privileges: [], roles: []}));
    assert.commandWorked(db.adminCommand({dropRole: 'testRole', apiVersion: "1", writeConcern}));

    /*
     * "getMore" accepts apiVersion.
     *
     * TODO (SERVER-56550): Test that getMore fails *without* API params.
     */
    assert.commandWorked(db.runCommand(
        {insert: "collection", documents: [{}, {}, {}], apiVersion: "1", writeConcern}));
    let reply = db.runCommand({find: "collection", batchSize: 1, apiVersion: "1"});
    assert.commandWorked(reply);
    assert.commandWorked(
        db.runCommand({getMore: reply.cursor.id, collection: "collection", batchSize: 1}));
    assert.commandWorked(
        db.runCommand({getMore: reply.cursor.id, collection: "collection", apiVersion: "1"}));

    if (supportsTransctions) {
        /*
         * Transaction-starting commands must have apiVersion, transaction-continuing commands may.
         *
         * TODO (SERVER-56550): Test that transaction-continuing commands fail *without* API params.
         */
        const session = db.getMongo().startSession({causalConsistency: false});
        const sessionDb = session.getDatabase(db.getName());
        reply = sessionDb.runCommand({
            find: "collection",
            batchSize: 1,
            apiVersion: "1",
            txnNumber: NumberLong(0),
            stmtId: NumberInt(0),
            startTransaction: true,
            autocommit: false
        });
        assert.commandWorked(reply);
        assert.commandWorked(sessionDb.runCommand({
            getMore: reply.cursor.id,
            collection: "collection",
            txnNumber: NumberLong(0),
            stmtId: NumberInt(1),
            autocommit: false
        }));
        assert.commandWorked(sessionDb.runCommand({
            find: "collection",
            batchSize: 1,
            txnNumber: NumberLong(0),
            stmtId: NumberInt(2),
            autocommit: false
        }));
        assert.commandWorked(sessionDb.runCommand(
            {commitTransaction: 1, apiVersion: "1", txnNumber: NumberLong(0), autocommit: false}));

        // Start a new txn so we can test abortTransaction.
        reply = sessionDb.runCommand({
            find: "collection",
            apiVersion: "1",
            txnNumber: NumberLong(1),
            stmtId: NumberInt(0),
            startTransaction: true,
            autocommit: false
        });
        assert.commandWorked(reply);
        assert.commandWorked(sessionDb.runCommand(
            {abortTransaction: 1, apiVersion: "1", txnNumber: NumberLong(1), autocommit: false}));
    }

    assert.commandWorked(
        db.runCommand({setParameter: 1, requireApiVersion: false, apiVersion: "1"}));
    for (const secondary of secondaries) {
        assert.commandWorked(
            secondary.adminCommand({setParameter: 1, requireApiVersion: false, apiVersion: "1"}));
    }
    assert.commandWorked(db.runCommand({ping: 1}));
}

function requireApiVersionOnShardOrConfigServerTest() {
    let shardsvrMongod =
        MongoRunner.runMongod({shardsvr: "", setParameter: {"requireApiVersion": true}});
    assert.eq(null,
              shardsvrMongod,
              "mongod should not be able to start up with --shardsvr and requireApiVersion=true");

    let configsvrMongod =
        MongoRunner.runMongod({configsvr: "", setParameter: {"requireApiVersion": 1}});
    assert.eq(null,
              configsvrMongod,
              "mongod should not be able to start up with --configsvr and requireApiVersion=true");

    shardsvrMongod = MongoRunner.runMongod({shardsvr: ""});
    assert.neq(null, shardsvrMongod, "mongod was not able to start up");
    assert.commandFailed(
        shardsvrMongod.adminCommand({setParameter: 1, requireApiVersion: true}),
        "should not be able to set requireApiVersion=true on mongod that was started with --shardsvr");
    MongoRunner.stopMongod(shardsvrMongod);

    configsvrMongod = MongoRunner.runMongod({configsvr: ""});
    assert.neq(null, configsvrMongod, "mongod was not able to start up");
    assert.commandFailed(
        configsvrMongod.adminCommand({setParameter: 1, requireApiVersion: 1}),
        "should not be able to set requireApiVersion=true on mongod that was started with --configsvr");
    MongoRunner.stopMongod(configsvrMongod);
}

requireApiVersionOnShardOrConfigServerTest();

const mongod = MongoRunner.runMongod();
runTest(mongod.getDB("admin"), false /* supportsTransactions */, false /* isMongos */);
MongoRunner.stopMongod(mongod);

const rst = new ReplSetTest({nodes: 3});
rst.startSet();
rst.initiateWithHighElectionTimeout();

runTest(rst.getPrimary().getDB("admin"),
        true /* supportsTransactions */,
        false /* isMongos */,
        {w: "majority"} /* writeConcern */,
        rst.getSecondaries());
rst.stopSet();

const st = new ShardingTest({});
runTest(st.s0.getDB("admin"), true /* supportsTransactions */, true /* isMongos */);
st.stop();
}());