component/dis: Check if instance alive
This commit is contained in:
parent
37cdd201f0
commit
492a0c0404
8 changed files with 145 additions and 22 deletions
|
|
@ -1,26 +1,70 @@
|
|||
package dis
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/component/instances"
|
||||
"github.com/tkw1536/goprogram/stream"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
func (dis Dis) info(io stream.IOStream) (http.Handler, error) {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
all, err := dis.Instances.All()
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte("internal server error"))
|
||||
io.EPrintln(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, wk := range all {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(wk.Slug))
|
||||
w.Write([]byte("\n"))
|
||||
}
|
||||
|
||||
}), nil
|
||||
func (dis *Dis) info(io stream.IOStream) (http.Handler, error) {
|
||||
return http.HandlerFunc(dis.handleDis), nil
|
||||
}
|
||||
|
||||
const disLimit = 2
|
||||
|
||||
func (dis *Dis) handleDis(w http.ResponseWriter, r *http.Request) {
|
||||
// make sure the user is authorized
|
||||
if !dis.authDis(r) {
|
||||
w.Header().Add("WWW-Authenticate", `Basic realm="WissKI Distillery Admin"`)
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
w.Write([]byte("Unauthorized"))
|
||||
return
|
||||
}
|
||||
|
||||
// create a new error group
|
||||
var errgroup errgroup.Group
|
||||
errgroup.SetLimit(disLimit)
|
||||
|
||||
// list all the instances
|
||||
all, err := dis.Instances.All()
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte("internal server error"))
|
||||
return
|
||||
}
|
||||
|
||||
// get all of their info!
|
||||
infos := make([]instances.Info, len(all))
|
||||
for i, instance := range all {
|
||||
{
|
||||
i := i
|
||||
instance := instance
|
||||
|
||||
errgroup.Go(func() (err error) {
|
||||
infos[i], err = instance.Info()
|
||||
return err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// if some info call failed
|
||||
if err := errgroup.Wait(); err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte("internal server error"))
|
||||
w.Write([]byte("\n"))
|
||||
return
|
||||
}
|
||||
|
||||
// and return the json
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(infos)
|
||||
}
|
||||
|
||||
func (dis *Dis) authDis(r *http.Request) bool {
|
||||
user, pass, ok := r.BasicAuth()
|
||||
return ok && user == dis.Config.DisAdminUser && pass == dis.Config.DisAdminPassword
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM docker.io/library/alpine
|
||||
FROM docker.io/library/docker:20.10-cli
|
||||
|
||||
COPY wdcli /wdcli
|
||||
EXPOSE 8888
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
version: "3.7"
|
||||
|
||||
services:
|
||||
wdresolve:
|
||||
dis:
|
||||
build: .
|
||||
restart: always
|
||||
environment:
|
||||
|
|
@ -16,6 +16,8 @@ services:
|
|||
LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL}
|
||||
|
||||
volumes:
|
||||
# TODO: Mount docker socket properly!
|
||||
- "/var/run/docker.sock:/var/run/docker.sock"
|
||||
- "${CONFIG_PATH}:${CONFIG_PATH}:ro"
|
||||
- "${DEPLOY_ROOT}:${DEPLOY_ROOT}:ro"
|
||||
- "${GLOBAL_AUTHORIZED_KEYS_FILE}:${GLOBAL_AUTHORIZED_KEYS_FILE}:ro"
|
||||
|
|
|
|||
22
internal/component/instances/wisski_status.go
Normal file
22
internal/component/instances/wisski_status.go
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
package instances
|
||||
|
||||
import "github.com/tkw1536/goprogram/stream"
|
||||
|
||||
// Info represents some info about this WissKI
|
||||
type Info struct {
|
||||
Slug string // The slug of the instance
|
||||
|
||||
Running bool // is the instance running?
|
||||
}
|
||||
|
||||
// Info returns info about this instance
|
||||
func (wisski *WissKI) Info() (info Info, err error) {
|
||||
info.Slug = wisski.Slug
|
||||
|
||||
ps, err := wisski.Barrel().Ps(stream.FromNil())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
info.Running = len(ps) > 0
|
||||
return
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@
|
|||
package component
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/execx"
|
||||
|
|
@ -119,6 +121,38 @@ func (ds Stack) Restart(io stream.IOStream) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
var errStackPs = errors.New("Stack.Ps: Down returned non-zero exit code")
|
||||
|
||||
// Ps returns the ids of the containers currently running
|
||||
func (ds Stack) Ps(io stream.IOStream) ([]string, error) {
|
||||
// create a buffer
|
||||
var buffer bytes.Buffer
|
||||
|
||||
// read the ids from the command!
|
||||
code, err := ds.compose(io.Streams(&buffer, nil, nil, 0), "ps", "-q")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if code != 0 {
|
||||
return nil, errStackPs
|
||||
}
|
||||
|
||||
// scan each of the lines
|
||||
var results []string
|
||||
scanner := bufio.NewScanner(&buffer)
|
||||
for scanner.Scan() {
|
||||
if text := scanner.Text(); text != "" {
|
||||
results = append(results, text)
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// return them!
|
||||
return results, nil
|
||||
}
|
||||
|
||||
var errStackDown = errors.New("Stack.Down: Down returned non-zero exit code")
|
||||
|
||||
// Down stops and removes all containers in this Stack.
|
||||
|
|
|
|||
|
|
@ -74,7 +74,11 @@ type Config struct {
|
|||
|
||||
// admin credentials for the Mysql database
|
||||
MysqlAdminUser string `env:"MYSQL_ADMIN_USER" default:"admin" parser:"nonempty"`
|
||||
MysqlAdminPassword string `env:"MYSQL_ADMIN_PASSWORD" default:"admin" parser:"nonempty"`
|
||||
MysqlAdminPassword string `env:"MYSQL_ADMIN_PASSWORD" default:"" parser:"nonempty"`
|
||||
|
||||
// admin credentials for the dis server
|
||||
DisAdminUser string `env:"DIS_ADMIN_USER" default:"admin" parser:"nonempty"`
|
||||
DisAdminPassword string `env:"DIS_ADMIN_PASSWORD" default:"" parser:"nonempty"`
|
||||
|
||||
// ConfigPath is the path this configuration was loaded from (if any)
|
||||
ConfigPath string
|
||||
|
|
|
|||
|
|
@ -58,6 +58,10 @@ GLOBAL_AUTHORIZED_KEYS_FILE=${AUTHORIZED_KEYS_FILE}
|
|||
GRAPHDB_ADMIN_USER=${GRAPHDB_ADMIN_USER}
|
||||
GRAPHDB_ADMIN_PASSWORD=${GRAPHDB_ADMIN_PASSWORD}
|
||||
|
||||
# The admin password to use for access to mysql
|
||||
# The admin user and password of the MySQL interface, to be used for provisioning
|
||||
MYSQL_ADMIN_USER=${MYSQL_ADMIN_USER}
|
||||
MYSQL_ADMIN_PASSWORD=${MYSQL_ADMIN_PASSWORD}
|
||||
|
||||
# The admin user and password required to access the /dis/ server and api
|
||||
DIS_ADMIN_USER=${DIS_ADMIN_USER}
|
||||
DIS_ADMIN_PASSWORD=${DIS_ADMIN_PASSWORD}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import (
|
|||
_ "embed"
|
||||
)
|
||||
|
||||
// Template is a template for the cofiguration file
|
||||
// Template is a template for the configuration file
|
||||
type Template struct {
|
||||
DeployRoot string `env:"DEPLOY_ROOT"`
|
||||
DefaultDomain string `env:"DEFAULT_DOMAIN"`
|
||||
|
|
@ -24,6 +24,8 @@ type Template struct {
|
|||
TriplestoreAdminPassword string `env:"GRAPHDB_ADMIN_PASSWORD"`
|
||||
MysqlAdminUsername string `env:"MYSQL_ADMIN_USER"`
|
||||
MysqlAdminPassword string `env:"MYSQL_ADMIN_PASSWORD"`
|
||||
DisAdminUsername string `env:"DIS_ADMIN_USER"`
|
||||
DisAdminPassword string `env:"DIS_ADMIN_PASSWORD"`
|
||||
}
|
||||
|
||||
// SetDefaults sets defaults on the template
|
||||
|
|
@ -66,6 +68,17 @@ func (tpl *Template) SetDefaults() (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
if tpl.DisAdminUsername == "" {
|
||||
tpl.DisAdminUsername = "admin"
|
||||
}
|
||||
|
||||
if tpl.DisAdminPassword == "" {
|
||||
tpl.DisAdminPassword, err = password.Password(64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue