From 7cde4c819d11835765026bc260c1cb35a540ef9f Mon Sep 17 00:00:00 2001 From: Wilfried OLLIVIER Date: Mon, 28 Feb 2022 17:40:28 +0100 Subject: [PATCH 1/2] Create a more generic task "something" page Can be used to either outpout a result, a message, logs etc.. --- application/result.go | 38 ----------------- application/task_page.go | 42 +++++++++++++++++++ .../templates/{result.html => task.html} | 4 +- application/volume.go | 12 +++--- 4 files changed, 50 insertions(+), 46 deletions(-) delete mode 100644 application/result.go create mode 100644 application/task_page.go rename application/templates/{result.html => task.html} (87%) diff --git a/application/result.go b/application/result.go deleted file mode 100644 index ae291f6..0000000 --- a/application/result.go +++ /dev/null @@ -1,38 +0,0 @@ -package application - -import ( - "html/template" - "net/url" - - "github.com/factorysh/microdensity/task" -) - -// Result of a task for html rendering -type Result struct { - GitlabDomain string - Domain string - Project string - Commit string - Service string - ID string - CreatedAt string - Inner template.HTML -} - -// NewResultFromTask inits a result for a task -func NewResultFromTask(t *task.Task, inner template.HTML, gitlabDomain string) (*Result, error) { - prettyPath, err := url.PathUnescape(t.Project) - if err != nil { - return nil, err - } - - return &Result{ - Project: prettyPath, - GitlabDomain: gitlabDomain, - Commit: t.Commit, - Service: t.Service, - ID: t.Id.String(), - CreatedAt: t.Creation.Format("2006-01-02 15:04:05"), - Inner: inner, - }, nil -} diff --git a/application/task_page.go b/application/task_page.go new file mode 100644 index 0000000..4c3ebd3 --- /dev/null +++ b/application/task_page.go @@ -0,0 +1,42 @@ +package application + +import ( + "html/template" + "net/url" + + "github.com/factorysh/microdensity/task" +) + +// TaskPage present a page and an associated inner content +type TaskPage struct { + GitlabDomain string + Domain string + Project string + Commit string + Service string + ID string + CreatedAt string + InnerDivClasses string + InnerTitle string + Inner template.HTML +} + +// NewTaskPage inits a result for a task +func NewTaskPage(t *task.Task, inner template.HTML, gitlabDomain, InnerTitle, InnerDivClasses string) (*TaskPage, error) { + prettyPath, err := url.PathUnescape(t.Project) + if err != nil { + return nil, err + } + + return &TaskPage{ + Project: prettyPath, + GitlabDomain: gitlabDomain, + Commit: t.Commit, + Service: t.Service, + ID: t.Id.String(), + CreatedAt: t.Creation.Format("2006-01-02 15:04:05"), + InnerTitle: InnerTitle, + InnerDivClasses: InnerDivClasses, + Inner: inner, + }, nil +} diff --git a/application/templates/result.html b/application/templates/task.html similarity index 87% rename from application/templates/result.html rename to application/templates/task.html index 2ba9793..e9991bb 100644 --- a/application/templates/result.html +++ b/application/templates/task.html @@ -8,8 +8,8 @@

