mirror of
https://github.com/sablierapp/sablier.git
synced 2025-12-21 13:23:03 +01:00
@@ -11,11 +11,12 @@ testData:
|
||||
names: whoami,nginx # Comma separated names of containers/services/deployments etc.
|
||||
sessionDuration: 1m # The session duration after which containers/services/deployments instances are shutdown
|
||||
# You can only use one strategy at a time
|
||||
# To do so, only declare `dynamic` or `blockin`
|
||||
# To do so, only declare `dynamic` or `blocking`
|
||||
|
||||
# Dynamic strategy, provides the waiting webui
|
||||
dynamic:
|
||||
displayName: My Title # (Optional) Defaults to the middleware name
|
||||
showDetails: true # (Optional) Set to true or false to show details specifcally for this middleware, unset to use Sablier server defaults
|
||||
theme: hacker-terminal # (Optional) The theme to use
|
||||
refreshFrequency: 5s # (Optional) The loading page refresh frequency
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ type RenderOptionsInstanceState struct {
|
||||
|
||||
type RenderOptions struct {
|
||||
DisplayName string
|
||||
ShowDetails bool
|
||||
InstanceStates []RenderOptionsInstanceState
|
||||
SessionDuration time.Duration
|
||||
RefreshFrequency time.Duration
|
||||
@@ -61,9 +62,15 @@ func Render(options RenderOptions, writer io.Writer) error {
|
||||
return err
|
||||
}
|
||||
|
||||
instanceStates := []RenderOptionsInstanceState{}
|
||||
|
||||
if options.ShowDetails {
|
||||
instanceStates = options.InstanceStates
|
||||
}
|
||||
|
||||
return tpl.Execute(writer, TemplateValues{
|
||||
DisplayName: options.DisplayName,
|
||||
InstanceStates: options.InstanceStates,
|
||||
InstanceStates: instanceStates,
|
||||
SessionDuration: humanizeDuration(options.SessionDuration),
|
||||
RefreshFrequency: fmt.Sprintf("%d", int64(options.RefreshFrequency.Seconds())),
|
||||
Version: options.Version,
|
||||
|
||||
@@ -242,6 +242,38 @@ func TestRenderContent(t *testing.T) {
|
||||
},
|
||||
wantContent: "<meta http-equiv=\"refresh\" content=\"10\" />",
|
||||
},
|
||||
{
|
||||
name: "details is rendered",
|
||||
args: args{
|
||||
options: RenderOptions{
|
||||
DisplayName: "Test",
|
||||
ShowDetails: true,
|
||||
InstanceStates: instanceStates,
|
||||
Theme: "ghost",
|
||||
SessionDuration: 10 * time.Minute,
|
||||
RefreshFrequency: 10 * time.Second,
|
||||
CustomThemes: nil,
|
||||
Version: "v0.0.0",
|
||||
},
|
||||
},
|
||||
wantContent: "started (4/4)",
|
||||
},
|
||||
{
|
||||
name: "details is not rendered",
|
||||
args: args{
|
||||
options: RenderOptions{
|
||||
DisplayName: "Test",
|
||||
ShowDetails: false,
|
||||
InstanceStates: instanceStates,
|
||||
Theme: "ghost",
|
||||
SessionDuration: 10 * time.Minute,
|
||||
RefreshFrequency: 10 * time.Second,
|
||||
CustomThemes: nil,
|
||||
Version: "v0.0.0",
|
||||
},
|
||||
},
|
||||
wantContent: "<table></table>",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
type DynamicRequest struct {
|
||||
Names []string `form:"names" binding:"required"`
|
||||
ShowDetails bool `form:"show_details"`
|
||||
DisplayName string `form:"display_name"`
|
||||
Theme string `form:"theme"`
|
||||
SessionDuration time.Duration `form:"session_duration" binding:"required"`
|
||||
|
||||
@@ -49,6 +49,7 @@ func NewServeStrategy(sessionsManager sessions.Manager, conf config.Strategy) *S
|
||||
func (s *ServeStrategy) ServeDynamic(c *gin.Context) {
|
||||
request := models.DynamicRequest{
|
||||
Theme: s.StrategyConfig.Dynamic.DefaultTheme,
|
||||
ShowDetails: s.StrategyConfig.Dynamic.ShowDetailsByDefault,
|
||||
RefreshFrequency: s.StrategyConfig.Dynamic.DefaultRefreshFrequency,
|
||||
}
|
||||
|
||||
@@ -67,6 +68,7 @@ func (s *ServeStrategy) ServeDynamic(c *gin.Context) {
|
||||
|
||||
renderOptions := pages.RenderOptions{
|
||||
DisplayName: request.DisplayName,
|
||||
ShowDetails: request.ShowDetails,
|
||||
SessionDuration: request.SessionDuration,
|
||||
Theme: request.Theme,
|
||||
CustomThemes: s.customThemesFS,
|
||||
|
||||
@@ -66,6 +66,8 @@ It provides an integrations with multiple reverse proxies and different loading
|
||||
viper.BindPFlag("strategy.dynamic.custom-themes-path", startCmd.Flags().Lookup("strategy.dynamic.custom-themes-path"))
|
||||
startCmd.Flags().StringVar(&conf.Strategy.Dynamic.DefaultTheme, "strategy.dynamic.default-theme", "hacker-terminal", "Default theme used for dynamic strategy")
|
||||
viper.BindPFlag("strategy.dynamic.default-theme", startCmd.Flags().Lookup("strategy.dynamic.default-theme"))
|
||||
startCmd.Flags().BoolVar(&conf.Strategy.Dynamic.ShowDetailsByDefault, "strategy.dynamic.show-details-by-default", true, "Show the loading instances details by default")
|
||||
viper.BindPFlag("strategy.dynamic.show-details-by-default", startCmd.Flags().Lookup("strategy.dynamic.show-details-by-default"))
|
||||
startCmd.Flags().DurationVar(&conf.Strategy.Dynamic.DefaultRefreshFrequency, "strategy.dynamic.default-refresh-frequency", 5*time.Second, "Default refresh frequency in the HTML page for dynamic strategy")
|
||||
viper.BindPFlag("strategy.dynamic.default-refresh-frequency", startCmd.Flags().Lookup("strategy.dynamic.default-refresh-frequency"))
|
||||
startCmd.Flags().DurationVar(&conf.Strategy.Blocking.DefaultTimeout, "strategy.blocking.default-timeout", 1*time.Minute, "Default timeout used for blocking strategy")
|
||||
|
||||
@@ -106,6 +106,8 @@ func TestPrecedence(t *testing.T) {
|
||||
"--sessions.expiration-interval", "3h",
|
||||
"--logging.level", "info",
|
||||
"--strategy.dynamic.custom-themes-path", "/tmp/cli/themes",
|
||||
// Must use `=` see https://github.com/spf13/cobra/issues/613
|
||||
"--strategy.dynamic.show-details-by-default=false",
|
||||
"--strategy.dynamic.default-theme", "cli",
|
||||
"--strategy.dynamic.default-refresh-frequency", "3h",
|
||||
"--strategy.blocking.default-timeout", "3h",
|
||||
|
||||
1
cmd/testdata/config.env
vendored
1
cmd/testdata/config.env
vendored
@@ -6,6 +6,7 @@ SESSIONS_DEFAULT_DURATION=2h
|
||||
SESSIONS_EXPIRATION_INTERVAL=2h
|
||||
LOGGING_LEVEL=debug
|
||||
STRATEGY_DYNAMIC_CUSTOM_THEMES_PATH=/tmp/envvar/themes
|
||||
STRATEGY_SHOW_DETAILS_BY_DEFAULT=false
|
||||
STRATEGY_DYNAMIC_DEFAULT_THEME=envvar
|
||||
STRATEGY_DYNAMIC_DEFAULT_REFRESH_FREQUENCY=2h
|
||||
STRATEGY_BLOCKING_DEFAULT_TIMEOUT=2h
|
||||
1
cmd/testdata/config.yml
vendored
1
cmd/testdata/config.yml
vendored
@@ -13,6 +13,7 @@ logging:
|
||||
strategy:
|
||||
dynamic:
|
||||
custom-themes-path: /tmp/configfile/themes
|
||||
show-details-by-default: false
|
||||
default-theme: configfile
|
||||
default-refresh-frequency: 1h
|
||||
blocking:
|
||||
|
||||
1
cmd/testdata/config_cli_wanted.json
vendored
1
cmd/testdata/config_cli_wanted.json
vendored
@@ -19,6 +19,7 @@
|
||||
"Strategy": {
|
||||
"Dynamic": {
|
||||
"CustomThemesPath": "/tmp/cli/themes",
|
||||
"ShowDetailsByDefault": false,
|
||||
"DefaultTheme": "cli",
|
||||
"DefaultRefreshFrequency": 10800000000000
|
||||
},
|
||||
|
||||
1
cmd/testdata/config_env_wanted.json
vendored
1
cmd/testdata/config_env_wanted.json
vendored
@@ -19,6 +19,7 @@
|
||||
"Strategy": {
|
||||
"Dynamic": {
|
||||
"CustomThemesPath": "/tmp/envvar/themes",
|
||||
"ShowDetailsByDefault": false,
|
||||
"DefaultTheme": "envvar",
|
||||
"DefaultRefreshFrequency": 7200000000000
|
||||
},
|
||||
|
||||
1
cmd/testdata/config_yaml_wanted.json
vendored
1
cmd/testdata/config_yaml_wanted.json
vendored
@@ -19,6 +19,7 @@
|
||||
"Strategy": {
|
||||
"Dynamic": {
|
||||
"CustomThemesPath": "/tmp/configfile/themes",
|
||||
"ShowDetailsByDefault": false,
|
||||
"DefaultTheme": "configfile",
|
||||
"DefaultRefreshFrequency": 3600000000000
|
||||
},
|
||||
|
||||
@@ -4,6 +4,7 @@ import "time"
|
||||
|
||||
type DynamicStrategy struct {
|
||||
CustomThemesPath string `mapstructure:"CUSTOM_THEMES_PATH" yaml:"customThemesPath"`
|
||||
ShowDetailsByDefault bool `mapstructure:"SHOW_DETAILS_BY_DEFAULT" yaml:"showDetailsByDefault"`
|
||||
DefaultTheme string `mapstructure:"DEFAULT_THEME" yaml:"defaultTheme" default:"hacker-terminal"`
|
||||
DefaultRefreshFrequency time.Duration `mapstructure:"DEFAULT_REFRESH_FREQUENCY" yaml:"defaultRefreshFrequency" default:"5s"`
|
||||
}
|
||||
@@ -27,6 +28,7 @@ func NewStrategyConfig() Strategy {
|
||||
func newDynamicStrategy() DynamicStrategy {
|
||||
return DynamicStrategy{
|
||||
DefaultTheme: "hacker-terminal",
|
||||
ShowDetailsByDefault: true,
|
||||
DefaultRefreshFrequency: 5 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,14 @@ package traefik
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type DynamicConfiguration struct {
|
||||
DisplayName string `yaml:"displayname"`
|
||||
ShowDetails *bool `yaml:"showDetails"`
|
||||
Theme string `yaml:"theme"`
|
||||
RefreshFrequency string `yaml:"refreshFrequency"`
|
||||
}
|
||||
@@ -110,6 +112,10 @@ func (c *Config) buildDynamicRequest(middlewareName string) (*http.Request, erro
|
||||
q.Add("refresh_frequency", c.Dynamic.RefreshFrequency)
|
||||
}
|
||||
|
||||
if c.Dynamic.ShowDetails != nil {
|
||||
q.Add("show_details", strconv.FormatBool(*c.Dynamic.ShowDetails))
|
||||
}
|
||||
|
||||
request.URL.RawQuery = q.Encode()
|
||||
|
||||
return request, nil
|
||||
|
||||
@@ -9,6 +9,9 @@ import (
|
||||
"github.com/acouvreur/sablier/plugins/traefik"
|
||||
)
|
||||
|
||||
var fals bool = false
|
||||
var tru bool = true
|
||||
|
||||
func TestConfig_BuildRequest(t *testing.T) {
|
||||
type fields struct {
|
||||
SablierURL string
|
||||
@@ -98,6 +101,48 @@ func TestConfig_BuildRequest(t *testing.T) {
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "dynamic session with show details to true",
|
||||
fields: fields{
|
||||
SablierURL: "http://sablier:10000",
|
||||
Names: "nginx , apache",
|
||||
SessionDuration: "1m",
|
||||
Dynamic: &traefik.DynamicConfiguration{
|
||||
ShowDetails: &tru,
|
||||
RefreshFrequency: "1m",
|
||||
},
|
||||
},
|
||||
want: createRequest("GET", "http://sablier:10000/api/strategies/dynamic?display_name=sablier-middleware&names=nginx&names=apache&refresh_frequency=1m&session_duration=1m&show_details=true", nil),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "dynamic session with show details to false",
|
||||
fields: fields{
|
||||
SablierURL: "http://sablier:10000",
|
||||
Names: "nginx , apache",
|
||||
SessionDuration: "1m",
|
||||
Dynamic: &traefik.DynamicConfiguration{
|
||||
ShowDetails: &fals,
|
||||
RefreshFrequency: "1m",
|
||||
},
|
||||
},
|
||||
want: createRequest("GET", "http://sablier:10000/api/strategies/dynamic?display_name=sablier-middleware&names=nginx&names=apache&refresh_frequency=1m&session_duration=1m&show_details=false", nil),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "dynamic session without show details set",
|
||||
fields: fields{
|
||||
SablierURL: "http://sablier:10000",
|
||||
Names: "nginx , apache",
|
||||
SessionDuration: "1m",
|
||||
Dynamic: &traefik.DynamicConfiguration{
|
||||
ShowDetails: nil,
|
||||
RefreshFrequency: "1m",
|
||||
},
|
||||
},
|
||||
want: createRequest("GET", "http://sablier:10000/api/strategies/dynamic?display_name=sablier-middleware&names=nginx&names=apache&refresh_frequency=1m&session_duration=1m", nil),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "blocking session with default values",
|
||||
fields: fields{
|
||||
|
||||
Reference in New Issue
Block a user