diff --git a/.changes/unreleased/Added-20250207-212429.yaml b/.changes/unreleased/Added-20250207-212429.yaml new file mode 100644 index 0000000..403a802 --- /dev/null +++ b/.changes/unreleased/Added-20250207-212429.yaml @@ -0,0 +1,3 @@ +kind: Added +body: Flag `--s3-endpoint` for config file fetching from S3 +time: 2025-02-07T21:24:29.596055611-06:00 diff --git a/.changes/unreleased/Changed-20250208-151508.yaml b/.changes/unreleased/Changed-20250208-151508.yaml new file mode 100644 index 0000000..441431a --- /dev/null +++ b/.changes/unreleased/Changed-20250208-151508.yaml @@ -0,0 +1,3 @@ +kind: Changed +body: Flags that took comma-separated lists now have to be passed multiple times for each argument. +time: 2025-02-08T15:15:08.457086102-06:00 diff --git a/.changes/unreleased/Fixed-20250202-194523.yaml b/.changes/unreleased/Fixed-20250202-194523.yaml new file mode 100644 index 0000000..7f136d9 --- /dev/null +++ b/.changes/unreleased/Fixed-20250202-194523.yaml @@ -0,0 +1,3 @@ +kind: Fixed +body: Incorrect error notification template value +time: 2025-02-02T19:45:23.872797604-06:00 diff --git a/.gitignore b/.gitignore index d258465..1862edd 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ dist/ .codegpt -*.log \ No newline at end of file +*.log +*.sh \ No newline at end of file diff --git a/cmd/backup.go b/cmd/backup.go index 0e73523..d39f224 100644 --- a/cmd/backup.go +++ b/cmd/backup.go @@ -12,8 +12,8 @@ import ( var ( backupCmd = &cobra.Command{ - Use: "backup [--lists=list1,list2,... | -l list1, list2,...]", - Short: "Runs commands defined in config file.", + Use: "backup [--lists=list1 --lists list2 ... | -l list1 -l list2 ...]", + Short: "Runs commands defined in config file. Use -l flag multiple times to run multiple lists.", Long: "Backup executes commands defined in config file.\nUse the --lists or -l flag to execute the specified lists. If not flag is not given, all lists will be executed.", Run: Backup, } @@ -23,8 +23,9 @@ var ( var cmdLists []string func init() { + parseS3Config() - backupCmd.Flags().StringSliceVarP(&cmdLists, "lists", "l", nil, "Accepts comma-separated names of command lists to execute.") + backupCmd.Flags().StringArrayVarP(&cmdLists, "lists", "l", nil, "Accepts comma-separated names of command lists to execute.") } diff --git a/cmd/cron.go b/cmd/cron.go index cae3f46..644002e 100644 --- a/cmd/cron.go +++ b/cmd/cron.go @@ -16,8 +16,9 @@ var ( ) func cron(cmd *cobra.Command, args []string) { + parseS3Config() - opts := backy.NewOpts(cfgFile, backy.CronEnabled()) + opts := backy.NewOpts(cfgFile, backy.EnableCron()) opts.InitConfig() opts.ReadConfig() diff --git a/cmd/exec.go b/cmd/exec.go index 45b8716..c28a302 100644 --- a/cmd/exec.go +++ b/cmd/exec.go @@ -23,12 +23,11 @@ var ( func init() { execCmd.AddCommand(hostExecCommand) - hostExecCommand.Flags().StringSliceVarP(&hostsList, "hosts", "m", nil, "Accepts comma-separated names of hosts.") - hostExecCommand.Flags().StringSliceVarP(&cmdList, "commands", "c", nil, "Accepts comma-separated names of commands.") - } func execute(cmd *cobra.Command, args []string) { + parseS3Config() + if len(args) < 1 { logging.ExitWithMSG("Please provide a command to run. Pass --help to see options.", 1, nil) } diff --git a/cmd/host.go b/cmd/host.go index 036994c..62f27d2 100644 --- a/cmd/host.go +++ b/cmd/host.go @@ -8,7 +8,7 @@ import ( var ( hostExecCommand = &cobra.Command{ - Use: "host [--commands=command1,command2, ... | -c command1,command2, ...] [--hosts=host1,hosts2, ... | -m host1,host2, ...] ", + Use: "host [--command=command1 --command=command2 ... | -c command1 -c command2 ...] [--hosts=host1 --hosts=hosts2 ... | -m host1 -m host2 ...] ", Short: "Runs command defined in config file on the hosts in order specified.", Long: "Host executes specified commands on the hosts defined in config file.\nUse the --commands or -c flag to choose the commands.", Run: Host, @@ -21,6 +21,10 @@ var cmdList []string func init() { + hostExecCommand.Flags().StringArrayVarP(&hostsList, "hosts", "m", nil, "Accepts space-separated names of hosts.") + hostExecCommand.Flags().StringArrayVarP(&cmdList, "command", "c", nil, "Accepts space-separated names of commands.") + parseS3Config() + } // cli input should be hosts and commands. Hosts are defined in config files. @@ -40,6 +44,7 @@ func Host(cmd *cobra.Command, args []string) { } // host is only checked when we read the SSH File // so a check may not be needed here + // but we can check if the host is in the config file for _, h := range hostsList { _, hostFound := backyConfOpts.Hosts[h] if !hostFound { diff --git a/cmd/list.go b/cmd/list.go index 8936a78..22a5384 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -38,6 +38,7 @@ func List(cmd *cobra.Command, args []string) { if cmdLists != nil { } + parseS3Config() opts := backy.NewOpts(cfgFile) diff --git a/cmd/root.go b/cmd/root.go index 59ba257..d10339b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -13,9 +13,10 @@ import ( var ( // Used for flags. - cfgFile string - verbose bool - logFile string + cfgFile string + verbose bool + logFile string + s3Endpoint string rootCmd = &cobra.Command{ Use: "backy", @@ -33,11 +34,16 @@ func Execute() { } func init() { - rootCmd.PersistentFlags().StringVar(&logFile, "log-file", "", "log file to write to") rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "f", "", "config file to read from") rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Sets verbose level") - + rootCmd.PersistentFlags().StringVar(&s3Endpoint, "s3-endpoint", "", "Sets the S3 endpoint used for config file fetching. Overrides S3_ENDPOINT env variable.") rootCmd.AddCommand(backupCmd, execCmd, cronCmd, versionCmd, listCmd) } + +func parseS3Config() { + if s3Endpoint != "" { + os.Setenv("S3_ENDPOINT", s3Endpoint) + } +} diff --git a/docs/content/config/_index.md b/docs/content/config/_index.md index bf69d54..3dfed6a 100644 --- a/docs/content/config/_index.md +++ b/docs/content/config/_index.md @@ -10,6 +10,13 @@ This is the section on the config file. To use a specific file: ```backy [command] -f /path/to/file``` +You can also use a remote file: +``` +backy [command] -f `s3/http source` +``` + +See remote resources docs for specific info. + If you leave the config path blank, the following paths will be searched in order: 1. `./backy.yml` diff --git a/docs/content/config/command-lists.md b/docs/content/config/command-lists.md index ec28de7..472feca 100644 --- a/docs/content/config/command-lists.md +++ b/docs/content/config/command-lists.md @@ -11,8 +11,16 @@ The top-level object key can be anything you want but not the same as another. Lists can go in a separate file. Command lists should be in a separate file if: -1. key 'cmd-lists.file' is found -2. hosts.yml or hosts.yaml is found in the same directory as the backy config file +1. key 'cmd-lists.file' is specified +2. lists.yml or lists.yaml is found in the same directory as the backy config file + +{{% notice info %}} +The lists file is also checked in remote resources. + +The lists file is ignored under the following condition: + +If a remote config file is specified (on the command-line using `-f`) and the lists file is not found in the same directory, the lists file is assumed to not exist. +{{% /notice %}} ```yaml {lineNos="true" wrap="true" title="yaml"} test2: diff --git a/docs/content/config/commands.md b/docs/content/config/commands/_index.md similarity index 83% rename from docs/content/config/commands.md rename to docs/content/config/commands/_index.md index 63ca86b..d462525 100644 --- a/docs/content/config/commands.md +++ b/docs/content/config/commands/_index.md @@ -4,9 +4,7 @@ description: Commands are just that, commands weight: 1 --- -The yaml top-level map can be any string. -The top-level name must be unique. ### Example Config @@ -43,8 +41,8 @@ Values available for this section **(case-sensitive)**: | --- | --- | --- | --- | | `cmd` | Defines the command to execute | `string` | yes | | `Args` | Defines the arguments to the command | `[]string` | no | -| `environment` | Defines evironment variables for the command | `[]string` | no | -| `type` | May be `scriptFile`, `script`, or `package`. Runs script from local machine on remote. `Package` is the only one that can be run on local and remote hosts. | `string` | no | +| `environment` | Defines environment variables for the command | `[]string` | no | +| `type` | See documentation further down the page. Additional fields may be required. | `string` | no | | `getOutput` | Command(s) output is in the notification(s) | `bool` | no | | `host` | If not specified, the command will execute locally. | `string` | no | | `scriptEnvFile` | When type is `scriptFile` or `script`, this file is prepended to the input. | `string` | no | @@ -108,13 +106,14 @@ This is useful for specifying environment variables or other things so they don' ### type -May be `scriptFile` or `script`. Runs script from local machine on remote host passed to the SSH session as standard input. +The following options are available: -If `type` is `script`, `cmd` is used as the script. - -If `type` is `scriptFile`, cmd must be a script file. - -If `type` is `package`, there are additional fields that must be specified. +| name | description | +| --- | --- | +| script | `cmd` is used as the script | +| scriptFile | Can only be run on a host. `cmd` is read and used as the script, and `scriptEnvFile` can be used to add env variables | +| package | Run package operations. See [dedicated page](/config/packages) for configuring package commands | +| user | Run user operations. See [dedicated page](/config/user-commands) for configuring package commands | ### environment @@ -122,7 +121,7 @@ The environment variables support expansion: - using escaped values `$VAR` or `${VAR}` -For now, the variables have to be defined in an `.env` file in the same directory as the config file. +For now, the variables have to be defined in an `.env` file in the same directory that the program is run from. If using it with host specified, the SSH server has to be configured to accept those env variables. diff --git a/docs/content/config/packages.md b/docs/content/config/commands/packages.md similarity index 76% rename from docs/content/config/packages.md rename to docs/content/config/commands/packages.md index ab45c59..309a024 100644 --- a/docs/content/config/packages.md +++ b/docs/content/config/commands/packages.md @@ -10,8 +10,8 @@ This is dedicated to `package` commands. The command `type` field must be `packa | --- | --- | --- | --- | | `packageName` | The name of a package to be modified. | `string` | yes | | `packageManager` | The name of the package manger to be used. | `string` | yes | -| `packageOperation` | The type of operation to be perform. | `string` | yes | -| `packageVersion` | The version of a package to be modified. | `string` | no | +| `packageOperation` | The type of operation to perform. | `string` | yes | +| `packageVersion` | The version of a package. | `string` | no | #### example @@ -35,6 +35,7 @@ The following package operations are supported: - `install` - `remove` - `upgrade` +- `checkVersion` #### packageManager @@ -46,11 +47,11 @@ The following package managers are recognized: #### package command args -You can add additional arguments using the standard `Args` key. This is useful for adding more packages. +You can add additional arguments using the standard `Args` key. This is useful for adding more packages, yet it does not work with `checkVersion`. ### Development -The PackageManager interface provides an easy to enforce functions and options. There are two interfaces, `PackageManager` and `ConfigurablePackageManager` in the directory `pkg/pkgman`. Go's import-cycle "feature" caused me to implement functional options using a third interface. `PackageManagerOption`is a function that takes an interface. +The PackageManager interface provides an easy way to enforce functions and options. There are two interfaces, `PackageManager` and `ConfigurablePackageManager` in the directory `pkg/pkgman`. Go's import-cycle "feature" caused me to implement functional options using a third interface. `PackageManagerOption`is a function that takes an interface. #### PackageManager diff --git a/docs/content/config/commands/user-commands.md b/docs/content/config/commands/user-commands.md new file mode 100644 index 0000000..91f649e --- /dev/null +++ b/docs/content/config/commands/user-commands.md @@ -0,0 +1,62 @@ +--- +title: "User commands" +weight: 2 +description: This is dedicated to user commands. +--- + +This is dedicated to `user` commands. The command `type` field must be `user`. User is a type that allows one to perform user operations. There are several additional options available when `type` is `user`: + +| name | notes | type | required | +| --- | --- | --- | --- | +| `userName` | The name of a user to be configured. | `string` | yes | +| `userOperation` | The type of operation to perform. | `string` | yes | +| `userID` | The user ID to use. | `string` | yes | +| `userGroups` | The groups the user should be added to. | `[]string` | yes | +| `userShell` | The shell for the user. | `string` | yes | +| `userHome` | The user's home directory. | `string` | no | + + +#### example + +The following is an example of a package command: + +```yaml + addUser: + name: add user backy with custom home dir + type: user + userName: backy + userHome: /opt/backy + userOperation: add + host: some-host +``` + +#### userOperation + +The following package operations are supported: + +- `add` +- `remove` +- `modify` +- `password` +- `checkIfExists` + +### Development + +The UserManager interface provides an way easy to add new commands. There is one interface `Usermanager` in directory `pkg/usermanager`. + +#### UserManager + +```go +// UserManager defines the interface for user management operations. +// All functions but one return a string for the command and any args. +type UserManager interface { + AddUser(username, homeDir, shell string, isSystem bool, groups, args []string) (string, []string) + RemoveUser(username string) (string, []string) + ModifyUser(username, homeDir, shell string, groups []string) (string, []string) + // Modify password uses chpasswd for Linux systems to build the command to change the password + // Should return a password as the last argument + // TODO: refactor when adding more systems instead of Linux + ModifyPassword(username, password string) (string, *strings.Reader, string) + UserExists(username string) (string, []string) +} +``` \ No newline at end of file diff --git a/docs/content/config/hosts.md b/docs/content/config/hosts.md new file mode 100644 index 0000000..47096db --- /dev/null +++ b/docs/content/config/hosts.md @@ -0,0 +1,24 @@ +--- +title: "Hosts" +weight: 2 +description: > + This page tells you how to use hosts. +--- + +| Key | Description | Type | Required | +|----------------------|---------------------------------------------------------------|----------|----------| +| `OS` | Operating system of the host (used for package commands) | `string` | no | +| `config` | Path to the SSH config file | `string` | no | +| `host` | Specifies the `Host` ssh_config(5) directive | `string` | yes | +| `hostname` | Hostname of the host | `string` | no | +| `knownhostsfile` | Path to the known hosts file | `string` | no | +| `port` | Port number to connect to | `uint16` | no | +| `proxyjump` | Proxy jump hosts, comma-separated | `string` | no | +| `password` | Password for SSH authentication | `string` | no | +| `privatekeypath` | Path to the private key file | `string` | no | +| `privatekeypassword` | Password for the private key file | `string` | no | +| `user` | Username for SSH authentication | `string` | no | + +## exec host subcommand + +Backy has a subcommand `exec host`. This subcommand takes the flags of `-m host1 -m host2`. For now these hosts need to be defined in the config file. \ No newline at end of file diff --git a/docs/content/config/notifications.md b/docs/content/config/notifications.md index c2a28d1..23dd116 100644 --- a/docs/content/config/notifications.md +++ b/docs/content/config/notifications.md @@ -5,6 +5,7 @@ description: > This page tells you how to get set up Backy notifications. --- +Notifications are only configurable for command lists, as of right now. Notifications can be sent on command list completion and failure. diff --git a/docs/content/config/remote-resources.md b/docs/content/config/remote-resources.md new file mode 100644 index 0000000..036d972 --- /dev/null +++ b/docs/content/config/remote-resources.md @@ -0,0 +1,17 @@ +--- +title: "Remote resources" +weight: 2 +description: This is dedicated to configuring remote resources. +--- + +Remote resources can be used for a lot of things, including config files and scripts. + +## Config file + +For the main config file to be fetched remotely, pass the URL using `-f [url]`. + +If using S3, you should use the s3 protocol URI: `s3://bucketName/key/path`. You will also need to set the env variable `S3_ENDPOINT` to the appropriate value. The flag `--s3-endpoint` can be used to override this value or to set this value, if not already set. + +## Scripts + +Scripts will be coming later. \ No newline at end of file diff --git a/go.mod b/go.mod index 70217ba..ae52c91 100644 --- a/go.mod +++ b/go.mod @@ -1,92 +1,95 @@ module git.andrewnw.xyz/CyberShell/backy -go 1.21 +go 1.23 -toolchain go1.22.2 +toolchain go1.23.1 replace git.andrewnw.xyz/CyberShell/backy => /home/andrew/Projects/backy require ( - github.com/aws/aws-sdk-go-v2/config v1.18.27 - github.com/aws/aws-sdk-go-v2/service/s3 v1.72.0 - github.com/go-co-op/gocron v1.33.1 - github.com/hashicorp/vault/api v1.10.0 + github.com/aws/aws-sdk-go-v2/service/s3 v1.76.0 + github.com/go-co-op/gocron v1.37.0 + github.com/hashicorp/vault/api v1.15.0 github.com/joho/godotenv v1.5.1 github.com/kevinburke/ssh_config v1.2.0 github.com/knadh/koanf/parsers/yaml v0.1.0 github.com/knadh/koanf/providers/rawbytes v0.1.0 - github.com/knadh/koanf/v2 v2.0.1 - github.com/mattn/go-isatty v0.0.19 - github.com/nikoksr/notify v0.41.0 + github.com/knadh/koanf/v2 v2.1.2 + github.com/mattn/go-isatty v0.0.20 + github.com/minio/minio-go/v7 v7.0.84 + github.com/mitchellh/go-homedir v1.1.0 + github.com/nikoksr/notify v1.3.0 github.com/pkg/errors v0.9.1 - github.com/rs/zerolog v1.30.0 + github.com/rs/zerolog v1.33.0 github.com/sethvargo/go-password v0.3.1 - github.com/spf13/cobra v1.7.0 - golang.org/x/crypto v0.31.0 + github.com/spf13/cobra v1.8.1 + golang.org/x/crypto v0.33.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/yaml.v3 v3.0.1 - maunium.net/go/mautrix v0.16.0 - mvdan.cc/sh/v3 v3.7.0 + maunium.net/go/mautrix v0.23.0 + mvdan.cc/sh/v3 v3.10.0 ) require ( - github.com/aws/aws-sdk-go-v2 v1.32.7 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.13.26 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.4 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.26 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.26 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.35 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.26 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.7 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.7 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.7 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.12.12 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.12 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.19.2 // indirect - github.com/aws/smithy-go v1.22.1 // indirect + filippo.io/edwards25519 v1.1.0 // indirect + github.com/aws/aws-sdk-go-v2 v1.36.1 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.8 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.32 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.32 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.32 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.6 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.13 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.13 // indirect + github.com/aws/smithy-go v1.22.2 // indirect github.com/cenkalti/backoff/v3 v3.2.2 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-jose/go-jose/v3 v3.0.0 // indirect - github.com/google/uuid v1.3.1 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/go-ini/ini v1.67.0 // indirect + github.com/go-jose/go-jose/v3 v3.0.3 // indirect + github.com/go-jose/go-jose/v4 v4.0.1 // indirect + github.com/go-viper/mapstructure/v2 v2.2.1 // indirect + github.com/goccy/go-json v0.10.5 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-retryablehttp v0.7.4 // indirect + github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect - github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 // indirect + github.com/hashicorp/go-secure-stdlib/parseutil v0.1.9 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect - github.com/hashicorp/go-sockaddr v1.0.5 // indirect + github.com/hashicorp/go-sockaddr v1.0.7 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible // indirect + github.com/klauspost/compress v1.17.11 // indirect + github.com/klauspost/cpuid/v2 v2.2.9 // indirect github.com/knadh/koanf/maps v0.1.1 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/minio/md5-simd v1.1.2 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect - github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/rogpeppe/go-internal v1.13.1 // indirect + github.com/rs/xid v1.6.0 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/pflag v1.0.6 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/stretchr/testify v1.10.0 // indirect - github.com/tidwall/gjson v1.16.0 // indirect + github.com/tidwall/gjson v1.18.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect - go.mau.fi/util v0.0.0-20230906155759-14bad39a8718 // indirect + go.mau.fi/util v0.8.4 // indirect go.uber.org/atomic v1.11.0 // indirect - golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect - golang.org/x/net v0.33.0 // indirect - golang.org/x/sync v0.10.0 // indirect - golang.org/x/sys v0.28.0 // indirect - golang.org/x/text v0.21.0 // indirect - golang.org/x/time v0.3.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + golang.org/x/exp v0.0.0-20250207012021-f9890c6ad9f3 // indirect + golang.org/x/net v0.34.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect + golang.org/x/time v0.10.0 // indirect maunium.net/go/maulogger/v2 v2.4.1 // indirect ) diff --git a/go.sum b/go.sum index 1c75f44..7111d54 100644 --- a/go.sum +++ b/go.sum @@ -1,71 +1,98 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aws/aws-sdk-go-v2 v1.18.1/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2 v1.32.7 h1:ky5o35oENWi0JYWUZkB7WYvVPP+bcRF5/Iq7JWSb5Rw= github.com/aws/aws-sdk-go-v2 v1.32.7/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= +github.com/aws/aws-sdk-go-v2 v1.36.1 h1:iTDl5U6oAhkNPba0e1t1hrwAo02ZMqbrGq4k5JBWM5E= +github.com/aws/aws-sdk-go-v2 v1.36.1/go.mod h1:5PMILGVKiW32oDzjj6RU52yrNrDPUHcbZQYr1sM7qmM= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 h1:lL7IfaFzngfx0ZwUGOZdsFFnQ5uLvR0hWqqhyE7Q9M8= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7/go.mod h1:QraP0UcVlQJsmHfioCrveWOC1nbiWUl3ej08h4mXWoc= -github.com/aws/aws-sdk-go-v2/config v1.18.27 h1:Az9uLwmssTE6OGTpsFqOnaGpLnKDqNYOJzWuC6UAYzA= -github.com/aws/aws-sdk-go-v2/config v1.18.27/go.mod h1:0My+YgmkGxeqjXZb5BYme5pc4drjTnM+x1GJ3zv42Nw= -github.com/aws/aws-sdk-go-v2/credentials v1.13.26 h1:qmU+yhKmOCyujmuPY7tf5MxR/RKyZrOPO3V4DobiTUk= -github.com/aws/aws-sdk-go-v2/credentials v1.13.26/go.mod h1:GoXt2YC8jHUBbA4jr+W3JiemnIbkXOfxSXcisUsZ3os= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.4 h1:LxK/bitrAr4lnh9LnIS6i7zWbCOdMsfzKFBI6LUCS0I= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.4/go.mod h1:E1hLXN/BL2e6YizK1zFlYd8vsfi2GTjbjBazinMmeaM= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.34/go.mod h1:wZpTEecJe0Btj3IYnDx/VlUzor9wm3fJHyvLpQF0VwY= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.8 h1:zAxi9p3wsZMIaVCdoiQp2uZ9k1LsZvmAnoTBeZPXom0= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.8/go.mod h1:3XkePX5dSaxveLAYY7nsbsZZrKxCyEuE5pM4ziFxyGg= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.26 h1:I/5wmGMffY4happ8NOCuIUEWGUvvFp5NSeQcXl9RHcI= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.26/go.mod h1:FR8f4turZtNy6baO0KJ5FJUmXH/cSkI9fOngs0yl6mA= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.28/go.mod h1:7VRpKQQedkfIEXb4k52I7swUnZP0wohVajJMRn3vsUw= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.32 h1:BjUcr3X3K0wZPGFg2bxOWW3VPN8rkE3/61zhP+IHviA= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.32/go.mod h1:80+OGC/bgzzFFTUmcuwD0lb4YutwQeKLFpmt6hoWapU= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.26 h1:zXFLuEuMMUOvEARXFUVJdfqZ4bvvSgdGRq/ATcrQxzM= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.26/go.mod h1:3o2Wpy0bogG1kyOPrgkXA8pgIfEEv0+m19O9D5+W8y8= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.35 h1:LWA+3kDM8ly001vJ1X1waCuLJdtTl48gwkPKWy9sosI= -github.com/aws/aws-sdk-go-v2/internal/ini v1.3.35/go.mod h1:0Eg1YjxE0Bhn56lx+SHJwCzhW+2JGtizsrx+lCqrfm0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.32 h1:m1GeXHVMJsRsUAqG6HjZWx9dj7F5TR+cF1bjyfYyBd4= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.32/go.mod h1:IitoQxGfaKdVLNg0hD8/DXmAqNy0H4K2H2Sf91ti8sI= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.26 h1:GeNJsIFHB+WW5ap2Tec4K6dzcVTsRbsT1Lra46Hv9ME= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.26/go.mod h1:zfgMpwHDXX2WGoG84xG2H+ZlPTkJUU4YUvx2svLQYWo= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.32 h1:OIHj/nAhVzIXGzbAE+4XmZ8FPvro3THr6NlqErJc3wY= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.32/go.mod h1:LiBEsDo34OJXqdDlRGsilhlIiXR7DL+6Cx2f4p1EgzI= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 h1:D4oz8/CzT9bAEYtVhSBmFj2dNOtaHOtMKc2vHBwYizA= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2/go.mod h1:Za3IHqTQ+yNcRHxu1OFucBh0ACZT4j4VQFF0BqpZcLY= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.7 h1:tB4tNw83KcajNAzaIMhkhVI2Nt8fAZd5A5ro113FEMY= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.7/go.mod h1:lvpyBGkZ3tZ9iSsUIcC2EWp+0ywa7aK3BLT+FwZi+mQ= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.28/go.mod h1:jj7znCIg05jXlaGBlFMGP8+7UN3VtCkRBG2spnmRQkU= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.6 h1:cCBJaT7EeEojpJ4s7wTDbhZlHVJOgNHN7iw6qVurGaw= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.5.6/go.mod h1:WYH1ABybY7JK9TITPnk6ZlP7gQB8psI4c9qDmMsnLSA= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.7 h1:8eUsivBQzZHqe/3FE+cqwfH+0p5Jo8PFM/QYQSmeZ+M= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.7/go.mod h1:kLPQvGUmxn/fqiCrDeohwG33bq2pQpGeY62yRO6Nrh0= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.13 h1:SYVGSFQHlchIcy6e7x12bsrxClCXSP5et8cqVhL8cuw= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.13/go.mod h1:kizuDaLX37bG5WZaoxGPQR/LNFXpxp0vsUnqfkWXfNE= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.7 h1:Hi0KGbrnr57bEHWM0bJ1QcBzxLrL/k2DHvGYhb8+W1w= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.7/go.mod h1:wKNgWgExdjjrm4qvfbTorkvocEstaoDl4WCvGfeCy9c= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.13 h1:OBsrtam3rk8NfBEq7OLOMm5HtQ9Yyw32X4UQMya/wjw= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.13/go.mod h1:3U4gFA5pmoCOja7aq4nSaIAGbaOHv2Yl2ug018cmC+Q= github.com/aws/aws-sdk-go-v2/service/s3 v1.72.0 h1:SAfh4pNx5LuTafKKWR02Y+hL3A+3TX8cTKG1OIAJaBk= github.com/aws/aws-sdk-go-v2/service/s3 v1.72.0/go.mod h1:r+xl5yzMk9083rMR+sJ5TYj9Tihvf/l1oxzZXDgGj2Q= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.12 h1:nneMBM2p79PGWBQovYO/6Xnc2ryRMw3InnDJq1FHkSY= -github.com/aws/aws-sdk-go-v2/service/sso v1.12.12/go.mod h1:HuCOxYsF21eKrerARYO6HapNeh9GBNq7fius2AcwodY= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.12 h1:2qTR7IFk7/0IN/adSFhYu9Xthr0zVFTgBrmPldILn80= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.12/go.mod h1:E4VrHCPzmVB/KFXtqBGKb3c8zpbNBgKe3fisDNLAW5w= -github.com/aws/aws-sdk-go-v2/service/sts v1.19.2 h1:XFJ2Z6sNUUcAz9poj+245DMkrHE4h2j5I9/xD50RHfE= -github.com/aws/aws-sdk-go-v2/service/sts v1.19.2/go.mod h1:dp0yLPsLBOi++WTxzCjA/oZqi6NPIhoR+uF7GeMU9eg= -github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/aws/aws-sdk-go-v2/service/s3 v1.76.0 h1:ehvUZNVrGA1Usa6yYo8A8pUqrigRelWXSbcCqYpRLeI= +github.com/aws/aws-sdk-go-v2/service/s3 v1.76.0/go.mod h1:KuLNrwYJFaC2AVZ+CVVc12k9NyqwgWsoNNHjwqF6QNk= github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ= +github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M= github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/go-co-op/gocron v1.33.1 h1:wjX+Dg6Ae29a/f9BSQjY1Rl+jflTpW9aDyMqseCj78c= github.com/go-co-op/gocron v1.33.1/go.mod h1:NLi+bkm4rRSy1F8U7iacZOz0xPseMoIOnvabGoSe/no= +github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0= +github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY= +github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= +github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= +github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= +github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= +github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U= +github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw= github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= +github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= +github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= +github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -74,37 +101,47 @@ github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/S github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA= github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= +github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 h1:UpiO20jno/eV1eVZcxqWnUohyKRe1g8FPV/xH1s/2qs= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= +github.com/hashicorp/go-secure-stdlib/parseutil v0.1.9 h1:FW0YttEnUNDJ2WL9XcrrfteS1xW8u+sh4ggM8pN5isQ= +github.com/hashicorp/go-secure-stdlib/parseutil v0.1.9/go.mod h1:Ll013mhdmsVDuoIXVfBtvgGJsXDYkTw1kooNcoCXuE0= github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hashicorp/go-sockaddr v1.0.5 h1:dvk7TIXCZpmfOlM+9mlcrWmWjw/wlKT+VDq2wMvfPJU= github.com/hashicorp/go-sockaddr v1.0.5/go.mod h1:uoUUmtwU7n9Dv3O4SNLeFvg0SxQ3lyjsj6+CCykpaxI= +github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw= +github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/vault/api v1.10.0 h1:/US7sIjWN6Imp4o/Rj1Ce2Nr5bki/AXi9vAW3p2tOJQ= github.com/hashicorp/vault/api v1.10.0/go.mod h1:jo5Y/ET+hNyz+JnKDt8XLAdKs+AM0G5W0Vp1IrFI8N8= +github.com/hashicorp/vault/api v1.15.0 h1:O24FYQCWwhwKnF7CuSqP30S51rTV7vz1iACXE/pj5DA= +github.com/hashicorp/vault/api v1.15.0/go.mod h1:+5YTO09JGn0u+b6ySD/LLVf8WkJCPLAL2Vkmrn2+CM8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA= github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY= +github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8= github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/parsers/yaml v0.1.0 h1:ZZ8/iGfRLvKSaMEECEBPM1HQslrZADk8fP1XFUxVI5w= @@ -113,6 +150,8 @@ github.com/knadh/koanf/providers/rawbytes v0.1.0 h1:dpzgu2KO6uf6oCb4aP05KDmKmAmI github.com/knadh/koanf/providers/rawbytes v0.1.0/go.mod h1:mMTB1/IcJ/yE++A2iEZbY1MLygX7vttU+C+S/YmPu9c= github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g= github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus= +github.com/knadh/koanf/v2 v2.1.2 h1:I2rtLRqXRy1p01m/utEtpZSSA6dcJbgGVuE27kW2PzQ= +github.com/knadh/koanf/v2 v2.1.2/go.mod h1:Gphfaen0q1Fc1HTgJgSTC4oRX9R2R5ErYMZJy8fLJBo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= @@ -126,11 +165,19 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= +github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= +github.com/minio/minio-go/v7 v7.0.84 h1:D1HVmAF8JF8Bpi6IU4V9vIEj+8pc+xU88EWMs2yed0E= +github.com/minio/minio-go/v7 v7.0.84/go.mod h1:57YXpvc5l3rjPdhqNrDsvVlY0qPI6UTk1bflAe+9doY= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= @@ -144,6 +191,8 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/nikoksr/notify v0.41.0 h1:4LGE41GpWdHX5M3Xo6DlWRwS2WLDbOq1Rk7IzY4vjmQ= github.com/nikoksr/notify v0.41.0/go.mod h1:FoE0UVPeopz1Vy5nm9vQZ+JVmYjEIjQgbFstbkw+cRE= +github.com/nikoksr/notify v1.3.0 h1:UxzfxzAYGQD9a5JYLBTVx0lFMxeHCke3rPCkfWdPgLs= +github.com/nikoksr/notify v1.3.0/go.mod h1:Xor2hMmkvrCfkCKvXGbcrESez4brac2zQjhd6U2BbeM= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -156,9 +205,15 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= +github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= @@ -167,8 +222,12 @@ github.com/sethvargo/go-password v0.3.1 h1:WqrLTjo7X6AcVYfC6R7GtSyuUQR9hGyAj/f1P github.com/sethvargo/go-password v0.3.1/go.mod h1:rXofC1zT54N7R8K/h1WDUdkf9BOx5OptoxrMBcrXzvs= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -186,6 +245,8 @@ github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg= github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= @@ -193,38 +254,91 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.mau.fi/util v0.0.0-20230906155759-14bad39a8718 h1:hmm5bZqE0M8+Uvys0HJPCSbAIZIwYtTkBKYPjAWHuMM= go.mau.fi/util v0.0.0-20230906155759-14bad39a8718/go.mod h1:AxuJUMCxpzgJ5eV9JbPWKRH8aAJJidxetNdUj7qcb84= +go.mau.fi/util v0.8.4 h1:mVKlJcXWfVo8ZW3f4vqtjGpqtZqJvX4ETekxawt2vnQ= +go.mau.fi/util v0.8.4/go.mod h1:MOfGTs1CBuK6ERTcSL4lb5YU7/ujz09eOPVEDckuazY= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/exp v0.0.0-20250207012021-f9890c6ad9f3 h1:qNgPs5exUA+G0C96DrPwNrvLSj7GT/9D+3WMWUcUg34= +golang.org/x/exp v0.0.0-20250207012021-f9890c6ad9f3/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4= +golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -233,9 +347,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -243,5 +354,9 @@ maunium.net/go/maulogger/v2 v2.4.1 h1:N7zSdd0mZkB2m2JtFUsiGTQQAdP0YeFWT7YMc80yAL maunium.net/go/maulogger/v2 v2.4.1/go.mod h1:omPuYwYBILeVQobz8uO3XC8DIRuEb5rXYlQSuqrbCho= maunium.net/go/mautrix v0.16.0 h1:iUqCzJE2yqBC1ddAK6eAn159My8rLb4X8g4SFtQh2Dk= maunium.net/go/mautrix v0.16.0/go.mod h1:XAjE9pTSGcr6vXaiNgQGiip7tddJ8FQV1a29u2QdBG4= +maunium.net/go/mautrix v0.23.0 h1:HNlR19eew5lvrNSL2muhExaGhYdaGk5FfEiA82QqUP4= +maunium.net/go/mautrix v0.23.0/go.mod h1:AGnnaz3ylGikUo1I1MJVn9QLsl2No1/ZNnGDyO0QD5s= mvdan.cc/sh/v3 v3.7.0 h1:lSTjdP/1xsddtaKfGg7Myu7DnlHItd3/M2tomOcNNBg= mvdan.cc/sh/v3 v3.7.0/go.mod h1:K2gwkaesF/D7av7Kxl0HbF5kGOd2ArupNTX3X44+8l8= +mvdan.cc/sh/v3 v3.10.0 h1:v9z7N1DLZ7owyLM/SXZQkBSXcwr2IGMm2LY2pmhVXj4= +mvdan.cc/sh/v3 v3.10.0/go.mod h1:z/mSSVyLFGZzqb3ZIKojjyqIx/xbmz/UHdCSv9HmqXY= diff --git a/pkg/backy/backy.go b/pkg/backy/backy.go index 3012449..8a18145 100644 --- a/pkg/backy/backy.go +++ b/pkg/backy/backy.go @@ -236,7 +236,8 @@ func notifyError(logger zerolog.Logger, templates *msgTemplates, list *CmdList, "CmdsRan": cmdsRan, "CmdOutput": outStructArr, "Err": err, - "Command": cmd.Name, + "CmdName": cmd.Name, + "Command": cmd.Cmd, "Args": cmd.Args, } var errMsg bytes.Buffer diff --git a/pkg/backy/config.go b/pkg/backy/config.go index 51a4410..b0bdb78 100644 --- a/pkg/backy/config.go +++ b/pkg/backy/config.go @@ -48,26 +48,29 @@ func (opts *ConfigOpts) InitConfig() { backyKoanf := koanf.New(".") opts.ConfigFilePath = strings.TrimSpace(opts.ConfigFilePath) - metadataFile := "hashMetadataSample.yml" + // metadataFile := "hashMetadataSample.yml" + cacheDir := homeCacheDir // Load metadata from file - opts.CachedData, err = remotefetcher.LoadMetadataFromFile(metadataFile) + opts.CachedData, err = remotefetcher.LoadMetadataFromFile(path.Join(backyHomeConfDir, "cache.yml")) if err != nil { fmt.Println("Error loading metadata:", err) - panic(err) + logging.ExitWithMSG(err.Error(), 1, &opts.Logger) } // Initialize cache with loaded metadata - cache, err := remotefetcher.NewCache(metadataFile, cacheDir) + cache, err := remotefetcher.NewCache(path.Join(backyHomeConfDir, "cache.yml"), cacheDir) if err != nil { fmt.Println("Error initializing cache:", err) - panic(err) + logging.ExitWithMSG(err.Error(), 1, &opts.Logger) } // Populate cache with loaded metadata for _, data := range opts.CachedData { - cache.AddDataToStore(data.Hash, *data) + if err := cache.AddDataToStore(data.Hash, *data); err != nil { + logging.ExitWithMSG(err.Error(), 1, &opts.Logger) + } } opts.Cache, err = remotefetcher.NewCache(path.Join(backyHomeConfDir, "cache.yml"), backyHomeConfDir) @@ -75,9 +78,9 @@ func (opts *ConfigOpts) InitConfig() { logging.ExitWithMSG(fmt.Sprintf("error initializing cache: %v", err), 1, nil) } // Initialize the fetcher - println("Creating new fetcher for source", opts.ConfigFilePath) - fetcher, err := remotefetcher.NewConfigFetcher(opts.ConfigFilePath, opts.Cache) - println("Created new fetcher for source", opts.ConfigFilePath) + // println("Creating new fetcher for source", opts.ConfigFilePath) + fetcher, err := remotefetcher.NewRemoteFetcher(opts.ConfigFilePath, opts.Cache) + // println("Created new fetcher for source", opts.ConfigFilePath) if err != nil { logging.ExitWithMSG(fmt.Sprintf("error initializing config fetcher: %v", err), 1, nil) @@ -92,7 +95,7 @@ func (opts *ConfigOpts) InitConfig() { opts.koanf = backyKoanf } -func loadConfigFile(fetcher remotefetcher.ConfigFetcher, filePath string, k *koanf.Koanf, opts *ConfigOpts) { +func loadConfigFile(fetcher remotefetcher.RemoteFetcher, filePath string, k *koanf.Koanf, opts *ConfigOpts) { data, err := fetcher.Fetch(filePath) if err != nil { logging.ExitWithMSG(fmt.Sprintf("Could not fetch config file %s: %v", filePath, err), 1, nil) @@ -103,7 +106,7 @@ func loadConfigFile(fetcher remotefetcher.ConfigFetcher, filePath string, k *koa } } -func loadDefaultConfigFiles(fetcher remotefetcher.ConfigFetcher, configFiles []string, k *koanf.Koanf, opts *ConfigOpts) { +func loadDefaultConfigFiles(fetcher remotefetcher.RemoteFetcher, configFiles []string, k *koanf.Koanf, opts *ConfigOpts) { cFileFailures := 0 for _, c := range configFiles { data, err := fetcher.Fetch(c) @@ -313,10 +316,10 @@ func getRemoteDir(filePath string) (string, *url.URL) { } func loadListConfigFile(filePath string, k *koanf.Koanf, opts *ConfigOpts) bool { - fetcher, err := remotefetcher.NewConfigFetcher(filePath, opts.Cache, remotefetcher.IgnoreFileNotFound()) + fetcher, err := remotefetcher.NewRemoteFetcher(filePath, opts.Cache, remotefetcher.IgnoreFileNotFound()) if err != nil { // if file not found, ignore - if errors.Is(err, remotefetcher.ErrFileNotFound) { + if errors.Is(err, remotefetcher.ErrIgnoreFileNotFound) { return true } @@ -342,7 +345,7 @@ func loadCmdListsFile(backyKoanf *koanf.Koanf, listsConfig *koanf.Koanf, opts *C opts.CmdListFile = path.Join(path.Dir(opts.ConfigFilePath), opts.CmdListFile) } - fetcher, err := remotefetcher.NewConfigFetcher(opts.CmdListFile, opts.Cache) + fetcher, err := remotefetcher.NewRemoteFetcher(opts.CmdListFile, opts.Cache) if err != nil { logging.ExitWithMSG(fmt.Sprintf("error initializing config fetcher: %v", err), 1, nil) @@ -603,23 +606,22 @@ func processCmds(opts *ConfigOpts) error { } } + + if cmd.Type == "remoteScript" { + if !isRemoteURL(cmd.Cmd) { + return fmt.Errorf("remoteScript command %s must be a remote resource", cmdName) + } + + } } return nil } // processHooks evaluates if hooks are valid Commands // -// Takes the following arguments: +// The cmd.hookRefs[hookType] is created with any hooks found. // -// 1. a []string of hooks -// 2. a map of Commands as arguments -// 3. a string hookType, must be the hook type -// -// The cmds.hookRef is modified in this function. -// -// Returns the following: -// -// An error, if any, if the command is not found +// Returns an error, if any, if the hook command is not found func processHooks(cmd *Command, hooks []string, opts *ConfigOpts, hookType string) error { // initialize hook type diff --git a/pkg/backy/templates/error.txt b/pkg/backy/templates/error.txt index d43c637..ae0a4a2 100644 --- a/pkg/backy/templates/error.txt +++ b/pkg/backy/templates/error.txt @@ -1,12 +1,12 @@ Command list {{.listName }} failed. -The command run was {{.Cmd}}. +The command run was {{.CmdName}}. The command executed was {{.Command}} {{ if .Args }} {{- range .Args}} {{.}} {{end}} {{end}} {{ if .Err }} The error was {{ .Err }}{{ end }} -{{ if .Output }} The output was {{- range .Output}} {{.}} {{end}} {{end}} +{{ if .Output }} The output was: {{- range .Output}} {{.}} {{end}} {{end}} {{ if .CmdsRan }} The following commands ran: diff --git a/pkg/backy/types.go b/pkg/backy/types.go index 682dbbc..56dc705 100644 --- a/pkg/backy/types.go +++ b/pkg/backy/types.go @@ -67,10 +67,7 @@ type ( // hook refs are internal references of commands for each hook type hookRefs map[string]map[string]*Command - /* - Shell specifies which shell to run the command in, if any. - Not applicable when host is defined. - */ + // Shell specifies which shell to run the command in, if any. Shell string `yaml:"shell,omitempty"` RemoteHost *Host `yaml:"-"` @@ -91,11 +88,14 @@ type ( Environment []string `yaml:"environment,omitempty"` // Output determines if output is requested. - // Only works if command is in a list. + // + // Only for when command is in a list. GetOutput bool `yaml:"getOutput,omitempty"` ScriptEnvFile string `yaml:"scriptEnvFile"` + // BEGIN PACKAGE COMMAND FIELDS + PackageManager string `yaml:"packageManager,omitempty"` PackageName string `yaml:"packageName,omitempty"` @@ -109,6 +109,7 @@ type ( pkgMan pkgman.PackageManager packageCmdSet bool + // END PACKAGE COMMAND FIELDS // RemoteSource specifies a URL to fetch the command or configuration remotely RemoteSource string `yaml:"remoteSource,omitempty"` @@ -116,8 +117,12 @@ type ( // FetchBeforeExecution determines if the remoteSource should be fetched before running FetchBeforeExecution bool `yaml:"fetchBeforeExecution,omitempty"` + // BEGIN USER COMMAND FIELDS + // Username specifies the username for user creation or related operations - Username string `yaml:"username,omitempty"` + Username string `yaml:"userName,omitempty"` + + UserID string `yaml:"userID,omitempty"` // UserGroups specifies the groups to add the user to UserGroups []string `yaml:"userGroups,omitempty"` @@ -144,12 +149,15 @@ type ( userCmdSet bool + // stdin only for userOperation = password (for now) stdin *strings.Reader + + // END USER STRUCT FIELDS } RemoteSource struct { URL string `yaml:"url"` - Type string `yaml:"type"` // e.g., yaml + Type string `yaml:"type"` // e.g., s3, http Auth struct { AccessKey string `yaml:"accessKey"` SecretKey string `yaml:"secretKey"` diff --git a/pkg/backy/utils.go b/pkg/backy/utils.go index 1349e67..a5f387f 100644 --- a/pkg/backy/utils.go +++ b/pkg/backy/utils.go @@ -43,7 +43,7 @@ func AddCommandLists(lists []string) BackyOptionFunc { } } -// AddPrintLists adds lists to print out +// SetListsToSearch adds lists to search func SetListsToSearch(lists []string) BackyOptionFunc { return func(bco *ConfigOpts) { bco.List.Lists = append(bco.List.Lists, lists...) @@ -64,8 +64,8 @@ func SetLogFile(logFile string) BackyOptionFunc { } } -// cronEnabled enables the execution of command lists at specified times -func CronEnabled() BackyOptionFunc { +// EnableCron enables the execution of command lists at specified times +func EnableCron() BackyOptionFunc { return func(bco *ConfigOpts) { bco.cronEnabled = true } diff --git a/pkg/pkgman/apt/apt.go b/pkg/pkgman/apt/apt.go index 0042508..761891a 100644 --- a/pkg/pkgman/apt/apt.go +++ b/pkg/pkgman/apt/apt.go @@ -40,7 +40,6 @@ func (a *AptManager) Install(pkg, version string, args []string) (string, []stri if args != nil { baseArgs = append(baseArgs, args...) } - fmt.Printf("baseArgs: %v\n", baseArgs) return baseCmd, baseArgs } diff --git a/pkg/remotefetcher/cache.go b/pkg/remotefetcher/cache.go index 8aa8116..51d046c 100644 --- a/pkg/remotefetcher/cache.go +++ b/pkg/remotefetcher/cache.go @@ -64,7 +64,6 @@ func (c *Cache) loadFromFile() error { } func (c *Cache) saveToFile() error { - // println("Saving cache to file:", c.file) c.mu.Lock() defer c.mu.Unlock() @@ -84,10 +83,8 @@ func (c *Cache) saveToFile() error { func (c *Cache) Get(hash string) ([]byte, CacheData, bool) { c.mu.Lock() defer c.mu.Unlock() - println("Getting cache data for hash:", hash) cacheData, exists := c.store[hash] if !exists { - println("Cache data does not exist for hash:", hash) return nil, CacheData{}, false } @@ -99,10 +96,9 @@ func (c *Cache) Get(hash string) ([]byte, CacheData, bool) { return data, cacheData, true } -func (c *Cache) AddDataToStore(hash string, cacheData CacheData) { - c.mu.Lock() - defer c.mu.Unlock() +func (c *Cache) AddDataToStore(hash string, cacheData CacheData) error { c.store[hash] = cacheData + return c.saveToFile() } func (c *Cache) Set(source, hash string, data []byte, dataType string) (CacheData, error) { @@ -164,9 +160,8 @@ func (cf *CachedFetcher) Hash(data []byte) string { return hex.EncodeToString(hash[:]) } -// Function to read and parse the hashMetadataSample.yml file +// Function to read and parse the metadata file func LoadMetadataFromFile(filePath string) ([]*CacheData, error) { - // fmt.Println("Loading metadata from file:", filePath) if _, err := os.Stat(filePath); os.IsNotExist(err) { // Create the file if it does not exist emptyData := []byte("[]") diff --git a/pkg/remotefetcher/configfetcher.go b/pkg/remotefetcher/configfetcher.go index 56cefd0..221a776 100644 --- a/pkg/remotefetcher/configfetcher.go +++ b/pkg/remotefetcher/configfetcher.go @@ -5,7 +5,7 @@ import ( "strings" ) -type ConfigFetcher interface { +type RemoteFetcher interface { // Fetch retrieves the configuration from the specified URL or source // Returns the raw data as bytes or an error Fetch(source string) ([]byte, error) @@ -18,30 +18,31 @@ type ConfigFetcher interface { Hash(data []byte) string } -// ErrFileNotFound is returned when the file is not found and should be ignored -var ErrFileNotFound = errors.New("remotefetcher: file not found") +// ErrIgnoreFileNotFound is returned when the file is not found and should be ignored +var ErrIgnoreFileNotFound = errors.New("remotefetcher: file not found") -func NewConfigFetcher(source string, cache *Cache, options ...Option) (ConfigFetcher, error) { - var fetcher ConfigFetcher - var dataType string +func NewRemoteFetcher(source string, cache *Cache, options ...FetcherOption) (RemoteFetcher, error) { + var fetcher RemoteFetcher config := FetcherConfig{} for _, option := range options { option(&config) } + + // If FileType is empty (i.e. WithFileType was not called), yaml is the default file type + if strings.TrimSpace(config.FileType) == "" { + config.FileType = "yaml" + } if strings.HasPrefix(source, "http") || strings.HasPrefix(source, "https") { fetcher = NewHTTPFetcher(options...) - dataType = "yaml" } else if strings.HasPrefix(source, "s3") { var err error - fetcher, err = NewS3Fetcher(options...) + fetcher, err = NewS3Fetcher(source, options...) if err != nil { return nil, err } - dataType = "yaml" } else { fetcher = &LocalFetcher{} - dataType = "yaml" return fetcher, nil } @@ -51,7 +52,7 @@ func NewConfigFetcher(source string, cache *Cache, options ...Option) (ConfigFet data, err := fetcher.Fetch(source) if err != nil { if config.IgnoreFileNotFound && isFileNotFoundError(err) { - return nil, ErrFileNotFound + return nil, ErrIgnoreFileNotFound } return nil, err } @@ -61,7 +62,7 @@ func NewConfigFetcher(source string, cache *Cache, options ...Option) (ConfigFet return &CachedFetcher{data: cachedData, path: cacheMeta.Path, dataType: cacheMeta.Type}, nil } - cacheData, err := cache.Set(source, hash, data, dataType) + cacheData, err := cache.Set(source, hash, data, config.FileType) if err != nil { return nil, err } diff --git a/pkg/remotefetcher/http.go b/pkg/remotefetcher/http.go index cf53dc3..d1d2a2b 100644 --- a/pkg/remotefetcher/http.go +++ b/pkg/remotefetcher/http.go @@ -16,7 +16,7 @@ type HTTPFetcher struct { } // NewHTTPFetcher creates a new instance of HTTPFetcher with the provided options. -func NewHTTPFetcher(options ...Option) *HTTPFetcher { +func NewHTTPFetcher(options ...FetcherOption) *HTTPFetcher { cfg := &FetcherConfig{} for _, opt := range options { opt(cfg) @@ -39,7 +39,7 @@ func (h *HTTPFetcher) Fetch(source string) ([]byte, error) { defer resp.Body.Close() if resp.StatusCode == http.StatusNotFound && h.config.IgnoreFileNotFound { - return nil, ErrFileNotFound + return nil, ErrIgnoreFileNotFound } if resp.StatusCode != http.StatusOK { diff --git a/pkg/remotefetcher/local.go b/pkg/remotefetcher/local.go index a4d81d3..b131597 100644 --- a/pkg/remotefetcher/local.go +++ b/pkg/remotefetcher/local.go @@ -18,7 +18,7 @@ func (l *LocalFetcher) Fetch(source string) ([]byte, error) { // Check if the file exists if _, err := os.Stat(source); os.IsNotExist(err) { if l.config.IgnoreFileNotFound { - return nil, ErrFileNotFound + return nil, ErrIgnoreFileNotFound } return nil, nil } diff --git a/pkg/remotefetcher/options.go b/pkg/remotefetcher/options.go index 9d4f0ae..c68f1ca 100644 --- a/pkg/remotefetcher/options.go +++ b/pkg/remotefetcher/options.go @@ -2,36 +2,48 @@ package remotefetcher import ( "net/http" + "strings" "github.com/aws/aws-sdk-go-v2/service/s3" ) // Option is a function that configures a fetcher. -type Option func(*FetcherConfig) +type FetcherOption func(*FetcherConfig) // FetcherConfig holds the configuration for a fetcher. type FetcherConfig struct { S3Client *s3.Client HTTPClient *http.Client + FileType string IgnoreFileNotFound bool } // WithS3Client sets the S3 client for the fetcher. -func WithS3Client(client *s3.Client) Option { +func WithS3Client(client *s3.Client) FetcherOption { return func(cfg *FetcherConfig) { cfg.S3Client = client } } // WithHTTPClient sets the HTTP client for the fetcher. -func WithHTTPClient(client *http.Client) Option { +func WithHTTPClient(client *http.Client) FetcherOption { return func(cfg *FetcherConfig) { cfg.HTTPClient = client } } -func IgnoreFileNotFound() Option { +func IgnoreFileNotFound() FetcherOption { return func(cfg *FetcherConfig) { cfg.IgnoreFileNotFound = true } } + +// WithFileType ensures the default FileType will be yaml +func WithFileType(fileType string) FetcherOption { + return func(cfg *FetcherConfig) { + cfg.FileType = fileType + if strings.TrimSpace(fileType) == "" { + cfg.FileType = "yaml" + } + } +} diff --git a/pkg/remotefetcher/s3.go b/pkg/remotefetcher/s3.go index 4c97283..338eec2 100644 --- a/pkg/remotefetcher/s3.go +++ b/pkg/remotefetcher/s3.go @@ -1,71 +1,109 @@ package remotefetcher import ( - "bytes" "context" "crypto/sha256" "encoding/hex" "errors" + "io" + "net/http" + "net/url" + "os" + "path" "strings" - "github.com/aws/aws-sdk-go-v2/config" - "github.com/aws/aws-sdk-go-v2/service/s3" - "github.com/aws/aws-sdk-go-v2/service/s3/types" + "github.com/minio/minio-go/v7" + "github.com/minio/minio-go/v7/pkg/credentials" + "github.com/mitchellh/go-homedir" "gopkg.in/yaml.v3" ) type S3Fetcher struct { - S3Client *s3.Client + S3Client *minio.Client config FetcherConfig } // NewS3Fetcher creates a new instance of S3Fetcher with the provided options. -func NewS3Fetcher(options ...Option) (*S3Fetcher, error) { +func NewS3Fetcher(endpoint string, options ...FetcherOption) (*S3Fetcher, error) { cfg := &FetcherConfig{} + var s3Client *minio.Client + var err error for _, opt := range options { opt(cfg) } + /* + options for S3 urls: + 1. s3://bucket.region.endpoint.tld/path/to/object + 2. alias with path and rest is looked up in file - add FetcherOptions + + + options for S3 credentials: + 1. from file ($HOME/.aws/credentials) + 2. env vars (AWS_SECRET_KEY, etc.) + */ + + s3Endpoint := os.Getenv("S3_ENDPOINT") + creds, err := getS3Credentials("default", s3Endpoint, cfg.HTTPClient) + if err != nil { + println(err.Error()) + return nil, err + } // Initialize S3 client if not provided if cfg.S3Client == nil { - awsCfg, err := config.LoadDefaultConfig(context.TODO()) + s3Client, err = minio.New(s3Endpoint, &minio.Options{ + Creds: creds, + Secure: true, + }) + if err != nil { return nil, err } - cfg.S3Client = s3.NewFromConfig(awsCfg) + } - return &S3Fetcher{S3Client: cfg.S3Client, config: *cfg}, nil + return &S3Fetcher{S3Client: s3Client, config: *cfg}, nil } // Fetch retrieves the configuration from an S3 bucket // Source should be in the format "bucket-name/object-key" func (s *S3Fetcher) Fetch(source string) ([]byte, error) { - bucket, key, err := parseS3Source(source) + bucket, object, err := parseS3Source(source) if err != nil { return nil, err } - resp, err := s.S3Client.GetObject(context.TODO(), &s3.GetObjectInput{ - Bucket: &bucket, - Key: &key, - }) - if err != nil { - var notFound *types.NoSuchKey - if errors.As(err, ¬Found) && s.config.IgnoreFileNotFound { - return nil, ErrFileNotFound + doesObjectExist, objErr := objectExists(bucket, object, s.S3Client) + if !doesObjectExist { + if objErr != nil { + return nil, err } + + if s.config.IgnoreFileNotFound { + return nil, ErrIgnoreFileNotFound + } + } + + fileObject, err := s.S3Client.GetObject(context.TODO(), bucket, object, minio.GetObjectOptions{}) + if err != nil { + println(err.Error()) + return nil, err } - defer resp.Body.Close() + defer fileObject.Close() + fileObjectStats, statErr := fileObject.Stat() + if statErr != nil { + return nil, statErr + } + buffer := make([]byte, fileObjectStats.Size) - buf := new(bytes.Buffer) - _, err = buf.ReadFrom(resp.Body) + // Read the object into the buffer + _, err = io.ReadFull(fileObject, buffer) if err != nil { return nil, err } - return buf.Bytes(), nil + return buffer, nil } // Parse decodes the raw data into the provided target structure @@ -79,10 +117,46 @@ func parseS3Source(source string) (bucket, key string, err error) { if len(parts) != 2 { return "", "", errors.New("invalid S3 source format, expected bucket-name/object-key") } - return parts[0], parts[1], nil + u, _ := url.Parse(source) + u.Path = strings.TrimPrefix(u.Path, "/") + return u.Host, u.Path, nil } func (s *S3Fetcher) Hash(data []byte) string { hash := sha256.Sum256(data) return hex.EncodeToString(hash[:]) } + +func getS3Credentials(profile, host string, httpClient *http.Client) (*credentials.Credentials, error) { + // println(s3utils.GetRegionFromURL(*u)) + homeDir, hdirErr := homedir.Dir() + if hdirErr != nil { + return nil, hdirErr + } + s3Creds := credentials.NewFileAWSCredentials(path.Join(homeDir, ".aws", "credentials"), "default") + credVals, credErr := s3Creds.GetWithContext(&credentials.CredContext{Endpoint: host, Client: httpClient}) + if credErr != nil { + return nil, credErr + } + creds := credentials.NewStaticV4(credVals.AccessKeyID, credVals.SecretAccessKey, "") + return creds, nil +} + +var ( + doesNotExist = "The specified key does not exist." +) + +// objectExists checks for name in bucket using client. +// It returns false and nil if the key does not exist +func objectExists(bucket, name string, client *minio.Client) (bool, error) { + _, err := client.StatObject(context.TODO(), bucket, name, minio.StatObjectOptions{}) + if err != nil { + switch err.Error() { + case doesNotExist: + return false, nil + default: + return false, errors.Join(err, errors.New("error stating object")) + } + } + return true, nil +} diff --git a/pkg/usermanager/common/options.go b/pkg/usermanager/common/options.go new file mode 100644 index 0000000..9c9416f --- /dev/null +++ b/pkg/usermanager/common/options.go @@ -0,0 +1,7 @@ +package common + +// ConfigurablePackageManager defines methods for setting configuration options. +type ConfigurableUserManager interface { + SetUseAuth(useAuth bool) + SetAuthCommand(authCommand string) +} diff --git a/pkg/usermanager/userman.go b/pkg/usermanager/userman.go index 9532d28..d0f6a4d 100644 --- a/pkg/usermanager/userman.go +++ b/pkg/usermanager/userman.go @@ -20,6 +20,7 @@ type UserManager interface { UserExists(username string) (string, []string) } +// NewUserManager returns a UserManager-compatible struct func NewUserManager(system string) (UserManager, error) { var manager UserManager