Commit a7420cfc authored by Bruce Flynn's avatar Bruce Flynn
Browse files

initial

parents
FROM golang:1.9 AS build
RUN curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
WORKDIR /go/src/gitlab.ssec.wisc.edu/brucef/chart-server
COPY . .
RUN dep ensure && ./build.sh
FROM debian:buster-slim
COPY --from=build /go/bin/chart-server .
ENTRYPOINT ["./chart-server"]
CMD ["$@"]
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
name = "github.com/pkg/errors"
packages = ["."]
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
version = "v0.8.0"
[[projects]]
name = "github.com/spf13/pflag"
packages = ["."]
revision = "9a97c102cda95a86cec2345a6f09f55a939babf5"
version = "v1.0.2"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "6a5cb0d32267ee88743a8972ec6d5c53e95e1e90a4711815b803c569c22340b6"
solver-name = "gps-cdcl"
solver-version = 1
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
#
# [prune]
# non-go = false
# go-tests = true
# unused-packages = true
[[constraint]]
name = "github.com/pkg/errors"
version = "0.8.0"
[[constraint]]
name = "github.com/spf13/pflag"
version = "1.0.2"
[prune]
go-tests = true
unused-packages = true
#!/usr/bin/env bash
ver=$(git describe)
sha=$(git rev-parse HEAD)
dt="$(date +%Y-%m-%d)T$(date +%H:%M:%S)Z"
buildStr="v${ver} (${dt})"
pkg=gitlab.ssec.wisc.edu/brucef/chart-server
go install --ldflags "-X 'main.buildStr=${buildStr}'" ${pkg}/...
package main // import "gitlab.ssec.wisc.edu/brucef/chart-server"
import (
"fmt"
"io"
"log"
"net/http"
"os"
"os/exec"
"path"
"github.com/pkg/errors"
"github.com/spf13/pflag"
)
func updateIndex() error {
cmd := exec.Command("helm", "repo", "index", "--url", url, dir)
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
return errors.Wrapf(err, "running helm")
}
return nil
}
func handleUpload(w http.ResponseWriter, r *http.Request) {
p := path.Join(dir, r.URL.Path)
st, err := os.Stat(p)
// got an error and the file exists... something interesting perhaps?
if err != nil && !os.IsNotExist(err) {
log.Printf("ERROR: could not stat %s : %s\n", p, err)
http.Error(w, "InternalServerError", http.StatusInternalServerError)
return
}
// got a stat result, file must exist
if st != nil {
http.Error(w, "File exists", http.StatusForbidden)
return
}
// file does not exist, proceed with upload
f, err := os.Create(p)
if err != nil {
log.Printf("InternalServerErrror: could not create %s: %s\n", p, err)
http.Error(w, "Could not complete upload", http.StatusInternalServerError)
return
}
if _, err := io.Copy(f, r.Body); err != nil {
log.Printf("InternalServerErrror: could not copy %s: %s\n", p, err)
http.Error(w, "Could not complete upload", http.StatusInternalServerError)
return
}
err = updateIndex()
if err != nil {
log.Printf("ERROR updating index: %s\n", err)
http.Error(w, "Could not update index", http.StatusInternalServerError)
// best-effort to remove the file if we could not update the index
os.Remove(p)
return
}
log.Printf("successfully handled chart %s", path.Base(p))
}
func handleGet(w http.ResponseWriter, r *http.Request) {
p := path.Join(dir, r.URL.Path)
if st, err := os.Stat(p); os.IsNotExist(err) || st.IsDir() {
http.Error(w, "Not Found", http.StatusNotFound)
return
}
f, err := os.Open(p)
if err != nil {
log.Printf("InternalServerErrror: could not open %s: %s\n", p, err)
http.Error(w, "InternalServerError", http.StatusInternalServerError)
return
}
if _, err := io.Copy(w, f); err != nil {
log.Printf("InternalServerErrror: could not copy %s: %s\n", p, err)
http.Error(w, "InternalServerError", http.StatusInternalServerError)
return
}
}
func handle(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "PUT":
handleUpload(w, r)
case "GET":
handleGet(w, r)
default:
http.Error(w, "Bad Request", http.StatusBadRequest)
}
}
func handleStatus(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK!\n"))
}
func getEnvDefault(name, def string) string {
if v, ok := os.LookupEnv(name); ok {
return v
}
return def
}
var (
dir string
host string
url string
buildStr string
)
func main() {
pflag.ErrHelp = errors.New("")
pflag.Usage = func() {
fmt.Fprintf(os.Stderr, `USAGE %s [options]
Helm chart server that only accepts PUT requests to upload charts and GET
requests to download them. Whenever a chart is successfully uploaded the index
will be updated. This requires a working helm client installation and the helm
binary on the current PATH. Most helm options, if they need to be set can be
set via the $HELM_* environment variables.
Options can also be specified as environment variables $CHART_SVR_<name>
`, os.Args[0])
pflag.PrintDefaults()
fmt.Fprintf(os.Stderr, "\n%s\n", buildStr)
}
pflag.StringVar(&dir, "dir", getEnvDefault("CHART_SVR_DIR", "."), "Chart report dir")
pflag.StringVar(&host, "host", getEnvDefault("CHART_SVR_HOST", ":8080"), "Host to bind to [<host>]:<port>")
pflag.StringVar(&url, "url", getEnvDefault("CHART_SVR_URL", ""), "URL to the chart repository")
pflag.Parse()
if len(url) == 0 {
fmt.Fprintf(os.Stderr, "either --url or CHART_SVR_URL is required\n")
os.Exit(1)
}
if !path.IsAbs(dir) {
p, err := os.Getwd()
if err != nil {
panic(err)
}
dir = path.Join(p, dir)
}
http.HandleFunc("/status", handleStatus)
http.HandleFunc("/", handle)
log.Printf("serving charts from %s on %s", dir, host)
log.Fatal(http.ListenAndServe(host, nil))
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment