diff --git a/go.mod b/go.mod index 6a6a962..a10ffb1 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/criteo/command-launcher -go 1.20 +go 1.21 require ( github.com/cavaliergopher/grab/v3 v3.0.1 diff --git a/internal/server/command_handler.go b/internal/server/command_handler.go new file mode 100644 index 0000000..92f4f8b --- /dev/null +++ b/internal/server/command_handler.go @@ -0,0 +1,34 @@ +package server + +import ( + "html/template" + "net/http" + "strings" +) + +func (server *Server) CommandHandler(w http.ResponseWriter, r *http.Request) { + fullName := strings.TrimPrefix(r.URL.Path, "/command/") + cmd, err := (*(server.backend)).FindCommandByFullName(fullName) + + if err != nil { + w.WriteHeader(http.StatusNotFound) + w.Write([]byte(err.Error())) + return + } + + tmpl_text, _ := templates.ReadFile("templates/command.html") + tmpl, _ := template.New("command").Parse(string(tmpl_text)) + command := Command{ + FullName: cmd.FullName(), + Group: cmd.Group(), + Name: cmd.Name(), + Package: cmd.PackageName(), + Registry: cmd.RepositoryID(), + Short: cmd.ShortDescription(), + Long: cmd.LongDescription(), + Examples: cmd.Examples(), + Flags: cmd.Flags(), + } + + tmpl.Execute(w, command) +} diff --git a/internal/server/command_index_handler.go b/internal/server/command_index_handler.go new file mode 100644 index 0000000..f1fb9d8 --- /dev/null +++ b/internal/server/command_index_handler.go @@ -0,0 +1,95 @@ +package server + +import ( + "bytes" + "fmt" + "html/template" + "net/http" + "slices" + "sort" + "strings" +) + +func (server *Server) CommandIndexHandler(w http.ResponseWriter, r *http.Request) { + repos := (*(server.backend)).AllRepositories() + cmdMap := map[string]*Command{} + + for _, repo := range repos { + pkgs := repo.InstalledPackages() + for _, pkg := range pkgs { + cmds := pkg.Commands() + for _, cmd := range cmds { + if slices.Contains([]string{"__setup__", "__login__"}, cmd.Name()) { + continue + } + if cmd.Group() == "" { // this is top level command + // add group command + if groupCmd, ok := cmdMap[cmd.FullName()]; !ok { + groupCmd = &Command{ + FullName: cmd.FullName(), + Group: cmd.Group(), + Name: cmd.Name(), + Package: pkg.Name(), + Registry: repo.Name(), + SubCmds: []*Command{}, + } + cmdMap[cmd.FullName()] = groupCmd + } + } else { // this is a sub command + // get the group command full name + groupCmdFullName := fmt.Sprintf("%s@@%s@%s", cmd.Group(), pkg.Name(), repo.Name()) + if groupCmd, ok := cmdMap[groupCmdFullName]; !ok { + groupCmd = &Command{ + FullName: groupCmdFullName, + Group: "", + Name: cmd.Group(), + Package: pkg.Name(), + Registry: repo.Name(), + SubCmds: []*Command{ + &Command{ + FullName: cmd.FullName(), + Group: cmd.Group(), + Name: cmd.Name(), + Package: pkg.Name(), + Registry: repo.Name(), + SubCmds: []*Command{}, + }, + }, + } + cmdMap[groupCmdFullName] = groupCmd + } else { + groupCmd.SubCmds = append(groupCmd.SubCmds, &Command{ + FullName: cmd.FullName(), + Group: cmd.Group(), + Name: cmd.Name(), + Package: pkg.Name(), + Registry: repo.Name(), + SubCmds: []*Command{}, + }) + } + + } + } + } + } + + // load the template + tmpl_text, _ := templates.ReadFile("templates/cmd_index.html") + tmpl, _ := template.New("command_index").Parse(string(tmpl_text)) + + groups := make([]*Command, 0, len(cmdMap)) + for _, cmd := range cmdMap { + groups = append(groups, cmd) + } + + sort.Slice(groups, func(i, j int) bool { + return groups[i].FullName < groups[j].FullName + }) + + var tpl bytes.Buffer + tmpl.Execute(&tpl, CommandIndex{Commands: groups}) + + html_wrapper, _ := templates.ReadFile("templates/html_wrapper.html") + content := strings.ReplaceAll(string(html_wrapper), "#INPUT#", tpl.String()) + w.Write([]byte(content)) +} diff --git a/internal/server/server.go b/internal/server/server.go index 63b8126..b59d6bc 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -1,13 +1,9 @@ package server import ( - "bytes" "embed" "fmt" - "html/template" "net/http" - "sort" - "strings" . "github.com/criteo/command-launcher/internal/backend" "github.com/criteo/command-launcher/internal/command" @@ -23,11 +19,6 @@ var fs embed.FS //go:embed templates var templates embed.FS -func (server *Server) IndexHandler(w http.ResponseWriter, r *http.Request) { - index, _ := fs.ReadFile("static/index.html") - w.Write(index) -} - type Command struct { FullName string Group string @@ -45,111 +36,9 @@ type CommandIndex struct { Commands []*Command } -func (server *Server) CommandIndexHandler(w http.ResponseWriter, r *http.Request) { - repos := (*(server.backend)).AllRepositories() - cmdMap := map[string]*Command{} - - for _, repo := range repos { - pkgs := repo.InstalledPackages() - for _, pkg := range pkgs { - cmds := pkg.Commands() - for _, cmd := range cmds { - if cmd.Name() == "__setup__" { - continue - } - if cmd.Group() == "" { // this is top level command - // add group command - if groupCmd, ok := cmdMap[cmd.FullName()]; !ok { - groupCmd = &Command{ - FullName: cmd.FullName(), - Group: cmd.Group(), - Name: cmd.Name(), - Package: pkg.Name(), - Registry: repo.Name(), - SubCmds: []*Command{}, - } - cmdMap[cmd.FullName()] = groupCmd - } - } else { // this is a sub command - // get the group command full name - groupCmdFullName := fmt.Sprintf("%s@@%s@%s", cmd.Group(), pkg.Name(), repo.Name()) - if groupCmd, ok := cmdMap[groupCmdFullName]; !ok { - groupCmd = &Command{ - FullName: groupCmdFullName, - Group: "", - Name: cmd.Group(), - Package: pkg.Name(), - Registry: repo.Name(), - SubCmds: []*Command{ - &Command{ - FullName: cmd.FullName(), - Group: cmd.Group(), - Name: cmd.Name(), - Package: pkg.Name(), - Registry: repo.Name(), - SubCmds: []*Command{}, - }, - }, - } - cmdMap[groupCmdFullName] = groupCmd - } else { - groupCmd.SubCmds = append(groupCmd.SubCmds, &Command{ - FullName: cmd.FullName(), - Group: cmd.Group(), - Name: cmd.Name(), - Package: pkg.Name(), - Registry: repo.Name(), - SubCmds: []*Command{}, - }) - } - - } - } - } - } - - // load the template - tmpl_text, _ := templates.ReadFile("templates/cmd_index.html") - tmpl, _ := template.New("command_index").Parse(string(tmpl_text)) - - groups := make([]*Command, 0, len(cmdMap)) - for _, cmd := range cmdMap { - groups = append(groups, cmd) - } - - sort.Slice(groups, func(i, j int) bool { - // return fmt.Sprintf("%s@%s", groups[i].Package, groups[i].Registry) < fmt.Sprintf("%s@%s", groups[j].Package, groups[j].Registry) - return groups[i].FullName < groups[j].FullName - }) - - var tpl bytes.Buffer - tmpl.Execute(&tpl, CommandIndex{Commands: groups}) - - html_wrapper, _ := templates.ReadFile("templates/html_wrapper.html") - content := strings.ReplaceAll(string(html_wrapper), "#INPUT#", tpl.String()) - w.Write([]byte(content)) -} - -func (server *Server) CommandHandler(w http.ResponseWriter, r *http.Request) { - fullName := strings.TrimPrefix(r.URL.Path, "/command/") - fmt.Println(r.URL.Path, fullName) - cmd, _ := (*(server.backend)).FindCommandByFullName(fullName) - - tmpl_text, _ := templates.ReadFile("templates/command.html") - tmpl, _ := template.New("command").Parse(string(tmpl_text)) - command := Command{ - FullName: cmd.FullName(), - Group: cmd.Group(), - Name: cmd.Name(), - Package: cmd.PackageName(), - Registry: cmd.RepositoryID(), - Short: cmd.ShortDescription(), - Long: cmd.LongDescription(), - Examples: cmd.Examples(), - Flags: cmd.Flags(), - } - - tmpl.Execute(w, command) +func (server *Server) IndexHandler(w http.ResponseWriter, r *http.Request) { + index, _ := fs.ReadFile("static/index.html") + w.Write(index) } func (server *Server) HealthHandler(w http.ResponseWriter, r *http.Request) { @@ -164,5 +53,6 @@ func Serve(backend *Backend, port int) error { http.HandleFunc("/test", server.CommandIndexHandler) http.HandleFunc("/command/", server.CommandHandler) http.HandleFunc("/health", server.HealthHandler) + return http.ListenAndServe(fmt.Sprintf(":%d", port), nil) }