From c2480dc2f14165e51aad12a291515b4cf04ed7e2 Mon Sep 17 00:00:00 2001 From: Michael Hohn Date: Mon, 13 May 2024 11:26:35 -0700 Subject: [PATCH] wip: start lcmem.go --- cmd/commander/main.go | 15 +-- lib/commander/lcmem/handlers.go | 178 -------------------------------- lib/commander/lcmem/lcmem.go | 140 ++++++++++++++++++++++++- 3 files changed, 147 insertions(+), 186 deletions(-) delete mode 100644 lib/commander/lcmem/handlers.go diff --git a/cmd/commander/main.go b/cmd/commander/main.go index cb3a528..9fd286c 100644 --- a/cmd/commander/main.go +++ b/cmd/commander/main.go @@ -59,6 +59,11 @@ func main() { // Read configuration config := mcc.LoadConfig("cconfig.toml") + // Output configuration summary + log.Printf("Help: %t\n", *helpFlag) + log.Printf("Log Level: %s\n", *logLevel) + log.Printf("Mode: %s\n", *mode) + // Apply 'mode' flag switch *mode { case "standalone": @@ -70,6 +75,9 @@ func main() { Storage: lsmem.Storage{}, Runner: lrmem.Runner{}, } + main := lcmem.Commander{} + main.Setup(state) + main.Run(state) case "container": // Assemble cccontainer @@ -80,11 +88,4 @@ func main() { os.Exit(1) } - // Output configuration summary - log.Printf("Help: %t\n", *helpFlag) - log.Printf("Log Level: %s\n", *logLevel) - log.Printf("Mode: %s\n", *mode) - - // Run in the chosen mode - } diff --git a/lib/commander/lcmem/handlers.go b/lib/commander/lcmem/handlers.go deleted file mode 100644 index b437615..0000000 --- a/lib/commander/lcmem/handlers.go +++ /dev/null @@ -1,178 +0,0 @@ -/* -Copyright © 2024 github -*/ -package lcmem - -import ( - "log" - "log/slog" - "net/http" - "strconv" - - "github.com/gorilla/mux" - "github.com/hohn/ghes-mirva-server/analyze" - co "github.com/hohn/ghes-mirva-server/common" - "github.com/hohn/ghes-mirva-server/store" - "github.com/spf13/cobra" -) - -// XX: no subcommands here -// StartCmd represents the Start command -var StartCmd = &cobra.Command{ - Use: "Start", - Short: "A brief description of your command", - Long: `A longer description that spans multiple lines and likely contains examples -and usage of using your command. For example: - -Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.`, - Run: func(cmd *cobra.Command, args []string) { - slog.Info("Starting server") - serve() - }, -} - -func serve() { - r := mux.NewRouter() - - // - // First are the API endpoints that mirror those used in the github API - // - r.HandleFunc("/repos/{owner}/{repo}/code-scanning/codeql/variant-analyses", MirvaRequest) - // /repos/hohn /mirva-controller/code-scanning/codeql/variant-analyses - // Or via - r.HandleFunc("/{repository_id}/code-scanning/codeql/variant-analyses", MirvaRequestID) - - r.HandleFunc("/", RootHandler) - - // This is the standalone status request. - // It's also the first request made when downloading; the difference is on the - // client side's handling. - r.HandleFunc("/repos/{owner}/{repo}/code-scanning/codeql/variant-analyses/{codeql_variant_analysis_id}", MirvaStatus) - - r.HandleFunc("/repos/{controller_owner}/{controller_repo}/code-scanning/codeql/variant-analyses/{codeql_variant_analysis_id}/repos/{repo_owner}/{repo_name}", MirvaDownloadArtifact) - - // Not implemented: - // r.HandleFunc("/codeql-query-console/codeql-variant-analysis-repo-tasks/{codeql_variant_analysis_id}/{repo_id}/{owner_id}/{controller_repo_id}", MirvaDownLoad3) - // r.HandleFunc("/github-codeql-query-console-prod/codeql-variant-analysis-repo-tasks/{codeql_variant_analysis_id}/{repo_id}", MirvaDownLoad4) - - // - // Now some support API endpoints - // - r.HandleFunc("/download-server/{local_path:.*}", MirvaDownloadServe) - - // - // Bind to a port and pass our router in - // - log.Fatal(http.ListenAndServe(":8080", r)) -} - -func RootHandler(w http.ResponseWriter, r *http.Request) { - slog.Info("Request on /") -} - -func MirvaStatus(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - slog.Info("mrva status request for ", - "owner", vars["owner"], - "repo", vars["repo"], - "codeql_variant_analysis_id", vars["codeql_variant_analysis_id"]) - id, err := strconv.Atoi(vars["codeql_variant_analysis_id"]) - if err != nil { - slog.Error("Variant analysis is is not integer", "id", - vars["codeql_variant_analysis_id"]) - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - // The status reports one status for all jobs belonging to an id. - // So we simply report the status of a job as the status of all. - spec := store.GetJobList(id) - if spec == nil { - slog.Error("No jobs found for given job id", - "id", vars["codeql_variant_analysis_id"]) - http.Error(w, err.Error(), http.StatusUnprocessableEntity) - return - } - - job := spec[0] - - js := co.JobSpec{ - ID: job.QueryPackId, - OwnerRepo: job.ORL, - } - - ji := store.GetJobInfo(js) - - analyze.StatusResponse(w, js, ji, id) - lcmem.StatusResponse(w, js, ji, id) -} - -// Download artifacts -func MirvaDownloadArtifact(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - slog.Info("MRVA artifact download", - "controller_owner", vars["controller_owner"], - "controller_repo", vars["controller_repo"], - "codeql_variant_analysis_id", vars["codeql_variant_analysis_id"], - "repo_owner", vars["repo_owner"], - "repo_name", vars["repo_name"], - ) - vaid, err := strconv.Atoi(vars["codeql_variant_analysis_id"]) - if err != nil { - slog.Error("Variant analysis is is not integer", "id", - vars["codeql_variant_analysis_id"]) - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - js := co.JobSpec{ - ID: vaid, - OwnerRepo: co.OwnerRepo{ - Owner: vars["repo_owner"], - Repo: vars["repo_name"], - }, - } - analyze.DownloadResponse(w, js, vaid) - -} - -func MirvaDownloadServe(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - slog.Info("File download request", "local_path", vars["local_path"]) - - analyze.FileDownload(w, vars["local_path"]) -} - -func MirvaRequestID(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - slog.Info("New mrva using repository_id=%v\n", vars["repository_id"]) -} - -func MirvaRequest(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - slog.Info("New mrva run ", "owner", vars["owner"], "repo", vars["repo"]) - // TODO Change this to functional style? - // session := new(MirvaSession) - // session.id = next_id() - // session.owner = vars["owner"] - // session.controller_repo = vars["repo"] - // session.collect_info(w, r) - // session.find_available_DBs() - // session.start_analyses() - // session.submit_response(w) - // session.save() -} - -func init() { - rootCmd.AddCommand(StartCmd) - - // Here you will define your flags and configuration settings. - - // Cobra supports Persistent Flags which will work for this command - // and all subcommands, e.g.: - // startCmd.PersistentFlags().String("foo", "", "A help for foo") - - // Cobra supports local flags which will only run when this command - // is called directly, e.g.: - // startCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") -} diff --git a/lib/commander/lcmem/lcmem.go b/lib/commander/lcmem/lcmem.go index 26ef695..96b9995 100644 --- a/lib/commander/lcmem/lcmem.go +++ b/lib/commander/lcmem/lcmem.go @@ -4,9 +4,14 @@ package lcmem import ( "encoding/json" "fmt" + "log" "log/slog" "net/http" + "strconv" + "github.com/advanced-security/mrvacommander/interfaces/mci" + "github.com/gorilla/mux" + "github.com/hohn/ghes-mirva-server/analyze" "github.com/hohn/ghes-mirva-server/api" co "github.com/hohn/ghes-mirva-server/common" "github.com/hohn/ghes-mirva-server/store" @@ -15,7 +20,45 @@ import ( type Commander struct { } -func StatusResponse(w http.ResponseWriter, js co.JobSpec, ji co.JobInfo, vaid int) { +func (c *Commander) Run(st mci.State) { +} + +func (c *Commander) Setup(st mci.State) { + r := mux.NewRouter() + + // + // First are the API endpoints that mirror those used in the github API + // + r.HandleFunc("/repos/{owner}/{repo}/code-scanning/codeql/variant-analyses", c.MirvaRequest) + // /repos/hohn /mirva-controller/code-scanning/codeql/variant-analyses + // Or via + r.HandleFunc("/{repository_id}/code-scanning/codeql/variant-analyses", c.MirvaRequestID) + + r.HandleFunc("/", c.RootHandler) + + // This is the standalone status request. + // It's also the first request made when downloading; the difference is on the + // client side's handling. + r.HandleFunc("/repos/{owner}/{repo}/code-scanning/codeql/variant-analyses/{codeql_variant_analysis_id}", c.MirvaStatus) + + r.HandleFunc("/repos/{controller_owner}/{controller_repo}/code-scanning/codeql/variant-analyses/{codeql_variant_analysis_id}/repos/{repo_owner}/{repo_name}", c.MirvaDownloadArtifact) + + // Not implemented: + // r.HandleFunc("/codeql-query-console/codeql-variant-analysis-repo-tasks/{codeql_variant_analysis_id}/{repo_id}/{owner_id}/{controller_repo_id}", MirvaDownLoad3) + // r.HandleFunc("/github-codeql-query-console-prod/codeql-variant-analysis-repo-tasks/{codeql_variant_analysis_id}/{repo_id}", MirvaDownLoad4) + + // + // Now some support API endpoints + // + r.HandleFunc("/download-server/{local_path:.*}", c.MirvaDownloadServe) + + // + // Bind to a port and pass our router in + // + log.Fatal(http.ListenAndServe(":8080", r)) +} + +func (c *Commander) StatusResponse(w http.ResponseWriter, js co.JobSpec, ji co.JobInfo, vaid int) { slog.Debug("Submitting status response", "session", vaid) all_scanned := []api.ScannedRepo{} @@ -68,3 +111,98 @@ func StatusResponse(w http.ResponseWriter, js co.JobSpec, ji co.JobInfo, vaid in w.Header().Set("Content-Type", "application/json") w.Write(submitStatus) } + +func (c *Commander) RootHandler(w http.ResponseWriter, r *http.Request) { + slog.Info("Request on /") +} + +func (c *Commander) MirvaStatus(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + slog.Info("mrva status request for ", + "owner", vars["owner"], + "repo", vars["repo"], + "codeql_variant_analysis_id", vars["codeql_variant_analysis_id"]) + id, err := strconv.Atoi(vars["codeql_variant_analysis_id"]) + if err != nil { + slog.Error("Variant analysis is is not integer", "id", + vars["codeql_variant_analysis_id"]) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + // The status reports one status for all jobs belonging to an id. + // So we simply report the status of a job as the status of all. + spec := store.GetJobList(id) + if spec == nil { + slog.Error("No jobs found for given job id", + "id", vars["codeql_variant_analysis_id"]) + http.Error(w, err.Error(), http.StatusUnprocessableEntity) + return + } + + job := spec[0] + + js := co.JobSpec{ + ID: job.QueryPackId, + OwnerRepo: job.ORL, + } + + ji := store.GetJobInfo(js) + + analyze.StatusResponse(w, js, ji, id) + c.StatusResponse(w, js, ji, id) +} + +// Download artifacts +func (c *Commander) MirvaDownloadArtifact(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + slog.Info("MRVA artifact download", + "controller_owner", vars["controller_owner"], + "controller_repo", vars["controller_repo"], + "codeql_variant_analysis_id", vars["codeql_variant_analysis_id"], + "repo_owner", vars["repo_owner"], + "repo_name", vars["repo_name"], + ) + vaid, err := strconv.Atoi(vars["codeql_variant_analysis_id"]) + if err != nil { + slog.Error("Variant analysis is is not integer", "id", + vars["codeql_variant_analysis_id"]) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + js := co.JobSpec{ + ID: vaid, + OwnerRepo: co.OwnerRepo{ + Owner: vars["repo_owner"], + Repo: vars["repo_name"], + }, + } + analyze.DownloadResponse(w, js, vaid) + +} + +func (c *Commander) MirvaDownloadServe(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + slog.Info("File download request", "local_path", vars["local_path"]) + + analyze.FileDownload(w, vars["local_path"]) +} + +func (c *Commander) MirvaRequestID(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + slog.Info("New mrva using repository_id=%v\n", vars["repository_id"]) +} + +func (c *Commander) MirvaRequest(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + slog.Info("New mrva run ", "owner", vars["owner"], "repo", vars["repo"]) + // TODO Change this to functional style? + // session := new(MirvaSession) + // session.id = next_id() + // session.owner = vars["owner"] + // session.controller_repo = vars["repo"] + // session.collect_info(w, r) + // session.find_available_DBs() + // session.start_analyses() + // session.submit_response(w) + // session.save() +}