Skip to content
This repository has been archived by the owner on Oct 22, 2024. It is now read-only.

Commit

Permalink
feat: add new cli system (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
acouvreur committed Oct 3, 2022
1 parent 551a146 commit 0daddf3
Show file tree
Hide file tree
Showing 17 changed files with 757 additions and 275 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ WORKDIR /go/src/sablier

ARG TARGETOS
ARG TARGETARCH
RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -buildvcs=false -o /go/bin/sablier
RUN GIN_MODE=release GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -buildvcs=false -o /go/bin/sablier

FROM alpine
EXPOSE 10000
Expand Down
11 changes: 9 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@ os = $(word 1, $(temp))
arch = $(word 2, $(temp))
version = draft

release: $(PLATFORMS)
# Version info for binaries
GIT_REVISION := $(shell git rev-parse --short HEAD)
GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD)

VPREFIX := github.com/acouvreur/sablier/version
GO_LDFLAGS := -X $(VPREFIX).Branch=$(GIT_BRANCH) -X $(VPREFIX).Version=$(version) -X $(VPREFIX).Revision=$(GIT_REVISION) -X $(VPREFIX).BuildUser=$(shell whoami)@$(shell hostname) -X $(VPREFIX).BuildDate=$(shell date -u +"%Y-%m-%dT%H:%M:%SZ")

$(PLATFORMS):
GOOS=$(os) GOARCH=$(arch) go build -o 'sablier_$(version)_$(os)-$(arch)' .
GIN_MODE=release GOOS=$(os) GOARCH=$(arch) go build -ldflags="${GO_LDFLAGS}" -o 'sablier_$(version)_$(os)-$(arch)' .


release: $(PLATFORMS)
.PHONY: release $(PLATFORMS)
100 changes: 81 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,39 @@
# Sablier ![Github Actions](https://img.shields.io/github/workflow/status/acouvreur/sablier/Build?style=flat-square) ![Go Report](https://goreportcard.com/badge/github.com/acouvreur/sablier?style=flat-square) ![Go Version](https://img.shields.io/github/go-mod/go-version/acouvreur/sablier?style=flat-square) ![Latest Release](https://img.shields.io/github/release/acouvreur/sablier/all.svg?style=flat-square)
# Sablier

