Add /v1/core/config endpoint to cluster API

This commit is contained in:
Ingo Oppermann
2023-06-22 16:33:06 +02:00
parent faf0aab53a
commit cbe6754b2f
5 changed files with 1905 additions and 39 deletions

View File

@@ -16,6 +16,7 @@ package cluster
import (
"context"
"fmt"
"io/fs"
"net/http"
"strings"
@@ -125,6 +126,7 @@ func NewAPI(config APIConfig) (API, error) {
a.router.DELETE("/v1/kv/:key", a.UnsetKV)
a.router.GET("/v1/core", a.CoreAPIAddress)
a.router.GET("/v1/core/config", a.CoreConfig)
return a, nil
}
@@ -157,7 +159,7 @@ func (a *api) AddServer(c echo.Context) error {
r := client.JoinRequest{}
if err := util.ShouldBindJSON(c, &r); err != nil {
return Err(http.StatusBadRequest, "Invalid JSON", "%s", err.Error())
return Err(http.StatusBadRequest, "", "Invalid JSON: %s", err.Error())
}
a.logger.Debug().WithFields(log.Fields{
@@ -174,7 +176,7 @@ func (a *api) AddServer(c echo.Context) error {
err := a.cluster.Join(origin, r.ID, r.RaftAddress, "")
if err != nil {
a.logger.Debug().WithError(err).WithField("id", r.ID).Log("Unable to join cluster")
return Err(http.StatusInternalServerError, "unable to join cluster", "%s", err.Error())
return Err(http.StatusInternalServerError, "", "unable to join cluster: %s", err.Error())
}
return c.JSON(http.StatusOK, "OK")
@@ -208,7 +210,7 @@ func (a *api) RemoveServer(c echo.Context) error {
err := a.cluster.Leave(origin, id)
if err != nil {
a.logger.Debug().WithError(err).WithField("id", id).Log("Unable to leave cluster")
return Err(http.StatusInternalServerError, "unable to leave cluster", "%s", err.Error())
return Err(http.StatusInternalServerError, "", "unable to leave cluster%s", err.Error())
}
return c.JSON(http.StatusOK, "OK")
@@ -227,7 +229,7 @@ func (a *api) Snapshot(c echo.Context) error {
data, err := a.cluster.Snapshot()
if err != nil {
a.logger.Debug().WithError(err).Log("Unable to create snaphot")
return Err(http.StatusInternalServerError, "unable to create snapshot", "%s", err.Error())
return Err(http.StatusInternalServerError, "", "unable to create snapshot: %s", err.Error())
}
defer data.Close()
@@ -253,7 +255,7 @@ func (a *api) AddProcess(c echo.Context) error {
r := client.AddProcessRequest{}
if err := util.ShouldBindJSON(c, &r); err != nil {
return Err(http.StatusBadRequest, "Invalid JSON", "%s", err.Error())
return Err(http.StatusBadRequest, "", "invalid JSON: %s", err.Error())
}
origin := c.Request().Header.Get("X-Cluster-Origin")
@@ -267,7 +269,7 @@ func (a *api) AddProcess(c echo.Context) error {
err := a.cluster.AddProcess(origin, &r.Config)
if err != nil {
a.logger.Debug().WithError(err).WithField("id", r.Config.ID).Log("Unable to add process")
return Err(http.StatusInternalServerError, "unable to add process", "%s", err.Error())
return Err(http.StatusInternalServerError, "", "unable to add process: %s", err.Error())
}
return c.JSON(http.StatusOK, "OK")
@@ -303,7 +305,7 @@ func (a *api) RemoveProcess(c echo.Context) error {
err := a.cluster.RemoveProcess(origin, pid)
if err != nil {
a.logger.Debug().WithError(err).WithField("id", pid).Log("Unable to remove process")
return Err(http.StatusInternalServerError, "unable to remove process", "%s", err.Error())
return Err(http.StatusInternalServerError, "", "unable to remove process: %s", err.Error())
}
return c.JSON(http.StatusOK, "OK")
@@ -330,7 +332,7 @@ func (a *api) UpdateProcess(c echo.Context) error {
r := client.UpdateProcessRequest{}
if err := util.ShouldBindJSON(c, &r); err != nil {
return Err(http.StatusBadRequest, "Invalid JSON", "%s", err.Error())
return Err(http.StatusBadRequest, "", "invalid JSON: %s", err.Error())
}
origin := c.Request().Header.Get("X-Cluster-Origin")
@@ -349,7 +351,7 @@ func (a *api) UpdateProcess(c echo.Context) error {
err := a.cluster.UpdateProcess(origin, pid, &r.Config)
if err != nil {
a.logger.Debug().WithError(err).WithField("id", pid).Log("Unable to update process")
return Err(http.StatusInternalServerError, "unable to update process", "%s", err.Error())
return Err(http.StatusInternalServerError, "", "unable to update process: %s", err.Error())
}
return c.JSON(http.StatusOK, "OK")
@@ -377,7 +379,7 @@ func (a *api) SetProcessMetadata(c echo.Context) error {
r := client.SetProcessMetadataRequest{}
if err := util.ShouldBindJSON(c, &r); err != nil {
return Err(http.StatusBadRequest, "Invalid JSON", "%s", err.Error())
return Err(http.StatusBadRequest, "", "invalid JSON: %s", err.Error())
}
origin := c.Request().Header.Get("X-Cluster-Origin")
@@ -391,7 +393,7 @@ func (a *api) SetProcessMetadata(c echo.Context) error {
err := a.cluster.SetProcessMetadata(origin, pid, key, r.Metadata)
if err != nil {
a.logger.Debug().WithError(err).WithField("id", pid).Log("Unable to update metadata")
return Err(http.StatusInternalServerError, "unable to update metadata", "%s", err.Error())
return Err(http.StatusInternalServerError, "", "unable to update metadata: %s", err.Error())
}
return c.JSON(http.StatusOK, "OK")
@@ -415,7 +417,7 @@ func (a *api) AddIdentity(c echo.Context) error {
r := client.AddIdentityRequest{}
if err := util.ShouldBindJSON(c, &r); err != nil {
return Err(http.StatusBadRequest, "Invalid JSON", "%s", err.Error())
return Err(http.StatusBadRequest, "", "invalid JSON: %s", err.Error())
}
origin := c.Request().Header.Get("X-Cluster-Origin")
@@ -429,7 +431,7 @@ func (a *api) AddIdentity(c echo.Context) error {
err := a.cluster.AddIdentity(origin, r.Identity)
if err != nil {
a.logger.Debug().WithError(err).WithField("identity", r.Identity).Log("Unable to add identity")
return Err(http.StatusInternalServerError, "unable to add identity", "%s", err.Error())
return Err(http.StatusInternalServerError, "", "unable to add identity: %s", err.Error())
}
return c.JSON(http.StatusOK, "OK")
@@ -454,7 +456,7 @@ func (a *api) UpdateIdentity(c echo.Context) error {
r := client.UpdateIdentityRequest{}
if err := util.ShouldBindJSON(c, &r); err != nil {
return Err(http.StatusBadRequest, "Invalid JSON", "%s", err.Error())
return Err(http.StatusBadRequest, "", "invalid JSON: %s", err.Error())
}
origin := c.Request().Header.Get("X-Cluster-Origin")
@@ -474,7 +476,7 @@ func (a *api) UpdateIdentity(c echo.Context) error {
"name": name,
"identity": r.Identity,
}).Log("Unable to add identity")
return Err(http.StatusInternalServerError, "unable to update identity", "%s", err.Error())
return Err(http.StatusInternalServerError, "", "unable to update identity: %s", err.Error())
}
return c.JSON(http.StatusOK, "OK")
@@ -499,7 +501,7 @@ func (a *api) SetIdentityPolicies(c echo.Context) error {
r := client.SetPoliciesRequest{}
if err := util.ShouldBindJSON(c, &r); err != nil {
return Err(http.StatusBadRequest, "Invalid JSON", "%s", err.Error())
return Err(http.StatusBadRequest, "", "invalid JSON: %s", err.Error())
}
origin := c.Request().Header.Get("X-Cluster-Origin")
@@ -513,7 +515,7 @@ func (a *api) SetIdentityPolicies(c echo.Context) error {
err := a.cluster.SetPolicies(origin, name, r.Policies)
if err != nil {
a.logger.Debug().WithError(err).WithField("policies", r.Policies).Log("Unable to set policies")
return Err(http.StatusInternalServerError, "unable to add identity", "%s", err.Error())
return Err(http.StatusInternalServerError, "", "unable to add identity: %s", err.Error())
}
return c.JSON(http.StatusOK, "OK")
@@ -545,7 +547,7 @@ func (a *api) RemoveIdentity(c echo.Context) error {
err := a.cluster.RemoveIdentity(origin, name)
if err != nil {
a.logger.Debug().WithError(err).WithField("identity", name).Log("Unable to remove identity")
return Err(http.StatusInternalServerError, "unable to remove identity", "%s", err.Error())
return Err(http.StatusInternalServerError, "", "unable to remove identity: %s", err.Error())
}
return c.JSON(http.StatusOK, "OK")
@@ -558,13 +560,25 @@ func (a *api) RemoveIdentity(c echo.Context) error {
// @ID cluster-1-core-api-address
// @Produce json
// @Success 200 {string} string
// @Success 500 {object} Error
// @Router /v1/core [get]
func (a *api) CoreAPIAddress(c echo.Context) error {
address, _ := a.cluster.CoreAPIAddress("")
return c.JSON(http.StatusOK, address)
}
// CoreConfig returns the Core config of this node
// @Summary Core config
// @Description Core config of this node
// @Tags v1.0.0
// @ID cluster-1-core-config
// @Produce json
// @Success 200 {object} config.Config
// @Router /v1/core/config [get]
func (a *api) CoreConfig(c echo.Context) error {
config := a.cluster.CoreConfig()
return c.JSON(http.StatusOK, config)
}
// Lock tries to acquire a named lock
// @Summary Acquire a named lock
// @Description Acquire a named lock
@@ -574,14 +588,14 @@ func (a *api) CoreAPIAddress(c echo.Context) error {
// @Param data body client.LockRequest true "Lock request"
// @Param X-Cluster-Origin header string false "Origin ID of request"
// @Success 200 {string} string
// @Success 500 {object} Error
// @Failure 500 {object} Error
// @Failure 508 {object} Error
// @Router /v1/lock [post]
func (a *api) Lock(c echo.Context) error {
r := client.LockRequest{}
if err := util.ShouldBindJSON(c, &r); err != nil {
return Err(http.StatusBadRequest, "Invalid JSON", "%s", err.Error())
return Err(http.StatusBadRequest, "", "invalid JSON: %s", err.Error())
}
origin := c.Request().Header.Get("X-Cluster-Origin")
@@ -595,7 +609,7 @@ func (a *api) Lock(c echo.Context) error {
err := a.cluster.CreateLock(origin, r.Name, r.ValidUntil)
if err != nil {
a.logger.Debug().WithError(err).WithField("name", r.Name).Log("Unable to acquire lock")
return Err(http.StatusInternalServerError, "unable to acquire lock", "%s", err.Error())
return Err(http.StatusInternalServerError, "", "unable to acquire lock: %s", err.Error())
}
return c.JSON(http.StatusOK, "OK")
@@ -611,6 +625,7 @@ func (a *api) Lock(c echo.Context) error {
// @Param X-Cluster-Origin header string false "Origin ID of request"
// @Success 200 {string} string
// @Failure 404 {object} Error
// @Failure 500 {object} Error
// @Failure 508 {object} Error
// @Router /v1/lock/{name} [delete]
func (a *api) Unlock(c echo.Context) error {
@@ -627,7 +642,7 @@ func (a *api) Unlock(c echo.Context) error {
err := a.cluster.DeleteLock(origin, name)
if err != nil {
a.logger.Debug().WithError(err).WithField("name", name).Log("Unable to remove lock")
return Err(http.StatusInternalServerError, "unable to remove lock", "%s", err.Error())
return Err(http.StatusInternalServerError, "", "unable to remove lock: %s", err.Error())
}
return c.JSON(http.StatusOK, "OK")
@@ -642,14 +657,14 @@ func (a *api) Unlock(c echo.Context) error {
// @Param data body client.SetKVRequest true "Set KV request"
// @Param X-Cluster-Origin header string false "Origin ID of request"
// @Success 200 {string} string
// @Success 500 {object} Error
// @Failure 500 {object} Error
// @Failure 508 {object} Error
// @Router /v1/kv [post]
func (a *api) SetKV(c echo.Context) error {
r := client.SetKVRequest{}
if err := util.ShouldBindJSON(c, &r); err != nil {
return Err(http.StatusBadRequest, "Invalid JSON", "%s", err.Error())
return Err(http.StatusBadRequest, "", "invalid JSON: %s", err.Error())
}
origin := c.Request().Header.Get("X-Cluster-Origin")
@@ -663,7 +678,7 @@ func (a *api) SetKV(c echo.Context) error {
err := a.cluster.SetKV(origin, r.Key, r.Value)
if err != nil {
a.logger.Debug().WithError(err).WithField("key", r.Key).Log("Unable to store value")
return Err(http.StatusInternalServerError, "unable to store value", "%s", err.Error())
return Err(http.StatusInternalServerError, "", "unable to store value: %s", err.Error())
}
return c.JSON(http.StatusOK, "OK")
@@ -679,6 +694,7 @@ func (a *api) SetKV(c echo.Context) error {
// @Param X-Cluster-Origin header string false "Origin ID of request"
// @Success 200 {string} string
// @Failure 404 {object} Error
// @Failure 500 {object} Error
// @Failure 508 {object} Error
// @Router /v1/kv/{key} [delete]
func (a *api) UnsetKV(c echo.Context) error {
@@ -694,8 +710,11 @@ func (a *api) UnsetKV(c echo.Context) error {
err := a.cluster.UnsetKV(origin, key)
if err != nil {
if err == fs.ErrNotExist {
return Err(http.StatusNotFound, "", "%s", err.Error())
}
a.logger.Debug().WithError(err).WithField("key", key).Log("Unable to remove key")
return Err(http.StatusInternalServerError, "unable to remove key", "%s", err.Error())
return Err(http.StatusInternalServerError, "", "unable to remove key: %s", err.Error())
}
return c.JSON(http.StatusOK, "OK")

View File

@@ -39,6 +39,7 @@ type Cluster interface {
// CoreAPIAddress returns the address of the core API of a node with
// the given raft address.
CoreAPIAddress(raftAddress string) (string, error)
CoreConfig() *config.Config
About() (ClusterAbout, error)
@@ -361,6 +362,10 @@ func (c *cluster) CoreAPIAddress(raftAddress string) (string, error) {
return coreAddress, err
}
func (c *cluster) CoreConfig() *config.Config {
return c.config.Clone()
}
func (c *cluster) Shutdown() error {
c.logger.Info().Log("Shutting down cluster")
c.shutdownLock.Lock()

View File

@@ -41,11 +41,26 @@ const docTemplateClusterAPI = `{
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal Server Error",
}
}
}
},
"/v1/core/config": {
"get": {
"description": "Core config of this node",
"produces": [
"application/json"
],
"tags": [
"v1.0.0"
],
"summary": "Core config",
"operationId": "cluster-1-core-config",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/cluster.Error"
"$ref": "#/definitions/config.Config"
}
}
}
@@ -356,6 +371,12 @@ const docTemplateClusterAPI = `{
"$ref": "#/definitions/cluster.Error"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/cluster.Error"
}
},
"508": {
"description": "Loop Detected",
"schema": {
@@ -454,6 +475,12 @@ const docTemplateClusterAPI = `{
"$ref": "#/definitions/cluster.Error"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/cluster.Error"
}
},
"508": {
"description": "Loop Detected",
"schema": {
@@ -1076,6 +1103,595 @@ const docTemplateClusterAPI = `{
}
}
},
"config.Config": {
"type": "object",
"properties": {
"address": {
"type": "string"
},
"api": {
"type": "object",
"properties": {
"access": {
"type": "object",
"properties": {
"http": {
"type": "object",
"properties": {
"allow": {
"type": "array",
"items": {
"type": "string"
}
},
"block": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"https": {
"type": "object",
"properties": {
"allow": {
"type": "array",
"items": {
"type": "string"
}
},
"block": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
},
"auth": {
"type": "object",
"properties": {
"auth0": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"tenants": {
"type": "array",
"items": {
"$ref": "#/definitions/value.Auth0Tenant"
}
}
}
},
"disable_localhost": {
"type": "boolean"
},
"enable": {
"type": "boolean"
},
"jwt": {
"type": "object",
"properties": {
"secret": {
"type": "string"
}
}
},
"password": {
"type": "string"
},
"username": {
"type": "string"
}
}
},
"read_only": {
"type": "boolean"
}
}
},
"cluster": {
"type": "object",
"properties": {
"address": {
"description": "ip:port",
"type": "string"
},
"debug": {
"type": "boolean"
},
"emergency_leader_timeout_sec": {
"description": "seconds",
"type": "integer",
"format": "int64"
},
"enable": {
"type": "boolean"
},
"node_recover_timeout_sec": {
"description": "seconds",
"type": "integer",
"format": "int64"
},
"peers": {
"type": "array",
"items": {
"type": "string"
}
},
"sync_interval_sec": {
"description": "seconds",
"type": "integer",
"format": "int64"
}
}
},
"created_at": {
"description": "When this config has been persisted",
"type": "string"
},
"db": {
"type": "object",
"properties": {
"dir": {
"type": "string"
}
}
},
"debug": {
"type": "object",
"properties": {
"auto_max_procs": {
"type": "boolean"
},
"force_gc": {
"description": "deprecated, use MemoryLimit instead",
"type": "integer",
"format": "int"
},
"memory_limit_mbytes": {
"type": "integer",
"format": "int64"
},
"profiling": {
"type": "boolean"
}
}
},
"ffmpeg": {
"type": "object",
"properties": {
"access": {
"type": "object",
"properties": {
"input": {
"type": "object",
"properties": {
"allow": {
"type": "array",
"items": {
"type": "string"
}
},
"block": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"output": {
"type": "object",
"properties": {
"allow": {
"type": "array",
"items": {
"type": "string"
}
},
"block": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
},
"binary": {
"type": "string"
},
"log": {
"type": "object",
"properties": {
"max_history": {
"type": "integer",
"format": "int"
},
"max_lines": {
"type": "integer",
"format": "int"
},
"max_minimal_history": {
"type": "integer",
"format": "int"
}
}
},
"max_processes": {
"type": "integer",
"format": "int64"
}
}
},
"host": {
"type": "object",
"properties": {
"auto": {
"type": "boolean"
},
"name": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"id": {
"type": "string"
},
"log": {
"type": "object",
"properties": {
"level": {
"type": "string",
"enum": [
"debug",
"info",
"warn",
"error",
"silent"
]
},
"max_lines": {
"type": "integer",
"format": "int"
},
"topics": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"metrics": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"enable_prometheus": {
"type": "boolean"
},
"interval_sec": {
"description": "seconds",
"type": "integer",
"format": "int64"
},
"range_sec": {
"description": "seconds",
"type": "integer",
"format": "int64"
}
}
},
"name": {
"type": "string"
},
"playout": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"max_port": {
"type": "integer",
"format": "int"
},
"min_port": {
"type": "integer",
"format": "int"
}
}
},
"resources": {
"type": "object",
"properties": {
"max_cpu_usage": {
"description": "percent 0-100",
"type": "number"
},
"max_memory_usage": {
"description": "percent 0-100",
"type": "number"
}
}
},
"router": {
"type": "object",
"properties": {
"blocked_prefixes": {
"type": "array",
"items": {
"type": "string"
}
},
"routes": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"ui_path": {
"type": "string"
}
}
},
"rtmp": {
"type": "object",
"properties": {
"address": {
"type": "string"
},
"address_tls": {
"type": "string"
},
"app": {
"type": "string"
},
"enable": {
"type": "boolean"
},
"enable_tls": {
"type": "boolean"
},
"token": {
"description": "Deprecated, use IAM",
"type": "string"
}
}
},
"service": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"token": {
"type": "string"
},
"url": {
"type": "string"
}
}
},
"sessions": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"ip_ignorelist": {
"type": "array",
"items": {
"type": "string"
}
},
"max_bitrate_mbit": {
"type": "integer",
"format": "uint64"
},
"max_sessions": {
"type": "integer",
"format": "uint64"
},
"persist": {
"type": "boolean"
},
"persist_interval_sec": {
"type": "integer",
"format": "int"
},
"session_log_buffer_sec": {
"type": "integer",
"format": "int"
},
"session_log_path_pattern": {
"type": "string"
},
"session_timeout_sec": {
"type": "integer",
"format": "int"
}
}
},
"srt": {
"type": "object",
"properties": {
"address": {
"type": "string"
},
"enable": {
"type": "boolean"
},
"log": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"topics": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"passphrase": {
"type": "string"
},
"token": {
"description": "Deprecated, use IAM",
"type": "string"
}
}
},
"storage": {
"type": "object",
"properties": {
"cors": {
"type": "object",
"properties": {
"origins": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"disk": {
"type": "object",
"properties": {
"cache": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"max_file_size_mbytes": {
"type": "integer",
"format": "uint64"
},
"max_size_mbytes": {
"type": "integer",
"format": "uint64"
},
"ttl_seconds": {
"type": "integer",
"format": "int64"
},
"types": {
"type": "object",
"properties": {
"allow": {
"type": "array",
"items": {
"type": "string"
}
},
"block": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
},
"dir": {
"type": "string"
},
"max_size_mbytes": {
"type": "integer",
"format": "int64"
}
}
},
"memory": {
"type": "object",
"properties": {
"auth": {
"description": "Deprecated, use IAM",
"type": "object",
"properties": {
"enable": {
"description": "Deprecated, use IAM",
"type": "boolean"
},
"password": {
"description": "Deprecated, use IAM",
"type": "string"
},
"username": {
"description": "Deprecated, use IAM",
"type": "string"
}
}
},
"max_size_mbytes": {
"type": "integer",
"format": "int64"
},
"purge": {
"type": "boolean"
}
}
},
"mimetypes_file": {
"type": "string"
},
"s3": {
"type": "array",
"items": {
"$ref": "#/definitions/value.S3Storage"
}
}
}
},
"tls": {
"type": "object",
"properties": {
"address": {
"type": "string"
},
"auto": {
"type": "boolean"
},
"cert_file": {
"type": "string"
},
"email": {
"type": "string"
},
"enable": {
"type": "boolean"
},
"key_file": {
"type": "string"
}
}
},
"update_check": {
"type": "boolean"
},
"version": {
"type": "integer",
"format": "int64"
}
}
},
"identity.Auth0Tenant": {
"type": "object",
"properties": {
@@ -1162,6 +1778,80 @@ const docTemplateClusterAPI = `{
}
}
}
},
"value.Auth0Tenant": {
"type": "object",
"properties": {
"audience": {
"type": "string"
},
"clientid": {
"type": "string"
},
"domain": {
"type": "string"
},
"users": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"value.S3Storage": {
"type": "object",
"properties": {
"access_key_id": {
"type": "string"
},
"auth": {
"description": "Deprecated, use IAM",
"allOf": [
{
"$ref": "#/definitions/value.S3StorageAuth"
}
]
},
"bucket": {
"type": "string"
},
"endpoint": {
"type": "string"
},
"mountpoint": {
"type": "string"
},
"name": {
"type": "string"
},
"region": {
"type": "string"
},
"secret_access_key": {
"type": "string"
},
"use_ssl": {
"type": "boolean"
}
}
},
"value.S3StorageAuth": {
"type": "object",
"properties": {
"enable": {
"description": "Deprecated, use IAM",
"type": "boolean"
},
"password": {
"description": "Deprecated, use IAM",
"type": "string"
},
"username": {
"description": "Deprecated, use IAM",
"type": "string"
}
}
}
}
}`

View File

@@ -33,11 +33,26 @@
"schema": {
"type": "string"
}
},
"500": {
"description": "Internal Server Error",
}
}
}
},
"/v1/core/config": {
"get": {
"description": "Core config of this node",
"produces": [
"application/json"
],
"tags": [
"v1.0.0"
],
"summary": "Core config",
"operationId": "cluster-1-core-config",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/cluster.Error"
"$ref": "#/definitions/config.Config"
}
}
}
@@ -348,6 +363,12 @@
"$ref": "#/definitions/cluster.Error"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/cluster.Error"
}
},
"508": {
"description": "Loop Detected",
"schema": {
@@ -446,6 +467,12 @@
"$ref": "#/definitions/cluster.Error"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/cluster.Error"
}
},
"508": {
"description": "Loop Detected",
"schema": {
@@ -1068,6 +1095,595 @@
}
}
},
"config.Config": {
"type": "object",
"properties": {
"address": {
"type": "string"
},
"api": {
"type": "object",
"properties": {
"access": {
"type": "object",
"properties": {
"http": {
"type": "object",
"properties": {
"allow": {
"type": "array",
"items": {
"type": "string"
}
},
"block": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"https": {
"type": "object",
"properties": {
"allow": {
"type": "array",
"items": {
"type": "string"
}
},
"block": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
},
"auth": {
"type": "object",
"properties": {
"auth0": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"tenants": {
"type": "array",
"items": {
"$ref": "#/definitions/value.Auth0Tenant"
}
}
}
},
"disable_localhost": {
"type": "boolean"
},
"enable": {
"type": "boolean"
},
"jwt": {
"type": "object",
"properties": {
"secret": {
"type": "string"
}
}
},
"password": {
"type": "string"
},
"username": {
"type": "string"
}
}
},
"read_only": {
"type": "boolean"
}
}
},
"cluster": {
"type": "object",
"properties": {
"address": {
"description": "ip:port",
"type": "string"
},
"debug": {
"type": "boolean"
},
"emergency_leader_timeout_sec": {
"description": "seconds",
"type": "integer",
"format": "int64"
},
"enable": {
"type": "boolean"
},
"node_recover_timeout_sec": {
"description": "seconds",
"type": "integer",
"format": "int64"
},
"peers": {
"type": "array",
"items": {
"type": "string"
}
},
"sync_interval_sec": {
"description": "seconds",
"type": "integer",
"format": "int64"
}
}
},
"created_at": {
"description": "When this config has been persisted",
"type": "string"
},
"db": {
"type": "object",
"properties": {
"dir": {
"type": "string"
}
}
},
"debug": {
"type": "object",
"properties": {
"auto_max_procs": {
"type": "boolean"
},
"force_gc": {
"description": "deprecated, use MemoryLimit instead",
"type": "integer",
"format": "int"
},
"memory_limit_mbytes": {
"type": "integer",
"format": "int64"
},
"profiling": {
"type": "boolean"
}
}
},
"ffmpeg": {
"type": "object",
"properties": {
"access": {
"type": "object",
"properties": {
"input": {
"type": "object",
"properties": {
"allow": {
"type": "array",
"items": {
"type": "string"
}
},
"block": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"output": {
"type": "object",
"properties": {
"allow": {
"type": "array",
"items": {
"type": "string"
}
},
"block": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
},
"binary": {
"type": "string"
},
"log": {
"type": "object",
"properties": {
"max_history": {
"type": "integer",
"format": "int"
},
"max_lines": {
"type": "integer",
"format": "int"
},
"max_minimal_history": {
"type": "integer",
"format": "int"
}
}
},
"max_processes": {
"type": "integer",
"format": "int64"
}
}
},
"host": {
"type": "object",
"properties": {
"auto": {
"type": "boolean"
},
"name": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"id": {
"type": "string"
},
"log": {
"type": "object",
"properties": {
"level": {
"type": "string",
"enum": [
"debug",
"info",
"warn",
"error",
"silent"
]
},
"max_lines": {
"type": "integer",
"format": "int"
},
"topics": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"metrics": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"enable_prometheus": {
"type": "boolean"
},
"interval_sec": {
"description": "seconds",
"type": "integer",
"format": "int64"
},
"range_sec": {
"description": "seconds",
"type": "integer",
"format": "int64"
}
}
},
"name": {
"type": "string"
},
"playout": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"max_port": {
"type": "integer",
"format": "int"
},
"min_port": {
"type": "integer",
"format": "int"
}
}
},
"resources": {
"type": "object",
"properties": {
"max_cpu_usage": {
"description": "percent 0-100",
"type": "number"
},
"max_memory_usage": {
"description": "percent 0-100",
"type": "number"
}
}
},
"router": {
"type": "object",
"properties": {
"blocked_prefixes": {
"type": "array",
"items": {
"type": "string"
}
},
"routes": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"ui_path": {
"type": "string"
}
}
},
"rtmp": {
"type": "object",
"properties": {
"address": {
"type": "string"
},
"address_tls": {
"type": "string"
},
"app": {
"type": "string"
},
"enable": {
"type": "boolean"
},
"enable_tls": {
"type": "boolean"
},
"token": {
"description": "Deprecated, use IAM",
"type": "string"
}
}
},
"service": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"token": {
"type": "string"
},
"url": {
"type": "string"
}
}
},
"sessions": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"ip_ignorelist": {
"type": "array",
"items": {
"type": "string"
}
},
"max_bitrate_mbit": {
"type": "integer",
"format": "uint64"
},
"max_sessions": {
"type": "integer",
"format": "uint64"
},
"persist": {
"type": "boolean"
},
"persist_interval_sec": {
"type": "integer",
"format": "int"
},
"session_log_buffer_sec": {
"type": "integer",
"format": "int"
},
"session_log_path_pattern": {
"type": "string"
},
"session_timeout_sec": {
"type": "integer",
"format": "int"
}
}
},
"srt": {
"type": "object",
"properties": {
"address": {
"type": "string"
},
"enable": {
"type": "boolean"
},
"log": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"topics": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"passphrase": {
"type": "string"
},
"token": {
"description": "Deprecated, use IAM",
"type": "string"
}
}
},
"storage": {
"type": "object",
"properties": {
"cors": {
"type": "object",
"properties": {
"origins": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"disk": {
"type": "object",
"properties": {
"cache": {
"type": "object",
"properties": {
"enable": {
"type": "boolean"
},
"max_file_size_mbytes": {
"type": "integer",
"format": "uint64"
},
"max_size_mbytes": {
"type": "integer",
"format": "uint64"
},
"ttl_seconds": {
"type": "integer",
"format": "int64"
},
"types": {
"type": "object",
"properties": {
"allow": {
"type": "array",
"items": {
"type": "string"
}
},
"block": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
},
"dir": {
"type": "string"
},
"max_size_mbytes": {
"type": "integer",
"format": "int64"
}
}
},
"memory": {
"type": "object",
"properties": {
"auth": {
"description": "Deprecated, use IAM",
"type": "object",
"properties": {
"enable": {
"description": "Deprecated, use IAM",
"type": "boolean"
},
"password": {
"description": "Deprecated, use IAM",
"type": "string"
},
"username": {
"description": "Deprecated, use IAM",
"type": "string"
}
}
},
"max_size_mbytes": {
"type": "integer",
"format": "int64"
},
"purge": {
"type": "boolean"
}
}
},
"mimetypes_file": {
"type": "string"
},
"s3": {
"type": "array",
"items": {
"$ref": "#/definitions/value.S3Storage"
}
}
}
},
"tls": {
"type": "object",
"properties": {
"address": {
"type": "string"
},
"auto": {
"type": "boolean"
},
"cert_file": {
"type": "string"
},
"email": {
"type": "string"
},
"enable": {
"type": "boolean"
},
"key_file": {
"type": "string"
}
}
},
"update_check": {
"type": "boolean"
},
"version": {
"type": "integer",
"format": "int64"
}
}
},
"identity.Auth0Tenant": {
"type": "object",
"properties": {
@@ -1154,6 +1770,80 @@
}
}
}
},
"value.Auth0Tenant": {
"type": "object",
"properties": {
"audience": {
"type": "string"
},
"clientid": {
"type": "string"
},
"domain": {
"type": "string"
},
"users": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"value.S3Storage": {
"type": "object",
"properties": {
"access_key_id": {
"type": "string"
},
"auth": {
"description": "Deprecated, use IAM",
"allOf": [
{
"$ref": "#/definitions/value.S3StorageAuth"
}
]
},
"bucket": {
"type": "string"
},
"endpoint": {
"type": "string"
},
"mountpoint": {
"type": "string"
},
"name": {
"type": "string"
},
"region": {
"type": "string"
},
"secret_access_key": {
"type": "string"
},
"use_ssl": {
"type": "boolean"
}
}
},
"value.S3StorageAuth": {
"type": "object",
"properties": {
"enable": {
"description": "Deprecated, use IAM",
"type": "boolean"
},
"password": {
"description": "Deprecated, use IAM",
"type": "string"
},
"username": {
"description": "Deprecated, use IAM",
"type": "string"
}
}
}
}
}

View File

@@ -158,6 +158,402 @@ definitions:
message:
type: string
type: object
config.Config:
properties:
address:
type: string
api:
properties:
access:
properties:
http:
properties:
allow:
items:
type: string
type: array
block:
items:
type: string
type: array
type: object
https:
properties:
allow:
items:
type: string
type: array
block:
items:
type: string
type: array
type: object
type: object
auth:
properties:
auth0:
properties:
enable:
type: boolean
tenants:
items:
$ref: '#/definitions/value.Auth0Tenant'
type: array
type: object
disable_localhost:
type: boolean
enable:
type: boolean
jwt:
properties:
secret:
type: string
type: object
password:
type: string
username:
type: string
type: object
read_only:
type: boolean
type: object
cluster:
properties:
address:
description: ip:port
type: string
debug:
type: boolean
emergency_leader_timeout_sec:
description: seconds
format: int64
type: integer
enable:
type: boolean
node_recover_timeout_sec:
description: seconds
format: int64
type: integer
peers:
items:
type: string
type: array
sync_interval_sec:
description: seconds
format: int64
type: integer
type: object
created_at:
description: When this config has been persisted
type: string
db:
properties:
dir:
type: string
type: object
debug:
properties:
auto_max_procs:
type: boolean
force_gc:
description: deprecated, use MemoryLimit instead
format: int
type: integer
memory_limit_mbytes:
format: int64
type: integer
profiling:
type: boolean
type: object
ffmpeg:
properties:
access:
properties:
input:
properties:
allow:
items:
type: string
type: array
block:
items:
type: string
type: array
type: object
output:
properties:
allow:
items:
type: string
type: array
block:
items:
type: string
type: array
type: object
type: object
binary:
type: string
log:
properties:
max_history:
format: int
type: integer
max_lines:
format: int
type: integer
max_minimal_history:
format: int
type: integer
type: object
max_processes:
format: int64
type: integer
type: object
host:
properties:
auto:
type: boolean
name:
items:
type: string
type: array
type: object
id:
type: string
log:
properties:
level:
enum:
- debug
- info
- warn
- error
- silent
type: string
max_lines:
format: int
type: integer
topics:
items:
type: string
type: array
type: object
metrics:
properties:
enable:
type: boolean
enable_prometheus:
type: boolean
interval_sec:
description: seconds
format: int64
type: integer
range_sec:
description: seconds
format: int64
type: integer
type: object
name:
type: string
playout:
properties:
enable:
type: boolean
max_port:
format: int
type: integer
min_port:
format: int
type: integer
type: object
resources:
properties:
max_cpu_usage:
description: percent 0-100
type: number
max_memory_usage:
description: percent 0-100
type: number
type: object
router:
properties:
blocked_prefixes:
items:
type: string
type: array
routes:
additionalProperties:
type: string
type: object
ui_path:
type: string
type: object
rtmp:
properties:
address:
type: string
address_tls:
type: string
app:
type: string
enable:
type: boolean
enable_tls:
type: boolean
token:
description: Deprecated, use IAM
type: string
type: object
service:
properties:
enable:
type: boolean
token:
type: string
url:
type: string
type: object
sessions:
properties:
enable:
type: boolean
ip_ignorelist:
items:
type: string
type: array
max_bitrate_mbit:
format: uint64
type: integer
max_sessions:
format: uint64
type: integer
persist:
type: boolean
persist_interval_sec:
format: int
type: integer
session_log_buffer_sec:
format: int
type: integer
session_log_path_pattern:
type: string
session_timeout_sec:
format: int
type: integer
type: object
srt:
properties:
address:
type: string
enable:
type: boolean
log:
properties:
enable:
type: boolean
topics:
items:
type: string
type: array
type: object
passphrase:
type: string
token:
description: Deprecated, use IAM
type: string
type: object
storage:
properties:
cors:
properties:
origins:
items:
type: string
type: array
type: object
disk:
properties:
cache:
properties:
enable:
type: boolean
max_file_size_mbytes:
format: uint64
type: integer
max_size_mbytes:
format: uint64
type: integer
ttl_seconds:
format: int64
type: integer
types:
properties:
allow:
items:
type: string
type: array
block:
items:
type: string
type: array
type: object
type: object
dir:
type: string
max_size_mbytes:
format: int64
type: integer
type: object
memory:
properties:
auth:
description: Deprecated, use IAM
properties:
enable:
description: Deprecated, use IAM
type: boolean
password:
description: Deprecated, use IAM
type: string
username:
description: Deprecated, use IAM
type: string
type: object
max_size_mbytes:
format: int64
type: integer
purge:
type: boolean
type: object
mimetypes_file:
type: string
s3:
items:
$ref: '#/definitions/value.S3Storage'
type: array
type: object
tls:
properties:
address:
type: string
auto:
type: boolean
cert_file:
type: string
email:
type: string
enable:
type: boolean
key_file:
type: string
type: object
update_check:
type: boolean
version:
format: int64
type: integer
type: object
identity.Auth0Tenant:
properties:
audience:
@@ -215,6 +611,54 @@ definitions:
type: string
type: array
type: object
value.Auth0Tenant:
properties:
audience:
type: string
clientid:
type: string
domain:
type: string
users:
items:
type: string
type: array
type: object
value.S3Storage:
properties:
access_key_id:
type: string
auth:
allOf:
- $ref: '#/definitions/value.S3StorageAuth'
description: Deprecated, use IAM
bucket:
type: string
endpoint:
type: string
mountpoint:
type: string
name:
type: string
region:
type: string
secret_access_key:
type: string
use_ssl:
type: boolean
type: object
value.S3StorageAuth:
properties:
enable:
description: Deprecated, use IAM
type: boolean
password:
description: Deprecated, use IAM
type: string
username:
description: Deprecated, use IAM
type: string
type: object
info:
contact:
email: hello@datarhei.com
@@ -238,13 +682,23 @@ paths:
description: OK
schema:
type: string
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/cluster.Error'
summary: Core API address and login
tags:
- v1.0.0
/v1/core/config:
get:
description: Core config of this node
operationId: cluster-1-core-config
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/config.Config'
summary: Core config
tags:
- v1.0.0
/v1/iam/user:
post:
consumes:
@@ -448,6 +902,10 @@ paths:
description: Not Found
schema:
$ref: '#/definitions/cluster.Error'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/cluster.Error'
"508":
description: Loop Detected
schema:
@@ -513,6 +971,10 @@ paths:
description: Not Found
schema:
$ref: '#/definitions/cluster.Error'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/cluster.Error'
"508":
description: Loop Detected
schema: