// Init performs preliminary setup operations for MongoDump. func (dump *MongoDump) Init() error { err := dump.ValidateOptions() if err != nil { return fmt.Errorf("bad option: %v", err) } if dump.stdout == nil { dump.stdout = os.Stdout } dump.sessionProvider, err = db.NewSessionProvider(*dump.ToolOptions) if err != nil { return fmt.Errorf("can't create session: %v", err) } // temporarily allow secondary reads for the isMongos check dump.sessionProvider.SetReadPreference(mgo.Nearest) dump.isMongos, err = dump.sessionProvider.IsMongos() if err != nil { return err } if dump.isMongos && dump.OutputOptions.Oplog { return fmt.Errorf("can't use --oplog option when dumping from a mongos") } var mode mgo.Mode if dump.ToolOptions.ReplicaSetName != "" || dump.isMongos { mode = mgo.Primary } else { mode = mgo.Nearest } var tags bson.D if dump.InputOptions.ReadPreference != "" { mode, tags, err = db.ParseReadPreference(dump.InputOptions.ReadPreference) if err != nil { return fmt.Errorf("error parsing --readPreference : %v", err) } if len(tags) > 0 { dump.sessionProvider.SetTags(tags) } } // warn if we are trying to dump from a secondary in a sharded cluster if dump.isMongos && mode != mgo.Primary { log.Logf(log.Always, db.WarningNonPrimaryMongosConnection) } dump.sessionProvider.SetReadPreference(mode) dump.sessionProvider.SetTags(tags) dump.sessionProvider.SetFlags(db.DisableSocketTimeout) // return a helpful error message for mongos --repair if dump.OutputOptions.Repair && dump.isMongos { return fmt.Errorf("--repair flag cannot be used on a mongos") } dump.manager = intents.NewIntentManager() dump.progressManager = progress.NewProgressBarManager(log.Writer(0), progressBarWaitTime) return nil }
func main() { // initialize command-line opts opts := options.New("mongoexport", mongoexport.Usage, options.EnabledOptions{Auth: true, Connection: true, Namespace: true}) outputOpts := &mongoexport.OutputFormatOptions{} opts.AddOptions(outputOpts) inputOpts := &mongoexport.InputOptions{} opts.AddOptions(inputOpts) args, err := opts.Parse() if err != nil { log.Logvf(log.Always, "error parsing command line options: %v", err) log.Logvf(log.Always, "try 'mongoexport --help' for more information") os.Exit(util.ExitBadOptions) } if len(args) != 0 { log.Logvf(log.Always, "too many positional arguments: %v", args) log.Logvf(log.Always, "try 'mongoexport --help' for more information") os.Exit(util.ExitBadOptions) } log.SetVerbosity(opts.Verbosity) signals.Handle() // print help, if specified if opts.PrintHelp(false) { return } // print version, if specified if opts.PrintVersion() { return } // connect directly, unless a replica set name is explicitly specified _, setName := util.ParseConnectionString(opts.Host) opts.Direct = (setName == "") opts.ReplicaSetName = setName provider, err := db.NewSessionProvider(*opts) // temporarily allow secondary reads for the isMongos check provider.SetReadPreference(mgo.Nearest) isMongos, err := provider.IsMongos() if err != nil { log.Logvf(log.Always, "%v", err) os.Exit(util.ExitError) } provider.SetFlags(db.DisableSocketTimeout) if inputOpts.SlaveOk { if inputOpts.ReadPreference != "" { log.Logvf(log.Always, "--slaveOk can't be specified when --readPreference is specified") os.Exit(util.ExitBadOptions) } log.Logvf(log.Always, "--slaveOk is deprecated and being internally rewritten as --readPreference=nearest") inputOpts.ReadPreference = "nearest" } var mode mgo.Mode if opts.ReplicaSetName != "" || isMongos { mode = mgo.Primary } else { mode = mgo.Nearest } var tags bson.D if inputOpts.ReadPreference != "" { mode, tags, err = db.ParseReadPreference(inputOpts.ReadPreference) if err != nil { log.Logvf(log.Always, "error parsing --ReadPreference: %v", err) os.Exit(util.ExitBadOptions) } if len(tags) > 0 { provider.SetTags(tags) } } // warn if we are trying to export from a secondary in a sharded cluster if isMongos && mode != mgo.Primary { log.Logvf(log.Always, db.WarningNonPrimaryMongosConnection) } provider.SetReadPreference(mode) if err != nil { log.Logvf(log.Always, "error connecting to host: %v", err) os.Exit(util.ExitError) } exporter := mongoexport.MongoExport{ ToolOptions: *opts, OutputOpts: outputOpts, InputOpts: inputOpts, SessionProvider: provider, } err = exporter.ValidateSettings() if err != nil { log.Logvf(log.Always, "error validating settings: %v", err) log.Logvf(log.Always, "try 'mongoexport --help' for more information") os.Exit(util.ExitBadOptions) } writer, err := exporter.GetOutputWriter() if err != nil { log.Logvf(log.Always, "error opening output stream: %v", err) os.Exit(util.ExitError) } if writer == nil { writer = os.Stdout } else { defer writer.Close() } numDocs, err := exporter.Export(writer) if err != nil { log.Logvf(log.Always, "Failed: %v", err) os.Exit(util.ExitError) } if numDocs == 1 { log.Logvf(log.Always, "exported %v record", numDocs) } else { log.Logvf(log.Always, "exported %v records", numDocs) } }
// Run the mongofiles utility. If displayHost is true, the connected host/port is // displayed. func (mf *MongoFiles) Run(displayHost bool) (string, error) { connUrl := mf.ToolOptions.Host if connUrl == "" { connUrl = util.DefaultHost } if mf.ToolOptions.Port != "" { connUrl = fmt.Sprintf("%s:%s", connUrl, mf.ToolOptions.Port) } var mode = mgo.Nearest var tags bson.D if mf.InputOptions.ReadPreference != "" { var err error mode, tags, err = db.ParseReadPreference(mf.InputOptions.ReadPreference) if err != nil { return "", fmt.Errorf("error parsing --readPreference : %v", err) } if len(tags) > 0 { mf.SessionProvider.SetTags(tags) } } mf.SessionProvider.SetReadPreference(mode) mf.SessionProvider.SetTags(tags) mf.SessionProvider.SetFlags(db.DisableSocketTimeout) // get session session, err := mf.SessionProvider.GetSession() if err != nil { return "", err } defer session.Close() // check type of node we're connected to, and fall back to w=1 if standalone (for <= 2.4) nodeType, err := mf.SessionProvider.GetNodeType() if err != nil { return "", fmt.Errorf("error determining type of node connected: %v", err) } log.Logvf(log.DebugLow, "connected to node type: %v", nodeType) safety, err := db.BuildWriteConcern(mf.StorageOptions.WriteConcern, nodeType) if err != nil { return "", fmt.Errorf("error parsing write concern: %v", err) } // configure the session with the appropriate write concern and ensure the // socket does not timeout session.SetSafe(safety) if displayHost { log.Logvf(log.Always, "connected to: %v", connUrl) } // first validate the namespaces we'll be using: <db>.<prefix>.files and <db>.<prefix>.chunks // it's ok to validate only <db>.<prefix>.chunks (the longer one) err = util.ValidateFullNamespace(fmt.Sprintf("%s.%s.chunks", mf.StorageOptions.DB, mf.StorageOptions.GridFSPrefix)) if err != nil { return "", err } // get GridFS handle gfs := session.DB(mf.StorageOptions.DB).GridFS(mf.StorageOptions.GridFSPrefix) var output string log.Logvf(log.Info, "handling mongofiles '%v' command...", mf.Command) switch mf.Command { case List: query := bson.M{} if mf.FileName != "" { regex := bson.M{"$regex": "^" + regexp.QuoteMeta(mf.FileName)} query = bson.M{"filename": regex} } output, err = mf.findAndDisplay(gfs, query) if err != nil { return "", err } case Search: regex := bson.M{"$regex": mf.FileName} query := bson.M{"filename": regex} output, err = mf.findAndDisplay(gfs, query) if err != nil { return "", err } case Get: output, err = mf.handleGet(gfs) if err != nil { return "", err } case GetID: output, err = mf.handleGetID(gfs) if err != nil { return "", err } case Put: output, err = mf.handlePut(gfs) if err != nil { return "", err } case Delete: err = gfs.Remove(mf.FileName) if err != nil { return "", fmt.Errorf("error while removing '%v' from GridFS: %v\n", mf.FileName, err) } output = fmt.Sprintf("successfully deleted all instances of '%v' from GridFS\n", mf.FileName) case DeleteID: output, err = mf.handleDeleteID(gfs) if err != nil { return "", err } } return output, nil }