![Github Actions](https://img.shields.io/github/workflow/status/acouvreur/sablier/Build?style=flat-square) ![Go Report](https://goreportcard.com/badge/github.com/acouvreur/sablier?style=flat-square) ![Go Version](https://img.shields.io/github/go-mod/go-version/acouvreur/sablier?style=flat-square) ![Latest Release](https://img.shields.io/github/release/acouvreur/sablier/all.svg?style=flat-square)

Sablier is an API that start containers on demand.
It provides an integrations with multiple reverse proxies and different loading strategies.

- [Sablier](#sablier)
- [Getting started](#getting-started)
- [Features](#features)
- [CLI Usage](#cli-usage)
- [Configuration](#configuration)
- [Reverse proxies integration plugins](#reverse-proxies-integration-plugins)
- [Traefik Integration](#traefik-integration)
- [Kubernetes](#kubernetes)
- [API](#api)

## Getting started

Binary

```bash
docker run -d --name nginx nginx
docker stop nginx
docker run -v /var/run/docker.sock:/var/run/docker.sock -p 10000:10000 ghcr.io/acouvreur/sablier:latest --swarmode=false
./sablier start
curl 'http://localhost:10000/?name=nginx&timeout=1m'
```

## Plugins
Docker

```bash
docker run -d --name nginx nginx
docker stop nginx
docker run -v /var/run/docker.sock:/var/run/docker.sock -p 10000:10000 ghcr.io/acouvreur/sablier:latest --swarmode=false
curl 'http://localhost:10000/?name=nginx&timeout=1m'
```

## Features

Expand All @@ -21,32 +45,70 @@ curl 'http://localhost:10000/?name=nginx&timeout=1m'
- Dynamic loading page (cloudflare or grafana cloud style)
- Customize dynamic and loading pages

## Usage
## CLI Usage

```
Usage:
sablier [command]
Available Commands:
completion Generate the autocompletion script for the specified shell
help Help about any command
start Start the Sablier server
version Print the version Sablier
`docker run -v /var/run/docker.sock:/var/run/docker.sock -p 10000:10000 ghcr.io/acouvreur/sablier:latest --swarmode=true`
Flags:
-h, --help help for sablier
Use "sablier [command] --help" for more information about a command.
```

Start options

```
Start the Sablier server
### CLI
Usage:
sablier start [flags]
`./sablier --swarmMode=true --kubernetesMode=false`
Flags:
-h, --help help for start
--provider.name string Provider to use to manage containers [docker swarm kubernetes] (default "docker")
--server.base-path string The base path for the API (default "/")
--server.port int The server port to use (default 10000)
--storage.file string File path to save the state
```

## Configuration

Sablier can be configured in that order:

1. command line arguments
2. environment variable
3. config.yaml file

```yaml
server:
port: 10000
basePath: /
storage:
file:
provider:
name: docker # available providers are docker, swarm and kubernetes
```
| Argument | Value | Description |
| ---------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `swarmMode` | true,false (default true) | Enable/Disable swarm mode. Used to determine the scaler implementation. |
| `kubernetesMode` | true,false (default false) | Enable/Disable Kubernetes mode. Used to determine the scaler implementation. |
| `storagePath` | path/to/storage/file (default nil) | Enables persistent storage, file will be used to load previous state upon starting and will sync the current content to memory into the file every 5 seconds |
## Reverse proxies integration plugins
### Docker
### Traefik Integration
- Docker Hub `acouvreur/sablier`
- Ghcr `ghcr.io/acouvreur/sablier`
see [Traefik Integration](./plugins/traefik/README.md)
`docker run -v /var/run/docker.sock:/var/run/docker.sock -p 10000:10000 ghcr.io/acouvreur/sablier:latest --swarmode=true`
### Kubernetes
## Kubernetes
see <a href="https://github.com/acouvreur/sablier/blob/main/KUBERNETES.md">KUBERNETES.md</a>
see [KUBERNETES.md](https://github.com/acouvreur/sablier/blob/main/KUBERNETES.md)
### API
## API
```
GET <service_url>:10000/?name=<service_name>&timeout=<timeout>
Expand Down
78 changes: 78 additions & 0 deletions app/middleware/logging.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package middleware

import (
"fmt"
"math"
"net/http"
"os"
"time"

"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
)

var timeFormat = "02/Jan/2006:15:04:05 -0700"

// Logger is the logrus logger handler
func Logger(logger logrus.FieldLogger, notLogged ...string) gin.HandlerFunc {
hostname, err := os.Hostname()
if err != nil {
hostname = "unknow"
}

var skip map[string]struct{}

if length := len(notLogged); length > 0 {
skip = make(map[string]struct{}, length)

for _, p := range notLogged {
skip[p] = struct{}{}
}
}

return func(c *gin.Context) {
// other handler can change c.Path so:
path := c.Request.URL.Path
start := time.Now()
c.Next()
stop := time.Since(start)
latency := int(math.Ceil(float64(stop.Nanoseconds()) / 1000000.0))
statusCode := c.Writer.Status()
clientIP := c.ClientIP()
clientUserAgent := c.Request.UserAgent()
referer := c.Request.Referer()
dataLength := c.Writer.Size()
if dataLength < 0 {
dataLength = 0
}

if _, ok := skip[path]; ok {
return
}

entry := logger.WithFields(logrus.Fields{
"hostname": hostname,
"statusCode": statusCode,
"latency": latency, // time to process
"clientIP": clientIP,
"method": c.Request.Method,
"path": path,
"referer": referer,
"dataLength": dataLength,
"userAgent": clientUserAgent,
})

if len(c.Errors) > 0 {
entry.Error(c.Errors.ByType(gin.ErrorTypePrivate).String())
} else {
msg := fmt.Sprintf("%s - %s [%s] \"%s %s\" %d %d \"%s\" \"%s\" (%dms)", clientIP, hostname, time.Now().Format(timeFormat), c.Request.Method, path, statusCode, dataLength, referer, clientUserAgent, latency)
if statusCode >= http.StatusInternalServerError {
entry.Error(msg)
} else if statusCode >= http.StatusBadRequest {
entry.Warn(msg)
} else {
entry.Info(msg)
}
}
}
}
Loading

0 comments on commit 0daddf3

Please sign in to comment.