diff --git a/README.md b/README.md index e3ce5606..95de2f46 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,12 @@ Additionally check out the sparrow [configuration](#configuration) variants. ## Usage -Use `sparrow run` to execute the instance using the binary. +Use `sparrow run` to execute the instance using the binary. A `sparrowName` (a valid DNS name) is required to be passed, else +the sparrow will not start: + +```sh +sparrow run --sparrowName sparrow.telekom.de +``` ### Container Image diff --git a/cmd/run.go b/cmd/run.go index 8a185959..026465c8 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -40,6 +40,7 @@ const ( func NewCmdRun() *cobra.Command { flagMapping := config.RunFlagsNameMapping{ ApiAddress: "apiAddress", + SparrowName: "sparrowName", LoaderType: "loaderType", LoaderInterval: "loaderInterval", LoaderHttpUrl: "loaderHttpUrl", @@ -59,6 +60,7 @@ func NewCmdRun() *cobra.Command { } cmd.PersistentFlags().String(flagMapping.ApiAddress, ":8080", "api: The address the server is listening on") + cmd.PersistentFlags().String(flagMapping.SparrowName, "sparrow", "The DNS name of the sparrow") cmd.PersistentFlags().StringP(flagMapping.LoaderType, "l", "http", "defines the loader type that will load the checks configuration during the runtime. The fallback is the fileLoader") cmd.PersistentFlags().Int(flagMapping.LoaderInterval, defaultLoaderInterval, "defines the interval the loader reloads the configuration in seconds") @@ -71,6 +73,7 @@ func NewCmdRun() *cobra.Command { cmd.PersistentFlags().String(flagMapping.TargetManagerConfig, "tmconfig.yaml", "target manager: The path to the file to read the target manager config from") _ = viper.BindPFlag(flagMapping.ApiAddress, cmd.PersistentFlags().Lookup(flagMapping.ApiAddress)) + _ = viper.BindPFlag(flagMapping.SparrowName, cmd.PersistentFlags().Lookup(flagMapping.SparrowName)) _ = viper.BindPFlag(flagMapping.LoaderType, cmd.PersistentFlags().Lookup(flagMapping.LoaderType)) _ = viper.BindPFlag(flagMapping.LoaderInterval, cmd.PersistentFlags().Lookup(flagMapping.LoaderInterval)) _ = viper.BindPFlag(flagMapping.LoaderHttpUrl, cmd.PersistentFlags().Lookup(flagMapping.LoaderHttpUrl)) @@ -94,6 +97,7 @@ func run(fm *config.RunFlagsNameMapping) func(cmd *cobra.Command, args []string) cfg.SetTargetManagerConfig(config.NewTargetManagerConfig(viper.GetString(fm.TargetManagerConfig))) cfg.SetApiAddress(viper.GetString(fm.ApiAddress)) + cfg.SetSparrowName(viper.GetString(fm.SparrowName)) cfg.SetLoaderType(viper.GetString(fm.LoaderType)) cfg.SetLoaderInterval(viper.GetInt(fm.LoaderInterval)) diff --git a/docs/sparrow_run.md b/docs/sparrow_run.md index 80b12f51..6fb373fa 100644 --- a/docs/sparrow_run.md +++ b/docs/sparrow_run.md @@ -23,6 +23,7 @@ sparrow run [flags] --loaderHttpUrl string http loader: The url where to get the remote configuration --loaderInterval int defines the interval the loader reloads the configuration in seconds (default 300) -l, --loaderType string defines the loader type that will load the checks configuration during the runtime. The fallback is the fileLoader (default "http") + --sparrowName string The DNS name of the sparrow (default "sparrow") --tmconfig string target manager: The path to the file to read the target manager config from (default "tmconfig.yaml") ``` diff --git a/pkg/config/config.go b/pkg/config/config.go index 4f57b84b..547ffc61 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -41,6 +41,9 @@ type TargetManagerConfig struct { } type Config struct { + // SparrowName is the DNS name of the sparrow + SparrowName string + // Checks is a map of configurations for the checks Checks map[string]any Loader LoaderConfig Api ApiConfig @@ -101,6 +104,11 @@ func (c *Config) SetApiAddress(address string) { c.Api.ListeningAddress = address } +// SetSparrowName sets the DNS name of the sparrow +func (c *Config) SetSparrowName(name string) { + c.SparrowName = name +} + // SetLoaderType sets the loader type func (c *Config) SetLoaderType(loaderType string) { c.Loader.Type = loaderType diff --git a/pkg/config/flags.go b/pkg/config/flags.go index 098adc1b..2509c186 100644 --- a/pkg/config/flags.go +++ b/pkg/config/flags.go @@ -19,7 +19,8 @@ package config type RunFlagsNameMapping struct { - ApiAddress string + ApiAddress string + SparrowName string LoaderType string LoaderInterval string diff --git a/pkg/config/validate.go b/pkg/config/validate.go index 4ed3cc1c..e87b845e 100644 --- a/pkg/config/validate.go +++ b/pkg/config/validate.go @@ -22,6 +22,7 @@ import ( "context" "fmt" "net/url" + "regexp" "github.com/caas-team/sparrow/internal/logger" ) @@ -33,6 +34,12 @@ func (c *Config) Validate(ctx context.Context, fm *RunFlagsNameMapping) error { log := logger.FromContext(ctx) ok := true + + if !isDNSName(c.SparrowName) { + ok = false + log.Error("The name of the sparrow must be DNS compliant", fm.SparrowName, c.SparrowName) + } + switch c.Loader.Type { //nolint:gocritic case "http": if _, err := url.ParseRequestURI(c.Loader.http.url); err != nil { @@ -52,3 +59,9 @@ func (c *Config) Validate(ctx context.Context, fm *RunFlagsNameMapping) error { } return nil } + +// isDNSName checks if the given string is a valid DNS name +func isDNSName(s string) bool { + re := regexp.MustCompile(`^([a-z0-9]([a-z0-9\-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$`) + return re.MatchString(s) +} diff --git a/pkg/config/validate_test.go b/pkg/config/validate_test.go index e5c340fe..451299bf 100644 --- a/pkg/config/validate_test.go +++ b/pkg/config/validate_test.go @@ -115,8 +115,9 @@ func TestConfig_Validate(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { c := &Config{ - Checks: nil, - Loader: tt.fields.Loader, + Checks: nil, + SparrowName: "cool-dns-name.org", + Loader: tt.fields.Loader, } if err := c.Validate(ctx, &RunFlagsNameMapping{}); (err != nil) != tt.wantErr { t.Errorf("Config.Validate() error = %v, wantErr %v", err, tt.wantErr) @@ -124,3 +125,30 @@ func TestConfig_Validate(t *testing.T) { }) } } + +func Test_isDNSName(t *testing.T) { + tests := []struct { + name string + dnsName string + want bool + }{ + {name: "dns name", dnsName: "sparrow.de", want: true}, + {name: "dns name with subdomain", dnsName: "sparrow.test.de", want: true}, + {name: "dns name with subdomain and tld and -", dnsName: "sub-sparrow.test.de", want: true}, + {name: "empty name", dnsName: "", want: false}, + {name: "dns name without tld", dnsName: "sparrow", want: false}, + {name: "name with underscore", dnsName: "test_de", want: false}, + {name: "name with space", dnsName: "test de", want: false}, + {name: "name with special chars", dnsName: "test!de", want: false}, + {name: "name with capitals", dnsName: "tEst.de", want: false}, + {name: "name with empty tld", dnsName: "tEst.de.", want: false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := isDNSName(tt.dnsName); got != tt.want { + t.Errorf("isDNSName() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/sparrow/run.go b/pkg/sparrow/run.go index 41925bb7..4288ae32 100644 --- a/pkg/sparrow/run.go +++ b/pkg/sparrow/run.go @@ -69,7 +69,7 @@ func New(cfg *config.Config) *Sparrow { } // Set the target manager - gm := targets.NewGitlabManager("sparrow-with-cfg-file", cfg.TargetManager) + gm := targets.NewGitlabManager(cfg.SparrowName, cfg.TargetManager) sparrow.targets = gm sparrow.loader = config.NewLoader(cfg, sparrow.cCfgChecks)