func (s *RepoTestSuite) TestInit(t *C) { im := instance.NewRepo(s.logger, s.configDir, s.api) t.Assert(im, NotNil) err := im.Init() t.Check(err, IsNil) err = test.CopyFile(test.RootDir+"/mm/config/mysql-1.conf", s.configDir) t.Assert(err, IsNil) err = im.Init() t.Assert(err, IsNil) mysqlIt := &proto.MySQLInstance{} err = im.Get("mysql", 1, mysqlIt) t.Assert(err, IsNil) expect := &proto.MySQLInstance{ Id: 1, Hostname: "db1", DSN: "user:host@tcp:(127.0.0.1:3306)", Distro: "Percona Server", Version: "5.6.16", } if same, diff := test.IsDeeply(mysqlIt, expect); !same { test.Dump(mysqlIt) test.Dump(expect) t.Error(diff) } }
func (s *ManagerTestSuite) SetUpSuite(t *C) { s.dsn = os.Getenv("PCT_TEST_MYSQL_DSN") if s.dsn == "" { t.Fatal("PCT_TEST_MYSQL_DSN is not set") } s.logChan = make(chan *proto.LogEntry, 10) s.logger = pct.NewLogger(s.logChan, query.SERVICE_NAME+"-manager-test") var err error s.tmpDir, err = ioutil.TempDir("/tmp", "agent-test") t.Assert(err, IsNil) if err := pct.Basedir.Init(s.tmpDir); err != nil { t.Fatal(err) } s.configDir = pct.Basedir.Dir("config") // Real instance repo s.repo = instance.NewRepo(pct.NewLogger(s.logChan, "im-test"), s.configDir, s.api) data, err := json.Marshal(&proto.MySQLInstance{ Hostname: "db1", DSN: s.dsn, }) t.Assert(err, IsNil) s.repo.Add("mysql", 1, data, false) s.mysqlInstance = proto.ServiceInstance{Service: "mysql", InstanceId: 1} links := map[string]string{ "agent": "http://localhost/agent", "instances": "http://localhost/instances", } s.api = mock.NewAPI("http://localhost", "http://localhost", "123", "abc-123-def", links) }
func (i *Installer) writeInstances(si *proto.ServerInstance, mi *proto.MySQLInstance) error { // We could write the instance structs directly, but this is the job of an // instance repo and it's easy enough to create one, so do the right thing. logChan := make(chan *proto.LogEntry, 100) logger := pct.NewLogger(logChan, "instance-repo") repo := instance.NewRepo(logger, pct.Basedir.Dir("config"), i.api) if si != nil { bytes, err := json.Marshal(si) if err != nil { return err } if err := repo.Add("server", si.Id, bytes, true); err != nil { return err } } if mi != nil { bytes, err := json.Marshal(mi) if err != nil { return err } if err := repo.Add("mysql", mi.Id, bytes, true); err != nil { return err } } return nil }
func (s *ManagerTestSuite) SetUpSuite(t *C) { s.logChan = make(chan *proto.LogEntry, 10) s.logger = pct.NewLogger(s.logChan, "sysconfig-manager-test") s.mockMonitor = mock.NewSysconfigMonitor() s.factory = mock.NewSysconfigMonitorFactory([]sysconfig.Monitor{s.mockMonitor}) s.tickChan = make(chan time.Time) s.dataChan = make(chan interface{}, 1) s.spool = mock.NewSpooler(s.dataChan) var err error s.tmpDir, err = ioutil.TempDir("/tmp", "agent-test") t.Assert(err, IsNil) if err := pct.Basedir.Init(s.tmpDir); err != nil { t.Fatal(err) } s.configDir = pct.Basedir.Dir("config") links := map[string]string{ "agent": "http://localhost/agent", "instances": "http://localhost/instances", } s.api = mock.NewAPI("http://localhost", "http://localhost", "123", "abc-123-def", links) s.im = instance.NewRepo(pct.NewLogger(s.logChan, "im-test"), s.configDir, s.api) }
func (i *InstallerTestSuite) TestIsSupportedMySQLVersion(t *C) { var got bool var err error agentConfig := &agent.Config{} flags := installer.Flags{} apiConnector := pct.NewAPI() api := api.New(apiConnector, false) logChan := make(chan *proto.LogEntry, 100) logger := pct.NewLogger(logChan, "instance-repo") instanceRepo := instance.NewRepo(logger, pct.Basedir.Dir("config"), apiConnector) terminal := term.NewTerminal(os.Stdin, false, true) inst := installer.NewInstaller(terminal, "", api, instanceRepo, agentConfig, flags) conn := mock.NewNullMySQL() errSomethingWentWrong := fmt.Errorf("Something went wrong") conn.SetAtLeastVersion(false, errSomethingWentWrong) got, err = inst.IsVersionSupported(conn) t.Assert(conn.Version, Equals, agent.MIN_SUPPORTED_MYSQL_VERSION) t.Assert(err, Equals, errSomethingWentWrong) t.Assert(got, Equals, false) conn.SetAtLeastVersion(true, nil) got, err = inst.IsVersionSupported(conn) t.Assert(conn.Version, Equals, agent.MIN_SUPPORTED_MYSQL_VERSION) t.Assert(err, IsNil) t.Assert(got, Equals, true) conn.Close() }
func (s *ManagerTestSuite) SetUpSuite(t *C) { s.dsn = os.Getenv("PCT_TEST_MYSQL_DSN") if s.dsn == "" { t.Fatal("PCT_TEST_MYSQL_DSN is not set") } s.realmysql = mysql.NewConnection(s.dsn) if err := s.realmysql.Connect(1); err != nil { t.Fatal(err) } s.reset = []mysql.Query{ mysql.Query{Set: "SET GLOBAL slow_query_log=OFF"}, mysql.Query{Set: "SET GLOBAL long_query_time=10"}, } s.nullmysql = mock.NewNullMySQL() s.logChan = make(chan *proto.LogEntry, 1000) s.logger = pct.NewLogger(s.logChan, "qan-test") s.intervalChan = make(chan *qan.Interval, 1) s.iter = mock.NewMockIntervalIter(s.intervalChan) s.iterFactory = &mock.IntervalIterFactory{ Iters: []qan.IntervalIter{s.iter}, TickChans: make(map[qan.IntervalIter]chan time.Time), } s.dataChan = make(chan interface{}, 2) s.spool = mock.NewSpooler(s.dataChan) s.workerFactory = &qan.SlowLogWorkerFactory{} var err error s.tmpDir, err = ioutil.TempDir("/tmp", "agent-test") t.Assert(err, IsNil) if err := pct.Basedir.Init(s.tmpDir); err != nil { t.Fatal(err) } s.configDir = pct.Basedir.Dir("config") s.im = instance.NewRepo(pct.NewLogger(s.logChan, "im-test"), s.configDir, s.api) data, err := json.Marshal(&proto.MySQLInstance{ Hostname: "db1", DSN: s.dsn, }) t.Assert(err, IsNil) s.im.Add("mysql", 1, data, false) s.mysqlInstance = proto.ServiceInstance{Service: "mysql", InstanceId: 1} links := map[string]string{ "agent": "http://localhost/agent", "instances": "http://localhost/instances", } s.api = mock.NewAPI("http://localhost", "http://localhost", "123", "abc-123-def", links) }
func (s *ManagerTestSuite) SetUpSuite(t *C) { s.logChan = make(chan *proto.LogEntry, 10) s.logger = pct.NewLogger(s.logChan, "mm-manager-test") s.tickChan = make(chan time.Time) s.traceChan = make(chan string, 10) s.dataChan = make(chan interface{}, 1) s.spool = mock.NewSpooler(s.dataChan) var err error s.tmpDir, err = ioutil.TempDir("/tmp", "agent-test") t.Assert(err, IsNil) if err := pct.Basedir.Init(s.tmpDir); err != nil { t.Fatal(err) } s.configDir = pct.Basedir.Dir("config") s.im = instance.NewRepo(pct.NewLogger(s.logChan, "im"), s.configDir, s.api) data, err := json.Marshal(&proto.MySQLInstance{ Hostname: "db1", DSN: "user:host@tcp:(127.0.0.1:3306)", }) t.Assert(err, IsNil) s.im.Add("mysql", 1, data, false) data, err = json.Marshal(&proto.ServerInstance{Hostname: "host1"}) t.Assert(err, IsNil) s.im.Add("server", 1, data, false) s.mysqlMonitor = mock.NewMmMonitor() s.systemMonitor = mock.NewMmMonitor() s.factory = mock.NewMmMonitorFactory(map[string]mm.Monitor{ "mysql-1": s.mysqlMonitor, "server-1": s.systemMonitor, }) links := map[string]string{ "agent": "http://localhost/agent", "instances": "http://localhost/instances", } s.api = mock.NewAPI("http://localhost", "http://localhost", "123", "abc-123-def", links) }
func (s *RepoTestSuite) TestAddRemove(t *C) { im := instance.NewRepo(s.logger, s.configDir, s.api) t.Assert(im, NotNil) t.Check(test.FileExists(s.configDir+"/mysql-1.conf"), Equals, false) mysqlIt := &proto.MySQLInstance{ Id: 1, Hostname: "db1", DSN: "user:host@tcp:(127.0.0.1:3306)", Distro: "Percona Server", Version: "5.6.16", } data, err := json.Marshal(mysqlIt) t.Assert(err, IsNil) err = im.Add("mysql", 1, data, true) t.Assert(err, IsNil) t.Check(test.FileExists(s.configDir+"/mysql-1.conf"), Equals, true) got := &proto.MySQLInstance{} err = im.Get("mysql", 1, got) t.Assert(err, IsNil) if same, diff := test.IsDeeply(got, mysqlIt); !same { t.Error(diff) } data, err = ioutil.ReadFile(s.configDir + "/mysql-1.conf") t.Assert(err, IsNil) got = &proto.MySQLInstance{} err = json.Unmarshal(data, got) t.Assert(err, IsNil) if same, diff := test.IsDeeply(got, mysqlIt); !same { t.Error(diff) } im.Remove("mysql", 1) t.Check(test.FileExists(s.configDir+"/mysql-1.conf"), Equals, false) }
func (s *AnalyzerTestSuite) SetUpSuite(t *C) { s.nullmysql = mock.NewNullMySQL() s.logChan = make(chan *proto.LogEntry, 1000) s.logger = pct.NewLogger(s.logChan, "qan-test") s.intervalChan = make(chan *qan.Interval, 1) s.iter = mock.NewIter(s.intervalChan) s.dataChan = make(chan interface{}, 1) s.spool = mock.NewSpooler(s.dataChan) var err error s.tmpDir, err = ioutil.TempDir("/tmp", "agent-test") t.Assert(err, IsNil) if err := pct.Basedir.Init(s.tmpDir); err != nil { t.Fatal(err) } s.configDir = pct.Basedir.Dir("config") s.im = instance.NewRepo(pct.NewLogger(s.logChan, "im-test"), s.configDir, s.api) data, err := json.Marshal(&proto.MySQLInstance{ Hostname: "bm-cloud-db01", Alias: "db01", DSN: "user:pass@tcp/", }) t.Assert(err, IsNil) s.im.Add("mysql", 1, data, false) s.mysqlInstance = proto.ServiceInstance{Service: "mysql", InstanceId: 1} links := map[string]string{ "agent": "http://localhost/agent", "instances": "http://localhost/instances", } s.api = mock.NewAPI("http://localhost", "http://localhost", "123", "abc-123-def", links) s.restartChan = make(chan bool, 1) }
func (s *RepoTestSuite) TestErrors(t *C) { im := instance.NewRepo(s.logger, s.configDir, s.api) t.Assert(im, NotNil) mysqlIt := &proto.MySQLInstance{ Id: 0, Hostname: "db1", DSN: "user:host@tcp:(127.0.0.1:3306)", Distro: "Percona Server", Version: "5.6.16", } data, err := json.Marshal(mysqlIt) t.Assert(err, IsNil) // Instance ID must be > 0. err = im.Add("mysql", 0, data, false) t.Assert(err, NotNil) // Service name must be one of proto.ExternalService. err = im.Add("foo", 1, data, false) t.Assert(err, NotNil) }
func main() { // It flag is unknown it exist with os.Exit(10), // so exit code=10 is strictly reserved for flags // Don't use it anywhere else, as shell script install.sh depends on it // NOTE: standard flag.Parse() was using os.Exit(2) // which was the same as returned with ctrl+c if err := flag.CommandLine.Parse(os.Args[1:]); err != nil { os.Exit(10) } agentConfig := &agent.Config{ ApiHostname: flagApiHostname, ApiKey: flagApiKey, } // todo: do flags a better way if !flagMySQL { flagCreateMySQLInstance = false flagStartMySQLServices = false } if flagMySQLSocket != "" && flagMySQLHost != "" { log.Println("Options -mysql-socket and -mysql-host are exclusive\n") os.Exit(1) } if flagMySQLSocket != "" && flagMySQLPort != "" { log.Println("Options -mysql-socket and -mysql-port are exclusive\n") os.Exit(1) } flags := installer.Flags{ Bool: map[string]bool{ "debug": flagDebug, "create-server-instance": flagCreateServerInstance, "start-services": flagStartServices, "create-mysql-instance": flagCreateMySQLInstance, "start-mysql-services": flagStartMySQLServices, "create-agent": flagCreateAgent, "old-passwords": flagOldPasswords, "plain-passwords": flagPlainPasswords, "interactive": flagInteractive, "auto-detect-mysql": flagAutoDetectMySQL, "create-mysql-user": flagCreateMySQLUser, "mysql": flagMySQL, }, String: map[string]string{ "app-host": DEFAULT_APP_HOSTNAME, "mysql-defaults-file": flagMySQLDefaultsFile, "agent-mysql-user": flagAgentMySQLUser, "agent-mysql-pass": flagAgentMySQLPass, "mysql-user": flagMySQLUser, "mysql-pass": flagMySQLPass, "mysql-host": flagMySQLHost, "mysql-port": flagMySQLPort, "mysql-socket": flagMySQLSocket, }, Int64: map[string]int64{ "mysql-max-user-connections": flagMySQLMaxUserConnections, }, } // Agent stores all its files in the basedir. This must be called first // because installer uses pct.Basedir and assumes it's already initialized. if err := pct.Basedir.Init(flagBasedir); err != nil { log.Printf("Error initializing basedir %s: %s\n", flagBasedir, err) os.Exit(1) } apiConnector := pct.NewAPI() api := api.New(apiConnector, flagDebug) logChan := make(chan *proto.LogEntry, 100) logger := pct.NewLogger(logChan, "instance-repo") instanceRepo := instance.NewRepo(logger, pct.Basedir.Dir("config"), apiConnector) terminal := term.NewTerminal(os.Stdin, flagInteractive, flagDebug) agentInstaller := installer.NewInstaller(terminal, flagBasedir, api, instanceRepo, agentConfig, flags) fmt.Println("CTRL-C at any time to quit") // todo: catch SIGINT and clean up if err := agentInstaller.Run(); err != nil { fmt.Println(err) os.Exit(1) } os.Exit(0) }