// ValidateSettings returns an error if any settings specified on the command line // were invalid, or nil if they are valid. func (exp *MongoExport) ValidateSettings() error { // Namespace must have a valid database if none is specified, // use 'test' if exp.ToolOptions.Namespace.DB == "" { exp.ToolOptions.Namespace.DB = "test" } err := util.ValidateDBName(exp.ToolOptions.Namespace.DB) if err != nil { return err } if exp.ToolOptions.Namespace.Collection == "" { return fmt.Errorf("must specify a collection") } if err = util.ValidateCollectionGrammar(exp.ToolOptions.Namespace.Collection); err != nil { return err } exp.OutputOpts.Type = strings.ToLower(exp.OutputOpts.Type) if exp.OutputOpts.CSVOutputType { log.Logv(log.Always, "csv flag is deprecated; please use --type=csv instead") exp.OutputOpts.Type = CSV } if exp.OutputOpts.Type == "" { // special error for an empty type value return fmt.Errorf("--type cannot be empty") } if exp.OutputOpts.Type != CSV && exp.OutputOpts.Type != JSON { return fmt.Errorf("invalid output type '%v', choose 'json' or 'csv'", exp.OutputOpts.Type) } if exp.InputOpts.Query != "" && exp.InputOpts.ForceTableScan { return fmt.Errorf("cannot use --forceTableScan when specifying --query") } if exp.InputOpts.Query != "" && exp.InputOpts.QueryFile != "" { return fmt.Errorf("either --query or --queryFile can be specified as a query option") } if exp.InputOpts != nil && exp.InputOpts.HasQuery() { content, err := exp.InputOpts.GetQuery() if err != nil { return err } _, err2 := getObjectFromByteArg(content) if err2 != nil { return err2 } } if exp.InputOpts != nil && exp.InputOpts.Sort != "" { _, err := getSortFromArg(exp.InputOpts.Sort) if err != nil { return err } } return nil }
// ParseAndValidateOptions returns a non-nil error if user-supplied options are invalid. func (restore *MongoRestore) ParseAndValidateOptions() error { // Can't use option pkg defaults for --objcheck because it's two separate flags, // and we need to be able to see if they're both being used. We default to // true here and then see if noobjcheck is enabled. log.Logv(log.DebugHigh, "checking options") if restore.InputOptions.Objcheck { restore.objCheck = true log.Logv(log.DebugHigh, "\tdumping with object check enabled") } else { log.Logv(log.DebugHigh, "\tdumping with object check disabled") } if restore.NSOptions.DB == "" && restore.NSOptions.Collection != "" { return fmt.Errorf("cannot restore a collection without a specified database") } if restore.NSOptions.DB != "" { if err := util.ValidateDBName(restore.NSOptions.DB); err != nil { return fmt.Errorf("invalid db name: %v", err) } } if restore.NSOptions.Collection != "" { if err := util.ValidateCollectionGrammar(restore.NSOptions.Collection); err != nil { return fmt.Errorf("invalid collection name: %v", err) } } if restore.InputOptions.RestoreDBUsersAndRoles && restore.NSOptions.DB == "" { return fmt.Errorf("cannot use --restoreDbUsersAndRoles without a specified database") } if restore.InputOptions.RestoreDBUsersAndRoles && restore.NSOptions.DB == "admin" { return fmt.Errorf("cannot use --restoreDbUsersAndRoles with the admin database") } var err error restore.isMongos, err = restore.SessionProvider.IsMongos() if err != nil { return err } if restore.isMongos { log.Logv(log.DebugLow, "restoring to a sharded system") } if restore.InputOptions.OplogLimit != "" { if !restore.InputOptions.OplogReplay { return fmt.Errorf("cannot use --oplogLimit without --oplogReplay enabled") } restore.oplogLimit, err = ParseTimestampFlag(restore.InputOptions.OplogLimit) if err != nil { return fmt.Errorf("error parsing timestamp argument to --oplogLimit: %v", err) } } if restore.InputOptions.OplogFile != "" { if !restore.InputOptions.OplogReplay { return fmt.Errorf("cannot use --oplogFile without --oplogReplay enabled") } if restore.InputOptions.Archive != "" { return fmt.Errorf("cannot use --oplogFile with --archive specified") } } // check if we are using a replica set and fall back to w=1 if we aren't (for <= 2.4) nodeType, err := restore.SessionProvider.GetNodeType() if err != nil { return fmt.Errorf("error determining type of connected node: %v", err) } log.Logvf(log.DebugLow, "connected to node type: %v", nodeType) restore.safety, err = db.BuildWriteConcern(restore.OutputOptions.WriteConcern, nodeType) if err != nil { return fmt.Errorf("error parsing write concern: %v", err) } // deprecations with --nsInclude --nsExclude if restore.NSOptions.DB != "" || restore.NSOptions.Collection != "" { // these are only okay if restoring from a bson file _, fileType := restore.getInfoFromFilename(restore.TargetDirectory) if fileType != BSONFileType { log.Logvf(log.Always, "the --db and --collection args should only be used when "+ "restoring from a BSON file. Other uses are deprecated and will not exist "+ "in the future; use --nsInclude instead") } } if len(restore.NSOptions.ExcludedCollections) > 0 || len(restore.NSOptions.ExcludedCollectionPrefixes) > 0 { log.Logvf(log.Always, "the --excludeCollections and --excludeCollectionPrefixes options "+ "are deprecated and will not exist in the future; use --nsExclude instead") } if restore.InputOptions.OplogReplay { if len(restore.NSOptions.NSInclude) > 0 || restore.NSOptions.DB != "" { return fmt.Errorf("cannot use --oplogReplay with includes specified") } if len(restore.NSOptions.NSExclude) > 0 || len(restore.NSOptions.ExcludedCollections) > 0 || len(restore.NSOptions.ExcludedCollectionPrefixes) > 0 { return fmt.Errorf("cannot use --oplogReplay with excludes specified") } if len(restore.NSOptions.NSFrom) > 0 { return fmt.Errorf("cannot use --oplogReplay with namespace renames specified") } } includes := restore.NSOptions.NSInclude if restore.NSOptions.DB != "" && restore.NSOptions.Collection != "" { includes = append(includes, ns.Escape(restore.NSOptions.DB)+"."+ restore.NSOptions.Collection) } else if restore.NSOptions.DB != "" { includes = append(includes, ns.Escape(restore.NSOptions.DB)+".*") } if len(includes) == 0 { includes = []string{"*"} } restore.includer, err = ns.NewMatcher(includes) if err != nil { return fmt.Errorf("invalid includes: %v", err) } if len(restore.NSOptions.ExcludedCollections) > 0 && restore.NSOptions.Collection != "" { return fmt.Errorf("--collection is not allowed when --excludeCollection is specified") } if len(restore.NSOptions.ExcludedCollectionPrefixes) > 0 && restore.NSOptions.Collection != "" { return fmt.Errorf("--collection is not allowed when --excludeCollectionsWithPrefix is specified") } excludes := restore.NSOptions.NSExclude for _, col := range restore.NSOptions.ExcludedCollections { excludes = append(excludes, "*."+ns.Escape(col)) } for _, colPrefix := range restore.NSOptions.ExcludedCollectionPrefixes { excludes = append(excludes, "*."+ns.Escape(colPrefix)+"*") } restore.excluder, err = ns.NewMatcher(excludes) if err != nil { return fmt.Errorf("invalid excludes: %v", err) } if len(restore.NSOptions.NSFrom) != len(restore.NSOptions.NSTo) { return fmt.Errorf("--nsFrom and --nsTo arguments must be specified an equal number of times") } restore.renamer, err = ns.NewRenamer(restore.NSOptions.NSFrom, restore.NSOptions.NSTo) if err != nil { return fmt.Errorf("invalid renames: %v", err) } if restore.OutputOptions.NumInsertionWorkers < 0 { return fmt.Errorf( "cannot specify a negative number of insertion workers per collection") } // a single dash signals reading from stdin if restore.TargetDirectory == "-" { if restore.InputOptions.Archive != "" { return fmt.Errorf( "cannot restore from \"-\" when --archive is specified") } if restore.NSOptions.Collection == "" { return fmt.Errorf("cannot restore from stdin without a specified collection") } } if restore.stdin == nil { restore.stdin = os.Stdin } return nil }
// ParseAndValidateOptions returns a non-nil error if user-supplied options are invalid. func (restore *MongoRestore) ParseAndValidateOptions() error { // Can't use option pkg defaults for --objcheck because it's two separate flags, // and we need to be able to see if they're both being used. We default to // true here and then see if noobjcheck is enabled. log.Log(log.DebugHigh, "checking options") if restore.InputOptions.Objcheck { restore.objCheck = true log.Log(log.DebugHigh, "\tdumping with object check enabled") } else { log.Log(log.DebugHigh, "\tdumping with object check disabled") } if restore.ToolOptions.DB == "" && restore.ToolOptions.Collection != "" { return fmt.Errorf("cannot dump a collection without a specified database") } if restore.ToolOptions.DB != "" { if err := util.ValidateDBName(restore.ToolOptions.DB); err != nil { return fmt.Errorf("invalid db name: %v", err) } } if restore.ToolOptions.Collection != "" { if err := util.ValidateCollectionGrammar(restore.ToolOptions.Collection); err != nil { return fmt.Errorf("invalid collection name: %v", err) } } if restore.InputOptions.RestoreDBUsersAndRoles && restore.ToolOptions.DB == "" { return fmt.Errorf("cannot use --restoreDbUsersAndRoles without a specified database") } if restore.InputOptions.RestoreDBUsersAndRoles && restore.ToolOptions.DB == "admin" { return fmt.Errorf("cannot use --restoreDbUsersAndRoles with the admin database") } var err error restore.isMongos, err = restore.SessionProvider.IsMongos() if err != nil { return err } if restore.isMongos { log.Log(log.DebugLow, "restoring to a sharded system") } if restore.InputOptions.OplogLimit != "" { if !restore.InputOptions.OplogReplay { return fmt.Errorf("cannot use --oplogLimit without --oplogReplay enabled") } restore.oplogLimit, err = ParseTimestampFlag(restore.InputOptions.OplogLimit) if err != nil { return fmt.Errorf("error parsing timestamp argument to --oplogLimit: %v", err) } } // check if we are using a replica set and fall back to w=1 if we aren't (for <= 2.4) nodeType, err := restore.SessionProvider.GetNodeType() if err != nil { return fmt.Errorf("error determining type of connected node: %v", err) } log.Logf(log.DebugLow, "connected to node type: %v", nodeType) restore.safety, err = db.BuildWriteConcern(restore.OutputOptions.WriteConcern, nodeType) if err != nil { return fmt.Errorf("error parsing write concern: %v", err) } // handle the hidden auth collection flags if restore.ToolOptions.HiddenOptions.TempUsersColl == nil { restore.tempUsersCol = "tempusers" } else { restore.tempUsersCol = *restore.ToolOptions.HiddenOptions.TempUsersColl } if restore.ToolOptions.HiddenOptions.TempRolesColl == nil { restore.tempRolesCol = "temproles" } else { restore.tempRolesCol = *restore.ToolOptions.HiddenOptions.TempRolesColl } if restore.OutputOptions.NumInsertionWorkers < 0 { return fmt.Errorf( "cannot specify a negative number of insertion workers per collection") } // a single dash signals reading from stdin if restore.TargetDirectory == "-" { restore.useStdin = true if restore.InputOptions.Archive != "" { return fmt.Errorf( "cannot restore from \"-\" when --archive is specified") } if restore.ToolOptions.Collection == "" { return fmt.Errorf("cannot restore from stdin without a specified collection") } } return nil }