If you’re using Go, you’ve likely heard of ent. Some Ex-Facebook employee maintaining and developing an open source version of the public version of Meta’s entity framework for Go. Well there’s a catch. Migrations. They sweet talk you in their documentation to use Atlas. Ariga’s Atlas, not the MongoDB one. But Atlas is a proprietary […]
Tag: go
Golang get openid-connect userinfo
It might not be news to you, but this will explain a little bit about Go, making http requests and parsing the result. OpenID-Connect (oidc) is an identity protocol, you could call it an Oauth2 dialect. It manages your users per realm, well not the protocol but the server does. Every oidc idp (identity provider […]
Using gin with pongo2/v4 or v5 and embedded templates
You’d like to use pongo2/v4 with gin and embed templates with go:embed. I’m using cobra for my cli parsing and commands. So
|
1 2 3 4 |
mkdir -p ~/go/src/git.icod.de/dalu/ui cd ~/go/src/git.icod.de/dalu/ui cobra init --pkg-name git.icod.de/dalu/ui cobra add ui |
edit cmd/ui.go
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
package cmd import ( "errors" "fmt" "io/fs" "os" "strings" "<your pkg path>/ui" "code.icod.de/dalu/ginpongo2/v5" "github.com/flosch/pongo2/v5" "github.com/gin-gonic/gin" "github.com/spf13/cobra" ) const ( prefixTCP = "tcp:" prefixUNIX = "unix:" ) var ( uiDebug bool uiAddr string ) // uiCmd represents the ui command var uiCmd = &cobra.Command{ Use: "ui", Short: "serves the management ui over http", RunE: func(cmd *cobra.Command, args []string) error { if !uiDebug { gin.SetMode(gin.ReleaseMode) } r := gin.Default() r.SecureJsonPrefix(")]}',\n") r.MaxMultipartMemory = 8 << 20 if uiDebug { fmt.Println("debug mode") fl, e := pongo2.NewLocalFileSystemLoader("ui/templates/") if e != nil { return e } hr := ginpongo2.New(true, fl) r.HTMLRender = hr } else { fmt.Println("release mode") subFS, e := fs.Sub(ui.Templates, "templates") if e != nil { return e } fl := pongo2.NewFSLoader(subFS) hr := ginpongo2.New(false, fl) r.HTMLRender = hr } // Static r.Static("/assets/", "./assets/") r.GET("/", func(cx *gin.Context) { ctx := make(pongo2.Context) type Data struct { Target string Message string } ctx["data"] = &Data{ Target: "World", Message: "It's a great day to be alive", } cx.HTML(200, "index", ctx) }) // serve if strings.HasPrefix(uiAddr, prefixTCP) { addr := strings.TrimPrefix(uiAddr, prefixTCP) fmt.Println("listening on", addr) return r.Run(addr) } else if strings.HasPrefix(uiAddr, prefixUNIX) { addr := strings.TrimPrefix(uiAddr, prefixUNIX) if _, e := os.Stat(addr); errors.Is(e, os.ErrNotExist) { fmt.Println("listening on", addr) return r.RunUnix(addr) } else { if e := os.Remove(addr); e != nil { return e } else { fmt.Println("listening on", addr) return r.RunUnix(addr) } } } else { return nil } }, } func init() { rootCmd.AddCommand(uiCmd) uiCmd.Flags().BoolVar(&uiDebug, "debug", false, "enable dev mode") uiCmd.Flags().StringVar( &uiAddr, "addr", "tcp:localhost:8080", "either tcp: or unix: e.g. tcp:localhost:3030 unix:/tmp/listen.sock", ) } |
ui/templates.go
|
1 2 3 4 5 6 |
package ui import "embed" //go:embed templates/* var Templates embed.FS |
ui/templates/base.html.twig
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> {%- block meta %}{% endblock -%} <title>{{ title }}</title> {%- block js %}{% endblock -%} {%- block css %}{% endblock -%} </head> <body> {%- block body %}{% endblock -%} {%- block jsbottom %}{% endblock -%} </body> </html> |
ui/templates/layout.html.twig
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
{% extends "base.html.twig" %} {%- block css %} <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous"> {% endblock -%} {%- block js %} <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script> {% endblock -%} {%- block body %} <div class="container"> <div class="row"> <div class="col-2"> {%- block left -%}{% endblock -%} </div> <div class="col-8"> {%- block middle -%}{% endblock -%} </div> <div class="col-2"> {%- block right -%}{% endblock -%} </div> </div> </div> {% endblock -%} |
ui/templates/index.html.twig
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{% extends "layout.html.twig" %} {%- block middle %} <div class="px-4 py-5 my-5 text-center"> <h1 class="display-5 fw-bold">Hello {{data.Target}}</h1> <div class="col-lg-6 mx-auto"> <p class="lead mb-4">{{data.Message}}</p> <div class="d-grid gap-2 d-sm-flex justify-content-sm-center"> <button type="button" class="btn btn-primary btn-lg px-4 gap-3">You got it</button> <button type="button" class="btn btn-outline-secondary btn-lg px-4">Huh?</button> </div> </div> </div> {% endblock -%} |
and finally run
|
1 |
go mod tidy |
to download packages Any questions -> leave a comment
Go/Golang Run embedded bash script or node/js,python,php,ruby etc
Since Go v1.16 there’s the embed package, a simple tool to embed files as filesystems of simple strings or []bytes. While it has its downsides, I was recently met with a challenge. I’d like to run bash scripts I wrote because it’s more efficient to just run a bash script than breaking my fingers writing […]