diff --git a/internal/template/base_templates.go b/internal/template/base_templates.go new file mode 100644 index 0000000..04943c8 --- /dev/null +++ b/internal/template/base_templates.go @@ -0,0 +1,34 @@ +package template + +type baseTemplate struct { + Name string `json:"name"` + ID string `json:"id"` + Content string `json:"-"` +} + +var baseTemplates = []baseTemplate{fedora40WithSSH} + +var baseTemplateMap = map[string]baseTemplate{ + "empty": { + Name: "Empty", + ID: "empty", + Content: "", + }, + "fedora-40-openssh": fedora40WithSSH, +} + +var fedora40WithSSH = baseTemplate{ + Name: "Fedora 40 With OpenSSH Server", + ID: "fedora-40-openssh", + Content: `FROM fedora:40 + +RUN dnf install -y openssh-server \ + && mkdir -p /etc/ssh \ + && ssh-keygen -q -N "" -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key \ + && useradd testuser \ + && echo "testuser:12345678" | chpasswd + && usermod -aG wheel testuser + +CMD ["/usr/sbin/sshd", "-D"] +`, +} diff --git a/internal/template/http_handlers.go b/internal/template/http_handlers.go index 11e7298..c08007c 100644 --- a/internal/template/http_handlers.go +++ b/internal/template/http_handlers.go @@ -14,6 +14,7 @@ type createTemplateRequestBody struct { Description string `json:"description"` Content string `json:"content"` Documentation string `json:"documentation"` + BaseTemplate string `json:"baseTemplate"` } type postTemplateRequestBody struct { @@ -33,6 +34,15 @@ func fetchAllTemplates(c echo.Context) error { return c.JSON(http.StatusOK, templates) } +func fetchBaseTemplates(c echo.Context) error { + mgr := templateManagerFrom(c) + templates, err := mgr.findBaseTemplates(c.Request().Context()) + if err != nil { + return err + } + return c.JSON(http.StatusOK, templates) +} + func fetchTemplate(c echo.Context) error { mgr := templateManagerFrom(c) template, err := mgr.findTemplate(c.Request().Context(), c.Param("templateName")) @@ -79,8 +89,9 @@ func createTemplate(c echo.Context) error { } createdTemplate, err := mgr.createTemplate(c.Request().Context(), createTemplateOptions{ - name: name, - description: body.Description, + name: name, + description: body.Description, + baseTemplate: body.BaseTemplate, }) if err != nil { return err diff --git a/internal/template/routes.go b/internal/template/routes.go index 6398b1a..636dc49 100644 --- a/internal/template/routes.go +++ b/internal/template/routes.go @@ -14,4 +14,5 @@ func DefineRoutes(g *echo.Group, services service.Services) { g.GET("/templates/:templateName/:filePath", fetchTemplateFile, validateTemplateName, validateTemplateFilePath) g.POST("/templates/:templateName/:filePath", updateTemplateFile, validateTemplateName, validateTemplateFilePath) g.GET("/template-images", fetchAllTemplateImages) + g.GET("/base-templates", fetchBaseTemplates) } diff --git a/internal/template/template_manager.go b/internal/template/template_manager.go index 94dbdb0..7421418 100644 --- a/internal/template/template_manager.go +++ b/internal/template/template_manager.go @@ -22,8 +22,9 @@ type templateManager struct { } type createTemplateOptions struct { - name string - description string + baseTemplate string + name string + description string } type updateTemplateOptions struct { @@ -38,6 +39,7 @@ type buildTemplateOptions struct { } var errTemplateNotFound = errors.New("template not found") +var errBaseTemplateNotFound = errors.New("base template not found") var errTemplateFileNotFound = errors.New("template file not found") func (mgr *templateManager) beginTx(ctx context.Context) (bun.Tx, error) { @@ -48,6 +50,10 @@ func (mgr *templateManager) beginTx(ctx context.Context) (bun.Tx, error) { return tx, nil } +func (mgr *templateManager) findBaseTemplates(ctx context.Context) ([]baseTemplate, error) { + return baseTemplates, nil +} + func (mgr *templateManager) findAllTemplates(ctx context.Context) ([]template, error) { var templates []template err := mgr.db.NewSelect().Model(&templates).Scan(ctx) @@ -69,7 +75,7 @@ func (mgr *templateManager) findTemplate(ctx context.Context, name string) (*tem var template template err := mgr.db.NewSelect().Model(&template). Relation("Files"). - Where("name = ?", name). + Where("Name = ?", name). Scan(ctx) if err != nil { if errors.Is(err, sql.ErrNoRows) { @@ -91,7 +97,7 @@ func (mgr *templateManager) findTemplate(ctx context.Context, name string) (*tem func (mgr *templateManager) hasTemplate(ctx context.Context, name string) (bool, error) { exists, err := mgr.db.NewSelect(). Table("templates"). - Where("name = ?", name). + Where("Name = ?", name). Exists(ctx) if err != nil { if errors.Is(err, sql.ErrNoRows) { @@ -115,6 +121,11 @@ func (mgr *templateManager) createTemplate(ctx context.Context, opts createTempl now := time.Now().Format(time.RFC3339) + baseTemplate, ok := baseTemplateMap[opts.baseTemplate] + if !ok { + return nil, errBaseTemplateNotFound + } + t := template{ ID: id, Name: opts.name, @@ -126,7 +137,7 @@ func (mgr *templateManager) createTemplate(ctx context.Context, opts createTempl dockerfile := templateFile{ TemplateID: id, FilePath: "Dockerfile", - Content: make([]byte, 0), + Content: []byte(baseTemplate.Content), } readme := templateFile{ TemplateID: id, @@ -167,7 +178,7 @@ func (mgr *templateManager) updateTemplate(ctx context.Context, name string, opt var template template err := tx.NewUpdate().Model(&template). - Where("name = ?", name). + Where("Name = ?", name). Set("description = ?", opts.description). Returning("*"). Scan(ctx) @@ -320,7 +331,7 @@ func (mgr *templateManager) deleteTemplate(ctx context.Context, name string) err } res, err := tx.NewDelete().Table("templates"). - Where("name = ?", name). + Where("Name = ?", name). Exec(ctx) if err != nil { if errors.Is(err, sql.ErrNoRows) { @@ -353,7 +364,7 @@ func (mgr *templateManager) findTemplateFile(ctx context.Context, templateName, var tmpl template err := mgr.db.NewSelect().Model(&tmpl). Column("id"). - Where("name = ?", templateName). + Where("Name = ?", templateName). Scan(ctx) if err != nil { if errors.Is(err, sql.ErrNoRows) { @@ -386,7 +397,7 @@ func (mgr *templateManager) updateTemplateFile(ctx context.Context, templateName var template template err = tx.NewSelect().Model(&template). Column("id"). - Where("name = ?", templateName). + Where("Name = ?", templateName). Scan(ctx) if err != nil { if errors.Is(err, sql.ErrNoRows) { diff --git a/web/src/templates/api.ts b/web/src/templates/api.ts index 6d97b93..7a170cd 100644 --- a/web/src/templates/api.ts +++ b/web/src/templates/api.ts @@ -1,6 +1,11 @@ import { useCallback, useState } from "react"; import useSWR, { useSWRConfig } from "swr"; -import type { Template, TemplateMeta, TemplateImage } from "./types"; +import type { + Template, + TemplateMeta, + TemplateImage, + BaseTemplate, +} from "./types"; import { fetchApi } from "@/api"; function useTemplates() { @@ -47,11 +52,16 @@ function useCreateTemplate() { async ({ name, description, - }: { name: string; description: string }): Promise