diff --git a/Makefile b/Makefile index 67019516..15f1a00d 100644 --- a/Makefile +++ b/Makefile @@ -93,7 +93,7 @@ $(GOBIN)/golangci-lint: verify $(GOBIN)/eget $(GOBIN)/hugo: $(GOBIN)/eget @echo "[*] $@" - "$(GOBIN)/eget" gohugoio/hugo --tag 0.145.0 --upgrade-only --asset=extended_0 --to '$(GOBIN)' + "$(GOBIN)/eget" gohugoio/hugo --tag v0.145.0 --upgrade-only --asset=extended_0 --to '$(GOBIN)' prepare_build: verify download @echo "[*] $@" diff --git a/config/profile.go b/config/profile.go index 14feaa35..e0ab602e 100644 --- a/config/profile.go +++ b/config/profile.go @@ -70,53 +70,58 @@ type Profile struct { config *Config resticVersion *semver.Version Name string - Description string `mapstructure:"description" description:"Describes the profile"` - BaseDir string `mapstructure:"base-dir" description:"Sets the working directory for this profile. The profile will fail when the working directory cannot be changed. Leave empty to use the current directory instead"` - Quiet bool `mapstructure:"quiet" argument:"quiet"` - Verbose int `mapstructure:"verbose" argument:"verbose"` - KeyHint string `mapstructure:"key-hint" argument:"key-hint"` - Repository ConfidentialValue `mapstructure:"repository" argument:"repo"` - RepositoryFile string `mapstructure:"repository-file" argument:"repository-file"` - PasswordFile string `mapstructure:"password-file" argument:"password-file"` - PasswordCommand string `mapstructure:"password-command" argument:"password-command"` - CacheDir string `mapstructure:"cache-dir" argument:"cache-dir"` - CACert string `mapstructure:"cacert" argument:"cacert"` - TLSClientCert string `mapstructure:"tls-client-cert" argument:"tls-client-cert"` - Initialize bool `mapstructure:"initialize" default:"" description:"Initialize the restic repository if missing"` - Inherit string `mapstructure:"inherit" show:"noshow" description:"Name of the profile to inherit all of the settings from"` - Lock string `mapstructure:"lock" description:"Path to the lock file to use with resticprofile locks"` - ForceLock bool `mapstructure:"force-inactive-lock" description:"Allows to lock when the existing lock is considered stale"` - StreamError []StreamErrorSection `mapstructure:"stream-error" description:"Run shell command(s) when a pattern matches the stderr of restic"` - StatusFile string `mapstructure:"status-file" description:"Path to the status file to update with a summary of last restic command result"` - PrometheusSaveToFile string `mapstructure:"prometheus-save-to-file" description:"Path to the prometheus metrics file to update with a summary of the last restic command result"` - PrometheusPush string `mapstructure:"prometheus-push" format:"uri" description:"URL of the prometheus push gateway to send the summary of the last restic command result to"` - PrometheusPushJob string `mapstructure:"prometheus-push-job" description:"Prometheus push gateway job name. $command placeholder is replaced with restic command"` - PrometheusPushFormat string `mapstructure:"prometheus-push-format" default:"text" enum:"text;protobuf" description:"Prometheus push gateway request format"` - PrometheusLabels map[string]string `mapstructure:"prometheus-labels" description:"Additional prometheus labels to set"` - SystemdDropInFiles []string `mapstructure:"systemd-drop-in-files" default:"" description:"Files containing systemd drop-in (override) files - see https://creativeprojects.github.io/resticprofile/schedules/systemd/"` - Environment map[string]ConfidentialValue `mapstructure:"env" description:"Additional environment variables to set in any child process. Inline env variables take precedence over dotenv files declared with \"env-file\"."` - EnvironmentFiles []string `mapstructure:"env-file" description:"Additional dotenv files to load and set as environment in any child process"` - Init *InitSection `mapstructure:"init"` - Backup *BackupSection `mapstructure:"backup"` - Retention *RetentionSection `mapstructure:"retention" command:"forget"` - Check *SectionWithScheduleAndMonitoring `mapstructure:"check"` - Prune *SectionWithScheduleAndMonitoring `mapstructure:"prune"` - Forget *SectionWithScheduleAndMonitoring `mapstructure:"forget"` - Copy *CopySection `mapstructure:"copy"` - OtherSections map[string]*GenericSection `show:",remain"` + Description string `mapstructure:"description" description:"Describes the profile"` + BaseDir string `mapstructure:"base-dir" description:"Sets the working directory for this profile. The profile will fail when the working directory cannot be changed. Leave empty to use the current directory instead"` + Quiet bool `mapstructure:"quiet" argument:"quiet"` + Verbose int `mapstructure:"verbose" argument:"verbose"` + KeyHint string `mapstructure:"key-hint" argument:"key-hint"` + Repository ConfidentialValue `mapstructure:"repository" argument:"repo"` + RepositoryFile string `mapstructure:"repository-file" argument:"repository-file"` + PasswordFile string `mapstructure:"password-file" argument:"password-file"` + PasswordCommand string `mapstructure:"password-command" argument:"password-command"` + CacheDir string `mapstructure:"cache-dir" argument:"cache-dir"` + CACert string `mapstructure:"cacert" argument:"cacert"` + TLSClientCert string `mapstructure:"tls-client-cert" argument:"tls-client-cert"` + Initialize bool `mapstructure:"initialize" default:"" description:"Initialize the restic repository if missing"` + Inherit string `mapstructure:"inherit" show:"noshow" description:"Name of the profile to inherit all of the settings from"` + Lock string `mapstructure:"lock" description:"Path to the lock file to use with resticprofile locks"` + ForceLock bool `mapstructure:"force-inactive-lock" description:"Allows to lock when the existing lock is considered stale"` + StreamError []StreamErrorSection `mapstructure:"stream-error" description:"Run shell command(s) when a pattern matches the stderr of restic"` + StatusFile string `mapstructure:"status-file" description:"Path to the status file to update with a summary of last restic command result"` + PrometheusSaveToFile string `mapstructure:"prometheus-save-to-file" description:"Path to the prometheus metrics file to update with a summary of the last restic command result"` + PrometheusPush string `mapstructure:"prometheus-push" format:"uri" description:"URL of the prometheus push gateway to send the summary of the last restic command result to"` + PrometheusPushJob string `mapstructure:"prometheus-push-job" description:"Prometheus push gateway job name. $command placeholder is replaced with restic command"` + PrometheusPushFormat string `mapstructure:"prometheus-push-format" default:"text" enum:"text;protobuf" description:"Prometheus push gateway request format"` + PrometheusLabels map[string]string `mapstructure:"prometheus-labels" description:"Additional prometheus labels to set"` + SystemdDropInFiles []string `mapstructure:"systemd-drop-in-files" default:"" description:"Files containing systemd drop-in (override) files - see https://creativeprojects.github.io/resticprofile/schedules/systemd/"` + Environment map[string]ConfidentialValue `mapstructure:"env" description:"Additional environment variables to set in any child process. Inline env variables take precedence over dotenv files declared with \"env-file\"."` + EnvironmentFiles []string `mapstructure:"env-file" description:"Additional dotenv files to load and set as environment in any child process"` + Init *InitSection `mapstructure:"init"` + Backup *BackupSection `mapstructure:"backup"` + Retention *RetentionSection `mapstructure:"retention" command:"forget"` + Check *GenericSectionWithSchedule `mapstructure:"check"` + Prune *GenericSectionWithSchedule `mapstructure:"prune"` + Forget *GenericSectionWithSchedule `mapstructure:"forget"` + Copy *CopySection `mapstructure:"copy"` + OtherSections map[string]*GenericSection `show:",remain"` } // GenericSection is used for all restic commands that are not covered in specific section types type GenericSection struct { OtherFlagsSection `mapstructure:",squash"` RunShellCommandsSection `mapstructure:",squash"` + SendMonitoringSections `mapstructure:",squash"` +} + +func (g *GenericSection) setRootPath(p *Profile, rootPath string) { + g.SendMonitoringSections.setRootPath(p, rootPath) } func (g *GenericSection) IsEmpty() bool { return g == nil } // InitSection contains the specific configuration to the 'init' command type InitSection struct { - OtherFlagsSection `mapstructure:",squash"` + GenericSection `mapstructure:",squash"` CopyChunkerParams bool `mapstructure:"copy-chunker-params" argument:"copy-chunker-params"` FromKeyHint string `mapstructure:"from-key-hint" argument:"from-key-hint"` FromRepository ConfidentialValue `mapstructure:"from-repository" argument:"from-repo"` @@ -164,25 +169,24 @@ func (i *InitSection) getCommandFlags(profile *Profile) (flags *shell.Args) { // BackupSection contains the specific configuration to the 'backup' command type BackupSection struct { - SectionWithScheduleAndMonitoring `mapstructure:",squash"` - RunShellCommandsSection `mapstructure:",squash"` - unresolvedSource []string - CheckBefore bool `mapstructure:"check-before" description:"Check the repository before starting the backup command"` - CheckAfter bool `mapstructure:"check-after" description:"Check the repository after the backup command succeeded"` - UseStdin bool `mapstructure:"stdin" argument:"stdin"` - StdinCommand []string `mapstructure:"stdin-command" description:"Shell command(s) that generate content to redirect into the stdin of restic. When set, the flag \"stdin\" is always set to \"true\"."` - SourceRelative bool `mapstructure:"source-relative" description:"Enable backup with relative source paths. This will change the working directory of the \"restic backup\" command to \"source-base\", and will not expand \"source\" to an absolute path."` - SourceBase string `mapstructure:"source-base" examples:"/;$PWD;C:\\;%cd%" description:"The base path to resolve relative backup paths against. Defaults to current directory if unset or empty (see also \"base-dir\" in profile)"` - Source []string `mapstructure:"source" examples:"/opt/;/home/user/;C:\\Users\\User\\Documents" description:"The paths to backup"` - Exclude []string `mapstructure:"exclude" argument:"exclude" argument-type:"no-glob"` - Iexclude []string `mapstructure:"iexclude" argument:"iexclude" argument-type:"no-glob"` - ExcludeFile []string `mapstructure:"exclude-file" argument:"exclude-file"` - IexcludeFile []string `mapstructure:"iexclude-file" argument:"iexclude-file"` - FilesFrom []string `mapstructure:"files-from" argument:"files-from"` - FilesFromRaw []string `mapstructure:"files-from-raw" argument:"files-from-raw"` - FilesFromVerbatim []string `mapstructure:"files-from-verbatim" argument:"files-from-verbatim"` - ExtendedStatus bool `mapstructure:"extended-status" argument:"json"` - NoErrorOnWarning bool `mapstructure:"no-error-on-warning" description:"Do not fail the backup when some files could not be read"` + GenericSectionWithSchedule `mapstructure:",squash"` + unresolvedSource []string + CheckBefore bool `mapstructure:"check-before" description:"Check the repository before starting the backup command"` + CheckAfter bool `mapstructure:"check-after" description:"Check the repository after the backup command succeeded"` + UseStdin bool `mapstructure:"stdin" argument:"stdin"` + StdinCommand []string `mapstructure:"stdin-command" description:"Shell command(s) that generate content to redirect into the stdin of restic. When set, the flag \"stdin\" is always set to \"true\"."` + SourceRelative bool `mapstructure:"source-relative" description:"Enable backup with relative source paths. This will change the working directory of the \"restic backup\" command to \"source-base\", and will not expand \"source\" to an absolute path."` + SourceBase string `mapstructure:"source-base" examples:"/;$PWD;C:\\;%cd%" description:"The base path to resolve relative backup paths against. Defaults to current directory if unset or empty (see also \"base-dir\" in profile)"` + Source []string `mapstructure:"source" examples:"/opt/;/home/user/;C:\\Users\\User\\Documents" description:"The paths to backup"` + Exclude []string `mapstructure:"exclude" argument:"exclude" argument-type:"no-glob"` + Iexclude []string `mapstructure:"iexclude" argument:"iexclude" argument-type:"no-glob"` + ExcludeFile []string `mapstructure:"exclude-file" argument:"exclude-file"` + IexcludeFile []string `mapstructure:"iexclude-file" argument:"iexclude-file"` + FilesFrom []string `mapstructure:"files-from" argument:"files-from"` + FilesFromRaw []string `mapstructure:"files-from-raw" argument:"files-from-raw"` + FilesFromVerbatim []string `mapstructure:"files-from-verbatim" argument:"files-from-verbatim"` + ExtendedStatus bool `mapstructure:"extended-status" argument:"json"` + NoErrorOnWarning bool `mapstructure:"no-error-on-warning" description:"Do not fail the backup when some files could not be read"` } func (s *BackupSection) IsEmpty() bool { return s == nil } @@ -219,7 +223,7 @@ func (b *BackupSection) resolve(profile *Profile) { } func (s *BackupSection) setRootPath(p *Profile, rootPath string) { - s.SectionWithScheduleAndMonitoring.setRootPath(p, rootPath) + s.GenericSectionWithSchedule.setRootPath(p, rootPath) s.ExcludeFile = fixPaths(s.ExcludeFile, expandEnv, expandUserHome, absolutePrefix(rootPath)) s.IexcludeFile = fixPaths(s.IexcludeFile, expandEnv, expandUserHome, absolutePrefix(rootPath)) @@ -287,20 +291,19 @@ func (r *RetentionSection) resolve(profile *Profile) { } } -// SectionWithScheduleAndMonitoring is a section containing schedule, shell command hooks and monitoring +// GenericSectionWithSchedule is a section containing schedule, shell command hooks and monitoring // (all the other parameters being for restic) -type SectionWithScheduleAndMonitoring struct { - ScheduleBaseSection `mapstructure:",squash"` - SendMonitoringSections `mapstructure:",squash"` - OtherFlagsSection `mapstructure:",squash"` +type GenericSectionWithSchedule struct { + GenericSection `mapstructure:",squash"` + ScheduleBaseSection `mapstructure:",squash"` } -func (s *SectionWithScheduleAndMonitoring) setRootPath(p *Profile, rootPath string) { - s.SendMonitoringSections.setRootPath(p, rootPath) +func (s *GenericSectionWithSchedule) setRootPath(p *Profile, rootPath string) { + s.GenericSection.setRootPath(p, rootPath) s.ScheduleBaseSection.setRootPath(p, rootPath) } -func (s *SectionWithScheduleAndMonitoring) IsEmpty() bool { return s == nil } +func (s *GenericSectionWithSchedule) IsEmpty() bool { return s == nil } // ScheduleBaseSection contains the parameters for scheduling a command (backup, check, forget, etc.) type ScheduleBaseSection struct { @@ -341,16 +344,16 @@ func (s *ScheduleBaseSection) getScheduleConfig(p *Profile, command string) *Sch // CopySection contains the destination parameters for a copy command type CopySection struct { - SectionWithScheduleAndMonitoring `mapstructure:",squash"` - RunShellCommandsSection `mapstructure:",squash"` - Initialize bool `mapstructure:"initialize" description:"Initialize the secondary repository if missing"` - InitializeCopyChunkerParams maybe.Bool `mapstructure:"initialize-copy-chunker-params" default:"true" description:"Copy chunker parameters when initializing the secondary repository"` - Repository ConfidentialValue `mapstructure:"repository" description:"Destination repository to copy snapshots to"` - RepositoryFile string `mapstructure:"repository-file" description:"File from which to read the destination repository location to copy snapshots to"` - PasswordFile string `mapstructure:"password-file" description:"File to read the destination repository password from"` - PasswordCommand string `mapstructure:"password-command" description:"Shell command to obtain the destination repository password from"` - KeyHint string `mapstructure:"key-hint" description:"Key ID of key to try decrypting the destination repository first"` - Snapshots []string `mapstructure:"snapshot" description:"Snapshot IDs to copy (if empty, all snapshots are copied)"` + GenericSectionWithSchedule `mapstructure:",squash"` + RunShellCommandsSection `mapstructure:",squash"` + Initialize bool `mapstructure:"initialize" description:"Initialize the secondary repository if missing"` + InitializeCopyChunkerParams maybe.Bool `mapstructure:"initialize-copy-chunker-params" default:"true" description:"Copy chunker parameters when initializing the secondary repository"` + Repository ConfidentialValue `mapstructure:"repository" description:"Destination repository to copy snapshots to"` + RepositoryFile string `mapstructure:"repository-file" description:"File from which to read the destination repository location to copy snapshots to"` + PasswordFile string `mapstructure:"password-file" description:"File to read the destination repository password from"` + PasswordCommand string `mapstructure:"password-command" description:"Shell command to obtain the destination repository password from"` + KeyHint string `mapstructure:"key-hint" description:"Key ID of key to try decrypting the destination repository first"` + Snapshots []string `mapstructure:"snapshot" description:"Snapshot IDs to copy (if empty, all snapshots are copied)"` } func (s *CopySection) IsEmpty() bool { return s == nil } @@ -362,7 +365,7 @@ func (c *CopySection) resolve(p *Profile) { } func (c *CopySection) setRootPath(p *Profile, rootPath string) { - c.SectionWithScheduleAndMonitoring.setRootPath(p, rootPath) + c.GenericSectionWithSchedule.setRootPath(p, rootPath) c.PasswordFile = fixPath(c.PasswordFile, expandEnv, expandUserHome, absolutePrefix(rootPath)) c.RepositoryFile = fixPath(c.RepositoryFile, expandEnv, expandUserHome, absolutePrefix(rootPath)) @@ -455,49 +458,6 @@ type RunShellCommandsSection struct { func (r *RunShellCommandsSection) GetRunShellCommands() *RunShellCommandsSection { return r } -// SendMonitoringSections is a group of target to send monitoring information -type SendMonitoringSections struct { - SendBefore []SendMonitoringSection `mapstructure:"send-before" description:"Send HTTP request(s) before a restic command"` - SendAfter []SendMonitoringSection `mapstructure:"send-after" description:"Send HTTP request(s) after a successful restic command"` - SendAfterFail []SendMonitoringSection `mapstructure:"send-after-fail" description:"Send HTTP request(s) after failed restic or shell commands"` - SendFinally []SendMonitoringSection `mapstructure:"send-finally" description:"Send HTTP request(s) always, after all other commands"` -} - -func (s *SendMonitoringSections) setRootPath(_ *Profile, rootPath string) { - for _, monitoringSections := range s.getAllSendMonitoringSections() { - for index, value := range monitoringSections { - monitoringSections[index].BodyTemplate = fixPath(value.BodyTemplate, expandEnv, expandUserHome, absolutePrefix(rootPath)) - } - } -} - -func (s *SendMonitoringSections) GetSendMonitoring() *SendMonitoringSections { return s } - -func (s *SendMonitoringSections) getAllSendMonitoringSections() [][]SendMonitoringSection { - return [][]SendMonitoringSection{ - s.SendBefore, - s.SendAfter, - s.SendAfterFail, - s.SendFinally, - } -} - -// SendMonitoringSection is used to send monitoring information to third party software -type SendMonitoringSection struct { - Method string `mapstructure:"method" enum:"GET;DELETE;HEAD;OPTIONS;PATCH;POST;PUT;TRACE" default:"GET" description:"HTTP method of the request"` - URL ConfidentialValue `mapstructure:"url" format:"uri" description:"URL of the target to send to"` - Headers []SendMonitoringHeader `mapstructure:"headers" description:"Additional HTTP headers to send with the request"` - Body string `mapstructure:"body" description:"Request body, overrides \"body-template\""` - BodyTemplate string `mapstructure:"body-template" description:"Path to a file containing the request body (go template). See https://creativeprojects.github.io/resticprofile/configuration/http_hooks/#body-template"` - SkipTLS bool `mapstructure:"skip-tls-verification" description:"Enables insecure TLS (without verification), see also \"global.ca-certificates\""` -} - -// SendMonitoringHeader is used to send HTTP headers -type SendMonitoringHeader struct { - Name string `mapstructure:"name" regex:"^\\w([\\w-]+)\\w$" examples:"\"Authorization\";\"Cache-Control\";\"Content-Disposition\";\"Content-Type\"" description:"Name of the HTTP header"` - Value ConfidentialValue `mapstructure:"value" examples:"\"Bearer ...\";\"Basic ...\";\"no-cache\";\"attachment;; filename=stats.txt\";\"application/json\";\"text/plain\";\"text/xml\"" description:"Value of the header"` -} - // OtherFlagsSection contains additional restic command line flags type OtherFlagsSection struct { OtherFlags map[string]any `mapstructure:",remain"` diff --git a/config/profile_test.go b/config/profile_test.go index f782e924..eaa98160 100644 --- a/config/profile_test.go +++ b/config/profile_test.go @@ -1393,7 +1393,8 @@ profile: {"copy", true}, {"prune", true}, {"forget", true}, - {"init", false}, + {"init", true}, + {"other", false}, } for _, config := range configs { @@ -1604,3 +1605,51 @@ func TestGetCopyStructFields(t *testing.T) { assert.Equal(t, copySection.getInitFlags(profile).GetAll(), profile.GetCopyInitializeFlags().GetAll()) }) } + +// make sure all commands are supporting run-before +func TestRunBeforeOnAllCommands(t *testing.T) { + commands := restic.CommandNames() + assert.NotEmpty(t, commands) + + for _, command := range commands { + t.Run(command, func(t *testing.T) { + testConfig := ` +[profile] +[profile.%[1]s] +run-before = ["echo hello"] +` + profile, err := getProfile("toml", fmt.Sprintf(testConfig, command), "profile", "") + require.NoError(t, err) + assert.NotNil(t, profile) + profileCommands, sectionCommands := profile.GetRunShellCommandsSections(command) + assert.Empty(t, profileCommands) + assert.NotEmpty(t, sectionCommands) + assert.Equal(t, []string{"echo hello"}, sectionCommands.RunBefore) + assert.Empty(t, sectionCommands.RunAfter) + }) + } +} + +// make sure all commands are supporting send-before +func TestSendBeforeOnAllCommands(t *testing.T) { + commands := restic.CommandNames() + assert.NotEmpty(t, commands) + + for _, command := range commands { + t.Run(command, func(t *testing.T) { + testConfig := ` +[profile] +[profile.%[1]s] +[[profile.%[1]s.send-before]] +url = "http://example.com" +` + profile, err := getProfile("toml", fmt.Sprintf(testConfig, command), "profile", "") + require.NoError(t, err) + assert.NotNil(t, profile) + monitoring := profile.GetMonitoringSections(command) + assert.NotEmpty(t, monitoring) + assert.Equal(t, 1, len(monitoring.SendBefore)) + assert.Empty(t, monitoring.SendAfter) + }) + } +} diff --git a/config/send.go b/config/send.go new file mode 100644 index 00000000..4b453d1b --- /dev/null +++ b/config/send.go @@ -0,0 +1,44 @@ +package config + +// SendMonitoringSections is a group of target to send monitoring information +type SendMonitoringSections struct { + SendBefore []SendMonitoringSection `mapstructure:"send-before" description:"Send HTTP request(s) before a restic command"` + SendAfter []SendMonitoringSection `mapstructure:"send-after" description:"Send HTTP request(s) after a successful restic command"` + SendAfterFail []SendMonitoringSection `mapstructure:"send-after-fail" description:"Send HTTP request(s) after failed restic or shell commands"` + SendFinally []SendMonitoringSection `mapstructure:"send-finally" description:"Send HTTP request(s) always, after all other commands"` +} + +func (s *SendMonitoringSections) setRootPath(_ *Profile, rootPath string) { + for _, sections := range s.getAllSendMonitoringSections() { + for index := range sections { + sections[index].BodyTemplate = fixPath(sections[index].BodyTemplate, expandEnv, expandUserHome, absolutePrefix(rootPath)) + } + } +} + +func (s *SendMonitoringSections) GetSendMonitoring() *SendMonitoringSections { return s } + +func (s *SendMonitoringSections) getAllSendMonitoringSections() [][]SendMonitoringSection { + return [][]SendMonitoringSection{ + s.SendBefore, + s.SendAfter, + s.SendAfterFail, + s.SendFinally, + } +} + +// SendMonitoringSection is used to send monitoring information to third party software +type SendMonitoringSection struct { + Method string `mapstructure:"method" enum:"GET;DELETE;HEAD;OPTIONS;PATCH;POST;PUT;TRACE" default:"GET" description:"HTTP method of the request"` + URL ConfidentialValue `mapstructure:"url" format:"uri" description:"URL of the target to send to"` + Headers []SendMonitoringHeader `mapstructure:"headers" description:"Additional HTTP headers to send with the request"` + Body string `mapstructure:"body" description:"Request body, overrides \"body-template\""` + BodyTemplate string `mapstructure:"body-template" description:"Path to a file containing the request body (go template). See https://creativeprojects.github.io/resticprofile/configuration/http_hooks/#body-template"` + SkipTLS bool `mapstructure:"skip-tls-verification" description:"Enables insecure TLS (without verification), see also \"global.ca-certificates\""` +} + +// SendMonitoringHeader is used to send HTTP headers +type SendMonitoringHeader struct { + Name string `mapstructure:"name" regex:"^\\w([\\w-]+)\\w$" examples:"\"Authorization\";\"Cache-Control\";\"Content-Disposition\";\"Content-Type\"" description:"Name of the HTTP header"` + Value ConfidentialValue `mapstructure:"value" examples:"\"Bearer ...\";\"Basic ...\";\"no-cache\";\"attachment;; filename=stats.txt\";\"application/json\";\"text/plain\";\"text/xml\"" description:"Value of the header"` +} diff --git a/contrib/templates/reference.gomd b/contrib/templates/reference.gomd index 070a800b..b885f09f 100644 --- a/contrib/templates/reference.gomd +++ b/contrib/templates/reference.gomd @@ -4,6 +4,8 @@ archetype: "chapter" pre: "6. " linkTitle: Reference slug: reference +aliases: + - /configuration/reference {{ if .Env.META_TITLE -}} title: {{ .Env.META_TITLE }} {{- else -}} diff --git a/docs/version.toml b/docs/version.toml index 68e404cf..1970ac1a 100644 --- a/docs/version.toml +++ b/docs/version.toml @@ -1,2 +1,2 @@ [params] - version = "v0.30.0" + version = "v0.31.0" diff --git a/go.mod b/go.mod index 7639de0b..cdee0658 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/creativeprojects/resticprofile -go 1.24.2 +go 1.24.3 require ( github.com/Masterminds/semver/v3 v3.3.1 diff --git a/main.go b/main.go index 6a3d02c3..f4ca19f3 100644 --- a/main.go +++ b/main.go @@ -26,7 +26,7 @@ import ( // These fields are populated by the goreleaser build var ( - version = "0.30.0-dev" + version = "0.31.0-dev" commit = "" date = "" builtBy = "" diff --git a/monitor/hook/sender_test.go b/monitor/hook/sender_test.go index 1f6480b2..8281569f 100644 --- a/monitor/hook/sender_test.go +++ b/monitor/hook/sender_test.go @@ -252,11 +252,13 @@ func TestConfidentialURL(t *testing.T) { profile := &config.Profile{ Backup: &config.BackupSection{ - SectionWithScheduleAndMonitoring: config.SectionWithScheduleAndMonitoring{ - SendMonitoringSections: config.SendMonitoringSections{ - SendBefore: []config.SendMonitoringSection{ - { - URL: config.NewConfidentialValue(serverURL), + GenericSectionWithSchedule: config.GenericSectionWithSchedule{ + GenericSection: config.GenericSection{ + SendMonitoringSections: config.SendMonitoringSections{ + SendBefore: []config.SendMonitoringSection{ + { + URL: config.NewConfidentialValue(serverURL), + }, }, }, }, @@ -286,13 +288,15 @@ func TestConfidentialHeader(t *testing.T) { profile := &config.Profile{ Backup: &config.BackupSection{ - SectionWithScheduleAndMonitoring: config.SectionWithScheduleAndMonitoring{ - SendMonitoringSections: config.SendMonitoringSections{ - SendBefore: []config.SendMonitoringSection{ - { - URL: config.NewConfidentialValue(server.URL), - Headers: []config.SendMonitoringHeader{ - {Name: headerKey, Value: config.NewConfidentialValue(headerValue)}, + GenericSectionWithSchedule: config.GenericSectionWithSchedule{ + GenericSection: config.GenericSection{ + SendMonitoringSections: config.SendMonitoringSections{ + SendBefore: []config.SendMonitoringSection{ + { + URL: config.NewConfidentialValue(server.URL), + Headers: []config.SendMonitoringHeader{ + {Name: headerKey, Value: config.NewConfidentialValue(headerValue)}, + }, }, }, }, diff --git a/sonar-project.properties b/sonar-project.properties index d1490289..b099711f 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,7 +1,7 @@ sonar.organization=creativeprojects sonar.projectKey=creativeprojects_resticprofile sonar.projectName=resticprofile -sonar.projectVersion=0.30.0 +sonar.projectVersion=0.31.0 sonar.sources=. sonar.exclusions=**/*_test.go,/docs/** diff --git a/wrapper_test.go b/wrapper_test.go index bb07e1b4..c8702aca 100644 --- a/wrapper_test.go +++ b/wrapper_test.go @@ -1024,11 +1024,11 @@ func TestRunShellCommands(t *testing.T) { profile := config.NewProfile(&config.Config{}, "name") profile.Backup = &config.BackupSection{} - profile.Check = &config.SectionWithScheduleAndMonitoring{} + profile.Check = &config.GenericSectionWithSchedule{} profile.Copy = &config.CopySection{} - profile.Forget = &config.SectionWithScheduleAndMonitoring{} + profile.Forget = &config.GenericSectionWithSchedule{} profile.Init = &config.InitSection{} - profile.Prune = &config.SectionWithScheduleAndMonitoring{} + profile.Prune = &config.GenericSectionWithSchedule{} for name := range profile.OtherSections { profile.OtherSections[name] = new(config.GenericSection) }