Task Description

  • ID : {{ .ID }}
  • -

    Task Result

    +

    {{ .InnerTitle }}

    -
    +
    {{ .Inner }}
    diff --git a/application/volume.go b/application/volume.go index db36012..dd44ff4 100644 --- a/application/volume.go +++ b/application/volume.go @@ -19,8 +19,8 @@ import ( var ( // used to ensure embed import _ embed.FS - //go:embed templates/result.html - resultTemplate string + //go:embed templates/task.html + taskTemplate string ) // VolumesHandler expose volumes of a task @@ -65,7 +65,7 @@ func (a *Application) VolumesHandler(basePathLen int, latest bool) http.HandlerF if _, err := os.Stat(fullPath); os.IsNotExist(err) { l.Warn("Path not found", zap.Error(err)) - data, err := NewResultFromTask(t, "No result for this task", a.GitlabURL) + data, err := NewTaskPage(t, "No result for this task", a.GitlabURL, "Task Result", "container task-output") if err != nil { l.Error("when creating result from a task", zap.Error(err)) w.WriteHeader(http.StatusInternalServerError) @@ -76,7 +76,7 @@ func (a *Application) VolumesHandler(basePathLen int, latest bool) http.HandlerF Domain: a.Domain, Detail: fmt.Sprintf("%s / %s", t.Service, t.Commit), Partial: html.Partial{ - Template: resultTemplate, + Template: taskTemplate, Data: data, }} @@ -128,13 +128,13 @@ func (a *Application) renderResultPageForTask(t *task.Task, filePath string, w h return err } - data, err := NewResultFromTask(t, template.HTML(content), a.GitlabURL) + data, err := NewTaskPage(t, template.HTML(content), a.GitlabURL, "Task Result", "container task-output") // create the page p := html.Page{ Domain: a.Domain, Detail: fmt.Sprintf("%s / %s", t.Service, t.Commit), Partial: html.Partial{ - Template: resultTemplate, + Template: taskTemplate, Data: data, }, } From bbc84d6a5818df482372306d3ad01961f2b11139 Mon Sep 17 00:00:00 2001 From: Wilfried OLLIVIER Date: Mon, 28 Feb 2022 17:41:19 +0100 Subject: [PATCH 2/2] Add text/html logs endpoint --- application/application.go | 2 ++ application/logs.go | 45 ++++++++++++++++++++++++++++++++++++++ application/task.go | 36 ++++++++++++++++++++++++++++++ html/templates/styles.css | 19 ++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 application/logs.go diff --git a/application/application.go b/application/application.go index ce956d5..39b2f55 100644 --- a/application/application.go +++ b/application/application.go @@ -153,6 +153,7 @@ func New(cfg *conf.Conf) (*Application, error) { r.Get("/", a.TaskHandler(false)) r.Get("/volumes/*", a.VolumesHandler(6, false)) r.Get("/logs", a.TaskLogsHandler(false)) + r.Get("/logz", a.TaskLogzHandler(false)) }) r.Group(func(r chi.Router) { r.Use(a.RefererMiddleware) @@ -166,6 +167,7 @@ func New(cfg *conf.Conf) (*Application, error) { r.Get("/", a.TaskHandler(true)) r.Get("/volumes/*", a.VolumesHandler(6, true)) r.Get("/logs", a.TaskLogsHandler(true)) + r.Get("/logz", a.TaskLogzHandler(true)) }) r.Group(func(r chi.Router) { r.Use(a.RefererMiddleware) diff --git a/application/logs.go b/application/logs.go new file mode 100644 index 0000000..5940659 --- /dev/null +++ b/application/logs.go @@ -0,0 +1,45 @@ +package application + +import ( + "bytes" + "context" + "fmt" + "html/template" + "net/http" + + "github.com/docker/docker/pkg/stdcopy" + "github.com/factorysh/microdensity/html" + "github.com/factorysh/microdensity/task" +) + +func (a *Application) renderLogsPageForTask(ctx context.Context, t *task.Task, w http.ResponseWriter) error { + + reader, err := t.Logs(ctx, false) + if err != nil { + return err + } + + var buffer bytes.Buffer + var dropped bytes.Buffer + _, err = stdcopy.StdCopy(&buffer, &dropped, reader) + if err != nil { + return err + } + + data, err := NewTaskPage(t, template.HTML(fmt.Sprintf("
    %s
    ", buffer.String())), a.GitlabURL, "Task Logs", "terminal") + if err != nil { + return err + } + + p := html.Page{ + Domain: a.Domain, + Detail: fmt.Sprintf("%s / %s - logs", t.Service, t.Commit), + Partial: html.Partial{ + Template: taskTemplate, + Data: data, + }, + } + + w.WriteHeader(http.StatusOK) + return p.Render(w) +} diff --git a/application/task.go b/application/task.go index abf5d3e..8f3cecd 100644 --- a/application/task.go +++ b/application/task.go @@ -231,3 +231,39 @@ func (a *Application) TaskLogsHandler(latest bool) func(http.ResponseWriter, *ht } } + +// TaskLogzHandler get a logs for a task +func (a *Application) TaskLogzHandler(latest bool) func(http.ResponseWriter, *http.Request) { + + return func(w http.ResponseWriter, r *http.Request) { + l := a.logger.With( + zap.String("url", r.URL.String()), + zap.String("service", chi.URLParam(r, "serviceID")), + zap.String("project", chi.URLParam(r, "project")), + zap.String("branch", chi.URLParam(r, "branch")), + zap.String("commit", chi.URLParam(r, "commit")), + ) + + t, err := a.storage.GetByCommit( + chi.URLParam(r, "serviceID"), + chi.URLParam(r, "project"), + chi.URLParam(r, "branch"), + chi.URLParam(r, "commit"), + latest, + ) + if err != nil { + l.Warn("Task get error", zap.Error(err)) + w.WriteHeader(http.StatusNotFound) + w.Write([]byte(http.StatusText(http.StatusNotFound))) + return + } + + err = a.renderLogsPageForTask(r.Context(), t, w) + if err != nil { + l.Warn("when rendering a logs page", zap.Error(err)) + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(http.StatusText(http.StatusInternalServerError))) + return + } + } +} diff --git a/html/templates/styles.css b/html/templates/styles.css index 7401eab..e6b3911 100644 --- a/html/templates/styles.css +++ b/html/templates/styles.css @@ -69,3 +69,22 @@ h6 { background-color: white; padding: 2rem; } + +.terminal { + min-height: 30%; + padding: 2rem; + background-color: black; + color: white; + border-radius: 1rem; + font-family: monospace; + text-align: left; +} + +.terminal pre { + background-color: black; + border-left: none; + margin: 1rem; + padding: 1rem; + overflow-x: scroll; + overflow-y: hidden; +}