func main() { cfg := config.NewDefaultConfig("", "", "") err := cfg.LoadConfig() if err != nil { fmt.Printf("Error loading config") } err = canolog.Init(".canopy-ops.log") if err != nil { fmt.Println(err) return } flag.Parse() cmd := canopy_ops.FindCommand(cmds, flag.Arg(0)) info := canopy_ops.CommandInfo{ CmdList: cmds, Cfg: cfg, Args: flag.Args(), } if cmd != nil { cmd.Perform(info) } else if flag.Arg(0) == "create-account" { dl := cassandra_datalayer.NewDatalayer(cfg) conn, _ := dl.Connect("canopy") conn.CreateAccount(flag.Arg(1), flag.Arg(2), flag.Arg(3)) } else if flag.Arg(0) == "delete-account" { dl := cassandra_datalayer.NewDatalayer(cfg) conn, _ := dl.Connect("canopy") conn.DeleteAccount(flag.Arg(1)) } else if flag.Arg(0) == "create-device" { dl := cassandra_datalayer.NewDatalayer(cfg) conn, _ := dl.Connect("canopy") account, err := conn.LookupAccount(flag.Arg(1)) if err != nil { fmt.Println("Unable to lookup account ", flag.Arg(1), ":", err) return } device, err := conn.CreateDevice(flag.Arg(2), nil, "", datalayer.NoAccess) if err != nil { fmt.Println("Unable to create device: ", err) return } err = device.SetAccountAccess(account, datalayer.ReadWriteAccess, datalayer.ShareRevokeAllowed) if err != nil { fmt.Println("Unable to grant account access to device: ", err) return } } else if flag.Arg(0) == "list-devices" { dl := cassandra_datalayer.NewDatalayer(cfg) conn, _ := dl.Connect("canopy") account, err := conn.LookupAccount(flag.Arg(1)) if err != nil { fmt.Println("Unable to lookup account ", flag.Arg(1), ":", err) return } devices, err := account.Devices().DeviceList(0, -1) if err != nil { fmt.Println("Error reading devices: ", err) return } for _, device := range devices { fmt.Printf("%s %s\n", device.ID(), device.Name()) } } else if flag.Arg(0) == "gen-fake-sensor-data" { dl := cassandra_datalayer.NewDatalayer(cfg) conn, _ := dl.Connect("canopy") deviceId, err := gocql.ParseUUID(flag.Arg(1)) if err != nil { fmt.Println("Error parsing UUID: ", flag.Arg(1), ":", err) return } _, err = conn.LookupDevice(deviceId) if err != nil { fmt.Println("Device not found: ", flag.Arg(1), ":", err) return } for i := 0; i < 100; i++ { //val := float64(i % 16); //t := time.Now().Add(time.Duration(-i)*time.Second) //err = device.InsertSensorSample(flag.Arg(2), t, val) //if err != nil { fmt.Println("Error inserting sample: ", err) //} } } else if flag.Arg(0) == "clear-sensor-data" { dl := cassandra_datalayer.NewDatalayer(cfg) conn, _ := dl.Connect("canopy") conn.ClearSensorData() } else if flag.Arg(0) == "test-email" { mailer, err := mail.NewMailClient(cfg) if err != nil { fmt.Println("Error initializing mail client: ", err) return } mail := mailer.NewMail() err = mail.AddTo(flag.Arg(1), "Customer") if err != nil { fmt.Println("Invalid recipient: ", flag.Arg(1), err) return } mail.SetSubject("Test email from Canopy") mail.SetHTML("<b>Canopy Rulez</b>") mail.SetFrom("*****@*****.**", "The Canopy Team") err = mailer.Send(mail) if err != nil { fmt.Println("Error sending email:", err) return } fmt.Println("Email sent.") } else if flag.Arg(0) == "migrate-db" { startVersion := flag.Arg(1) if startVersion == "" { fmt.Println("<startVersion> required") return } endVersion := flag.Arg(2) if endVersion == "" { fmt.Println("<endVersion> required") return } dl := cassandra_datalayer.NewDatalayer(cfg) err := dl.MigrateDB("canopy", startVersion, endVersion) if err != nil { fmt.Println(err.Error()) } } else if len(flag.Args()) == 0 { cmds[0].Perform(info) } else { fmt.Println("Unknown command '" + flag.Arg(0) + "'. See 'canopy-ops help'.") } }
func main() { /*if true { passed := device_filter.RunTests() fmt.Println(passed) return }*/ r := mux.NewRouter() cfg := config.NewDefaultConfig(buildVersion, buildDate, buildCommit) err := cfg.LoadConfig() if err != nil { logFilename := config.JustGetOptLogFile() err2 := canolog.Init(logFilename) if err2 != nil { fmt.Println(err) return } canolog.Info("Starting Canopy Cloud Service") canolog.Error("Configuration error: %s", err) canolog.Info("Exiting") return } err = canolog.Init(cfg.OptLogFile()) if err != nil { fmt.Println(err) return } canolog.Info("Starting Canopy Cloud Service") canolog.Info("Version:", cfg.BuildVersion()) canolog.Info("Build Date:", cfg.BuildDate()) canolog.Info("Build Commit:", cfg.BuildCommit()) // Log crashes defer func() { r := recover() if r != nil { var buf [4096]byte runtime.Stack(buf[:], false) canolog.Error("PANIC ", r, string(buf[:])) panic(r) } shutdown() }() // handle SIGINT & SIGTERM c := make(chan os.Signal, 1) c2 := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) signal.Notify(c2, syscall.SIGTERM) go func() { <-c canolog.Info("SIGINT recieved") shutdown() os.Exit(1) }() go func() { <-c2 canolog.Info("SIGTERM recieved") shutdown() os.Exit(1) }() if cfg.OptHostname() == "" { canolog.Error("You must set the configuration option \"hostname\"") return } if cfg.OptPasswordSecretSalt() == "" { canolog.Error("You must set the configuration option \"password-secret-salt\"") return } canolog.Info(cfg.ToString()) pigeonSys, err := jobqueue.NewPigeonSystem(cfg) if err != nil { canolog.Error("Error initializing messaging system (Pigeon):", err) return } pigeonServer, err := pigeonSys.StartServer("localhost") // TODO use configured host if err != nil { canolog.Error("Unable to start messaging server (Pigeon):", err) return } pigeonOutbox := pigeonSys.NewOutbox() err = jobs.InitJobServer(cfg, pigeonServer) if err != nil { canolog.Error("Unable to initialize Job Server", err) return } if cfg.OptForwardOtherHosts() != "" { canolog.Info("Requests to hosts other than ", cfg.OptHostname(), " will be forwarded to ", cfg.OptForwardOtherHosts()) targetUrl, _ := url.Parse(cfg.OptForwardOtherHosts()) reverseProxy := httputil.NewSingleHostReverseProxy(targetUrl) http.Handle("/", reverseProxy) } else { canolog.Info("No reverse proxy for other hosts consfigured.") } hostname := cfg.OptHostname() webManagerPath := cfg.OptWebManagerPath() jsClientPath := cfg.OptJavascriptClientPath() http.Handle(hostname+"/echo", websocket.Handler(ws.NewCanopyWebsocketServer(cfg, pigeonOutbox, pigeonServer))) webapp.AddRoutes(r) rest.AddRoutes(r, cfg, pigeonSys) http.Handle(hostname+"/", r) if webManagerPath != "" { http.Handle(hostname+"/mgr/", http.StripPrefix("/mgr/", http.FileServer(http.Dir(webManagerPath)))) } if jsClientPath != "" { http.Handle(hostname+"/canopy-js-client/", http.StripPrefix("/canopy-js-client/", http.FileServer(http.Dir(jsClientPath)))) } // Run HTTP and HTTPS servers simultaneously (if both are enabled) httpResultChan := make(chan error) httpsResultChan := make(chan error) if cfg.OptEnableHTTP() { go func() { httpPort := cfg.OptHTTPPort() srv := &http.Server{ Addr: fmt.Sprintf(":%d", httpPort), Handler: context.ClearHandler(http.DefaultServeMux), } err = srv.ListenAndServe() httpResultChan <- err }() } if cfg.OptEnableHTTPS() { go func() { httpsPort := cfg.OptHTTPSPort() httpsCertFile := cfg.OptHTTPSCertFile() httpsPrivKeyFile := cfg.OptHTTPSPrivKeyFile() srv := &http.Server{ Addr: fmt.Sprintf(":%d", httpsPort), Handler: context.ClearHandler(http.DefaultServeMux), } err := srv.ListenAndServeTLS(httpsCertFile, httpsPrivKeyFile) httpsResultChan <- err }() } // Exit if either server has error select { case err := <-httpResultChan: canolog.Error(err) case err := <-httpsResultChan: canolog.Error(err) } }