From b568e349e73ffcba7bf702dc25ab34d461b79ed1 Mon Sep 17 00:00:00 2001 From: Franck Cuny Date: Fri, 30 Mar 2018 14:55:46 -0700 Subject: Redirect go code to github.com --- tools/govanity/main.go | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tools/govanity/main.go (limited to 'tools/govanity/main.go') diff --git a/tools/govanity/main.go b/tools/govanity/main.go new file mode 100644 index 0000000..4afe8d1 --- /dev/null +++ b/tools/govanity/main.go @@ -0,0 +1,35 @@ +package repo + +import ( + "html/template" + "net/http" +) + +type repository struct { + Name string +} + +var vanityTemplate = template.Must(template.New("code").Parse(` + + + + + + + + + + +`)) + +func init() { + http.HandleFunc("/", handleTransactions) +} + +func handleTransactions(w http.ResponseWriter, r *http.Request) { + repoName := r.URL.Path + p := &repository{Name: repoName} + if err := vanityTemplate.Execute(w, p); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } +} -- cgit 1.4.1 From 02734a5b4ffc555a47c5029422ae4015b59c138f Mon Sep 17 00:00:00 2001 From: Franck Cuny Date: Thu, 12 Aug 2021 13:10:25 -0700 Subject: vanity: rewrite with templates and external config Rewrite the program to use external templates and load the configuration from an external source. We don't want to blindly send all the requests to some SCM since we want to support only some modules / program that way. There's two templates, one for requests coming from a browser, which list all the supported modules, and one for the `go get` command. For requests coming from `go get`, we generate a template that indicates where the repository is. The external configuration is in YAML, and list all the supported repositories, and the URL of the repository. It assumes a default VCS for all the modules (git in our case). --- tools/govanity/go.mod | 2 + tools/govanity/go.sum | 3 + tools/govanity/main.go | 130 +++++++++++++++++++++++++------ tools/govanity/templates/index.html.tpl | 14 ++++ tools/govanity/templates/module.html.tpl | 12 +++ tools/govanity/vanity.yaml | 5 ++ 6 files changed, 144 insertions(+), 22 deletions(-) create mode 100644 tools/govanity/go.sum create mode 100644 tools/govanity/templates/index.html.tpl create mode 100644 tools/govanity/templates/module.html.tpl create mode 100644 tools/govanity/vanity.yaml (limited to 'tools/govanity/main.go') diff --git a/tools/govanity/go.mod b/tools/govanity/go.mod index 9d1ea60..d37f146 100644 --- a/tools/govanity/go.mod +++ b/tools/govanity/go.mod @@ -1,3 +1,5 @@ module golang.fcuny.net/vanity go 1.16 + +require gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b diff --git a/tools/govanity/go.sum b/tools/govanity/go.sum new file mode 100644 index 0000000..97f8991 --- /dev/null +++ b/tools/govanity/go.sum @@ -0,0 +1,3 @@ +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tools/govanity/main.go b/tools/govanity/main.go index 4afe8d1..dd6d653 100644 --- a/tools/govanity/main.go +++ b/tools/govanity/main.go @@ -1,35 +1,121 @@ -package repo +package main import ( + "bytes" + "embed" + "flag" "html/template" + "io/ioutil" + "log" "net/http" + "strings" + + "gopkg.in/yaml.v3" ) +//go:embed templates +var tpls embed.FS + type repository struct { - Name string + Name string `yaml:"name"` + Repo string `yaml:"repo"` +} + +type config struct { + BaseUrl string `yaml:"baseUrl"` + VCS string `yaml:"vcs"` + Repositories []repository `yaml:"repositories"` +} + +type moduleTmpl struct { + Name string + Repo string + VCS string + BaseUrl string +} + +func main() { + flag.Parse() + buf, err := ioutil.ReadFile("vanity.yaml") + if err != nil { + log.Fatalf("failed to read the configuration: %+v", err) + } + + cfg := &config{} + err = yaml.Unmarshal(buf, cfg) + if err != nil { + log.Fatalf("failed to parse the YAML configuration: %+v", err) + } + + http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + w.Write([]byte("ok")) + }) + + http.HandleFunc("/", goGet(cfg)) + + log.Printf("starting web server on :8080") + log.Fatal(http.ListenAndServe(":8080", nil)) } -var vanityTemplate = template.Must(template.New("code").Parse(` - - - - - - - - - - -`)) - -func init() { - http.HandleFunc("/", handleTransactions) +func goGet(cfg *config) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + status := http.StatusMethodNotAllowed + http.Error(w, http.StatusText(status), status) + return + } + + if r.FormValue("go-get") == "1" { + pathParts := strings.Split(r.URL.Path, "/") + for _, m := range cfg.Repositories { + if pathParts[1] == m.Name { + goGetModule(w, r, m, cfg) + return + } + } + status := http.StatusNotFound + http.Error(w, http.StatusText(status), status) + return + } + browserURL(w, r, cfg) + } } -func handleTransactions(w http.ResponseWriter, r *http.Request) { - repoName := r.URL.Path - p := &repository{Name: repoName} - if err := vanityTemplate.Execute(w, p); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) +func goGetModule(w http.ResponseWriter, r *http.Request, m repository, cfg *config) { + tmpl, err := template.ParseFS(tpls, "templates/module.html.tpl") + if err != nil { + log.Fatal(err) + } + mod := moduleTmpl{ + VCS: cfg.VCS, + BaseUrl: cfg.BaseUrl, + Name: m.Name, + Repo: m.Repo, + } + var buf bytes.Buffer + if err := tmpl.Execute(&buf, mod); err != nil { + log.Printf("error: %+v", err) + status := http.StatusInternalServerError + http.Error(w, http.StatusText(status), status) + } else { + w.Header().Set("Cache-Control", "no-store") + w.Write(buf.Bytes()) + } +} + +func browserURL(w http.ResponseWriter, r *http.Request, cfg *config) { + tmpl, err := template.ParseFS(tpls, "templates/index.html.tpl") + if err != nil { + log.Fatal(err) + } + var buf bytes.Buffer + if err := tmpl.Execute(&buf, cfg); err != nil { + log.Printf("error: %+v", err) + status := http.StatusInternalServerError + http.Error(w, http.StatusText(status), status) + } else { + w.Header().Set("Cache-Control", "no-store") + w.Write(buf.Bytes()) } } diff --git a/tools/govanity/templates/index.html.tpl b/tools/govanity/templates/index.html.tpl new file mode 100644 index 0000000..fd8fc56 --- /dev/null +++ b/tools/govanity/templates/index.html.tpl @@ -0,0 +1,14 @@ + + + + golang repo + + + + + + diff --git a/tools/govanity/templates/module.html.tpl b/tools/govanity/templates/module.html.tpl new file mode 100644 index 0000000..fab3414 --- /dev/null +++ b/tools/govanity/templates/module.html.tpl @@ -0,0 +1,12 @@ + + + + {{.Name}}: golang repo + + + + + + go get {{.BaseUrl}}/{{.Name}} + + diff --git a/tools/govanity/vanity.yaml b/tools/govanity/vanity.yaml new file mode 100644 index 0000000..a757729 --- /dev/null +++ b/tools/govanity/vanity.yaml @@ -0,0 +1,5 @@ +baseUrl: golang.fcuny.net +vcs: git +repositories: + - name: homelab + repo: https://git.fcuny.net/fcuny/homelab -- cgit 1.4.1