// Configure the connector to connect to the server over ssl. Parses the // connection string, and sets up the correct function to dial the server // based on the ssl options passed in. func (self *SSLDBConnector) Configure(opts options.ToolOptions) error { // create the addresses to be used to connect connectionAddrs := util.CreateConnectionAddrs(opts.Host, opts.Port) var err error self.ctx, err = setupCtx(opts) if err != nil { return fmt.Errorf("setupCtx: %v", err) } // create the dialer func that will be used to connect dialer := func(addr *mgo.ServerAddr) (net.Conn, error) { conn, err := openssl.Dial("tcp", addr.String(), self.ctx, 0) self.dialError = err return conn, err } // set up the dial info self.dialInfo = &mgo.DialInfo{ Addrs: connectionAddrs, Timeout: DefaultSSLDialTimeout, DialServer: dialer, Username: opts.Auth.Username, Password: opts.Auth.Password, Source: opts.Auth.Source, Mechanism: opts.Auth.Mechanism, } return nil }
// Configure the db connector. Parses the connection string and sets up // the dial info with the default dial timeout. func (self *KerberosDBConnector) Configure(opts options.ToolOptions) error { // create the addresses to be used to connect connectionAddrs := util.CreateConnectionAddrs(opts.Host, opts.Port) // set up the dial info self.dialInfo = &mgo.DialInfo{ Addrs: connectionAddrs, Timeout: KERBEROS_DIAL_TIMEOUT, Direct: opts.Direct, ReplicaSetName: opts.ReplicaSetName, // Kerberos principal Username: opts.Auth.Username, // Note: Password is only used on Windows. SASL doesn't allow you to specify // a password, so this field is ignored on Linux and OSX. Run the kinit // command to get a ticket first. Password: opts.Auth.Password, // This should always be '$external', but legacy tools still allow you to // specify a source DB Source: opts.Auth.Source, Service: opts.Kerberos.Service, ServiceHost: opts.Kerberos.ServiceHost, Mechanism: KERBEROS_AUTHENTICATION_MECHANISM, } return nil }
// Configure sets up the db connector using the options in opts. It parses the // connection string and then sets up the dial information using the default // dial timeout. func (self *VanillaDBConnector) Configure(opts options.ToolOptions) error { // create the addresses to be used to connect connectionAddrs := util.CreateConnectionAddrs(opts.Host, opts.Port) // set up the dial info self.dialInfo = &mgo.DialInfo{ Addrs: connectionAddrs, Timeout: DefaultDialTimeout, Direct: opts.Direct, ReplicaSetName: opts.ReplicaSetName, Username: opts.Auth.Username, Password: opts.Auth.Password, Source: opts.GetAuthenticationDatabase(), Mechanism: opts.Auth.Mechanism, } return nil }
// Configure the connector to connect to the server over ssl. Parses the // connection string, and sets up the correct function to dial the server // based on the ssl options passed in. func (self *SSLDBConnector) Configure(opts options.ToolOptions) error { // create the addresses to be used to connect connectionAddrs := util.CreateConnectionAddrs(opts.Host, opts.Port) var err error self.ctx, err = setupCtx(opts) if err != nil { return fmt.Errorf("openssl configuration: %v", err) } var flags openssl.DialFlags flags = 0 if opts.SSLAllowInvalidCert || opts.SSLAllowInvalidHost || opts.SSLCAFile == "" { flags = openssl.InsecureSkipHostVerification } // create the dialer func that will be used to connect dialer := func(addr *mgo.ServerAddr) (net.Conn, error) { conn, err := openssl.Dial("tcp", addr.String(), self.ctx, flags) self.dialError = err return conn, err } timeout := time.Duration(opts.Timeout) * time.Second // set up the dial info self.dialInfo = &mgo.DialInfo{ Addrs: connectionAddrs, Timeout: timeout, Direct: opts.Direct, ReplicaSetName: opts.ReplicaSetName, DialServer: dialer, Username: opts.Auth.Username, Password: opts.Auth.Password, Source: opts.GetAuthenticationDatabase(), Mechanism: opts.Auth.Mechanism, } return nil }
// Configure the db connector. Parses the connection string and sets up // the dial info with the default dial timeout. func (self *KerberosDBConnector) Configure(opts options.ToolOptions) error { // create the addresses to be used to connect connectionAddrs := util.CreateConnectionAddrs(opts.Host, opts.Port) // set up the dial info self.dialInfo = &mgo.DialInfo{ Addrs: connectionAddrs, Timeout: KERBEROS_DIAL_TIMEOUT, Direct: opts.Direct, Username: opts.Auth.Username, // This should always be '$external', but legacy tools require this Source: opts.Auth.Source, Service: opts.Kerberos.Service, ServiceHost: opts.Kerberos.ServiceHost, Mechanism: KERBEROS_AUTHENTICATION_MECHANISM, } return nil }
func main() { // initialize command-line opts opts := options.New( "mongostat", mongostat.Usage, options.EnabledOptions{Connection: true, Auth: true, Namespace: false}) opts.UseReadOnlyHostDescription() // add mongostat-specific options statOpts := &mongostat.StatOptions{} opts.AddOptions(statOpts) interactiveOption := opts.FindOptionByLongName("interactive") if _, available := stat_consumer.FormatterConstructors["interactive"]; !available { // make --interactive inaccessible interactiveOption.LongName = "" interactiveOption.ShortName = 0 } args, err := opts.Parse() if err != nil { log.Logvf(log.Always, "error parsing command line options: %v", err) log.Logvf(log.Always, "try 'mongostat --help' for more information") os.Exit(util.ExitBadOptions) } log.SetVerbosity(opts.Verbosity) signals.Handle() sleepInterval := 1 if len(args) > 0 { if len(args) != 1 { log.Logvf(log.Always, "too many positional arguments: %v", args) log.Logvf(log.Always, "try 'mongostat --help' for more information") os.Exit(util.ExitBadOptions) } sleepInterval, err = strconv.Atoi(args[0]) if err != nil { log.Logvf(log.Always, "invalid sleep interval: %v", args[0]) os.Exit(util.ExitBadOptions) } if sleepInterval < 1 { log.Logvf(log.Always, "sleep interval must be at least 1 second") os.Exit(util.ExitBadOptions) } } // print help, if specified if opts.PrintHelp(false) { return } // print version, if specified if opts.PrintVersion() { return } if opts.Auth.Username != "" && opts.Auth.Source == "" && !opts.Auth.RequiresExternalDB() { log.Logvf(log.Always, "--authenticationDatabase is required when authenticating against a non $external database") os.Exit(util.ExitBadOptions) } if statOpts.Interactive && statOpts.Json { log.Logvf(log.Always, "cannot use output formats --json and --interactive together") os.Exit(util.ExitBadOptions) } if statOpts.Deprecated && !statOpts.Json { log.Logvf(log.Always, "--useDeprecatedJsonKeys can only be used when --json is also specified") os.Exit(util.ExitBadOptions) } if statOpts.Columns != "" && statOpts.AppendColumns != "" { log.Logvf(log.Always, "-O cannot be used if -o is also specified") os.Exit(util.ExitBadOptions) } if statOpts.HumanReadable != "true" && statOpts.HumanReadable != "false" { log.Logvf(log.Always, "--humanReadable must be set to either 'true' or 'false'") os.Exit(util.ExitBadOptions) } // we have to check this here, otherwise the user will be prompted // for a password for each discovered node if opts.Auth.ShouldAskForPassword() { opts.Auth.Password = password.Prompt() } var factory stat_consumer.FormatterConstructor if statOpts.Json { factory = stat_consumer.FormatterConstructors["json"] } else if statOpts.Interactive { factory = stat_consumer.FormatterConstructors["interactive"] } else { factory = stat_consumer.FormatterConstructors[""] } formatter := factory(statOpts.RowCount, !statOpts.NoHeaders) cliFlags := 0 if statOpts.Columns == "" { cliFlags = line.FlagAlways if statOpts.Discover { cliFlags |= line.FlagDiscover cliFlags |= line.FlagHosts } if statOpts.All { cliFlags |= line.FlagAll } if strings.Contains(opts.Host, ",") { cliFlags |= line.FlagHosts } } var customHeaders []string if statOpts.Columns != "" { customHeaders = optionCustomHeaders(statOpts.Columns) } else if statOpts.AppendColumns != "" { customHeaders = optionCustomHeaders(statOpts.AppendColumns) } var keyNames map[string]string if statOpts.Deprecated { keyNames = line.DeprecatedKeyMap() } else if statOpts.Columns == "" { keyNames = line.DefaultKeyMap() } else { keyNames = optionKeyNames(statOpts.Columns) } if statOpts.AppendColumns != "" { addKN := optionKeyNames(statOpts.AppendColumns) for k, v := range addKN { keyNames[k] = v } } readerConfig := &status.ReaderConfig{ HumanReadable: statOpts.HumanReadable == "true", } if statOpts.Json { readerConfig.TimeFormat = "15:04:05" } consumer := stat_consumer.NewStatConsumer(cliFlags, customHeaders, keyNames, readerConfig, formatter, os.Stdout) seedHosts := util.CreateConnectionAddrs(opts.Host, opts.Port) var cluster mongostat.ClusterMonitor if statOpts.Discover || len(seedHosts) > 1 { cluster = &mongostat.AsyncClusterMonitor{ ReportChan: make(chan *status.ServerStatus), ErrorChan: make(chan *status.NodeError), LastStatLines: map[string]*line.StatLine{}, Consumer: consumer, } } else { cluster = &mongostat.SyncClusterMonitor{ ReportChan: make(chan *status.ServerStatus), ErrorChan: make(chan *status.NodeError), Consumer: consumer, } } var discoverChan chan string if statOpts.Discover { discoverChan = make(chan string, 128) } opts.Direct = true _, setName := util.ParseConnectionString(opts.Host) opts.ReplicaSetName = setName stat := &mongostat.MongoStat{ Options: opts, StatOptions: statOpts, Nodes: map[string]*mongostat.NodeMonitor{}, Discovered: discoverChan, SleepInterval: time.Duration(sleepInterval) * time.Second, Cluster: cluster, } for _, v := range seedHosts { stat.AddNewNode(v) } // kick it off err = stat.Run() if err != nil { log.Logvf(log.Always, "Failed: %v", err) os.Exit(util.ExitError) } }
func main() { go signals.Handle() // initialize command-line opts opts := options.New( "mongostat", mongostat.Usage, options.EnabledOptions{Connection: true, Auth: true, Namespace: false}) // add mongostat-specific options statOpts := &mongostat.StatOptions{} opts.AddOptions(statOpts) args, err := opts.Parse() if err != nil { log.Logf(log.Always, "error parsing command line options: %v", err) log.Logf(log.Always, "try 'mongostat --help' for more information") os.Exit(util.ExitBadOptions) } log.SetVerbosity(opts.Verbosity) sleepInterval := 1 if len(args) > 0 { if len(args) != 1 { log.Logf(log.Always, "too many positional arguments: %v", args) log.Logf(log.Always, "try 'mongostat --help' for more information") os.Exit(util.ExitBadOptions) } sleepInterval, err = strconv.Atoi(args[0]) if err != nil { log.Logf(log.Always, "invalid sleep interval: %v", args[0]) os.Exit(util.ExitBadOptions) } if sleepInterval < 1 { log.Logf(log.Always, "sleep interval must be at least 1 second") os.Exit(util.ExitBadOptions) } } // print help, if specified if opts.PrintHelp(false) { return } // print version, if specified if opts.PrintVersion() { return } if opts.Auth.Username != "" && opts.Auth.Source == "" && !opts.Auth.RequiresExternalDB() { log.Logf(log.Always, "--authenticationDatabase is required when authenticating against a non $external database") os.Exit(util.ExitBadOptions) } // we have to check this here, otherwise the user will be prompted // for a password for each discovered node if opts.Auth.ShouldAskForPassword() { opts.Auth.Password = password.Prompt() } var formatter mongostat.LineFormatter if statOpts.Json { formatter = &mongostat.JSONLineFormatter{} } else { formatter = &mongostat.GridLineFormatter{ IncludeHeader: !statOpts.NoHeaders, HeaderInterval: 10, Writer: &text.GridWriter{ColumnPadding: 1}, } } seedHosts := util.CreateConnectionAddrs(opts.Host, opts.Port) var cluster mongostat.ClusterMonitor if statOpts.Discover || len(seedHosts) > 1 { cluster = &mongostat.AsyncClusterMonitor{ ReportChan: make(chan mongostat.StatLine), LastStatLines: map[string]*mongostat.StatLine{}, Formatter: formatter, } } else { cluster = &mongostat.SyncClusterMonitor{ ReportChan: make(chan mongostat.StatLine), Formatter: formatter, } } var discoverChan chan string if statOpts.Discover { discoverChan = make(chan string, 128) } opts.Direct = true _, setName := util.ParseConnectionString(opts.Host) opts.ReplicaSetName = setName stat := &mongostat.MongoStat{ Options: opts, StatOptions: statOpts, Nodes: map[string]*mongostat.NodeMonitor{}, Discovered: discoverChan, SleepInterval: time.Duration(sleepInterval) * time.Second, Cluster: cluster, } for _, v := range seedHosts { stat.AddNewNode(v) } // kick it off err = stat.Run() if err != nil { log.Logf(log.Always, "Failed: %v", err) os.Exit(util.ExitError) } }