summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTess Avitabile <tess.avitabile@mongodb.com>2016-08-29 18:50:25 -0400
committerTess Avitabile <tess.avitabile@mongodb.com>2016-08-31 14:18:42 -0400
commitf41c549e109e16a6400eb93ca6cac2ef1ce1ce5d (patch)
tree0ac38c70827671862553d37dcac6b86f95ed2f8b
parent7b126b0eb8fc8bdab7e5c12c28d0ed58a48505bb (diff)
downloadmongo-f41c549e109e16a6400eb93ca6cac2ef1ce1ce5d.tar.gz
SERVER-25740 Prevent creation of views if featureCompatibilityVersion is 3.2
-rw-r--r--buildscripts/resmokeconfig/suites/views.yml1
-rw-r--r--buildscripts/resmokeconfig/suites/views_rs.yml1
-rw-r--r--jstests/views/durable_view_catalog.js3
-rw-r--r--jstests/views/initial_sync_views.js3
-rw-r--r--jstests/views/views_feature_compatibility_version.js89
-rw-r--r--jstests/views/views_legacy.js2
-rw-r--r--jstests/views/views_sharded.js6
-rw-r--r--src/mongo/db/catalog/database.cpp8
-rw-r--r--src/mongo/db/namespace_string.cpp3
-rw-r--r--src/mongo/db/namespace_string.h6
-rw-r--r--src/mongo/db/op_observer.cpp2
-rw-r--r--src/mongo/db/views/durable_view_catalog.cpp9
-rw-r--r--src/mongo/db/views/durable_view_catalog.h9
-rw-r--r--src/mongo/db/views/view_catalog.cpp22
14 files changed, 140 insertions, 24 deletions
diff --git a/buildscripts/resmokeconfig/suites/views.yml b/buildscripts/resmokeconfig/suites/views.yml
index 2b825ba753b..9a497f0b7ca 100644
--- a/buildscripts/resmokeconfig/suites/views.yml
+++ b/buildscripts/resmokeconfig/suites/views.yml
@@ -17,4 +17,3 @@ executor:
mongod_options:
set_parameters:
enableTestCommands: 1
- enableViews: 1
diff --git a/buildscripts/resmokeconfig/suites/views_rs.yml b/buildscripts/resmokeconfig/suites/views_rs.yml
index a4cacd25572..b29d8dc66df 100644
--- a/buildscripts/resmokeconfig/suites/views_rs.yml
+++ b/buildscripts/resmokeconfig/suites/views_rs.yml
@@ -23,5 +23,4 @@ executor:
oplogSize: 511
set_parameters:
enableTestCommands: 1
- enableViews: 1
num_nodes: 2
diff --git a/jstests/views/durable_view_catalog.js b/jstests/views/durable_view_catalog.js
index c37255d7af9..5c06cf31167 100644
--- a/jstests/views/durable_view_catalog.js
+++ b/jstests/views/durable_view_catalog.js
@@ -12,8 +12,7 @@
let dbpath = MongoRunner.dataPath + '_durable_view_catalog';
resetDbpath(dbpath);
- let mongodArgs =
- {dbpath: dbpath, noCleanData: true, journal: '', setParameter: "enableViews=1"};
+ let mongodArgs = {dbpath: dbpath, noCleanData: true, journal: ''};
// Start a mongod.
let conn = MongoRunner.runMongod(mongodArgs);
diff --git a/jstests/views/initial_sync_views.js b/jstests/views/initial_sync_views.js
index e5b0ffdae1f..d6557cb5805 100644
--- a/jstests/views/initial_sync_views.js
+++ b/jstests/views/initial_sync_views.js
@@ -10,8 +10,7 @@
let testName = "initial_sync_views";
let hostName = getHostName();
- let replTest =
- new ReplSetTest({name: testName, nodes: 1, nodeOptions: {setParameter: "enableViews=1"}});
+ let replTest = new ReplSetTest({name: testName, nodes: 1});
replTest.startSet();
replTest.initiate();
diff --git a/jstests/views/views_feature_compatibility_version.js b/jstests/views/views_feature_compatibility_version.js
new file mode 100644
index 00000000000..4e3d5ecb252
--- /dev/null
+++ b/jstests/views/views_feature_compatibility_version.js
@@ -0,0 +1,89 @@
+// Test that views are only enabled if featureCompatibilityVersion is 3.4.
+
+(function() {
+ "use strict";
+
+ const conn = MongoRunner.runMongod({});
+ assert.neq(null, conn, "mongod was unable to start up");
+
+ const viewsDB = conn.getDB("views_feature_compatibility_version");
+ assert.commandWorked(viewsDB.dropDatabase());
+ assert.commandWorked(viewsDB.runCommand({create: "collection"}));
+ assert.commandWorked(viewsDB.runCommand({create: "collection2"}));
+
+ const adminDB = conn.getDB("admin");
+
+ // Ensure the featureCompatibilityVersion is 3.4.
+ assert.commandWorked(adminDB.runCommand({setFeatureCompatibilityVersion: "3.4"}));
+ let res = adminDB.runCommand({getParameter: 1, featureCompatibilityVersion: 1});
+ assert.commandWorked(res);
+ assert.eq("3.4", res.featureCompatibilityVersion);
+
+ // We can create a view when the featureCompatibilityVersion is 3.4.
+ assert.commandWorked(viewsDB.runCommand({create: "view", viewOn: "collection", pipeline: []}));
+
+ // We can update a view when the featureCompatibilityVersion is 3.4.
+ assert.commandWorked(viewsDB.runCommand({collMod: "view", pipeline: []}));
+
+ // We can perform inserts on the system.views collection when the featureCompatibilityVersion is
+ // 3.4.
+ assert.writeOK(viewsDB.system.views.insert(
+ {_id: "views_feature_compatibility_version.view2", viewOn: "collection", pipeline: []}));
+
+ // We can perform updates on the system.views collection when the featureCompatibilityVersion is
+ // 3.4.
+ assert.writeOK(viewsDB.system.views.update({_id: "views_feature_compatibility_version.view2"},
+ {$set: {viewOn: "collection2"}}));
+
+ // We can perform deletes on the system.views collection when the featureCompatibilityVersion is
+ // 3.4.
+ assert.writeOK(viewsDB.system.views.remove({_id: "views_feature_compatibility_version.view2"}));
+
+ // We cannot drop the system.views collection when the featureCompatibilityVersion is 3.4.
+ assert.throws(function() {
+ viewsDB.system.views.drop();
+ });
+
+ // Ensure the featureCompatibilityVersion is 3.2.
+ assert.commandWorked(adminDB.runCommand({setFeatureCompatibilityVersion: "3.2"}));
+ res = adminDB.runCommand({getParameter: 1, featureCompatibilityVersion: 1});
+ assert.commandWorked(res);
+ assert.eq("3.2", res.featureCompatibilityVersion);
+
+ // We cannot create views when the featureCompatibilityVersion is 3.2.
+ assert.commandFailed(viewsDB.runCommand({create: "view2", viewOn: "collection", pipeline: []}));
+
+ // We cannot update views when the featureCompatibilityVersion is 3.2.
+ assert.commandFailed(viewsDB.runCommand({collMod: "view", pipeline: []}));
+
+ // We can read from a view when the featureCompatibilityVersion is 3.2.
+ assert.writeOK(viewsDB.collection.insert({a: 5}));
+ assert.eq(5, viewsDB.view.findOne().a);
+
+ // We cannot create a collection with the same name as a view when the
+ // featureCompatibilityVersion is 3.2.
+ assert.commandFailed(viewsDB.runCommand({create: "view"}));
+ assert.writeError(viewsDB.view.insert({a: 5}));
+
+ // We cannot perform inserts on the system.views collection when the featureCompatibilityVersion
+ // is 3.2.
+ assert.writeError(viewsDB.system.views.insert(
+ {_id: "views_feature_compatibility_version.view2", viewOn: "collection", pipeline: []}));
+
+ // We cannot perform updates on the system.views collection when the featureCompatibilityVersion
+ // is 3.2.
+ assert.writeError(viewsDB.system.views.update({_id: "views_feature_compatibility_version.view"},
+ {$set: {viewOn: "collection2"}}));
+
+ // We can drop a view namespace when the featureCompatibilityVersion is 3.2.
+ assert.eq(true, viewsDB.view.drop());
+
+ // We can perform deletes on the system.views collection when the featureCompatibilityVersion is
+ // 3.2.
+ assert.writeOK(viewsDB.system.views.remove({_id: "views_feature_compatibility_version.view"}));
+
+ // We can drop the system.views collection when the featureCompatibilityVersion is 3.2.
+ assert.eq(true, viewsDB.system.views.drop());
+
+ MongoRunner.stopMongod(conn);
+}());
diff --git a/jstests/views/views_legacy.js b/jstests/views/views_legacy.js
index 46154fbdc30..bd31d5bb74e 100644
--- a/jstests/views/views_legacy.js
+++ b/jstests/views/views_legacy.js
@@ -8,7 +8,7 @@
(function() {
"use strict";
- let conn = MongoRunner.runMongod({setParameter: "enableViews=1"});
+ let conn = MongoRunner.runMongod({});
let viewsDB = conn.getDB("views_legacy");
assert.commandWorked(viewsDB.dropDatabase());
diff --git a/jstests/views/views_sharded.js b/jstests/views/views_sharded.js
index 99408fcc9a3..42ca90c4ba3 100644
--- a/jstests/views/views_sharded.js
+++ b/jstests/views/views_sharded.js
@@ -8,11 +8,7 @@
(function() {
"use strict";
- let st = new ShardingTest({
- name: "views_sharded",
- shards: 2,
- other: {shardOptions: {setParameter: "enableViews=1"}, enableBalancer: false}
- });
+ let st = new ShardingTest({name: "views_sharded", shards: 2, other: {enableBalancer: false}});
let mongos = st.s;
let config = mongos.getDB("config");
diff --git a/src/mongo/db/catalog/database.cpp b/src/mongo/db/catalog/database.cpp
index 41746be60ef..c9482569f73 100644
--- a/src/mongo/db/catalog/database.cpp
+++ b/src/mongo/db/catalog/database.cpp
@@ -387,6 +387,14 @@ Status Database::dropCollection(OperationContext* txn, StringData fullns) {
if (_profile != 0)
return Status(ErrorCodes::IllegalOperation,
"turn off profiling before dropping system.profile collection");
+ } else if (nss.isSystemDotViews()) {
+ if (serverGlobalParams.featureCompatibilityVersion.load() !=
+ ServerGlobalParams::FeatureCompatibilityVersion_32) {
+ return Status(ErrorCodes::IllegalOperation,
+ "The featureCompatibilityVersion must be 3.2 to drop the "
+ "system.views collection. See "
+ "http://dochub.mongodb.org/core/3.4-feature-compatibility.");
+ }
} else {
return Status(ErrorCodes::IllegalOperation, "can't drop system ns");
}
diff --git a/src/mongo/db/namespace_string.cpp b/src/mongo/db/namespace_string.cpp
index 95d600fb27b..27495baa9d0 100644
--- a/src/mongo/db/namespace_string.cpp
+++ b/src/mongo/db/namespace_string.cpp
@@ -96,7 +96,7 @@ bool legalClientSystemNS(StringData ns) {
if (ns.find(".system.js") != string::npos)
return true;
- if (nsToCollectionSubstring(ns) == "system.views")
+ if (nsToCollectionSubstring(ns) == NamespaceString::kSystemDotViewsCol)
return true;
return false;
@@ -104,6 +104,7 @@ bool legalClientSystemNS(StringData ns) {
const StringData NamespaceString::kAdminDb = "admin"_sd;
const StringData NamespaceString::kLocalDb = "local"_sd;
+constexpr StringData NamespaceString::kSystemDotViewsCol;
const NamespaceString NamespaceString::kConfigCollectionNamespace(kConfigCollection);
diff --git a/src/mongo/db/namespace_string.h b/src/mongo/db/namespace_string.h
index e4b3be50075..93810d6307b 100644
--- a/src/mongo/db/namespace_string.h
+++ b/src/mongo/db/namespace_string.h
@@ -63,6 +63,9 @@ public:
// Namespace for the local database
static const StringData kLocalDb;
+ // Name for the system views collection
+ static constexpr StringData kSystemDotViewsCol = "system.views"_sd;
+
// Namespace for storing configuration data, which needs to be replicated if the server is
// running as a replica set. Documents in this collection should represent some configuration
// state of the server, which needs to be recovered/consulted at startup. Each document in this
@@ -162,6 +165,9 @@ public:
bool isSystemDotProfile() const {
return coll() == "system.profile";
}
+ bool isSystemDotViews() const {
+ return coll() == kSystemDotViewsCol;
+ }
bool isConfigDB() const {
return db() == "config";
}
diff --git a/src/mongo/db/op_observer.cpp b/src/mongo/db/op_observer.cpp
index 8defc1c71fe..f3e1a3729c8 100644
--- a/src/mongo/db/op_observer.cpp
+++ b/src/mongo/db/op_observer.cpp
@@ -91,6 +91,7 @@ void OpObserver::onInserts(OperationContext* txn,
}
if (nss.coll() == DurableViewCatalog::viewsCollectionName()) {
DurableViewCatalog::onExternalChange(txn, nss);
+ DurableViewCatalog::confirm34FeatureCompatibilityVersion();
}
}
@@ -117,6 +118,7 @@ void OpObserver::onUpdate(OperationContext* txn, const OplogUpdateEntryArgs& arg
NamespaceString nss(args.ns);
if (nss.coll() == DurableViewCatalog::viewsCollectionName()) {
DurableViewCatalog::onExternalChange(txn, nss);
+ DurableViewCatalog::confirm34FeatureCompatibilityVersion();
}
if (args.ns == FeatureCompatibilityVersion::kCollection) {
diff --git a/src/mongo/db/views/durable_view_catalog.cpp b/src/mongo/db/views/durable_view_catalog.cpp
index ba84432b7cf..7f7648160df 100644
--- a/src/mongo/db/views/durable_view_catalog.cpp
+++ b/src/mongo/db/views/durable_view_catalog.cpp
@@ -59,6 +59,15 @@ void DurableViewCatalog::onExternalChange(OperationContext* txn, const Namespace
}
}
+void DurableViewCatalog::confirm34FeatureCompatibilityVersion() {
+ uassert(40307,
+ "Cannot perform inserts or updates on system.views collection when "
+ "the featureCompatibilityVersion is 3.2. See "
+ "http://dochub.mongodb.org/core/3.4-feature-compatibility.",
+ serverGlobalParams.featureCompatibilityVersion.load() !=
+ ServerGlobalParams::FeatureCompatibilityVersion_32);
+}
+
// DurableViewCatalogImpl
const std::string& DurableViewCatalogImpl::getName() const {
diff --git a/src/mongo/db/views/durable_view_catalog.h b/src/mongo/db/views/durable_view_catalog.h
index 1ea7268f2ee..3ca577cdfbb 100644
--- a/src/mongo/db/views/durable_view_catalog.h
+++ b/src/mongo/db/views/durable_view_catalog.h
@@ -32,13 +32,13 @@
#include "mongo/base/status.h"
#include "mongo/base/string_data.h"
+#include "mongo/db/namespace_string.h"
#include "mongo/stdx/functional.h"
namespace mongo {
class BSONObj;
class Database;
-class NamespaceString;
class OperationContext;
/**
@@ -49,7 +49,7 @@ class OperationContext;
class DurableViewCatalog {
public:
static constexpr StringData viewsCollectionName() {
- return "system.views"_sd;
+ return NamespaceString::kSystemDotViewsCol;
}
/**
@@ -58,6 +58,11 @@ public:
*/
static void onExternalChange(OperationContext* txn, const NamespaceString& name);
+ /**
+ * Throws if featureCompatibilityVersion is 3.2.
+ */
+ static void confirm34FeatureCompatibilityVersion();
+
using Callback = stdx::function<void(const BSONObj& view)>;
virtual Status iterate(OperationContext* txn, Callback callback) = 0;
virtual void upsert(OperationContext* txn,
diff --git a/src/mongo/db/views/view_catalog.cpp b/src/mongo/db/views/view_catalog.cpp
index 9e4ad5c8b8f..6e8344059f9 100644
--- a/src/mongo/db/views/view_catalog.cpp
+++ b/src/mongo/db/views/view_catalog.cpp
@@ -47,15 +47,8 @@
#include "mongo/db/views/view.h"
#include "mongo/util/log.h"
-namespace {
-bool enableViews = true;
-} // namespace
-
namespace mongo {
-ExportedServerParameter<bool, ServerParameterType::kStartupOnly> enableViewsParameter(
- ServerParameterSet::getGlobal(), "enableViews", &enableViews);
-
Status ViewCatalog::reloadIfNeeded(OperationContext* txn) {
stdx::lock_guard<stdx::mutex> lk(_mutex);
return _reloadIfNeeded_inlock(txn);
@@ -178,8 +171,12 @@ Status ViewCatalog::createView(OperationContext* txn,
const BSONArray& pipeline) {
stdx::lock_guard<stdx::mutex> lk(_mutex);
- if (!enableViews)
- return Status(ErrorCodes::CommandNotSupported, "View support not enabled");
+ if (serverGlobalParams.featureCompatibilityVersion.load() ==
+ ServerGlobalParams::FeatureCompatibilityVersion_32) {
+ return Status(ErrorCodes::CommandNotSupported,
+ "Cannot create view when the featureCompatibilityVersion is 3.2. See "
+ "http://dochub.mongodb.org/core/3.4-feature-compatibility.");
+ }
if (viewName.db() != viewOn.db())
return Status(ErrorCodes::BadValue,
@@ -201,6 +198,13 @@ Status ViewCatalog::modifyView(OperationContext* txn,
const BSONArray& pipeline) {
stdx::lock_guard<stdx::mutex> lk(_mutex);
+ if (serverGlobalParams.featureCompatibilityVersion.load() ==
+ ServerGlobalParams::FeatureCompatibilityVersion_32) {
+ return Status(ErrorCodes::CommandNotSupported,
+ "Cannot modify view when the featureCompatibilityVersion is 3.2. See "
+ "http://dochub.mongodb.org/core/3.4-feature-compatibility.");
+ }
+
if (viewName.db() != viewOn.db())
return Status(ErrorCodes::BadValue,
"View must be created on a view or collection in the same database");