@@ -1232,6 +1232,76 @@ describe('Shard', function () {
12321232 expect ( warnSpy . calledOnce ) . to . equal ( true ) ;
12331233 } ) ;
12341234 } ) ;
1235+ describe ( 'disableMigrations' , function ( ) {
1236+ this . beforeEach ( ( ) => {
1237+ serviceProvider . runCommandWithCheck . onFirstCall ( ) . resolves ( {
1238+ ok : 1 ,
1239+ msg : 'not dbgrid' ,
1240+ } ) ;
1241+ serviceProvider . runCommandWithCheck . onSecondCall ( ) . resolves ( { ok : 1 } ) ;
1242+ } ) ;
1243+
1244+ it ( 'warns if not mongos' , async function ( ) {
1245+ await shard . disableMigrations ( 'ns' ) ;
1246+ expect ( warnSpy . calledOnce ) . to . equal ( true ) ;
1247+ } ) ;
1248+
1249+ it ( 'calls serviceProvider.runCommandWithCheck' , async function ( ) {
1250+ await shard . disableMigrations ( 'ns' ) ;
1251+
1252+ expect ( serviceProvider . runCommandWithCheck ) . to . have . been . calledWith (
1253+ ADMIN_DB ,
1254+ {
1255+ setAllowMigrations : 'ns' ,
1256+ allowMigrations : false ,
1257+ }
1258+ ) ;
1259+ } ) ;
1260+
1261+ it ( 'throws if serviceProvider.runCommandWithCheck rejects' , async function ( ) {
1262+ const expectedError = new Error ( ) ;
1263+ serviceProvider . runCommandWithCheck
1264+ . onSecondCall ( )
1265+ . rejects ( expectedError ) ;
1266+ const caughtError = await shard . disableMigrations ( 'ns' ) . catch ( ( e ) => e ) ;
1267+ expect ( caughtError ) . to . equal ( expectedError ) ;
1268+ } ) ;
1269+ } ) ;
1270+ describe ( 'enableMigrations' , function ( ) {
1271+ this . beforeEach ( ( ) => {
1272+ serviceProvider . runCommandWithCheck . onFirstCall ( ) . resolves ( {
1273+ ok : 1 ,
1274+ msg : 'not dbgrid' ,
1275+ } ) ;
1276+ serviceProvider . runCommandWithCheck . onSecondCall ( ) . resolves ( { ok : 1 } ) ;
1277+ } ) ;
1278+
1279+ it ( 'warns if not mongos' , async function ( ) {
1280+ await shard . enableMigrations ( 'ns' ) ;
1281+ expect ( warnSpy . calledOnce ) . to . equal ( true ) ;
1282+ } ) ;
1283+
1284+ it ( 'calls serviceProvider.runCommandWithCheck' , async function ( ) {
1285+ await shard . enableMigrations ( 'ns' ) ;
1286+
1287+ expect ( serviceProvider . runCommandWithCheck ) . to . have . been . calledWith (
1288+ ADMIN_DB ,
1289+ {
1290+ setAllowMigrations : 'ns' ,
1291+ allowMigrations : true ,
1292+ }
1293+ ) ;
1294+ } ) ;
1295+
1296+ it ( 'throws if serviceProvider.runCommandWithCheck rejects' , async function ( ) {
1297+ const expectedError = new Error ( ) ;
1298+ serviceProvider . runCommandWithCheck
1299+ . onSecondCall ( )
1300+ . rejects ( expectedError ) ;
1301+ const caughtError = await shard . enableMigrations ( 'ns' ) . catch ( ( e ) => e ) ;
1302+ expect ( caughtError ) . to . equal ( expectedError ) ;
1303+ } ) ;
1304+ } ) ;
12351305 describe ( 'getBalancerState' , function ( ) {
12361306 it ( 'returns whatever serviceProvider.find returns' , async function ( ) {
12371307 serviceProvider . runCommandWithCheck . resolves ( {
@@ -2530,6 +2600,71 @@ describe('Shard', function () {
25302600 ) ;
25312601 } ) ;
25322602 } ) ;
2603+ describe ( 'collection migrations' , function ( ) {
2604+ let db : Database ;
2605+
2606+ const dbName = 'shard-status-test' ;
2607+ const ns = `${ dbName } .test` ;
2608+
2609+ beforeEach ( async function ( ) {
2610+ db = sh . _database . getSiblingDB ( dbName ) ;
2611+ await db . getCollection ( 'test' ) . insertOne ( { key : 1 } ) ;
2612+ await db . getCollection ( 'test' ) . createIndex ( { key : 1 } ) ;
2613+ await sh . enableSharding ( dbName ) ;
2614+ await sh . shardCollection ( ns , { key : 1 } ) ;
2615+ } ) ;
2616+
2617+ afterEach ( async function ( ) {
2618+ await db . dropDatabase ( ) ;
2619+ } ) ;
2620+
2621+ const checkMigrationsEnabled = async ( ) : Promise < boolean > => {
2622+ return ( await sh . status ( ) ) . value . databases . find (
2623+ ( d ) => d . database . _id === dbName
2624+ ) ?. collections [ ns ] . allowMigrations ;
2625+ } ;
2626+
2627+ it ( 'has migrations enabled by default' , async function ( ) {
2628+ expect ( await checkMigrationsEnabled ( ) ) . to . be . true ;
2629+ } ) ;
2630+
2631+ it ( 'can disable migrations' , async function ( ) {
2632+ expect ( ( await sh . disableMigrations ( ns ) ) . ok ) . to . equal ( 1 ) ;
2633+ expect ( await checkMigrationsEnabled ( ) ) . to . be . false ;
2634+ } ) ;
2635+
2636+ it ( 'can enable migrations' , async function ( ) {
2637+ // Enabled by default, so disable first
2638+ expect ( ( await sh . disableMigrations ( ns ) ) . ok ) . to . equal ( 1 ) ;
2639+ expect ( await checkMigrationsEnabled ( ) ) . to . be . false ;
2640+
2641+ expect ( ( await sh . enableMigrations ( ns ) ) . ok ) . to . equal ( 1 ) ;
2642+ expect ( await checkMigrationsEnabled ( ) ) . to . be . true ;
2643+ } ) ;
2644+
2645+ it ( 'disabling migrations is idempotent' , async function ( ) {
2646+ expect ( await checkMigrationsEnabled ( ) ) . to . be . true ;
2647+
2648+ expect ( ( await sh . disableMigrations ( ns ) ) . ok ) . to . equal ( 1 ) ;
2649+ expect ( await checkMigrationsEnabled ( ) ) . to . be . false ;
2650+
2651+ // Run disable again to check idempotency
2652+ expect ( ( await sh . disableMigrations ( ns ) ) . ok ) . to . equal ( 1 ) ;
2653+ expect ( await checkMigrationsEnabled ( ) ) . to . be . false ;
2654+ } ) ;
2655+
2656+ it ( 'enabling migrations is idempotent' , async function ( ) {
2657+ expect ( await checkMigrationsEnabled ( ) ) . to . be . true ;
2658+
2659+ // Enabling when already enabled should not do anything
2660+ expect ( ( await sh . enableMigrations ( ns ) ) . ok ) . to . equal ( 1 ) ;
2661+ expect ( await checkMigrationsEnabled ( ) ) . to . be . true ;
2662+
2663+ // Run enable again to check idempotency
2664+ expect ( ( await sh . enableMigrations ( ns ) ) . ok ) . to . equal ( 1 ) ;
2665+ expect ( await checkMigrationsEnabled ( ) ) . to . be . true ;
2666+ } ) ;
2667+ } ) ;
25332668 describe ( 'automerge' , function ( ) {
25342669 it ( 'not shown if sh.status() if not explicitly enabled' , async function ( ) {
25352670 // It might be explicitly set from 7.0
0 commit comments