diff --git a/.gitignore b/.gitignore index 966c93e..5af4f4e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -finspect finspect.exe *.tar.gz *.zip @@ -7,4 +6,4 @@ finspect.exe .idea/ .jshintrc bin -.DS_Store \ No newline at end of file +.DS_Store diff --git a/dbase/dbase.go b/dbase/dbase.go deleted file mode 100644 index 06ab7d0..0000000 --- a/dbase/dbase.go +++ /dev/null @@ -1 +0,0 @@ -package main diff --git a/fileinfo/fileinfo.go b/fileinfo/fileinfo.go deleted file mode 100644 index 06ab7d0..0000000 --- a/fileinfo/fileinfo.go +++ /dev/null @@ -1 +0,0 @@ -package main diff --git a/finspect/finspect.go b/finspect/finspect.go new file mode 100644 index 0000000..cbb29bd --- /dev/null +++ b/finspect/finspect.go @@ -0,0 +1,249 @@ +package main + +// Import needed packages +import ( + "encoding/json" + "github.com/ant0ine/go-json-rest/rest" + "io/ioutil" + "log" + "net/http" + "os" +) + +// Define finspect internal constants (TODO: move config_dir const to a command flag) +const ( + FINSPECT_NAME string = "finspect" + FINSPECT_DESCRIPTION string = "" + FINSPECT_VERSION string = "0.0.1a" + FINSPECT_AUTHOR string = "Patrick Kuti " + FINSPECT_CONFIG_DIR string = "/etc/finspect/conf/" +) + +// Define log formats for finspect-http server +const ( + CommonLogFormat = "%h %l %u %t \"%r\" %s %b" // CLR + CombinedLogFormat = "%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\"" // NCSA extended/combined log format + DefaultLogFormat = "%t %S\033[0m \033[36;1m%Dμs\033[0m \"%r\" \033[1;30m%u \"%{User-Agent}i\"\033[0m" // Debug Format +) + +// JSON struct for finspect-http server configuration +type Configuration struct { + LogDirectory string +} + +// Variable for global finspect-http server configuration +var FinspectHttpConfiguration *Configuration = &Configuration{} + +// setDefaults sets default values for the configuration struct +func (self *Configuration) setDefaults() { + self.LogDirectory = "/var/log/finspect/" +} + +// Init parses configuration files, compiles global variables +// sets up logging and in general sets up the finspect-http server +func init() { + + // Check if finspect server configuration file exists + FinspectHttpConfigurationFilePath := FINSPECT_CONFIG_DIR + "http.json" + _, err := os.Stat(FinspectHttpConfigurationFilePath) + if err != nil { + log.Fatal("Error looking for configuration file: " + FinspectHttpConfigurationFilePath) + os.Exit(1) + } + + // Set default configurations + FinspectHttpConfiguration.setDefaults() + + // Attempt to load and parse json configuration file into global configuration variable + _loadConfig(FinspectHttpConfigurationFilePath) + + // Check if log directory exists and is a directory + LogDirectory, err := os.Stat(FinspectHttpConfiguration.LogDirectory) + if err != nil { + log.Fatal("Error trying to access log directory ("+FinspectHttpConfiguration.LogDirectory+"), error returned was: ", err) + os.Exit(1) + } + if !LogDirectory.IsDir() { + log.Fatal("Log directory is not a directory, error returned was: ", err) + os.Exit(1) + } +} + +// _loadConfig loads values from a configuration file into global a configuration variable +func _loadConfig(FinspectHttpConfigurationFilePath string) { + + // Try to open the finspect-http server configuration file and read it into global variable + FinspectHttpConfigurationFile, err := ioutil.ReadFile(FinspectHttpConfigurationFilePath) + if err != nil { + log.Fatal("Error reading configuration file, error returned was: ", err) + os.Exit(1) + } + + // Decode JSON from configuration file and dump into configuration struct to override default values + err = json.Unmarshal(FinspectHttpConfigurationFile, FinspectHttpConfiguration) + if err != nil { + log.Fatal("Error parsing configuration file, please ensure it is valid JSON. Error returned was: ", err) + os.Exit(1) + } + +} + +// Main defines the available REST resources, starts up the finspect-http server +// along with various configuration options, settings and sets up logging +func main() { + + // Default generic log handler + LogFileHandler, err := os.OpenFile(FinspectHttpConfiguration.LogDirectory+"http.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if err != nil { + log.Fatal("Error trying to open general logfile, error returned was: ", err) + os.Exit(1) + } + defer LogFileHandler.Close() + log.SetOutput(LogFileHandler) + log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) + + // HTTP access log handler + AccessLogFileHandler, err := os.OpenFile(FinspectHttpConfiguration.LogDirectory+"http-access.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if err != nil { + log.Fatal("Error trying to open access logfile, error returned was: ", err) + os.Exit(1) + } + defer AccessLogFileHandler.Close() + + // HTTP error log handler + ErrorLogFileHandler, err := os.OpenFile(FinspectHttpConfiguration.LogDirectory+"http-error.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if err != nil { + log.Fatal("Error trying to open error logfile, error returned was: ", err) + os.Exit(1) + } + defer ErrorLogFileHandler.Close() + + // Setting up configuration for the HTTP REST router + handler := rest.ResourceHandler{ + EnableGzip: true, + DisableJsonIndent: false, + EnableStatusService: true, + EnableResponseStackTrace: true, + EnableLogAsJson: false, + EnableRelaxedContentType: false, + Logger: log.New(AccessLogFileHandler, "", 0), + LoggerFormat: CombinedLogFormat, + DisableLogger: false, + ErrorLogger: log.New(ErrorLogFileHandler, "", 0), + XPoweredBy: FINSPECT_NAME + " - " + FINSPECT_VERSION, + DisableXPoweredBy: false, + } + + // Define some HTTP REST resources, log a fatal error if something goes wrong + err = handler.SetRoutes( + + // Watcher related routes + &rest.Route{"GET", "/watchpaths", getReturnWatchPaths}, + &rest.Route{"POST", "/watchpaths", postAddWatchPath}, + &rest.Route{"DELETE", "/watchpaths/:watchpathid:", deleteRemoveWatchPath}, + &rest.Route{"GET", "/watchpaths/:watchpathid:", getReturnWatchPath}, + + // Indexer related routes + &rest.Route{"POST", "/indexjobs", postAddIndexJob}, + &rest.Route{"GET", "/indexjobs/:indexjobid:", getReturnIndexJob}, + &rest.Route{"DELETE", "/indexjobs/:indexjobid:", deleteRemoveIndexJob}, + &rest.Route{"POST", "/indexjobs/search", postSearchIndexJobs}, + + // Ingester related routes + &rest.Route{"POST", "/ingestjobs", postAddIngestJob}, + &rest.Route{"GET", "/ingestjobs/:ingestjobid:", getReturnIngestJob}, + &rest.Route{"DELETE", "/ingestjobs/:ingestjobid:", deleteRemoveIngestJob}, + &rest.Route{"POST", "/ingestjobs/search", postSearchIngestJobs}, + + // File related routes + &rest.Route{"POST", "/files", postCreateFile}, + + // Admin and internally available resources + &rest.Route{"GET", "/.status", func(w rest.ResponseWriter, r *rest.Request) { w.WriteJson(handler.GetStatus()) }}, + &rest.Route{"POST", "/shutdown", postAdminShutdownHttpServer}, + &rest.Route{"POST", "/reload", postAdminReloadHttpServer}, + &rest.Route{"POST", "/restart", postAdminRestartHttpServer}, + ) + if err != nil { + log.Fatal("Error with HTTP router, error returned was: ", err) + os.Exit(1) + } + + // Start the finspect-http server + log.Fatal(http.ListenAndServe(":7070", &handler)) + os.Exit(1) +} + +// Mock watcher functions +func getReturnWatchPaths(w rest.ResponseWriter, r *rest.Request) { + w.WriteHeader(http.StatusOK) + w.WriteJson("OK") +} +func postAddWatchPath(w rest.ResponseWriter, r *rest.Request) { + w.WriteHeader(http.StatusOK) + w.WriteJson("OK") +} +func deleteRemoveWatchPath(w rest.ResponseWriter, r *rest.Request) { + w.WriteHeader(http.StatusOK) + w.WriteJson("OK") +} +func getReturnWatchPath(w rest.ResponseWriter, r *rest.Request) { + w.WriteHeader(http.StatusOK) + w.WriteJson("OK") +} + +// Mock indexer functions +func postAddIndexJob(w rest.ResponseWriter, r *rest.Request) { + w.WriteHeader(http.StatusOK) + w.WriteJson("OK") +} +func getReturnIndexJob(w rest.ResponseWriter, r *rest.Request) { + w.WriteHeader(http.StatusOK) + w.WriteJson("OK") +} +func deleteRemoveIndexJob(w rest.ResponseWriter, r *rest.Request) { + w.WriteHeader(http.StatusOK) + w.WriteJson("OK") +} +func postSearchIndexJobs(w rest.ResponseWriter, r *rest.Request) { + w.WriteHeader(http.StatusOK) + w.WriteJson("OK") +} + +// Mock ingester functions +func postAddIngestJob(w rest.ResponseWriter, r *rest.Request) { + w.WriteHeader(http.StatusOK) + w.WriteJson("OK") +} +func getReturnIngestJob(w rest.ResponseWriter, r *rest.Request) { + w.WriteHeader(http.StatusOK) + w.WriteJson("OK") +} +func deleteRemoveIngestJob(w rest.ResponseWriter, r *rest.Request) { + w.WriteHeader(http.StatusOK) + w.WriteJson("OK") +} +func postSearchIngestJobs(w rest.ResponseWriter, r *rest.Request) { + w.WriteHeader(http.StatusOK) + w.WriteJson("OK") +} + +// Mock files functions +func postCreateFile(w rest.ResponseWriter, r *rest.Request) { + w.WriteHeader(http.StatusOK) + w.WriteJson("OK") +} + +// Mock admin and internal functions +func postAdminShutdownHttpServer(w rest.ResponseWriter, r *rest.Request) { + w.WriteHeader(http.StatusOK) + w.WriteJson("OK") +} +func postAdminReloadHttpServer(w rest.ResponseWriter, r *rest.Request) { + w.WriteHeader(http.StatusOK) + w.WriteJson("OK") +} +func postAdminRestartHttpServer(w rest.ResponseWriter, r *rest.Request) { + w.WriteHeader(http.StatusOK) + w.WriteJson("OK") +} diff --git a/watcher/watcher.go b/watcher/watcher.go new file mode 100644 index 0000000..22f495c --- /dev/null +++ b/watcher/watcher.go @@ -0,0 +1,42 @@ +package main + +// Import needed packages +import ( + "github.com/finspect/finspect" + "gopkg.in/fsnotify.v1" + "log" +) + +// Example watcher from fsnotify +func ExampleNewWatcher() { + watcher, err := fsnotify.NewWatcher() + if err != nil { + log.Fatal(err) + } + defer watcher.Close() + + done := make(chan bool) + go func() { + for { + select { + case event := <-watcher.Events: + log.Println("event:", event) + if event.Op&fsnotify.Write == fsnotify.Write { + log.Println("modified file:", event.Name) + } + case err := <-watcher.Errors: + log.Println("error:", err) + } + } + }() + + err = watcher.Add("/tmp") + if err != nil { + log.Fatal(err) + } + <-done +} + +func main() { + ExampleNewWatcher() +}