forked from toolshed/abra
Compare commits
1 Commits
abra-app-m
...
private-re
Author | SHA1 | Date | |
---|---|---|---|
7a24bf9cd5 |
@ -1,6 +1,6 @@
|
|||||||
# integration test suite
|
# integration test suite
|
||||||
# export ABRA_DIR="$HOME/.abra_test"
|
# export ABRA_DIR="$HOME/.abra_test"
|
||||||
# export TEST_SERVER=test.example.com
|
# export ABRA_TEST_DOMAIN=test.example.com
|
||||||
# export ABRA_CI=1
|
# export ABRA_CI=1
|
||||||
|
|
||||||
# release automation
|
# release automation
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/leonelquinteros/gotext"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var AppCommand = &cobra.Command{
|
var AppCommand = &cobra.Command{
|
||||||
Use: "app [cmd] [args] [flags]",
|
Use: "app [cmd] [args] [flags]",
|
||||||
Aliases: []string{"a"},
|
Aliases: []string{"a"},
|
||||||
Short: gotext.Get("Manage apps"),
|
Short: "Manage apps",
|
||||||
}
|
}
|
||||||
|
@ -108,12 +108,8 @@ checkout as-is. Recipe commit hashes are also supported as values for
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := lint.LintForErrors(app.Recipe); err != nil {
|
if err := lint.LintForErrors(app.Recipe); err != nil {
|
||||||
if internal.Chaos {
|
|
||||||
log.Warn(err)
|
|
||||||
} else {
|
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if err := validateSecrets(cl, app); err != nil {
|
if err := validateSecrets(cl, app); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -142,7 +142,7 @@ Use "--status/-S" flag to query all servers for the live deployment status.`,
|
|||||||
appStats.AutoUpdate = autoUpdate
|
appStats.AutoUpdate = autoUpdate
|
||||||
|
|
||||||
var newUpdates []string
|
var newUpdates []string
|
||||||
if version != "unknown" && chaos == "false" {
|
if version != "unknown" && chaosVersion == "unknown" {
|
||||||
if err := app.Recipe.EnsureExists(); err != nil {
|
if err := app.Recipe.EnsureExists(); err != nil {
|
||||||
log.Fatalf("unable to clone %s: %s", app.Name, err)
|
log.Fatalf("unable to clone %s: %s", app.Name, err)
|
||||||
}
|
}
|
||||||
|
313
cli/app/move.go
313
cli/app/move.go
@ -1,313 +0,0 @@
|
|||||||
package app
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"coopcloud.tech/abra/cli/internal"
|
|
||||||
"coopcloud.tech/abra/pkg/app"
|
|
||||||
appPkg "coopcloud.tech/abra/pkg/app"
|
|
||||||
"coopcloud.tech/abra/pkg/autocomplete"
|
|
||||||
"coopcloud.tech/abra/pkg/client"
|
|
||||||
containerPkg "coopcloud.tech/abra/pkg/container"
|
|
||||||
"coopcloud.tech/abra/pkg/log"
|
|
||||||
"coopcloud.tech/abra/pkg/secret"
|
|
||||||
"coopcloud.tech/abra/pkg/upstream/stack"
|
|
||||||
"github.com/docker/docker/api/types"
|
|
||||||
containertypes "github.com/docker/docker/api/types/container"
|
|
||||||
"github.com/docker/docker/api/types/filters"
|
|
||||||
"github.com/docker/docker/api/types/mount"
|
|
||||||
"github.com/docker/docker/api/types/swarm"
|
|
||||||
"github.com/docker/docker/api/types/volume"
|
|
||||||
dockerclient "github.com/docker/docker/client"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
var AppMoveCommand = &cobra.Command{
|
|
||||||
Use: "move <domain> <server> [flags]",
|
|
||||||
Short: "Moves an app to a different server",
|
|
||||||
Long: `Move an app to a differnt server.
|
|
||||||
|
|
||||||
This will copy secrets and volumes from the old server to the new one. It will also undeploy the app from old server but not deploy it on the new. You will have to do that your self, after the move finished.
|
|
||||||
|
|
||||||
Use "--dry-run/-r" to see which secrets and volumes will be moved.`,
|
|
||||||
Example: ` # moving an app
|
|
||||||
abra app move nextcloud.example.com myserver.com`,
|
|
||||||
Args: cobra.RangeArgs(1, 2),
|
|
||||||
ValidArgsFunction: func(
|
|
||||||
cmd *cobra.Command,
|
|
||||||
args []string,
|
|
||||||
toComplete string,
|
|
||||||
) ([]string, cobra.ShellCompDirective) {
|
|
||||||
switch l := len(args); l {
|
|
||||||
case 0:
|
|
||||||
return autocomplete.AppNameComplete()
|
|
||||||
case 1:
|
|
||||||
return autocomplete.ServerNameComplete()
|
|
||||||
default:
|
|
||||||
return nil, cobra.ShellCompDirectiveDefault
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
app := internal.ValidateApp(args)
|
|
||||||
if len(args) <= 1 {
|
|
||||||
log.Fatal("no server provided")
|
|
||||||
}
|
|
||||||
newServer := args[1]
|
|
||||||
|
|
||||||
if err := app.Recipe.Ensure(internal.GetEnsureContext()); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cl, err := client.New(app.Server)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
resources, err := getAppResources(cl, app)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal.MoveOverview(app, newServer, resources.SecretNames(), resources.VolumeNames())
|
|
||||||
if err := internal.PromptProcced(); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: wait timeout will be removed, until it actually is just set it to a high value.
|
|
||||||
stack.WaitTimeout = 500
|
|
||||||
rmOpts := stack.Remove{
|
|
||||||
Namespaces: []string{app.StackName()},
|
|
||||||
Detach: false,
|
|
||||||
}
|
|
||||||
if err := stack.RunRemove(context.Background(), cl, rmOpts); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cl2, err := client.New(newServer)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range resources.SecretList {
|
|
||||||
sname := strings.Split(strings.TrimPrefix(s.Spec.Name, app.StackName()+"_"), "_")
|
|
||||||
secretName := strings.Join(sname[:len(sname)-1], "_")
|
|
||||||
data := resources.Secrets[secretName]
|
|
||||||
if err := client.StoreSecret(cl2, s.Spec.Name, data); err != nil {
|
|
||||||
log.Infof("creating secret: %s", s.Spec.Name)
|
|
||||||
log.Errorf("failed to store secret on new server: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range resources.Volumes {
|
|
||||||
log.Infof("moving volume: %s", v.Name)
|
|
||||||
|
|
||||||
// Need to create the volume before copying the data, because when
|
|
||||||
// docker creates a new volume it set the folder permissions to
|
|
||||||
// root, which might be wrong. This ensures we always have the
|
|
||||||
// correct folder permissions inside the volume.
|
|
||||||
log.Debug("creating volume: %s", v.Name)
|
|
||||||
_, err := cl2.VolumeCreate(context.Background(), volume.CreateOptions{
|
|
||||||
Name: v.Name,
|
|
||||||
Driver: v.Driver,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed to create volume: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fileName := fmt.Sprintf("%s.tar.gz", v.Name)
|
|
||||||
log.Debug("creating %s", fileName)
|
|
||||||
cmd := exec.Command("ssh", app.Server, "-tt", fmt.Sprintf("sudo tar --same-owner -czhpf %s -C /var/lib/docker/volumes %s", fileName, v.Name))
|
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
|
||||||
log.Errorf("failed to tar volume: %s", err)
|
|
||||||
fmt.Println(string(out))
|
|
||||||
}
|
|
||||||
log.Debug("copying %s to local machine", fileName)
|
|
||||||
cmd = exec.Command("scp", fmt.Sprintf("%s:%s", app.Server, fileName), fileName)
|
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
|
||||||
log.Errorf("failed to copy tar to local machine: %s", err)
|
|
||||||
fmt.Println(string(out))
|
|
||||||
}
|
|
||||||
log.Debug("copying %s to %s", fileName, newServer)
|
|
||||||
cmd = exec.Command("scp", fileName, fmt.Sprintf("%s:%s", newServer, fileName))
|
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
|
||||||
log.Errorf("failed to copy tar to new server: %s", err)
|
|
||||||
fmt.Println(string(out))
|
|
||||||
}
|
|
||||||
log.Debug("extracting %s on %s", fileName, newServer)
|
|
||||||
cmd = exec.Command("ssh", newServer, "-tt", fmt.Sprintf("sudo tar --same-owner -xzpf %s -C /var/lib/docker/volumes", fileName))
|
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
|
||||||
log.Errorf("failed to extract tar: %s", err)
|
|
||||||
fmt.Println(string(out))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove tar files
|
|
||||||
cmd = exec.Command("ssh", newServer, "-tt", fmt.Sprintf("sudo rm %s", fileName))
|
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
|
||||||
log.Errorf("failed to remove tar from new server: %s", err)
|
|
||||||
fmt.Println(string(out))
|
|
||||||
}
|
|
||||||
cmd = exec.Command("ssh", app.Server, "-tt", fmt.Sprintf("sudo rm %s", fileName))
|
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
|
||||||
log.Errorf("failed to remove tar from old server: %s", err)
|
|
||||||
fmt.Println(string(out))
|
|
||||||
}
|
|
||||||
cmd = exec.Command("rm", fileName)
|
|
||||||
if out, err := cmd.CombinedOutput(); err != nil {
|
|
||||||
log.Errorf("failed to remove tar on local machine: %s", err)
|
|
||||||
fmt.Println(string(out))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debug("moving app config to new server")
|
|
||||||
if err := copyFile(app.Path, strings.ReplaceAll(app.Path, app.Server, newServer)); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
if err := os.Remove(app.Path); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("% was succefully moved to %s", app.Name, newServer)
|
|
||||||
fmt.Println("Run the following command to deploy the app", app.Name, newServer)
|
|
||||||
fmt.Println(" abra app deploy --no-domain-checks", app.Domain)
|
|
||||||
fmt.Println()
|
|
||||||
fmt.Println("And don't forget to update you DNS record. And don't panic, as it might take a bit for the dust to settle. Traefik for example might fail to obtain the lets encrypt certificate for a while.", app.Domain)
|
|
||||||
fmt.Println()
|
|
||||||
fmt.Println("If anything goes wrong, you can always move the app config file to the original server and deploy it there again. There was no data removed on the old server")
|
|
||||||
return
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
type AppResources struct {
|
|
||||||
Secrets map[string]string
|
|
||||||
SecretList []swarm.Secret
|
|
||||||
Volumes map[string]containertypes.MountPoint
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *AppResources) SecretNames() []string {
|
|
||||||
secrets := []string{}
|
|
||||||
for name := range a.Secrets {
|
|
||||||
secrets = append(secrets, name)
|
|
||||||
}
|
|
||||||
return secrets
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *AppResources) VolumeNames() []string {
|
|
||||||
volumes := []string{}
|
|
||||||
for name := range a.Volumes {
|
|
||||||
volumes = append(volumes, name)
|
|
||||||
}
|
|
||||||
return volumes
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAppResources(cl *dockerclient.Client, app app.App) (*AppResources, error) {
|
|
||||||
filter, err := app.Filters(false, false)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
services, err := cl.ServiceList(context.Background(), types.ServiceListOptions{Filters: filter})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
composeFiles, err := app.Recipe.GetComposeFiles(app.Env)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
secretList, err := cl.SecretList(context.Background(), types.SecretListOptions{Filters: filter})
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
secretConfigs, err := secret.ReadSecretsConfig(app.Path, composeFiles, app.StackName())
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
opts := stack.Deploy{Composefiles: composeFiles, Namespace: app.StackName()}
|
|
||||||
compose, err := appPkg.GetAppComposeConfig(app.Name, opts, app.Env)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
resources := &AppResources{
|
|
||||||
Secrets: make(map[string]string),
|
|
||||||
SecretList: secretList,
|
|
||||||
Volumes: make(map[string]containertypes.MountPoint),
|
|
||||||
}
|
|
||||||
for _, s := range services {
|
|
||||||
secretNames := map[string]string{}
|
|
||||||
for _, serviceCompose := range compose.Services {
|
|
||||||
if app.StackName()+"_"+serviceCompose.Name != s.Spec.Name {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, secret := range serviceCompose.Secrets {
|
|
||||||
for _, s := range secretList {
|
|
||||||
if s.Spec.Name == app.StackName()+"_"+secret.Source+"_"+secretConfigs[secret.Source].Version {
|
|
||||||
secretNames[secret.Source] = s.ID
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
f := filters.NewArgs()
|
|
||||||
f.Add("name", s.Spec.Name)
|
|
||||||
targetContainer, err := containerPkg.GetContainer(context.Background(), cl, f, true)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, m := range targetContainer.Mounts {
|
|
||||||
if m.Type == mount.TypeVolume {
|
|
||||||
resources.Volumes[m.Name] = m
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for secretName, secretID := range secretNames {
|
|
||||||
if _, ok := resources.Secrets[secretName]; ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
log.Debugf("extracting secret %s", secretName)
|
|
||||||
|
|
||||||
out, err := exec.Command("ssh", app.Server, "-tt", fmt.Sprintf("sudo cat /var/lib/docker/containers/%s/mounts/secrets/%s", targetContainer.ID, secretID)).Output()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(string(out))
|
|
||||||
fmt.Println(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
resources.Secrets[secretName] = string(out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return resources, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyFile(src string, dst string) error {
|
|
||||||
// Read all content of src to data, may cause OOM for a large file.
|
|
||||||
data, err := os.ReadFile(src)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Write data to dst
|
|
||||||
err = os.WriteFile(dst, data, 0o644)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
AppMoveCommand.Flags().BoolVarP(
|
|
||||||
&internal.Dry,
|
|
||||||
"dry-run",
|
|
||||||
"r",
|
|
||||||
false,
|
|
||||||
"report changes that would be made",
|
|
||||||
)
|
|
||||||
}
|
|
@ -9,7 +9,7 @@ import (
|
|||||||
"coopcloud.tech/abra/pkg/autocomplete"
|
"coopcloud.tech/abra/pkg/autocomplete"
|
||||||
"coopcloud.tech/abra/pkg/client"
|
"coopcloud.tech/abra/pkg/client"
|
||||||
"coopcloud.tech/abra/pkg/log"
|
"coopcloud.tech/abra/pkg/log"
|
||||||
"coopcloud.tech/abra/pkg/upstream/stack"
|
stack "coopcloud.tech/abra/pkg/upstream/stack"
|
||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@ -78,22 +78,6 @@ flag.`,
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
configs, err := client.GetConfigs(cl, context.Background(), app.Server, fs)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
configNames := client.GetConfigNames(configs)
|
|
||||||
|
|
||||||
if len(configNames) > 0 {
|
|
||||||
if err := client.RemoveConfigs(cl, context.Background(), configNames, internal.Force); err != nil {
|
|
||||||
log.Fatalf("removing configs failed: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("%d config(s) removed successfully", len(configNames))
|
|
||||||
} else {
|
|
||||||
log.Info("no configs to remove")
|
|
||||||
}
|
|
||||||
|
|
||||||
secretList, err := cl.SecretList(context.Background(), types.SecretListOptions{Filters: fs})
|
secretList, err := cl.SecretList(context.Background(), types.SecretListOptions{Filters: fs})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@ -136,7 +120,7 @@ flag.`,
|
|||||||
log.Fatalf("removing volumes failed: %s", err)
|
log.Fatalf("removing volumes failed: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("%d volume(s) removed successfully", len(volumeNames))
|
log.Infof("%d volumes removed successfully", len(volumeNames))
|
||||||
} else {
|
} else {
|
||||||
log.Info("no volumes to remove")
|
log.Info("no volumes to remove")
|
||||||
}
|
}
|
||||||
|
@ -145,17 +145,9 @@ var AppSecretInsertCommand = &cobra.Command{
|
|||||||
Short: "Insert secret",
|
Short: "Insert secret",
|
||||||
Long: `This command inserts a secret into an app environment.
|
Long: `This command inserts a secret into an app environment.
|
||||||
|
|
||||||
Arbitrary secret insertion is not supported. Secrets that are inserted must
|
|
||||||
match those configured in the recipe beforehand.
|
|
||||||
|
|
||||||
This can be useful when you want to manually generate secrets for an app
|
This can be useful when you want to manually generate secrets for an app
|
||||||
environment. Typically, you can let Abra generate them for you on app creation
|
environment. Typically, you can let Abra generate them for you on app creation
|
||||||
(see "abra app new --secrets/-S" for more).`,
|
(see "abra app new --secrets/-S" for more).`,
|
||||||
Example: ` # insert regular secret
|
|
||||||
abra app secret insert 1312.net my_secret v1 mySuperSecret
|
|
||||||
|
|
||||||
# insert secret as file
|
|
||||||
abra app secret insert 1312.net my_secret v1 secret.txt -f`,
|
|
||||||
Args: cobra.MinimumNArgs(4),
|
Args: cobra.MinimumNArgs(4),
|
||||||
ValidArgsFunction: func(
|
ValidArgsFunction: func(
|
||||||
cmd *cobra.Command,
|
cmd *cobra.Command,
|
||||||
@ -191,26 +183,6 @@ environment. Typically, you can let Abra generate them for you on app creation
|
|||||||
version := args[2]
|
version := args[2]
|
||||||
data := args[3]
|
data := args[3]
|
||||||
|
|
||||||
composeFiles, err := app.Recipe.GetComposeFiles(app.Env)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
secrets, err := secret.ReadSecretsConfig(app.Path, composeFiles, app.StackName())
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var isRecipeSecret bool
|
|
||||||
for secretName := range secrets {
|
|
||||||
if secretName == name {
|
|
||||||
isRecipeSecret = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !isRecipeSecret {
|
|
||||||
log.Fatalf("no secret %s available for recipe %s?", name, app.Recipe.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if insertFromFile {
|
if insertFromFile {
|
||||||
raw, err := os.ReadFile(data)
|
raw, err := os.ReadFile(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -224,7 +196,7 @@ environment. Typically, you can let Abra generate them for you on app creation
|
|||||||
}
|
}
|
||||||
|
|
||||||
secretName := fmt.Sprintf("%s_%s_%s", app.StackName(), name, version)
|
secretName := fmt.Sprintf("%s_%s_%s", app.StackName(), name, version)
|
||||||
if err := client.StoreSecret(cl, secretName, data); err != nil {
|
if err := client.StoreSecret(cl, secretName, data, app.Server); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,11 +233,6 @@ var AppSecretRmCommand = &cobra.Command{
|
|||||||
Use: "remove <domain> [[secret] | --all] [flags]",
|
Use: "remove <domain> [[secret] | --all] [flags]",
|
||||||
Aliases: []string{"rm"},
|
Aliases: []string{"rm"},
|
||||||
Short: "Remove a secret",
|
Short: "Remove a secret",
|
||||||
Long: `This command removes a secret from an app environment.
|
|
||||||
|
|
||||||
Arbitrary secret removal is not supported. Secrets that are removed must
|
|
||||||
match those configured in the recipe beforehand.`,
|
|
||||||
Example: " abra app secret rm 1312.net oauth_key",
|
|
||||||
Args: cobra.RangeArgs(1, 2),
|
Args: cobra.RangeArgs(1, 2),
|
||||||
ValidArgsFunction: func(
|
ValidArgsFunction: func(
|
||||||
cmd *cobra.Command,
|
cmd *cobra.Command,
|
||||||
|
@ -38,10 +38,6 @@ Passing "--prune/-p" does not remove those volumes.`,
|
|||||||
app := internal.ValidateApp(args)
|
app := internal.ValidateApp(args)
|
||||||
stackName := app.StackName()
|
stackName := app.StackName()
|
||||||
|
|
||||||
if err := app.Recipe.EnsureExists(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cl, err := client.New(app.Server)
|
cl, err := client.New(app.Server)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -117,7 +117,7 @@ beforehand. See "abra app backup" for more.`,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if deployMeta.Version != config.UNKNOWN_DEFAULT && chosenUpgrade == "" {
|
if deployMeta.Version != config.UNKNOWN_DEFAULT && chosenUpgrade == "" {
|
||||||
upgradeAvailable, err := ensureUpgradesAvailable(app, versions, &availableUpgrades, deployMeta)
|
upgradeAvailable, err := ensureUpgradesAvailable(versions, &availableUpgrades, deployMeta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -314,18 +314,18 @@ func getReleaseNotes(
|
|||||||
) error {
|
) error {
|
||||||
parsedChosenUpgrade, err := tagcmp.Parse(chosenUpgrade)
|
parsedChosenUpgrade, err := tagcmp.Parse(chosenUpgrade)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("parsing chosen upgrade version failed: %s", err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version)
|
parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("parsing deployment version failed: %s", err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, version := range internal.SortVersionsDesc(versions) {
|
for _, version := range internal.SortVersionsDesc(versions) {
|
||||||
parsedVersion, err := tagcmp.Parse(version)
|
parsedVersion, err := tagcmp.Parse(version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("parsing recipe version failed: %s", err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if parsedVersion.IsGreaterThan(parsedDeployedVersion) &&
|
if parsedVersion.IsGreaterThan(parsedDeployedVersion) &&
|
||||||
@ -351,20 +351,19 @@ func getReleaseNotes(
|
|||||||
|
|
||||||
// ensureUpgradesAvailable ensures that there are available upgrades.
|
// ensureUpgradesAvailable ensures that there are available upgrades.
|
||||||
func ensureUpgradesAvailable(
|
func ensureUpgradesAvailable(
|
||||||
app app.App,
|
|
||||||
versions []string,
|
versions []string,
|
||||||
availableUpgrades *[]string,
|
availableUpgrades *[]string,
|
||||||
deployMeta stack.DeployMeta,
|
deployMeta stack.DeployMeta,
|
||||||
) (bool, error) {
|
) (bool, error) {
|
||||||
parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version)
|
parsedDeployedVersion, err := tagcmp.Parse(deployMeta.Version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("parsing deployed version failed: %s", err)
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, version := range versions {
|
for _, version := range versions {
|
||||||
parsedVersion, err := tagcmp.Parse(version)
|
parsedVersion, err := tagcmp.Parse(version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("parsing recipe version failed: %s", err)
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if parsedVersion.IsGreaterThan(parsedDeployedVersion) &&
|
if parsedVersion.IsGreaterThan(parsedDeployedVersion) &&
|
||||||
|
@ -2,7 +2,6 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"coopcloud.tech/abra/cli/internal"
|
"coopcloud.tech/abra/cli/internal"
|
||||||
"coopcloud.tech/abra/pkg/autocomplete"
|
"coopcloud.tech/abra/pkg/autocomplete"
|
||||||
@ -72,7 +71,7 @@ var AppVolumeListCommand = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
var AppVolumeRemoveCommand = &cobra.Command{
|
var AppVolumeRemoveCommand = &cobra.Command{
|
||||||
Use: "remove <domain> [volume] [flags]",
|
Use: "remove <domain> [flags]",
|
||||||
Short: "Remove volume(s) associated with an app",
|
Short: "Remove volume(s) associated with an app",
|
||||||
Long: `Remove volumes associated with an app.
|
Long: `Remove volumes associated with an app.
|
||||||
|
|
||||||
@ -84,11 +83,6 @@ you to make a seclection. Use the "?" key to see more help on navigating this
|
|||||||
interface.
|
interface.
|
||||||
|
|
||||||
Passing "--force/-f" will select all volumes for removal. Be careful.`,
|
Passing "--force/-f" will select all volumes for removal. Be careful.`,
|
||||||
Example: ` # delete volumes interactively
|
|
||||||
abra app volume rm 1312.net
|
|
||||||
|
|
||||||
# delete specific volume
|
|
||||||
abra app volume rm 1312.net my_volume`,
|
|
||||||
Aliases: []string{"rm"},
|
Aliases: []string{"rm"},
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
ValidArgsFunction: func(
|
ValidArgsFunction: func(
|
||||||
@ -100,11 +94,6 @@ Passing "--force/-f" will select all volumes for removal. Be careful.`,
|
|||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
app := internal.ValidateApp(args)
|
app := internal.ValidateApp(args)
|
||||||
|
|
||||||
var volumeToDelete string
|
|
||||||
if len(args) == 2 {
|
|
||||||
volumeToDelete = args[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
cl, err := client.New(app.Server)
|
cl, err := client.New(app.Server)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@ -130,30 +119,6 @@ Passing "--force/-f" will select all volumes for removal. Be careful.`,
|
|||||||
}
|
}
|
||||||
volumeNames := client.GetVolumeNames(volumeList)
|
volumeNames := client.GetVolumeNames(volumeList)
|
||||||
|
|
||||||
if volumeToDelete != "" {
|
|
||||||
var exactMatch bool
|
|
||||||
|
|
||||||
fullVolumeToDeleteName := fmt.Sprintf("%s_%s", app.StackName(), volumeToDelete)
|
|
||||||
for _, volName := range volumeNames {
|
|
||||||
if volName == fullVolumeToDeleteName {
|
|
||||||
exactMatch = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !exactMatch {
|
|
||||||
log.Fatalf("unable to remove volume: no volume with name '%s'?", volumeToDelete)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := client.RemoveVolumes(cl, context.Background(), []string{fullVolumeToDeleteName}, internal.Force, 5)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("removing volume %s failed: %s", volumeToDelete, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("volume %s removed successfully", volumeToDelete)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var volumesToRemove []string
|
var volumesToRemove []string
|
||||||
if !internal.Force && !internal.NoInput {
|
if !internal.Force && !internal.NoInput {
|
||||||
volumesPrompt := &survey.MultiSelect{
|
volumesPrompt := &survey.MultiSelect{
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
@ -141,66 +140,13 @@ func getDeployType(currentVersion, newVersion string) string {
|
|||||||
return "DOWNGRADE"
|
return "DOWNGRADE"
|
||||||
}
|
}
|
||||||
|
|
||||||
// MoveOverview shows a overview before moving an app to a different server
|
|
||||||
func MoveOverview(
|
|
||||||
app appPkg.App,
|
|
||||||
newServer string,
|
|
||||||
secrets []string,
|
|
||||||
volumes []string,
|
|
||||||
) {
|
|
||||||
server := app.Server
|
|
||||||
if app.Server == "default" {
|
|
||||||
server = "local"
|
|
||||||
}
|
|
||||||
|
|
||||||
domain := app.Domain
|
|
||||||
if domain == "" {
|
|
||||||
domain = config.NO_DOMAIN_DEFAULT
|
|
||||||
}
|
|
||||||
|
|
||||||
rows := [][]string{
|
|
||||||
{"DOMAIN", domain},
|
|
||||||
{"RECIPE", app.Recipe.Name},
|
|
||||||
{"OLD SERVER", server},
|
|
||||||
{"New SERVER", newServer},
|
|
||||||
{"SECRETS", strings.Join(secrets, "\n")},
|
|
||||||
{"VOLUMES", strings.Join(volumes, "\n")},
|
|
||||||
}
|
|
||||||
|
|
||||||
overview := formatter.CreateOverview("MOVE OVERVIEW", rows)
|
|
||||||
|
|
||||||
fmt.Println(overview)
|
|
||||||
}
|
|
||||||
|
|
||||||
func PromptProcced() error {
|
|
||||||
if NoInput {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if Dry {
|
|
||||||
return fmt.Errorf("dry run")
|
|
||||||
}
|
|
||||||
|
|
||||||
response := false
|
|
||||||
prompt := &survey.Confirm{Message: "proceed?"}
|
|
||||||
if err := survey.AskOne(prompt, &response); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !response {
|
|
||||||
return errors.New("cancelled")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// PostCmds parses a string of commands and executes them inside of the respective services
|
// PostCmds parses a string of commands and executes them inside of the respective services
|
||||||
// the commands string must have the following format:
|
// the commands string must have the following format:
|
||||||
// "<service> <command> <arguments>|<service> <command> <arguments>|... "
|
// "<service> <command> <arguments>|<service> <command> <arguments>|... "
|
||||||
func PostCmds(cl *dockerClient.Client, app appPkg.App, commands string) error {
|
func PostCmds(cl *dockerClient.Client, app appPkg.App, commands string) error {
|
||||||
if _, err := os.Stat(app.Recipe.AbraShPath); err != nil {
|
if _, err := os.Stat(app.Recipe.AbraShPath); err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return fmt.Errorf("%s does not exist for %s?", app.Recipe.AbraShPath, app.Name)
|
return fmt.Errorf(fmt.Sprintf("%s does not exist for %s?", app.Recipe.AbraShPath, app.Name))
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -208,7 +154,7 @@ func PostCmds(cl *dockerClient.Client, app appPkg.App, commands string) error {
|
|||||||
for _, command := range strings.Split(commands, "|") {
|
for _, command := range strings.Split(commands, "|") {
|
||||||
commandParts := strings.Split(command, " ")
|
commandParts := strings.Split(command, " ")
|
||||||
if len(commandParts) < 2 {
|
if len(commandParts) < 2 {
|
||||||
return fmt.Errorf("not enough arguments: %s", command)
|
return fmt.Errorf(fmt.Sprintf("not enough arguments: %s", command))
|
||||||
}
|
}
|
||||||
targetServiceName := commandParts[0]
|
targetServiceName := commandParts[0]
|
||||||
cmdName := commandParts[1]
|
cmdName := commandParts[1]
|
||||||
@ -235,7 +181,7 @@ func PostCmds(cl *dockerClient.Client, app appPkg.App, commands string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !matchingServiceName {
|
if !matchingServiceName {
|
||||||
return fmt.Errorf("no service %s for %s?", targetServiceName, app.Name)
|
return fmt.Errorf(fmt.Sprintf("no service %s for %s?", targetServiceName, app.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("running command %s %s within the context of %s_%s", cmdName, parsedCmdArgs, app.StackName(), targetServiceName)
|
log.Debugf("running command %s %s within the context of %s_%s", cmdName, parsedCmdArgs, app.StackName(), targetServiceName)
|
||||||
|
@ -17,6 +17,7 @@ func ValidateRecipe(args []string, cmdName string) recipe.Recipe {
|
|||||||
recipeName = args[0]
|
recipeName = args[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if recipeName == "" && !NoInput {
|
||||||
var recipes []string
|
var recipes []string
|
||||||
|
|
||||||
catl, err := recipe.ReadRecipeCatalogue(Offline)
|
catl, err := recipe.ReadRecipeCatalogue(Offline)
|
||||||
@ -31,20 +32,19 @@ func ValidateRecipe(args []string, cmdName string) recipe.Recipe {
|
|||||||
|
|
||||||
localRecipes, err := recipe.GetRecipesLocal()
|
localRecipes, err := recipe.GetRecipesLocal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("can't read local recipes: %s", err)
|
log.Fatal(err)
|
||||||
} else {
|
}
|
||||||
|
|
||||||
for _, recipeLocal := range localRecipes {
|
for _, recipeLocal := range localRecipes {
|
||||||
if _, ok := knownRecipes[recipeLocal]; !ok {
|
if _, ok := knownRecipes[recipeLocal]; !ok {
|
||||||
knownRecipes[recipeLocal] = true
|
knownRecipes[recipeLocal] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for recipeName := range knownRecipes {
|
for recipeName := range knownRecipes {
|
||||||
recipes = append(recipes, recipeName)
|
recipes = append(recipes, recipeName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if recipeName == "" && !NoInput {
|
|
||||||
prompt := &survey.Select{
|
prompt := &survey.Select{
|
||||||
Message: "Select recipe",
|
Message: "Select recipe",
|
||||||
Options: recipes,
|
Options: recipes,
|
||||||
@ -58,17 +58,11 @@ func ValidateRecipe(args []string, cmdName string) recipe.Recipe {
|
|||||||
log.Fatal("no recipe name provided")
|
log.Fatal("no recipe name provided")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := knownRecipes[recipeName]; !ok {
|
|
||||||
if !strings.Contains(recipeName, "/") {
|
|
||||||
log.Fatalf("no recipe '%s' exists?", recipeName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
chosenRecipe := recipe.Get(recipeName)
|
chosenRecipe := recipe.Get(recipeName)
|
||||||
if err := chosenRecipe.EnsureExists(); err != nil {
|
err := chosenRecipe.EnsureExists()
|
||||||
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = chosenRecipe.GetComposeConfig(nil)
|
_, err = chosenRecipe.GetComposeConfig(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if cmdName == "generate" {
|
if cmdName == "generate" {
|
||||||
|
@ -47,6 +47,7 @@ var RecipeFetchCommand = &cobra.Command{
|
|||||||
log.Fatal("cannot use [recipe] and --all/-a together")
|
log.Fatal("cannot use [recipe] and --all/-a together")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ensureCtx := internal.GetEnsureContext()
|
||||||
if recipeName != "" {
|
if recipeName != "" {
|
||||||
r := recipe.Get(recipeName)
|
r := recipe.Get(recipeName)
|
||||||
if _, err := os.Stat(r.Dir); !os.IsNotExist(err) {
|
if _, err := os.Stat(r.Dir); !os.IsNotExist(err) {
|
||||||
@ -90,7 +91,6 @@ var RecipeFetchCommand = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
catlBar := formatter.CreateProgressbar(len(catalogue), "fetching latest recipes...")
|
catlBar := formatter.CreateProgressbar(len(catalogue), "fetching latest recipes...")
|
||||||
ensureCtx := internal.GetEnsureContext()
|
|
||||||
for recipeName := range catalogue {
|
for recipeName := range catalogue {
|
||||||
r := recipe.Get(recipeName)
|
r := recipe.Get(recipeName)
|
||||||
if err := r.Ensure(ensureCtx); err != nil {
|
if err := r.Ensure(ensureCtx); err != nil {
|
||||||
|
22
cli/run.go
22
cli/run.go
@ -31,23 +31,23 @@ func Run(version, commit string) {
|
|||||||
"upgrade",
|
"upgrade",
|
||||||
},
|
},
|
||||||
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
||||||
dirs := []map[string]os.FileMode{
|
paths := []string{
|
||||||
{config.ABRA_DIR: 0764},
|
config.ABRA_DIR,
|
||||||
{config.SERVERS_DIR: 0700},
|
config.SERVERS_DIR,
|
||||||
{config.RECIPES_DIR: 0764},
|
config.RECIPES_DIR,
|
||||||
{config.LOGS_DIR: 0764},
|
config.LOGS_DIR,
|
||||||
|
config.VENDOR_DIR, // TODO(d1): remove > 0.9.x
|
||||||
|
config.BACKUP_DIR, // TODO(d1): remove > 0.9.x
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, dir := range dirs {
|
for _, path := range paths {
|
||||||
for path, perm := range dir {
|
if err := os.Mkdir(path, 0764); err != nil {
|
||||||
if err := os.Mkdir(path, perm); err != nil {
|
|
||||||
if !os.IsExist(err) {
|
if !os.IsExist(err) {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
log.Logger.SetStyles(charmLog.DefaultStyles())
|
log.Logger.SetStyles(charmLog.DefaultStyles())
|
||||||
charmLog.SetDefault(log.Logger)
|
charmLog.SetDefault(log.Logger)
|
||||||
@ -73,8 +73,7 @@ func Run(version, commit string) {
|
|||||||
Aliases: []string{"m"},
|
Aliases: []string{"m"},
|
||||||
Short: "Generate manpage",
|
Short: "Generate manpage",
|
||||||
Example: ` # generate the man pages into /usr/local/share/man/man1
|
Example: ` # generate the man pages into /usr/local/share/man/man1
|
||||||
abra_path=$(which abra) # pass abra absolute path to sudo below
|
sudo abra man
|
||||||
sudo $abra_path man
|
|
||||||
sudo mandb
|
sudo mandb
|
||||||
|
|
||||||
# read the man pages
|
# read the man pages
|
||||||
@ -204,7 +203,6 @@ func Run(version, commit string) {
|
|||||||
app.AppRestartCommand,
|
app.AppRestartCommand,
|
||||||
app.AppRestoreCommand,
|
app.AppRestoreCommand,
|
||||||
app.AppRollbackCommand,
|
app.AppRollbackCommand,
|
||||||
app.AppMoveCommand,
|
|
||||||
app.AppRunCommand,
|
app.AppRunCommand,
|
||||||
app.AppSecretCommand,
|
app.AppSecretCommand,
|
||||||
app.AppServicesCommand,
|
app.AppServicesCommand,
|
||||||
|
111
go.mod
111
go.mod
@ -1,59 +1,54 @@
|
|||||||
module coopcloud.tech/abra
|
module coopcloud.tech/abra
|
||||||
|
|
||||||
go 1.24.0
|
go 1.23.0
|
||||||
|
|
||||||
toolchain go1.24.1
|
toolchain go1.23.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
coopcloud.tech/tagcmp v0.0.0-20250818180036-0ec1b205b5ca
|
coopcloud.tech/tagcmp v0.0.0-20230809071031-eb3e7758d4eb
|
||||||
git.coopcloud.tech/toolshed/godotenv v1.5.2-0.20250103171850-4d0ca41daa5c
|
git.coopcloud.tech/toolshed/godotenv v1.5.2-0.20250103171850-4d0ca41daa5c
|
||||||
github.com/AlecAivazis/survey/v2 v2.3.7
|
github.com/AlecAivazis/survey/v2 v2.3.7
|
||||||
github.com/charmbracelet/bubbletea v1.3.6
|
github.com/charmbracelet/bubbletea v1.3.4
|
||||||
github.com/charmbracelet/lipgloss v1.1.0
|
github.com/charmbracelet/lipgloss v1.1.0
|
||||||
github.com/charmbracelet/log v0.4.2
|
github.com/charmbracelet/log v0.4.1
|
||||||
github.com/distribution/reference v0.6.0
|
github.com/distribution/reference v0.6.0
|
||||||
github.com/docker/cli v28.3.3+incompatible
|
github.com/docker/cli v28.0.1+incompatible
|
||||||
github.com/docker/docker v28.3.3+incompatible
|
github.com/docker/docker v28.0.1+incompatible
|
||||||
github.com/docker/go-units v0.5.0
|
github.com/docker/go-units v0.5.0
|
||||||
github.com/go-git/go-git/v5 v5.16.2
|
github.com/go-git/go-git/v5 v5.14.0
|
||||||
github.com/google/go-cmp v0.7.0
|
github.com/google/go-cmp v0.7.0
|
||||||
github.com/leonelquinteros/gotext v1.7.2
|
|
||||||
github.com/moby/sys/signal v0.7.1
|
github.com/moby/sys/signal v0.7.1
|
||||||
github.com/moby/term v0.5.2
|
github.com/moby/term v0.5.2
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/schollz/progressbar/v3 v3.18.0
|
github.com/schollz/progressbar/v3 v3.18.0
|
||||||
golang.org/x/term v0.34.0
|
golang.org/x/term v0.30.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
gotest.tools/v3 v3.5.2
|
gotest.tools/v3 v3.5.2
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
dario.cat/mergo v1.0.2 // indirect
|
dario.cat/mergo v1.0.1 // indirect
|
||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect
|
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
||||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
github.com/ProtonMail/go-crypto v1.3.0 // indirect
|
github.com/ProtonMail/go-crypto v1.1.6 // indirect
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/charmbracelet/colorprofile v0.3.2 // indirect
|
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
|
||||||
github.com/charmbracelet/x/ansi v0.10.1 // indirect
|
github.com/charmbracelet/x/ansi v0.8.0 // indirect
|
||||||
github.com/charmbracelet/x/cellbuf v0.0.13 // indirect
|
github.com/charmbracelet/x/cellbuf v0.0.13 // indirect
|
||||||
github.com/charmbracelet/x/term v0.2.1 // indirect
|
github.com/charmbracelet/x/term v0.2.1 // indirect
|
||||||
github.com/cloudflare/circl v1.6.1 // indirect
|
github.com/cloudflare/circl v1.6.0 // indirect
|
||||||
github.com/containerd/errdefs v1.0.0 // indirect
|
|
||||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
|
||||||
github.com/containerd/log v0.1.0 // indirect
|
github.com/containerd/log v0.1.0 // indirect
|
||||||
github.com/containerd/platforms v0.2.1 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
|
||||||
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
|
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||||
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect
|
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect
|
||||||
github.com/docker/go-connections v0.6.0 // indirect
|
github.com/docker/go-connections v0.5.0 // indirect
|
||||||
github.com/docker/go-metrics v0.0.1 // indirect
|
github.com/docker/go-metrics v0.0.1 // indirect
|
||||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
|
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
|
||||||
github.com/emirpasic/gods v1.18.1 // indirect
|
github.com/emirpasic/gods v1.18.1 // indirect
|
||||||
@ -64,13 +59,13 @@ require (
|
|||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
github.com/go-git/go-billy/v5 v5.6.2 // indirect
|
github.com/go-git/go-billy/v5 v5.6.2 // indirect
|
||||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||||
github.com/go-logr/logr v1.4.3 // indirect
|
github.com/go-logr/logr v1.4.2 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
@ -87,10 +82,8 @@ require (
|
|||||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||||
github.com/moby/go-archive v0.1.0 // indirect
|
github.com/moby/sys/mountinfo v0.6.2 // indirect
|
||||||
github.com/moby/sys/atomicwriter v0.1.0 // indirect
|
github.com/moby/sys/user v0.3.0 // indirect
|
||||||
github.com/moby/sys/mountinfo v0.7.2 // indirect
|
|
||||||
github.com/moby/sys/user v0.4.0 // indirect
|
|
||||||
github.com/moby/sys/userns v0.1.0 // indirect
|
github.com/moby/sys/userns v0.1.0 // indirect
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||||
@ -101,42 +94,42 @@ require (
|
|||||||
github.com/opencontainers/runc v1.1.13 // indirect
|
github.com/opencontainers/runc v1.1.13 // indirect
|
||||||
github.com/opencontainers/runtime-spec v1.1.0 // indirect
|
github.com/opencontainers/runtime-spec v1.1.0 // indirect
|
||||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||||
github.com/pjbgf/sha1cd v0.4.0 // indirect
|
github.com/pjbgf/sha1cd v0.3.2 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_model v0.6.2 // indirect
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
github.com/prometheus/common v0.65.0 // indirect
|
github.com/prometheus/common v0.63.0 // indirect
|
||||||
github.com/prometheus/procfs v0.17.0 // indirect
|
github.com/prometheus/procfs v0.15.1 // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/skeema/knownhosts v1.3.1 // indirect
|
github.com/skeema/knownhosts v1.3.1 // indirect
|
||||||
github.com/spf13/pflag v1.0.7 // indirect
|
github.com/spf13/pflag v1.0.6 // indirect
|
||||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.37.0 // indirect
|
go.opentelemetry.io/otel v1.35.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.37.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.37.0 // indirect
|
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
||||||
go.opentelemetry.io/otel/sdk v1.37.0 // indirect
|
go.opentelemetry.io/otel/sdk v1.35.0 // indirect
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect
|
go.opentelemetry.io/otel/sdk/metric v1.35.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.37.0 // indirect
|
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
|
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
|
||||||
golang.org/x/crypto v0.41.0 // indirect
|
golang.org/x/crypto v0.36.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 // indirect
|
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
|
||||||
golang.org/x/net v0.43.0 // indirect
|
golang.org/x/net v0.37.0 // indirect
|
||||||
golang.org/x/sync v0.16.0 // indirect
|
golang.org/x/sync v0.12.0 // indirect
|
||||||
golang.org/x/text v0.28.0 // indirect
|
golang.org/x/text v0.23.0 // indirect
|
||||||
golang.org/x/time v0.12.0 // indirect
|
golang.org/x/time v0.11.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250811230008-5f3141c8851a // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250811230008-5f3141c8851a // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect
|
||||||
google.golang.org/grpc v1.74.2 // indirect
|
google.golang.org/grpc v1.71.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.7 // indirect
|
google.golang.org/protobuf v1.36.5 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
)
|
)
|
||||||
@ -149,15 +142,15 @@ require (
|
|||||||
github.com/fvbommel/sortorder v1.1.0 // indirect
|
github.com/fvbommel/sortorder v1.1.0 // indirect
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||||
github.com/gorilla/mux v1.8.1 // indirect
|
github.com/gorilla/mux v1.8.1 // indirect
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.8
|
github.com/hashicorp/go-retryablehttp v0.7.7
|
||||||
github.com/moby/patternmatcher v0.6.0 // indirect
|
github.com/moby/patternmatcher v0.6.0 // indirect
|
||||||
github.com/moby/sys/sequential v0.6.0 // indirect
|
github.com/moby/sys/sequential v0.6.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||||
github.com/prometheus/client_golang v1.23.0 // indirect
|
github.com/prometheus/client_golang v1.21.1 // indirect
|
||||||
github.com/sergi/go-diff v1.4.0 // indirect
|
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
||||||
github.com/spf13/cobra v1.9.1
|
github.com/spf13/cobra v1.9.1
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
github.com/theupdateframework/notary v0.7.0 // indirect
|
github.com/theupdateframework/notary v0.7.0 // indirect
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||||
golang.org/x/sys v0.35.0
|
golang.org/x/sys v0.31.0
|
||||||
)
|
)
|
||||||
|
124
go.sum
124
go.sum
@ -24,21 +24,13 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
|
|||||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||||
coopcloud.tech/tagcmp v0.0.0-20230809071031-eb3e7758d4eb h1:Ws6WEwKXeaYEkfdkX6AqX1XLPuaCeyStEtxbmEJPllk=
|
coopcloud.tech/tagcmp v0.0.0-20230809071031-eb3e7758d4eb h1:Ws6WEwKXeaYEkfdkX6AqX1XLPuaCeyStEtxbmEJPllk=
|
||||||
coopcloud.tech/tagcmp v0.0.0-20230809071031-eb3e7758d4eb/go.mod h1:ESVm0wQKcbcFi06jItF3rI7enf4Jt2PvbkWpDDHk1DQ=
|
coopcloud.tech/tagcmp v0.0.0-20230809071031-eb3e7758d4eb/go.mod h1:ESVm0wQKcbcFi06jItF3rI7enf4Jt2PvbkWpDDHk1DQ=
|
||||||
coopcloud.tech/tagcmp v0.0.0-20250427094623-9ea3bbbde8e5 h1:tphJCjFJw9fdjyKnbU0f7f3z5KtYE8VbUcAfu+oHKg8=
|
|
||||||
coopcloud.tech/tagcmp v0.0.0-20250427094623-9ea3bbbde8e5/go.mod h1:ESVm0wQKcbcFi06jItF3rI7enf4Jt2PvbkWpDDHk1DQ=
|
|
||||||
coopcloud.tech/tagcmp v0.0.0-20250818180036-0ec1b205b5ca h1:gSD53tBAsbIGq4SnFfq+mEep6foekQ2a5ea7b38qkm0=
|
|
||||||
coopcloud.tech/tagcmp v0.0.0-20250818180036-0ec1b205b5ca/go.mod h1:ESVm0wQKcbcFi06jItF3rI7enf4Jt2PvbkWpDDHk1DQ=
|
|
||||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||||
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
|
||||||
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
git.coopcloud.tech/toolshed/godotenv v1.5.2-0.20250103171850-4d0ca41daa5c h1:oeKnUB79PKYD8D0/unYuu7MRcWryQQWOns8+JL+acrs=
|
git.coopcloud.tech/toolshed/godotenv v1.5.2-0.20250103171850-4d0ca41daa5c h1:oeKnUB79PKYD8D0/unYuu7MRcWryQQWOns8+JL+acrs=
|
||||||
git.coopcloud.tech/toolshed/godotenv v1.5.2-0.20250103171850-4d0ca41daa5c/go.mod h1:fQuhwrpg6qb9NlFXKYi/LysWu1wxjraS8sxyW12CUF0=
|
git.coopcloud.tech/toolshed/godotenv v1.5.2-0.20250103171850-4d0ca41daa5c/go.mod h1:fQuhwrpg6qb9NlFXKYi/LysWu1wxjraS8sxyW12CUF0=
|
||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
|
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
|
||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
|
|
||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
|
||||||
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
|
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
|
||||||
github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
|
github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
|
||||||
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||||
@ -59,8 +51,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
|||||||
github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
|
||||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||||
@ -91,8 +81,6 @@ github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDe
|
|||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw=
|
github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw=
|
||||||
github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
|
github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
|
||||||
github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
|
|
||||||
github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
|
|
||||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||||
@ -142,34 +130,21 @@ github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3k
|
|||||||
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
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/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||||
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
|
||||||
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/charmbracelet/bubbletea v1.3.4 h1:kCg7B+jSCFPLYRA52SDZjr51kG/fMUEoPoZrkaDHyoI=
|
github.com/charmbracelet/bubbletea v1.3.4 h1:kCg7B+jSCFPLYRA52SDZjr51kG/fMUEoPoZrkaDHyoI=
|
||||||
github.com/charmbracelet/bubbletea v1.3.4/go.mod h1:dtcUCyCGEX3g9tosuYiut3MXgY/Jsv9nKVdibKKRRXo=
|
github.com/charmbracelet/bubbletea v1.3.4/go.mod h1:dtcUCyCGEX3g9tosuYiut3MXgY/Jsv9nKVdibKKRRXo=
|
||||||
github.com/charmbracelet/bubbletea v1.3.6 h1:VkHIxPJQeDt0aFJIsVxw8BQdh/F/L2KKZGsK6et5taU=
|
|
||||||
github.com/charmbracelet/bubbletea v1.3.6/go.mod h1:oQD9VCRQFF8KplacJLo28/jofOI2ToOfGYeFgBBxHOc=
|
|
||||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
|
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs=
|
||||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk=
|
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk=
|
||||||
github.com/charmbracelet/colorprofile v0.3.1 h1:k8dTHMd7fgw4bnFd7jXTLZrSU/CQrKnL3m+AxCzDz40=
|
|
||||||
github.com/charmbracelet/colorprofile v0.3.1/go.mod h1:/GkGusxNs8VB/RSOh3fu0TJmQ4ICMMPApIIVn0KszZ0=
|
|
||||||
github.com/charmbracelet/colorprofile v0.3.2 h1:9J27WdztfJQVAQKX2WOlSSRB+5gaKqqITmrvb1uTIiI=
|
|
||||||
github.com/charmbracelet/colorprofile v0.3.2/go.mod h1:mTD5XzNeWHj8oqHb+S1bssQb7vIHbepiebQ2kPKVKbI=
|
|
||||||
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
|
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
|
||||||
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
|
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
|
||||||
github.com/charmbracelet/log v0.4.1 h1:6AYnoHKADkghm/vt4neaNEXkxcXLSV2g1rdyFDOpTyk=
|
github.com/charmbracelet/log v0.4.1 h1:6AYnoHKADkghm/vt4neaNEXkxcXLSV2g1rdyFDOpTyk=
|
||||||
github.com/charmbracelet/log v0.4.1/go.mod h1:pXgyTsqsVu4N9hGdHmQ0xEA4RsXof402LX9ZgiITn2I=
|
github.com/charmbracelet/log v0.4.1/go.mod h1:pXgyTsqsVu4N9hGdHmQ0xEA4RsXof402LX9ZgiITn2I=
|
||||||
github.com/charmbracelet/log v0.4.2 h1:hYt8Qj6a8yLnvR+h7MwsJv/XvmBJXiueUcI3cIxsyig=
|
|
||||||
github.com/charmbracelet/log v0.4.2/go.mod h1:qifHGX/tc7eluv2R6pWIpyHDDrrb/AG71Pf2ysQu5nw=
|
|
||||||
github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE=
|
github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE=
|
||||||
github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q=
|
github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q=
|
||||||
github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ=
|
|
||||||
github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
|
|
||||||
github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k=
|
github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k=
|
||||||
github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
|
github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs=
|
||||||
github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a h1:G99klV19u0QnhiizODirwVksQB91TJKV/UaTnACcG30=
|
github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a h1:G99klV19u0QnhiizODirwVksQB91TJKV/UaTnACcG30=
|
||||||
@ -195,8 +170,6 @@ github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e
|
|||||||
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
|
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
|
||||||
github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk=
|
github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk=
|
||||||
github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||||
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
|
|
||||||
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
@ -242,10 +215,6 @@ github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cE
|
|||||||
github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y=
|
github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y=
|
||||||
github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
|
github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
|
||||||
github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
|
github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
|
||||||
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
|
||||||
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
|
||||||
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
|
|
||||||
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
|
||||||
github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||||
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||||
github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
|
github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
|
||||||
@ -268,8 +237,6 @@ github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3
|
|||||||
github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c=
|
github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c=
|
||||||
github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
||||||
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY=
|
||||||
github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
|
|
||||||
github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
|
|
||||||
github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
|
github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM=
|
||||||
github.com/containerd/stargz-snapshotter/estargz v0.11.0/go.mod h1:/KsZXsJRllMbTKFfG0miFQWViQKdI9+9aSXs+HN0+ac=
|
github.com/containerd/stargz-snapshotter/estargz v0.11.0/go.mod h1:/KsZXsJRllMbTKFfG0miFQWViQKdI9+9aSXs+HN0+ac=
|
||||||
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||||
@ -318,8 +285,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
|
|||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
|
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
|
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
|
||||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||||
@ -349,8 +314,6 @@ github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyG
|
|||||||
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
github.com/docker/cli v28.0.1+incompatible h1:g0h5NQNda3/CxIsaZfH4Tyf6vpxFth7PYl3hgCPOKzs=
|
github.com/docker/cli v28.0.1+incompatible h1:g0h5NQNda3/CxIsaZfH4Tyf6vpxFth7PYl3hgCPOKzs=
|
||||||
github.com/docker/cli v28.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
github.com/docker/cli v28.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||||
github.com/docker/cli v28.3.3+incompatible h1:fp9ZHAr1WWPGdIWBM1b3zLtgCF+83gRdVMTJsUeiyAo=
|
|
||||||
github.com/docker/cli v28.3.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
|
||||||
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
|
||||||
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
@ -359,8 +322,6 @@ github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4Kfc
|
|||||||
github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/docker v28.0.1+incompatible h1:FCHjSRdXhNRFjlHMTv4jUNlIBbTeRjrWfeFuJp7jpo0=
|
github.com/docker/docker v28.0.1+incompatible h1:FCHjSRdXhNRFjlHMTv4jUNlIBbTeRjrWfeFuJp7jpo0=
|
||||||
github.com/docker/docker v28.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v28.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI=
|
|
||||||
github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
|
||||||
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
||||||
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
|
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
|
||||||
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
|
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
|
||||||
@ -369,8 +330,6 @@ github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK
|
|||||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
||||||
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
|
|
||||||
github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
|
|
||||||
github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
||||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
||||||
github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
|
github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
|
||||||
@ -432,8 +391,6 @@ github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMj
|
|||||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||||
github.com/go-git/go-git/v5 v5.14.0 h1:/MD3lCrGjCen5WfEAzKg00MJJffKhC8gzS80ycmCi60=
|
github.com/go-git/go-git/v5 v5.14.0 h1:/MD3lCrGjCen5WfEAzKg00MJJffKhC8gzS80ycmCi60=
|
||||||
github.com/go-git/go-git/v5 v5.14.0/go.mod h1:Z5Xhoia5PcWA3NF8vRLURn9E5FRhSl7dGj9ItW3Wk5k=
|
github.com/go-git/go-git/v5 v5.14.0/go.mod h1:Z5Xhoia5PcWA3NF8vRLURn9E5FRhSl7dGj9ItW3Wk5k=
|
||||||
github.com/go-git/go-git/v5 v5.16.2 h1:fT6ZIOjE5iEnkzKyxTHK1W4HGAsPhqEqiSAssSO77hM=
|
|
||||||
github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
|
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
@ -449,8 +406,6 @@ github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTg
|
|||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
|
||||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
|
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
|
||||||
@ -469,8 +424,6 @@ github.com/go-sql-driver/mysql v1.3.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG
|
|||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
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/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||||
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
|
||||||
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
|
||||||
github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||||
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
||||||
@ -575,12 +528,9 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de
|
|||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww=
|
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90=
|
|
||||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
||||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||||
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
@ -594,8 +544,6 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh
|
|||||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
|
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-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48=
|
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw=
|
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||||
@ -663,8 +611,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
|||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
github.com/leonelquinteros/gotext v1.7.2 h1:bDPndU8nt+/kRo1m4l/1OXiiy2v7Z7dfPQ9+YP7G1Mc=
|
|
||||||
github.com/leonelquinteros/gotext v1.7.2/go.mod h1:9/haCkm5P7Jay1sxKDGJ5WIg4zkz8oZKw4ekNpALob8=
|
|
||||||
github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v0.0.0-20150723085316-0dad96c0b94f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo=
|
github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo=
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||||
@ -715,20 +661,14 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
|
|||||||
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
|
||||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||||
github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ=
|
|
||||||
github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo=
|
|
||||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||||
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
|
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
|
||||||
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||||
github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
|
|
||||||
github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs=
|
|
||||||
github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
||||||
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
||||||
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
|
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
|
||||||
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
|
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
|
||||||
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
||||||
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
|
|
||||||
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
|
|
||||||
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
|
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
|
||||||
github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
|
github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
|
||||||
github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0=
|
github.com/moby/sys/signal v0.7.1 h1:PrQxdvxcGijdo6UXXo/lU/TvHUWyPhj7UOpSo8tuvk0=
|
||||||
@ -736,8 +676,6 @@ github.com/moby/sys/signal v0.7.1/go.mod h1:Se1VGehYokAkrSQwL4tDzHvETwUZlnY7S5Xt
|
|||||||
github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
|
github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
|
||||||
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
|
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
|
||||||
github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
|
github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
|
||||||
github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
|
|
||||||
github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
|
|
||||||
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
|
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
|
||||||
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
|
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
|
||||||
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
|
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
|
||||||
@ -826,8 +764,6 @@ github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko
|
|||||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||||
github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
|
github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
|
||||||
github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
|
github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
|
||||||
github.com/pjbgf/sha1cd v0.4.0 h1:NXzbL1RvjTUi6kgYZCX3fPwwl27Q1LJndxtUDVfJGRY=
|
|
||||||
github.com/pjbgf/sha1cd v0.4.0/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
|
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
@ -845,8 +781,6 @@ github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQ
|
|||||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||||
github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
|
github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
|
||||||
github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
|
github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
|
||||||
github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
|
|
||||||
github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
|
|
||||||
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
@ -854,8 +788,6 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
|
|||||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
|
||||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
|
||||||
github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
@ -864,8 +796,6 @@ github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+
|
|||||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||||
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
|
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
|
||||||
github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
|
github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
|
||||||
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
|
|
||||||
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
|
||||||
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
@ -879,8 +809,6 @@ github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
|
|||||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||||
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
|
|
||||||
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
|
|
||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
@ -890,7 +818,6 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L
|
|||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||||
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
|
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
@ -903,8 +830,6 @@ github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvW
|
|||||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
||||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||||
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
|
|
||||||
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||||
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||||
@ -945,8 +870,6 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
|
|||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
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 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
|
|
||||||
github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
|
||||||
github.com/spf13/viper v0.0.0-20150530192845-be5ff3e4840c/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
|
github.com/spf13/viper v0.0.0-20150530192845-be5ff3e4840c/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
|
||||||
github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
|
github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
|
||||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||||
@ -1025,47 +948,27 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS
|
|||||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 h1:Hf9xI/XLML9ElpiHVDNwvqI0hIFlzV8dgIr35kV1kRU=
|
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0/go.mod h1:NfchwuyNoMcZ5MLHwPrODwUF1HWCXWrL31s8gSAdIKY=
|
|
||||||
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||||
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
|
|
||||||
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 h1:QcFwRrZLc82r8wODjvyCbP7Ifp3UANaBSmhDSFjnqSc=
|
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 h1:QcFwRrZLc82r8wODjvyCbP7Ifp3UANaBSmhDSFjnqSc=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0/go.mod h1:CXIWhUomyWBG/oY2/r/kLp6K/cmx9e/7DLpBuuGdLCA=
|
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0/go.mod h1:CXIWhUomyWBG/oY2/r/kLp6K/cmx9e/7DLpBuuGdLCA=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.37.0 h1:zG8GlgXCJQd5BU98C0hZnBbElszTmUgCNCfYneaDL0A=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.37.0/go.mod h1:hOfBCz8kv/wuq73Mx2H2QnWokh/kHZxkh6SNF2bdKtw=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz/LekZmPLLdKejuO3NcK9MssM=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0/go.mod h1:MJTqhM0im3mRLw1i8uGHnCvUEeS7VwRyxlLC78PA18M=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 h1:EtFWSnwW9hGObjkIdmlnWSydO+Qs8OwzfzXLUPg4xOc=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0/go.mod h1:QjUEoiGCPkvFZ/MjK6ZZfNOS6mfVEVKYE99dFhuN2LI=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
|
||||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||||
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
|
|
||||||
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
|
|
||||||
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
||||||
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
||||||
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
|
|
||||||
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
|
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
|
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
|
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
|
|
||||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||||
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
|
|
||||||
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
|
|
||||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||||
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
|
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
|
||||||
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
|
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
|
||||||
go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4=
|
|
||||||
go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE=
|
|
||||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
@ -1092,8 +995,6 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
|
|||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
|
||||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@ -1106,10 +1007,6 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
|
|||||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
|
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
|
||||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
|
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
|
||||||
golang.org/x/exp v0.0.0-20250811191247-51f88131bc50 h1:3yiSh9fhy5/RhCSntf4Sy0Tnx50DmMpQ4MQdKKk4yg4=
|
|
||||||
golang.org/x/exp v0.0.0-20250811191247-51f88131bc50/go.mod h1:rT6SFzZ7oxADUDx58pcaKFTcZ+inxAa9fTrYx/uVYwg=
|
|
||||||
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 h1:SbTAbRFnd5kjQXbczszQ0hdk3ctwYf3qBNH9jIsGclE=
|
|
||||||
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
|
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
@ -1175,8 +1072,6 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
|
|||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
||||||
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
|
||||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@ -1196,8 +1091,6 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/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.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
|
||||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@ -1279,15 +1172,11 @@ golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
|
||||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
||||||
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
||||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
|
||||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@ -1299,8 +1188,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
|
||||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
@ -1309,8 +1196,6 @@ golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxb
|
|||||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
|
||||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@ -1406,12 +1291,8 @@ google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7Fc
|
|||||||
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4 h1:IFnXJq3UPB3oBREOodn1v1aGQeZYQclEmvWRMN0PSsY=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4 h1:IFnXJq3UPB3oBREOodn1v1aGQeZYQclEmvWRMN0PSsY=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:c8q6Z6OCqnfVIqUFJkCzKcrj8eCvUrz+K4KRzSTuANg=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:c8q6Z6OCqnfVIqUFJkCzKcrj8eCvUrz+K4KRzSTuANg=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250811230008-5f3141c8851a h1:DMCgtIAIQGZqJXMVzJF4MV8BlWoJh2ZuFiRdAleyr58=
|
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250811230008-5f3141c8851a/go.mod h1:y2yVLIE/CSMCPXaHnSKXxu1spLPnglFLegmgdY23uuE=
|
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250811230008-5f3141c8851a h1:tPE/Kp+x9dMSwUm/uM0JKK0IfdiJkwAbSMSeZBXXJXc=
|
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250811230008-5f3141c8851a/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo=
|
|
||||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
@ -1433,8 +1314,6 @@ google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
|
|||||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||||
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
|
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
|
||||||
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
|
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
|
||||||
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
|
|
||||||
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
@ -1450,8 +1329,6 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
|
|||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||||
google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
|
|
||||||
google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
|
||||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/cenkalti/backoff.v2 v2.2.1 h1:eJ9UAg01/HIHG987TwxvnzK2MgxXq97YY6rYDpY9aII=
|
gopkg.in/cenkalti/backoff.v2 v2.2.1 h1:eJ9UAg01/HIHG987TwxvnzK2MgxXq97YY6rYDpY9aII=
|
||||||
@ -1491,7 +1368,6 @@ 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.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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
|
||||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Language: \n"
|
|
||||||
"X-Generator: xgotext\n"
|
|
||||||
|
|
||||||
#: app.go:11
|
|
||||||
msgid "Manage apps"
|
|
||||||
msgstr ""
|
|
@ -1,20 +0,0 @@
|
|||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
|
||||||
"Report-Msgid-Bugs-To: \n"
|
|
||||||
"POT-Creation-Date: 2025-08-04 14:15+0000\n"
|
|
||||||
"PO-Revision-Date: 2025-08-04 14:15+0000\n"
|
|
||||||
"Last-Translator: 3wordchant <3wc.coopcloud@doesthisthing.work>\n"
|
|
||||||
"Language-Team: Spanish <https://translate.coopcloud.tech/projects/"
|
|
||||||
"co-op-cloud/abra/es/>\n"
|
|
||||||
"Language: es\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: ENCODING\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
|
||||||
"X-Generator: Weblate 5.12.2\n"
|
|
||||||
|
|
||||||
#: app.go:11
|
|
||||||
msgid "Manage apps"
|
|
||||||
msgstr "Gestionar aplicaciones"
|
|
@ -426,9 +426,7 @@ func GetAppStatuses(apps []App, MachineReadable bool) (map[string]map[string]str
|
|||||||
for server := range servers {
|
for server := range servers {
|
||||||
cl, err := client.New(server)
|
cl, err := client.New(server)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn(err)
|
return statuses, err
|
||||||
ch <- stack.StackStatus{}
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
go func(s string) {
|
go func(s string) {
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
package client
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/filters"
|
|
||||||
"github.com/docker/docker/api/types/swarm"
|
|
||||||
"github.com/docker/docker/client"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetConfigs(cl *client.Client, ctx context.Context, server string, fs filters.Args) ([]swarm.Config, error) {
|
|
||||||
configList, err := cl.ConfigList(ctx, swarm.ConfigListOptions{Filters: fs})
|
|
||||||
if err != nil {
|
|
||||||
return configList, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return configList, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetConfigNames(configs []swarm.Config) []string {
|
|
||||||
var confNames []string
|
|
||||||
|
|
||||||
for _, conf := range configs {
|
|
||||||
confNames = append(confNames, conf.Spec.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return confNames
|
|
||||||
}
|
|
||||||
|
|
||||||
func RemoveConfigs(cl *client.Client, ctx context.Context, configNames []string, force bool) error {
|
|
||||||
for _, confName := range configNames {
|
|
||||||
if err := cl.ConfigRemove(context.Background(), confName); err != nil {
|
|
||||||
return fmt.Errorf("conf %s: %s", confName, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func StoreSecret(cl *client.Client, secretName, secretValue string) error {
|
func StoreSecret(cl *client.Client, secretName, secretValue, server string) error {
|
||||||
ann := swarm.Annotations{Name: secretName}
|
ann := swarm.Annotations{Name: secretName}
|
||||||
spec := swarm.SecretSpec{Annotations: ann, Data: []byte(secretValue)}
|
spec := swarm.SecretSpec{Annotations: ann, Data: []byte(secretValue)}
|
||||||
|
|
||||||
|
@ -11,6 +11,11 @@ import (
|
|||||||
"git.coopcloud.tech/toolshed/godotenv"
|
"git.coopcloud.tech/toolshed/godotenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// envVarModifiers is a list of env var modifier strings. These are added to
|
||||||
|
// env vars as comments and modify their processing by Abra, e.g. determining
|
||||||
|
// how long secrets should be.
|
||||||
|
var envVarModifiers = []string{"length"}
|
||||||
|
|
||||||
// AppEnv is a map of the values in an apps env config
|
// AppEnv is a map of the values in an apps env config
|
||||||
type AppEnv = map[string]string
|
type AppEnv = map[string]string
|
||||||
|
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
package lang
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetLocale() string {
|
|
||||||
if loc := os.Getenv("LC_MESSAGES"); loc != "" {
|
|
||||||
return NormalizeLocale(loc)
|
|
||||||
}
|
|
||||||
|
|
||||||
if loc := os.Getenv("LANG"); loc != "" {
|
|
||||||
return NormalizeLocale(loc)
|
|
||||||
}
|
|
||||||
|
|
||||||
return "C.UTF-8"
|
|
||||||
}
|
|
||||||
|
|
||||||
func NormalizeLocale(loc string) string {
|
|
||||||
if idx := strings.Index(loc, "."); idx != -1 {
|
|
||||||
return loc[:idx]
|
|
||||||
}
|
|
||||||
|
|
||||||
if idx := strings.Index(loc, "@"); idx != -1 {
|
|
||||||
return loc[:idx]
|
|
||||||
}
|
|
||||||
|
|
||||||
return loc
|
|
||||||
}
|
|
@ -184,8 +184,6 @@ var LintRules = map[string][]LintRule{
|
|||||||
func LintForErrors(recipe recipe.Recipe) error {
|
func LintForErrors(recipe recipe.Recipe) error {
|
||||||
log.Debugf("linting for critical errors in %s configs", recipe.Name)
|
log.Debugf("linting for critical errors in %s configs", recipe.Name)
|
||||||
|
|
||||||
var errors string
|
|
||||||
|
|
||||||
for level := range LintRules {
|
for level := range LintRules {
|
||||||
if level != "error" {
|
if level != "error" {
|
||||||
continue
|
continue
|
||||||
@ -198,18 +196,14 @@ func LintForErrors(recipe recipe.Recipe) error {
|
|||||||
|
|
||||||
ok, err := rule.Function(recipe)
|
ok, err := rule.Function(recipe)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors += fmt.Sprintf("\nlint %s: %s", rule.Ref, err)
|
return fmt.Errorf("lint %s: %s", rule.Ref, err)
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
errors += fmt.Sprintf("\n * %s (%s)", rule.Description, rule.Ref)
|
return fmt.Errorf("lint error in %s configs: \"%s\" failed lint checks (%s)", recipe.Name, rule.Description, rule.Ref)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(errors) > 0 {
|
|
||||||
return fmt.Errorf("recipe '%s' failed lint checks:\n"+errors[1:], recipe.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("linting successful, %s is well configured", recipe.Name)
|
log.Debugf("linting successful, %s is well configured", recipe.Name)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -40,14 +40,14 @@ func (r Recipe) Ensure(ctx EnsureContext) error {
|
|||||||
|
|
||||||
if !ctx.Offline {
|
if !ctx.Offline {
|
||||||
if err := r.EnsureUpToDate(); err != nil {
|
if err := r.EnsureUpToDate(); err != nil {
|
||||||
return err
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.EnvVersion != "" && !ctx.IgnoreEnvVersion {
|
if r.EnvVersion != "" && !ctx.IgnoreEnvVersion {
|
||||||
log.Debugf("ensuring env version %s", r.EnvVersion)
|
log.Debugf("ensuring env version %s", r.EnvVersion)
|
||||||
if strings.Contains(r.EnvVersion, "+U") {
|
if strings.Contains(r.EnvVersion, "+U") {
|
||||||
return fmt.Errorf("can not redeploy chaos version (%s) without --chaos", r.EnvVersion)
|
log.Fatalf("can not redeploy chaos version (%s) without --chaos", r.EnvVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := r.EnsureVersion(r.EnvVersion); err != nil {
|
if _, err := r.EnsureVersion(r.EnvVersion); err != nil {
|
||||||
|
@ -37,9 +37,6 @@ type Secret struct {
|
|||||||
// variable. For Example:
|
// variable. For Example:
|
||||||
// SECRET_FOO=v1 # charset=default,special
|
// SECRET_FOO=v1 # charset=default,special
|
||||||
Charset string
|
Charset string
|
||||||
// Whether or not to skip generation of the secret or not
|
|
||||||
// For example: SECRET_FOO=v1 # generate=false
|
|
||||||
SkipGenerate bool
|
|
||||||
// RemoteName is the name of the secret on the server. For example:
|
// RemoteName is the name of the secret on the server. For example:
|
||||||
// name: ${STACK_NAME}_test_pass_two_${SECRET_TEST_PASS_TWO_VERSION}
|
// name: ${STACK_NAME}_test_pass_two_${SECRET_TEST_PASS_TWO_VERSION}
|
||||||
// With the following:
|
// With the following:
|
||||||
@ -52,7 +49,11 @@ type Secret struct {
|
|||||||
|
|
||||||
// GeneratePassword generates passwords.
|
// GeneratePassword generates passwords.
|
||||||
func GeneratePassword(length uint, charset string) (string, error) {
|
func GeneratePassword(length uint, charset string) (string, error) {
|
||||||
passwords, err := passgen.GeneratePasswords(1, length, charset)
|
passwords, err := passgen.GeneratePasswords(
|
||||||
|
1,
|
||||||
|
length,
|
||||||
|
charset,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -90,7 +91,6 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, stackName strin
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the STACK_NAME to be able to generate the remote name correctly.
|
// Set the STACK_NAME to be able to generate the remote name correctly.
|
||||||
appEnv["STACK_NAME"] = stackName
|
appEnv["STACK_NAME"] = stackName
|
||||||
|
|
||||||
@ -99,7 +99,6 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, stackName strin
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the compose files without injecting environment variables.
|
// Read the compose files without injecting environment variables.
|
||||||
configWithoutEnv, err := loader.LoadComposefile(opts, map[string]string{}, loader.SkipInterpolation)
|
configWithoutEnv, err := loader.LoadComposefile(opts, map[string]string{}, loader.SkipInterpolation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -147,7 +146,6 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, stackName strin
|
|||||||
if !strings.Contains(configWithoutEnv.Secrets[secretId].Name, envName) {
|
if !strings.Contains(configWithoutEnv.Secrets[secretId].Name, envName) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
lengthRaw, ok := modifierValues["length"]
|
lengthRaw, ok := modifierValues["length"]
|
||||||
if ok {
|
if ok {
|
||||||
length, err := strconv.Atoi(lengthRaw)
|
length, err := strconv.Atoi(lengthRaw)
|
||||||
@ -157,13 +155,6 @@ func ReadSecretsConfig(appEnvPath string, composeFiles []string, stackName strin
|
|||||||
value.Length = length
|
value.Length = length
|
||||||
}
|
}
|
||||||
|
|
||||||
generateRaw, ok := modifierValues["generate"]
|
|
||||||
if ok {
|
|
||||||
if generateRaw == "false" {
|
|
||||||
value.SkipGenerate = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
value.Charset = resolveCharset(modifierValues["charset"])
|
value.Charset = resolveCharset(modifierValues["charset"])
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -201,12 +192,6 @@ func GenerateSecrets(cl *dockerClient.Client, secrets map[string]Secret, server
|
|||||||
go func(secretName string, secret Secret) {
|
go func(secretName string, secret Secret) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
if secret.SkipGenerate {
|
|
||||||
log.Debugf("skipping generation of %s (generate=false)", secretName)
|
|
||||||
ch <- nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("attempting to generate and store %s on %s", secret.RemoteName, server)
|
log.Debugf("attempting to generate and store %s on %s", secret.RemoteName, server)
|
||||||
|
|
||||||
if secret.Length > 0 {
|
if secret.Length > 0 {
|
||||||
@ -216,7 +201,7 @@ func GenerateSecrets(cl *dockerClient.Client, secrets map[string]Secret, server
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := client.StoreSecret(cl, secret.RemoteName, password); err != nil {
|
if err := client.StoreSecret(cl, secret.RemoteName, password, server); err != nil {
|
||||||
if strings.Contains(err.Error(), "AlreadyExists") {
|
if strings.Contains(err.Error(), "AlreadyExists") {
|
||||||
log.Warnf("%s already exists", secret.RemoteName)
|
log.Warnf("%s already exists", secret.RemoteName)
|
||||||
ch <- nil
|
ch <- nil
|
||||||
@ -236,7 +221,7 @@ func GenerateSecrets(cl *dockerClient.Client, secrets map[string]Secret, server
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := client.StoreSecret(cl, secret.RemoteName, passphrase); err != nil {
|
if err := client.StoreSecret(cl, secret.RemoteName, passphrase, server); err != nil {
|
||||||
if strings.Contains(err.Error(), "AlreadyExists") {
|
if strings.Contains(err.Error(), "AlreadyExists") {
|
||||||
log.Warnf("%s already exists", secret.RemoteName)
|
log.Warnf("%s already exists", secret.RemoteName)
|
||||||
ch <- nil
|
ch <- nil
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
func CreateServerDir(serverName string) error {
|
func CreateServerDir(serverName string) error {
|
||||||
serverPath := path.Join(config.ABRA_DIR, "servers", serverName)
|
serverPath := path.Join(config.ABRA_DIR, "servers", serverName)
|
||||||
|
|
||||||
if err := os.Mkdir(serverPath, 0700); err != nil {
|
if err := os.Mkdir(serverPath, 0764); err != nil {
|
||||||
if !os.IsExist(err) {
|
if !os.IsExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ func RunRemove(ctx context.Context, client *apiclient.Client, opts Remove) error
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug("polling undeploy status")
|
log.Info("polling undeploy status")
|
||||||
timeout, err := waitOnTasks(ctx, client, namespace)
|
timeout, err := waitOnTasks(ctx, client, namespace)
|
||||||
if timeout {
|
if timeout {
|
||||||
errs = append(errs, err.Error())
|
errs = append(errs, err.Error())
|
||||||
@ -88,7 +88,7 @@ func RunRemove(ctx context.Context, client *apiclient.Client, opts Remove) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
errCh <- errors.New(strings.Join(errs, "\n"))
|
errCh <- errors.Errorf(strings.Join(errs, "\n"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
ABRA_VERSION="0.10.1-beta"
|
ABRA_VERSION="0.10.0-beta"
|
||||||
ABRA_RELEASE_URL="https://git.coopcloud.tech/api/v1/repos/toolshed/abra/releases/tags/$ABRA_VERSION"
|
ABRA_RELEASE_URL="https://git.coopcloud.tech/api/v1/repos/toolshed/abra/releases/tags/$ABRA_VERSION"
|
||||||
RC_VERSION="0.10.1-beta"
|
RC_VERSION="0.10.0-beta"
|
||||||
RC_VERSION_URL="https://git.coopcloud.tech/api/v1/repos/toolshed/abra/releases/tags/$RC_VERSION"
|
RC_VERSION_URL="https://git.coopcloud.tech/api/v1/repos/toolshed/abra/releases/tags/$RC_VERSION"
|
||||||
|
|
||||||
for arg in "$@"; do
|
for arg in "$@"; do
|
||||||
|
@ -75,45 +75,6 @@ teardown(){
|
|||||||
assert_success
|
assert_success
|
||||||
}
|
}
|
||||||
|
|
||||||
# bats test_tags=slow
|
|
||||||
@test "bail if recipe lint errors and no --chaos" {
|
|
||||||
# Break the recipe
|
|
||||||
run sed -i '/traefik.enable=.*/d' "$ABRA_DIR/recipes/$TEST_RECIPE/compose.yml"
|
|
||||||
assert_success
|
|
||||||
|
|
||||||
# Commit the breakage (so we can test without --chaos)
|
|
||||||
_set_git_author
|
|
||||||
|
|
||||||
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" commit -a -m 'Break recipe'
|
|
||||||
assert_success
|
|
||||||
|
|
||||||
# Make a broken release
|
|
||||||
run $ABRA recipe sync --patch "$TEST_RECIPE"
|
|
||||||
run $ABRA recipe release --patch -n "$TEST_RECIPE"
|
|
||||||
|
|
||||||
# Make sure we deploy latest
|
|
||||||
_wipe_env_version
|
|
||||||
|
|
||||||
run $ABRA app deploy "$TEST_APP_DOMAIN" --no-input
|
|
||||||
assert_failure
|
|
||||||
assert_output --partial 'failed lint checks'
|
|
||||||
|
|
||||||
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" reset --hard HEAD~1
|
|
||||||
latestRelease=$(_latest_release)
|
|
||||||
run git -C "$ABRA_DIR/recipes/$TEST_RECIPE" tag -d "$latestRelease"
|
|
||||||
}
|
|
||||||
|
|
||||||
# bats test_tags=slow
|
|
||||||
@test "warn on recipe lint errors with --chaos" {
|
|
||||||
# Break the recipe
|
|
||||||
run sed -i '/traefik.enable=.*/d' "$ABRA_DIR/recipes/$TEST_RECIPE/compose.yml"
|
|
||||||
assert_success
|
|
||||||
|
|
||||||
run $ABRA app deploy "$TEST_APP_DOMAIN" --no-input --no-converge-checks --chaos
|
|
||||||
assert_success
|
|
||||||
assert_output --partial 'failed lint checks'
|
|
||||||
}
|
|
||||||
|
|
||||||
# bats test_tags=slow
|
# bats test_tags=slow
|
||||||
@test "ensure recipe up to date if no --offline" {
|
@test "ensure recipe up to date if no --offline" {
|
||||||
wantHash=$(_get_n_hash 3)
|
wantHash=$(_get_n_hash 3)
|
||||||
@ -186,6 +147,16 @@ teardown(){
|
|||||||
assert_exists "$ABRA_DIR/recipes/$TEST_RECIPE"
|
assert_exists "$ABRA_DIR/recipes/$TEST_RECIPE"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "no deploy if lint error" {
|
||||||
|
run sed -i '/traefik.enable=.*/d' "$ABRA_DIR/recipes/$TEST_RECIPE/compose.yml"
|
||||||
|
assert_success
|
||||||
|
|
||||||
|
run $ABRA app deploy "$TEST_APP_DOMAIN" \
|
||||||
|
--no-input --no-converge-checks --chaos
|
||||||
|
assert_failure
|
||||||
|
assert_output --partial 'failed lint checks'
|
||||||
|
}
|
||||||
|
|
||||||
# bats test_tags=slow
|
# bats test_tags=slow
|
||||||
@test "error if already deployed and no --force/--chaos" {
|
@test "error if already deployed and no --force/--chaos" {
|
||||||
_deploy_app
|
_deploy_app
|
||||||
|
@ -8,19 +8,9 @@ setup_file(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
teardown_file(){
|
teardown_file(){
|
||||||
if [[ ! -f "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env" ]]; then
|
|
||||||
_new_app
|
|
||||||
fi
|
|
||||||
|
|
||||||
_undeploy_app
|
_undeploy_app
|
||||||
_rm_app
|
_rm_app
|
||||||
_rm_server
|
_rm_server
|
||||||
|
|
||||||
if [[ -d "$ABRA_DIR/servers/foo" ]]; then
|
|
||||||
run rm -rf "$ABRA_DIR/servers/foo"
|
|
||||||
assert_success
|
|
||||||
assert_not_exists "$ABRA_DIR/servers/foo"
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setup(){
|
setup(){
|
||||||
@ -29,19 +19,8 @@ setup(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
teardown(){
|
teardown(){
|
||||||
if [[ ! -f "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env" ]]; then
|
|
||||||
_new_app
|
|
||||||
fi
|
|
||||||
|
|
||||||
_undeploy_app
|
|
||||||
_wipe_env_version
|
|
||||||
_reset_recipe
|
_reset_recipe
|
||||||
|
_undeploy_app
|
||||||
if [[ -d "$ABRA_DIR/servers/foo" ]]; then
|
|
||||||
run rm -rf "$ABRA_DIR/servers/foo"
|
|
||||||
assert_success
|
|
||||||
assert_not_exists "$ABRA_DIR/servers/foo"
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "list without status" {
|
@test "list without status" {
|
||||||
@ -158,38 +137,3 @@ teardown(){
|
|||||||
assert_success
|
assert_success
|
||||||
assert_not_exists "$ABRA_DIR/servers/foo.com"
|
assert_not_exists "$ABRA_DIR/servers/foo.com"
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "list with status skips unknown servers" {
|
|
||||||
if [[ ! -d "$ABRA_DIR/servers/foo" ]]; then
|
|
||||||
run mkdir -p "$ABRA_DIR/servers/foo"
|
|
||||||
assert_success
|
|
||||||
assert_exists "$ABRA_DIR/servers/foo"
|
|
||||||
|
|
||||||
run cp "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env" \
|
|
||||||
"$ABRA_DIR/servers/foo/$TEST_APP_DOMAIN.env"
|
|
||||||
assert_success
|
|
||||||
assert_exists "$ABRA_DIR/servers/foo/$TEST_APP_DOMAIN.env"
|
|
||||||
fi
|
|
||||||
|
|
||||||
run $ABRA app ls --status
|
|
||||||
assert_success
|
|
||||||
assert_output --partial "unknown server"
|
|
||||||
}
|
|
||||||
|
|
||||||
# bats test_tags=slow
|
|
||||||
@test "list does not fail if missing .env" {
|
|
||||||
_deploy_app
|
|
||||||
|
|
||||||
run $ABRA app ls --status
|
|
||||||
assert_success
|
|
||||||
|
|
||||||
run rm -rf "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env"
|
|
||||||
assert_success
|
|
||||||
assert_not_exists "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env"
|
|
||||||
|
|
||||||
output=$("$ABRA" app ls --server "$TEST_SERVER" --status --machine)
|
|
||||||
run diff \
|
|
||||||
<(jq -S "." <(echo "$output")) \
|
|
||||||
<(jq -S "." <(echo '{}'))
|
|
||||||
assert_success
|
|
||||||
}
|
|
||||||
|
@ -124,33 +124,6 @@ teardown(){
|
|||||||
assert_output --partial 'removed'
|
assert_output --partial 'removed'
|
||||||
}
|
}
|
||||||
|
|
||||||
# bats test_tags=slow
|
|
||||||
@test "detect no configs to remove" {
|
|
||||||
_deploy_app
|
|
||||||
_undeploy_app
|
|
||||||
|
|
||||||
run $ABRA app rm "$TEST_APP_DOMAIN" --no-input
|
|
||||||
assert_success
|
|
||||||
assert_output --partial 'no configs to remove'
|
|
||||||
}
|
|
||||||
|
|
||||||
# bats test_tags=slow
|
|
||||||
@test "remove old app configs" {
|
|
||||||
_deploy_app
|
|
||||||
_undeploy_app
|
|
||||||
|
|
||||||
sanitisedDomainName="${TEST_APP_DOMAIN//./_}"
|
|
||||||
run docker config create "${sanitisedDomainName}_test_conf_v99" "$ABRA_DIR/recipes/abra-test-recipe/abra.sh"
|
|
||||||
assert_success
|
|
||||||
|
|
||||||
assert bash -c "docker config ls | grep -q test_conf_v99"
|
|
||||||
|
|
||||||
run $ABRA app rm "$TEST_APP_DOMAIN" --no-input
|
|
||||||
assert_success
|
|
||||||
|
|
||||||
refute bash -c "docker config ls | grep -q test_conf_v99"
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "remove .env file" {
|
@test "remove .env file" {
|
||||||
assert_exists "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env"
|
assert_exists "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env"
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ setup_file(){
|
|||||||
load "$PWD/tests/integration/helpers/common"
|
load "$PWD/tests/integration/helpers/common"
|
||||||
_common_setup
|
_common_setup
|
||||||
_add_server
|
_add_server
|
||||||
_fetch_recipe
|
|
||||||
|
|
||||||
# NOTE(d1): create new app without secrets
|
# NOTE(d1): create new app without secrets
|
||||||
run $ABRA app new "$TEST_RECIPE" \
|
run $ABRA app new "$TEST_RECIPE" \
|
||||||
@ -182,20 +181,6 @@ teardown(){
|
|||||||
assert_output --partial '10' # NOTE(d1): hardcoded # length=10 in recipe config
|
assert_output --partial '10' # NOTE(d1): hardcoded # length=10 in recipe config
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "generate: skip if generate=false" {
|
|
||||||
run sed -i 's/COMPOSE_FILE="compose.yml"/COMPOSE_FILE="compose.yml:compose.skip_pass.yml"/g' \
|
|
||||||
"$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env"
|
|
||||||
assert_success
|
|
||||||
|
|
||||||
run sed -i 's/#SECRET_TEST_SKIP_PASS_VERSION=v1/SECRET_TEST_SKIP_PASS_VERSION=v1/g' \
|
|
||||||
"$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env"
|
|
||||||
assert_success
|
|
||||||
|
|
||||||
run $ABRA app secret generate "$TEST_APP_DOMAIN" --all
|
|
||||||
assert_success
|
|
||||||
refute_output --partial 'test_skip_pass'
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "insert: validate arguments" {
|
@test "insert: validate arguments" {
|
||||||
run $ABRA app secret insert
|
run $ABRA app secret insert
|
||||||
assert_failure
|
assert_failure
|
||||||
@ -210,12 +195,6 @@ teardown(){
|
|||||||
assert_failure
|
assert_failure
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "insert: cannot insert unknown secret" {
|
|
||||||
run $ABRA app secret insert "$TEST_APP_DOMAIN" DOESNTEXIST v1 foo
|
|
||||||
assert_failure
|
|
||||||
assert_output --partial 'no secret'
|
|
||||||
}
|
|
||||||
|
|
||||||
@test "insert: create secret" {
|
@test "insert: create secret" {
|
||||||
run $ABRA app secret ls "$TEST_APP_DOMAIN"
|
run $ABRA app secret ls "$TEST_APP_DOMAIN"
|
||||||
assert_success
|
assert_success
|
||||||
|
@ -30,20 +30,6 @@ teardown(){
|
|||||||
assert_failure
|
assert_failure
|
||||||
}
|
}
|
||||||
|
|
||||||
# bats test_tags=slow
|
|
||||||
@test "retrieve recipe if missing" {
|
|
||||||
_deploy_app
|
|
||||||
|
|
||||||
run rm -rf "$ABRA_DIR/recipes/$TEST_RECIPE"
|
|
||||||
assert_success
|
|
||||||
assert_not_exists "$ABRA_DIR/recipes/$TEST_RECIPE"
|
|
||||||
|
|
||||||
run $ABRA app undeploy "$TEST_APP_DOMAIN" --no-input
|
|
||||||
assert_success
|
|
||||||
|
|
||||||
assert_exists "$ABRA_DIR/recipes/$TEST_RECIPE"
|
|
||||||
}
|
|
||||||
|
|
||||||
# bats test_tags=slow
|
# bats test_tags=slow
|
||||||
@test "ensure recipe up to date if no --offline" {
|
@test "ensure recipe up to date if no --offline" {
|
||||||
_deploy_app
|
_deploy_app
|
||||||
|
@ -76,7 +76,7 @@ teardown(){
|
|||||||
assert_output --partial 'UPGRADE OVERVIEW'
|
assert_output --partial 'UPGRADE OVERVIEW'
|
||||||
assert_output --partial 'CURRENT DEPLOYMENT 0.2.0+1.21.0'
|
assert_output --partial 'CURRENT DEPLOYMENT 0.2.0+1.21.0'
|
||||||
assert_output --partial 'ENV VERSION N/A'
|
assert_output --partial 'ENV VERSION N/A'
|
||||||
assert_output --partial "NEW DEPLOYMENT $latestRelease"
|
assert_output --partial 'NEW DEPLOYMENT 0.3.1+1.21.0'
|
||||||
|
|
||||||
run grep -q "TYPE=$TEST_RECIPE:${latestRelease}" \
|
run grep -q "TYPE=$TEST_RECIPE:${latestRelease}" \
|
||||||
"$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env"
|
"$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env"
|
||||||
|
@ -63,24 +63,20 @@ teardown(){
|
|||||||
|
|
||||||
# bats test_tags=slow
|
# bats test_tags=slow
|
||||||
@test "remove volumes" {
|
@test "remove volumes" {
|
||||||
|
sleep 3 # NOTE(d1): hack to avoid "network not found"
|
||||||
|
|
||||||
_deploy_app
|
_deploy_app
|
||||||
_undeploy_app
|
_undeploy_app
|
||||||
|
|
||||||
run $ABRA app volume ls "$TEST_APP_DOMAIN"
|
|
||||||
assert_success
|
|
||||||
assert_output --partial 'test-volume'
|
|
||||||
|
|
||||||
run $ABRA app volume rm "$TEST_APP_DOMAIN" --force
|
run $ABRA app volume rm "$TEST_APP_DOMAIN" --force
|
||||||
assert_success
|
assert_success
|
||||||
assert_output --partial 'volumes removed successfully'
|
assert_output --partial 'volumes removed successfully'
|
||||||
|
|
||||||
run $ABRA app volume ls "$TEST_APP_DOMAIN"
|
|
||||||
assert_success
|
|
||||||
assert_output --partial 'no volumes created'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# bats test_tags=slow
|
# bats test_tags=slow
|
||||||
@test "remove no volumes" {
|
@test "remove no volumes" {
|
||||||
|
sleep 3 # NOTE(d1): hack to avoid "network not found"
|
||||||
|
|
||||||
_deploy_app
|
_deploy_app
|
||||||
_undeploy_app
|
_undeploy_app
|
||||||
|
|
||||||
@ -92,59 +88,3 @@ teardown(){
|
|||||||
assert_success
|
assert_success
|
||||||
assert_output --partial 'no volumes removed'
|
assert_output --partial 'no volumes removed'
|
||||||
}
|
}
|
||||||
|
|
||||||
# bats test_tags=slow
|
|
||||||
@test "remove single volume" {
|
|
||||||
_deploy_app
|
|
||||||
_undeploy_app
|
|
||||||
|
|
||||||
run $ABRA app volume ls "$TEST_APP_DOMAIN"
|
|
||||||
assert_success
|
|
||||||
assert_output --partial 'test-volume'
|
|
||||||
assert_output --partial 'test-volume-two'
|
|
||||||
|
|
||||||
run $ABRA app volume rm "$TEST_APP_DOMAIN" test-volume-two --force
|
|
||||||
assert_success
|
|
||||||
assert_output --partial 'test-volume-two removed successfully'
|
|
||||||
|
|
||||||
run $ABRA app volume ls "$TEST_APP_DOMAIN"
|
|
||||||
assert_success
|
|
||||||
assert_output --partial 'test-volume'
|
|
||||||
refute_output --partial 'test-volume-two'
|
|
||||||
|
|
||||||
run $ABRA app volume rm "$TEST_APP_DOMAIN" --force
|
|
||||||
assert_success
|
|
||||||
assert_output --partial 'volumes removed successfully'
|
|
||||||
|
|
||||||
run $ABRA app volume ls "$TEST_APP_DOMAIN"
|
|
||||||
assert_success
|
|
||||||
assert_output --partial 'no volumes created'
|
|
||||||
}
|
|
||||||
|
|
||||||
# bats test_tags=slow
|
|
||||||
@test "remove single volume incorrect name" {
|
|
||||||
_deploy_app
|
|
||||||
_undeploy_app
|
|
||||||
|
|
||||||
run $ABRA app volume rm "$TEST_APP_DOMAIN" DOESNTEXIST --force
|
|
||||||
assert_failure
|
|
||||||
assert_output --partial 'no volume with name'
|
|
||||||
}
|
|
||||||
|
|
||||||
# bats test_tags=slow
|
|
||||||
@test "remove single volume doesn't delete similar name" {
|
|
||||||
_deploy_app
|
|
||||||
_undeploy_app
|
|
||||||
|
|
||||||
run $ABRA app volume ls "$TEST_APP_DOMAIN"
|
|
||||||
assert_success
|
|
||||||
assert_output --partial 'test-volume-two'
|
|
||||||
|
|
||||||
run $ABRA app volume rm "$TEST_APP_DOMAIN" test-volume --force
|
|
||||||
assert_success
|
|
||||||
assert_output --partial 'test-volume removed successfully'
|
|
||||||
|
|
||||||
run $ABRA app volume ls "$TEST_APP_DOMAIN"
|
|
||||||
assert_success
|
|
||||||
assert_output --partial 'test-volume-two'
|
|
||||||
}
|
|
||||||
|
@ -24,7 +24,7 @@ setup(){
|
|||||||
assert_success
|
assert_success
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "abra directories are created" {
|
@test "abra directory is created" {
|
||||||
run $ABRA app ls
|
run $ABRA app ls
|
||||||
|
|
||||||
# NOTE(d1): no servers yet, so will fail. however, it will run the required
|
# NOTE(d1): no servers yet, so will fail. however, it will run the required
|
||||||
@ -35,9 +35,8 @@ setup(){
|
|||||||
assert_exists "$ABRA_DIR"
|
assert_exists "$ABRA_DIR"
|
||||||
assert_exists "$ABRA_DIR/servers"
|
assert_exists "$ABRA_DIR/servers"
|
||||||
assert_exists "$ABRA_DIR/recipes"
|
assert_exists "$ABRA_DIR/recipes"
|
||||||
|
assert_exists "$ABRA_DIR/backups"
|
||||||
|
assert_exists "$ABRA_DIR/vendor"
|
||||||
|
|
||||||
assert_not_exists "$ABRA_DIR/catalogue"
|
assert_not_exists "$ABRA_DIR/catalogue"
|
||||||
|
|
||||||
server_dir_perms=$(stat -c "%a" "$ABRA_DIR/servers")
|
|
||||||
assert_equal $server_dir_perms "700"
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
_new_app() {
|
_new_app() {
|
||||||
_fetch_recipe
|
|
||||||
|
|
||||||
run $ABRA app new "$TEST_RECIPE" \
|
run $ABRA app new "$TEST_RECIPE" \
|
||||||
--no-input \
|
--no-input \
|
||||||
--server "$TEST_SERVER" \
|
--server "$TEST_SERVER" \
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
_ensure_swarm() {
|
_ensure_swarm() {
|
||||||
if [ "$(docker info | grep Swarm | sed 's/Swarm: //g' | tr -d ' ')" == "inactive" ]; then
|
if [ "$(docker info | grep Swarm | sed 's/Swarm: //g' | tr -d ' ')" == "inactive" ]; then
|
||||||
run docker swarm init --advertise-addr 127.0.0.1:2377
|
run docker swarm init
|
||||||
assert_success
|
assert_success
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
setup() {
|
setup() {
|
||||||
load "$PWD/tests/integration/helpers/common"
|
load "$PWD/tests/integration/helpers/common"
|
||||||
_common_setup
|
_common_setup
|
||||||
_fetch_recipe
|
|
||||||
}
|
}
|
||||||
|
|
||||||
teardown(){
|
teardown(){
|
||||||
|
@ -22,16 +22,14 @@ teardown(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
@test "retrieve recipe if missing" {
|
@test "retrieve recipe if missing" {
|
||||||
if [[ -d "$ABRA_DIR/recipe/custom-html" ]]; then
|
run rm -rf "$ABRA_DIR/recipes/$TEST_RECIPE"
|
||||||
run rm -rf "$ABRA_DIR/recipes/custom-html"
|
|
||||||
assert_success
|
assert_success
|
||||||
assert_not_exists "$ABRA_DIR/recipes/custom-html"
|
assert_not_exists "$ABRA_DIR/recipes/$TEST_RECIPE"
|
||||||
fi
|
|
||||||
|
|
||||||
run $ABRA recipe lint custom-html
|
run $ABRA recipe lint "$TEST_RECIPE"
|
||||||
assert_success
|
assert_success
|
||||||
|
|
||||||
assert_exists "$ABRA_DIR/recipes/custom-html"
|
assert_exists "$ABRA_DIR/recipes/$TEST_RECIPE"
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "bail if unstaged changes and no --chaos" {
|
@test "bail if unstaged changes and no --chaos" {
|
||||||
|
@ -30,17 +30,15 @@ teardown(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
@test "retrieve recipe if missing" {
|
@test "retrieve recipe if missing" {
|
||||||
if [[ -d "$ABRA_DIR/recipe/custom-html" ]]; then
|
run rm -rf "$ABRA_DIR/recipes/$TEST_RECIPE"
|
||||||
run rm -rf "$ABRA_DIR/recipes/custom-html"
|
|
||||||
assert_success
|
assert_success
|
||||||
assert_not_exists "$ABRA_DIR/recipes/custom-html"
|
assert_not_exists "$ABRA_DIR/recipes/$TEST_RECIPE"
|
||||||
fi
|
|
||||||
|
|
||||||
run $ABRA recipe upgrade "custom-html" --no-input
|
run $ABRA recipe upgrade "$TEST_RECIPE" --no-input
|
||||||
assert_success
|
assert_success
|
||||||
assert_output --partial 'can upgrade service: app'
|
assert_output --partial 'can upgrade service: app'
|
||||||
|
|
||||||
assert_exists "$ABRA_DIR/recipes/custom-html"
|
assert_exists "$ABRA_DIR/recipes/$TEST_RECIPE"
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "error if unstaged changes" {
|
@test "error if unstaged changes" {
|
||||||
|
@ -25,9 +25,6 @@ teardown(){
|
|||||||
assert_output --partial "$TEST_SERVER"
|
assert_output --partial "$TEST_SERVER"
|
||||||
|
|
||||||
assert bash -c "docker context ls | grep -q $TEST_SERVER"
|
assert bash -c "docker context ls | grep -q $TEST_SERVER"
|
||||||
|
|
||||||
server_dir_perms=$(stat -c "%a" "$ABRA_DIR/servers/$TEST_SERVER")
|
|
||||||
assert_equal $server_dir_perms "700"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "error if using name and --local together" {
|
@test "error if using name and --local together" {
|
||||||
@ -42,9 +39,6 @@ teardown(){
|
|||||||
assert_exists "$ABRA_DIR/servers/default"
|
assert_exists "$ABRA_DIR/servers/default"
|
||||||
assert bash -c "docker context ls | grep -q default"
|
assert bash -c "docker context ls | grep -q default"
|
||||||
assert_output --partial 'local server successfully added'
|
assert_output --partial 'local server successfully added'
|
||||||
|
|
||||||
server_dir_perms=$(stat -c "%a" "$ABRA_DIR/servers/$TEST_SERVER")
|
|
||||||
assert_equal $server_dir_perms "700"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "create local server fails when no docker swarm" {
|
@test "create local server fails when no docker swarm" {
|
||||||
|
3
vendor/coopcloud.tech/tagcmp/renovate.json
vendored
Normal file
3
vendor/coopcloud.tech/tagcmp/renovate.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json"
|
||||||
|
}
|
2
vendor/coopcloud.tech/tagcmp/tagcmp.go
vendored
2
vendor/coopcloud.tech/tagcmp/tagcmp.go
vendored
@ -290,7 +290,7 @@ func patternMatches(tag string) error {
|
|||||||
|
|
||||||
for _, pattern := range unsupported {
|
for _, pattern := range unsupported {
|
||||||
if match, _ := regexp.Match(pattern, []byte(tag)); match {
|
if match, _ := regexp.Match(pattern, []byte(tag)); match {
|
||||||
return fmt.Errorf("version %s is not supported (matched: %s)", tag, pattern)
|
return fmt.Errorf("'%s' is not supported (%s)", tag, pattern)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
7
vendor/dario.cat/mergo/FUNDING.json
vendored
7
vendor/dario.cat/mergo/FUNDING.json
vendored
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"drips": {
|
|
||||||
"ethereum": {
|
|
||||||
"ownedBy": "0x6160020e7102237aC41bdb156e94401692D76930"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
5
vendor/dario.cat/mergo/README.md
vendored
5
vendor/dario.cat/mergo/README.md
vendored
@ -85,6 +85,7 @@ Mergo is used by [thousands](https://deps.dev/go/dario.cat%2Fmergo/v1.0.0/depend
|
|||||||
* [goreleaser/goreleaser](https://github.com/goreleaser/goreleaser)
|
* [goreleaser/goreleaser](https://github.com/goreleaser/goreleaser)
|
||||||
* [go-micro/go-micro](https://github.com/go-micro/go-micro)
|
* [go-micro/go-micro](https://github.com/go-micro/go-micro)
|
||||||
* [grafana/loki](https://github.com/grafana/loki)
|
* [grafana/loki](https://github.com/grafana/loki)
|
||||||
|
* [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes)
|
||||||
* [masterminds/sprig](github.com/Masterminds/sprig)
|
* [masterminds/sprig](github.com/Masterminds/sprig)
|
||||||
* [moby/moby](https://github.com/moby/moby)
|
* [moby/moby](https://github.com/moby/moby)
|
||||||
* [slackhq/nebula](https://github.com/slackhq/nebula)
|
* [slackhq/nebula](https://github.com/slackhq/nebula)
|
||||||
@ -190,6 +191,10 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note: if test are failing due missing package, please execute:
|
||||||
|
|
||||||
|
go get gopkg.in/yaml.v3
|
||||||
|
|
||||||
### Transformers
|
### Transformers
|
||||||
|
|
||||||
Transformers allow to merge specific types differently than in the default behavior. In other words, now you can customize how some types are merged. For example, `time.Time` is a struct; it doesn't have zero value but IsZero can return true because it has fields with zero value. How can we merge a non-zero `time.Time`?
|
Transformers allow to merge specific types differently than in the default behavior. In other words, now you can customize how some types are merged. For example, `time.Time` is a struct; it doesn't have zero value but IsZero can return true because it has fields with zero value. How can we merge a non-zero `time.Time`?
|
||||||
|
4
vendor/dario.cat/mergo/SECURITY.md
vendored
4
vendor/dario.cat/mergo/SECURITY.md
vendored
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
| Version | Supported |
|
| Version | Supported |
|
||||||
| ------- | ------------------ |
|
| ------- | ------------------ |
|
||||||
| 1.x.x | :white_check_mark: |
|
| 0.3.x | :white_check_mark: |
|
||||||
| < 1.0 | :x: |
|
| < 0.3 | :x: |
|
||||||
|
|
||||||
## Security contact information
|
## Security contact information
|
||||||
|
|
||||||
|
2
vendor/github.com/BurntSushi/toml/README.md
generated
vendored
2
vendor/github.com/BurntSushi/toml/README.md
generated
vendored
@ -3,7 +3,7 @@ reflection interface similar to Go's standard library `json` and `xml` packages.
|
|||||||
|
|
||||||
Compatible with TOML version [v1.0.0](https://toml.io/en/v1.0.0).
|
Compatible with TOML version [v1.0.0](https://toml.io/en/v1.0.0).
|
||||||
|
|
||||||
Documentation: https://pkg.go.dev/github.com/BurntSushi/toml
|
Documentation: https://godocs.io/github.com/BurntSushi/toml
|
||||||
|
|
||||||
See the [releases page](https://github.com/BurntSushi/toml/releases) for a
|
See the [releases page](https://github.com/BurntSushi/toml/releases) for a
|
||||||
changelog; this information is also in the git tag annotations (e.g. `git show
|
changelog; this information is also in the git tag annotations (e.g. `git show
|
||||||
|
31
vendor/github.com/BurntSushi/toml/decode.go
generated
vendored
31
vendor/github.com/BurntSushi/toml/decode.go
generated
vendored
@ -196,19 +196,6 @@ func (md *MetaData) PrimitiveDecode(primValue Primitive, v any) error {
|
|||||||
return md.unify(primValue.undecoded, rvalue(v))
|
return md.unify(primValue.undecoded, rvalue(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// markDecodedRecursive is a helper to mark any key under the given tmap as
|
|
||||||
// decoded, recursing as needed
|
|
||||||
func markDecodedRecursive(md *MetaData, tmap map[string]any) {
|
|
||||||
for key := range tmap {
|
|
||||||
md.decoded[md.context.add(key).String()] = struct{}{}
|
|
||||||
if tmap, ok := tmap[key].(map[string]any); ok {
|
|
||||||
md.context = append(md.context, key)
|
|
||||||
markDecodedRecursive(md, tmap)
|
|
||||||
md.context = md.context[0 : len(md.context)-1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// unify performs a sort of type unification based on the structure of `rv`,
|
// unify performs a sort of type unification based on the structure of `rv`,
|
||||||
// which is the client representation.
|
// which is the client representation.
|
||||||
//
|
//
|
||||||
@ -235,16 +222,6 @@ func (md *MetaData) unify(data any, rv reflect.Value) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return md.parseErr(err)
|
return md.parseErr(err)
|
||||||
}
|
}
|
||||||
// Assume the Unmarshaler decoded everything, so mark all keys under
|
|
||||||
// this table as decoded.
|
|
||||||
if tmap, ok := data.(map[string]any); ok {
|
|
||||||
markDecodedRecursive(md, tmap)
|
|
||||||
}
|
|
||||||
if aot, ok := data.([]map[string]any); ok {
|
|
||||||
for _, tmap := range aot {
|
|
||||||
markDecodedRecursive(md, tmap)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if v, ok := rvi.(encoding.TextUnmarshaler); ok {
|
if v, ok := rvi.(encoding.TextUnmarshaler); ok {
|
||||||
@ -563,14 +540,12 @@ func (md *MetaData) badtype(dst string, data any) error {
|
|||||||
|
|
||||||
func (md *MetaData) parseErr(err error) error {
|
func (md *MetaData) parseErr(err error) error {
|
||||||
k := md.context.String()
|
k := md.context.String()
|
||||||
d := string(md.data)
|
|
||||||
return ParseError{
|
return ParseError{
|
||||||
Message: err.Error(),
|
|
||||||
err: err,
|
|
||||||
LastKey: k,
|
LastKey: k,
|
||||||
Position: md.keyInfo[k].pos.withCol(d),
|
Position: md.keyInfo[k].pos,
|
||||||
Line: md.keyInfo[k].pos.Line,
|
Line: md.keyInfo[k].pos.Line,
|
||||||
input: d,
|
err: err,
|
||||||
|
input: string(md.data),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
40
vendor/github.com/BurntSushi/toml/encode.go
generated
vendored
40
vendor/github.com/BurntSushi/toml/encode.go
generated
vendored
@ -402,30 +402,31 @@ func (enc *Encoder) eMap(key Key, rv reflect.Value, inline bool) {
|
|||||||
|
|
||||||
// Sort keys so that we have deterministic output. And write keys directly
|
// Sort keys so that we have deterministic output. And write keys directly
|
||||||
// underneath this key first, before writing sub-structs or sub-maps.
|
// underneath this key first, before writing sub-structs or sub-maps.
|
||||||
var mapKeysDirect, mapKeysSub []reflect.Value
|
var mapKeysDirect, mapKeysSub []string
|
||||||
for _, mapKey := range rv.MapKeys() {
|
for _, mapKey := range rv.MapKeys() {
|
||||||
|
k := mapKey.String()
|
||||||
if typeIsTable(tomlTypeOfGo(eindirect(rv.MapIndex(mapKey)))) {
|
if typeIsTable(tomlTypeOfGo(eindirect(rv.MapIndex(mapKey)))) {
|
||||||
mapKeysSub = append(mapKeysSub, mapKey)
|
mapKeysSub = append(mapKeysSub, k)
|
||||||
} else {
|
} else {
|
||||||
mapKeysDirect = append(mapKeysDirect, mapKey)
|
mapKeysDirect = append(mapKeysDirect, k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writeMapKeys := func(mapKeys []reflect.Value, trailC bool) {
|
var writeMapKeys = func(mapKeys []string, trailC bool) {
|
||||||
sort.Slice(mapKeys, func(i, j int) bool { return mapKeys[i].String() < mapKeys[j].String() })
|
sort.Strings(mapKeys)
|
||||||
for i, mapKey := range mapKeys {
|
for i, mapKey := range mapKeys {
|
||||||
val := eindirect(rv.MapIndex(mapKey))
|
val := eindirect(rv.MapIndex(reflect.ValueOf(mapKey)))
|
||||||
if isNil(val) {
|
if isNil(val) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if inline {
|
if inline {
|
||||||
enc.writeKeyValue(Key{mapKey.String()}, val, true)
|
enc.writeKeyValue(Key{mapKey}, val, true)
|
||||||
if trailC || i != len(mapKeys)-1 {
|
if trailC || i != len(mapKeys)-1 {
|
||||||
enc.wf(", ")
|
enc.wf(", ")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
enc.encode(key.add(mapKey.String()), val)
|
enc.encode(key.add(mapKey), val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -440,6 +441,8 @@ func (enc *Encoder) eMap(key Key, rv reflect.Value, inline bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const is32Bit = (32 << (^uint(0) >> 63)) == 32
|
||||||
|
|
||||||
func pointerTo(t reflect.Type) reflect.Type {
|
func pointerTo(t reflect.Type) reflect.Type {
|
||||||
if t.Kind() == reflect.Ptr {
|
if t.Kind() == reflect.Ptr {
|
||||||
return pointerTo(t.Elem())
|
return pointerTo(t.Elem())
|
||||||
@ -474,14 +477,15 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
|
|||||||
|
|
||||||
frv := eindirect(rv.Field(i))
|
frv := eindirect(rv.Field(i))
|
||||||
|
|
||||||
// Need to make a copy because ... ehm, I don't know why... I guess
|
if is32Bit {
|
||||||
// allocating a new array can cause it to fail(?)
|
// Copy so it works correct on 32bit archs; not clear why this
|
||||||
//
|
// is needed. See #314, and https://www.reddit.com/r/golang/comments/pnx8v4
|
||||||
// Done for: https://github.com/BurntSushi/toml/issues/430
|
// This also works fine on 64bit, but 32bit archs are somewhat
|
||||||
// Previously only on 32bit for: https://github.com/BurntSushi/toml/issues/314
|
// rare and this is a wee bit faster.
|
||||||
copyStart := make([]int, len(start))
|
copyStart := make([]int, len(start))
|
||||||
copy(copyStart, start)
|
copy(copyStart, start)
|
||||||
start = copyStart
|
start = copyStart
|
||||||
|
}
|
||||||
|
|
||||||
// Treat anonymous struct fields with tag names as though they are
|
// Treat anonymous struct fields with tag names as though they are
|
||||||
// not anonymous, like encoding/json does.
|
// not anonymous, like encoding/json does.
|
||||||
@ -503,7 +507,7 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
|
|||||||
}
|
}
|
||||||
addFields(rt, rv, nil)
|
addFields(rt, rv, nil)
|
||||||
|
|
||||||
writeFields := func(fields [][]int, totalFields int) {
|
writeFields := func(fields [][]int) {
|
||||||
for _, fieldIndex := range fields {
|
for _, fieldIndex := range fields {
|
||||||
fieldType := rt.FieldByIndex(fieldIndex)
|
fieldType := rt.FieldByIndex(fieldIndex)
|
||||||
fieldVal := rv.FieldByIndex(fieldIndex)
|
fieldVal := rv.FieldByIndex(fieldIndex)
|
||||||
@ -533,7 +537,7 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
|
|||||||
|
|
||||||
if inline {
|
if inline {
|
||||||
enc.writeKeyValue(Key{keyName}, fieldVal, true)
|
enc.writeKeyValue(Key{keyName}, fieldVal, true)
|
||||||
if fieldIndex[0] != totalFields-1 {
|
if fieldIndex[0] != len(fields)-1 {
|
||||||
enc.wf(", ")
|
enc.wf(", ")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -545,10 +549,8 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) {
|
|||||||
if inline {
|
if inline {
|
||||||
enc.wf("{")
|
enc.wf("{")
|
||||||
}
|
}
|
||||||
|
writeFields(fieldsDirect)
|
||||||
l := len(fieldsDirect) + len(fieldsSub)
|
writeFields(fieldsSub)
|
||||||
writeFields(fieldsDirect, l)
|
|
||||||
writeFields(fieldsSub, l)
|
|
||||||
if inline {
|
if inline {
|
||||||
enc.wf("}")
|
enc.wf("}")
|
||||||
}
|
}
|
||||||
|
69
vendor/github.com/BurntSushi/toml/error.go
generated
vendored
69
vendor/github.com/BurntSushi/toml/error.go
generated
vendored
@ -67,36 +67,21 @@ type ParseError struct {
|
|||||||
// Position of an error.
|
// Position of an error.
|
||||||
type Position struct {
|
type Position struct {
|
||||||
Line int // Line number, starting at 1.
|
Line int // Line number, starting at 1.
|
||||||
Col int // Error column, starting at 1.
|
|
||||||
Start int // Start of error, as byte offset starting at 0.
|
Start int // Start of error, as byte offset starting at 0.
|
||||||
Len int // Length of the error in bytes.
|
Len int // Lenght in bytes.
|
||||||
}
|
|
||||||
|
|
||||||
func (p Position) withCol(tomlFile string) Position {
|
|
||||||
var (
|
|
||||||
pos int
|
|
||||||
lines = strings.Split(tomlFile, "\n")
|
|
||||||
)
|
|
||||||
for i := range lines {
|
|
||||||
ll := len(lines[i]) + 1 // +1 for the removed newline
|
|
||||||
if pos+ll >= p.Start {
|
|
||||||
p.Col = p.Start - pos + 1
|
|
||||||
if p.Col < 1 { // Should never happen, but just in case.
|
|
||||||
p.Col = 1
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
pos += ll
|
|
||||||
}
|
|
||||||
return p
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pe ParseError) Error() string {
|
func (pe ParseError) Error() string {
|
||||||
|
msg := pe.Message
|
||||||
|
if msg == "" { // Error from errorf()
|
||||||
|
msg = pe.err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
if pe.LastKey == "" {
|
if pe.LastKey == "" {
|
||||||
return fmt.Sprintf("toml: line %d: %s", pe.Position.Line, pe.Message)
|
return fmt.Sprintf("toml: line %d: %s", pe.Position.Line, msg)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("toml: line %d (last key %q): %s",
|
return fmt.Sprintf("toml: line %d (last key %q): %s",
|
||||||
pe.Position.Line, pe.LastKey, pe.Message)
|
pe.Position.Line, pe.LastKey, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrorWithPosition returns the error with detailed location context.
|
// ErrorWithPosition returns the error with detailed location context.
|
||||||
@ -107,19 +92,26 @@ func (pe ParseError) ErrorWithPosition() string {
|
|||||||
return pe.Error()
|
return pe.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
lines = strings.Split(pe.input, "\n")
|
||||||
|
col = pe.column(lines)
|
||||||
|
b = new(strings.Builder)
|
||||||
|
)
|
||||||
|
|
||||||
|
msg := pe.Message
|
||||||
|
if msg == "" {
|
||||||
|
msg = pe.err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: don't show control characters as literals? This may not show up
|
// TODO: don't show control characters as literals? This may not show up
|
||||||
// well everywhere.
|
// well everywhere.
|
||||||
|
|
||||||
var (
|
|
||||||
lines = strings.Split(pe.input, "\n")
|
|
||||||
b = new(strings.Builder)
|
|
||||||
)
|
|
||||||
if pe.Position.Len == 1 {
|
if pe.Position.Len == 1 {
|
||||||
fmt.Fprintf(b, "toml: error: %s\n\nAt line %d, column %d:\n\n",
|
fmt.Fprintf(b, "toml: error: %s\n\nAt line %d, column %d:\n\n",
|
||||||
pe.Message, pe.Position.Line, pe.Position.Col)
|
msg, pe.Position.Line, col+1)
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(b, "toml: error: %s\n\nAt line %d, column %d-%d:\n\n",
|
fmt.Fprintf(b, "toml: error: %s\n\nAt line %d, column %d-%d:\n\n",
|
||||||
pe.Message, pe.Position.Line, pe.Position.Col, pe.Position.Col+pe.Position.Len-1)
|
msg, pe.Position.Line, col, col+pe.Position.Len)
|
||||||
}
|
}
|
||||||
if pe.Position.Line > 2 {
|
if pe.Position.Line > 2 {
|
||||||
fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-2, expandTab(lines[pe.Position.Line-3]))
|
fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line-2, expandTab(lines[pe.Position.Line-3]))
|
||||||
@ -137,7 +129,7 @@ func (pe ParseError) ErrorWithPosition() string {
|
|||||||
diff := len(expanded) - len(lines[pe.Position.Line-1])
|
diff := len(expanded) - len(lines[pe.Position.Line-1])
|
||||||
|
|
||||||
fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line, expanded)
|
fmt.Fprintf(b, "% 7d | %s\n", pe.Position.Line, expanded)
|
||||||
fmt.Fprintf(b, "% 10s%s%s\n", "", strings.Repeat(" ", pe.Position.Col-1+diff), strings.Repeat("^", pe.Position.Len))
|
fmt.Fprintf(b, "% 10s%s%s\n", "", strings.Repeat(" ", col+diff), strings.Repeat("^", pe.Position.Len))
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +151,23 @@ func (pe ParseError) ErrorWithUsage() string {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pe ParseError) column(lines []string) int {
|
||||||
|
var pos, col int
|
||||||
|
for i := range lines {
|
||||||
|
ll := len(lines[i]) + 1 // +1 for the removed newline
|
||||||
|
if pos+ll >= pe.Position.Start {
|
||||||
|
col = pe.Position.Start - pos
|
||||||
|
if col < 0 { // Should never happen, but just in case.
|
||||||
|
col = 0
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
pos += ll
|
||||||
|
}
|
||||||
|
|
||||||
|
return col
|
||||||
|
}
|
||||||
|
|
||||||
func expandTab(s string) string {
|
func expandTab(s string) string {
|
||||||
var (
|
var (
|
||||||
b strings.Builder
|
b strings.Builder
|
||||||
|
31
vendor/github.com/BurntSushi/toml/lex.go
generated
vendored
31
vendor/github.com/BurntSushi/toml/lex.go
generated
vendored
@ -275,9 +275,7 @@ func (lx *lexer) errorPos(start, length int, err error) stateFn {
|
|||||||
func (lx *lexer) errorf(format string, values ...any) stateFn {
|
func (lx *lexer) errorf(format string, values ...any) stateFn {
|
||||||
if lx.atEOF {
|
if lx.atEOF {
|
||||||
pos := lx.getPos()
|
pos := lx.getPos()
|
||||||
if lx.pos >= 1 && lx.input[lx.pos-1] == '\n' {
|
|
||||||
pos.Line--
|
pos.Line--
|
||||||
}
|
|
||||||
pos.Len = 1
|
pos.Len = 1
|
||||||
pos.Start = lx.pos - 1
|
pos.Start = lx.pos - 1
|
||||||
lx.items <- item{typ: itemError, pos: pos, err: fmt.Errorf(format, values...)}
|
lx.items <- item{typ: itemError, pos: pos, err: fmt.Errorf(format, values...)}
|
||||||
@ -494,9 +492,6 @@ func lexKeyEnd(lx *lexer) stateFn {
|
|||||||
lx.emit(itemKeyEnd)
|
lx.emit(itemKeyEnd)
|
||||||
return lexSkip(lx, lexValue)
|
return lexSkip(lx, lexValue)
|
||||||
default:
|
default:
|
||||||
if r == '\n' {
|
|
||||||
return lx.errorPrevLine(fmt.Errorf("expected '.' or '=', but got %q instead", r))
|
|
||||||
}
|
|
||||||
return lx.errorf("expected '.' or '=', but got %q instead", r)
|
return lx.errorf("expected '.' or '=', but got %q instead", r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -565,9 +560,6 @@ func lexValue(lx *lexer) stateFn {
|
|||||||
if r == eof {
|
if r == eof {
|
||||||
return lx.errorf("unexpected EOF; expected value")
|
return lx.errorf("unexpected EOF; expected value")
|
||||||
}
|
}
|
||||||
if r == '\n' {
|
|
||||||
return lx.errorPrevLine(fmt.Errorf("expected value but found %q instead", r))
|
|
||||||
}
|
|
||||||
return lx.errorf("expected value but found %q instead", r)
|
return lx.errorf("expected value but found %q instead", r)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1119,7 +1111,7 @@ func lexBaseNumberOrDate(lx *lexer) stateFn {
|
|||||||
case 'x':
|
case 'x':
|
||||||
r = lx.peek()
|
r = lx.peek()
|
||||||
if !isHex(r) {
|
if !isHex(r) {
|
||||||
lx.errorf("not a hexadecimal number: '%s%c'", lx.current(), r)
|
lx.errorf("not a hexidecimal number: '%s%c'", lx.current(), r)
|
||||||
}
|
}
|
||||||
return lexHexInteger
|
return lexHexInteger
|
||||||
}
|
}
|
||||||
@ -1267,6 +1259,23 @@ func isBinary(r rune) bool { return r == '0' || r == '1' }
|
|||||||
func isOctal(r rune) bool { return r >= '0' && r <= '7' }
|
func isOctal(r rune) bool { return r >= '0' && r <= '7' }
|
||||||
func isHex(r rune) bool { return (r >= '0' && r <= '9') || (r|0x20 >= 'a' && r|0x20 <= 'f') }
|
func isHex(r rune) bool { return (r >= '0' && r <= '9') || (r|0x20 >= 'a' && r|0x20 <= 'f') }
|
||||||
func isBareKeyChar(r rune, tomlNext bool) bool {
|
func isBareKeyChar(r rune, tomlNext bool) bool {
|
||||||
return (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') ||
|
if tomlNext {
|
||||||
(r >= '0' && r <= '9') || r == '_' || r == '-'
|
return (r >= 'A' && r <= 'Z') ||
|
||||||
|
(r >= 'a' && r <= 'z') ||
|
||||||
|
(r >= '0' && r <= '9') ||
|
||||||
|
r == '_' || r == '-' ||
|
||||||
|
r == 0xb2 || r == 0xb3 || r == 0xb9 || (r >= 0xbc && r <= 0xbe) ||
|
||||||
|
(r >= 0xc0 && r <= 0xd6) || (r >= 0xd8 && r <= 0xf6) || (r >= 0xf8 && r <= 0x037d) ||
|
||||||
|
(r >= 0x037f && r <= 0x1fff) ||
|
||||||
|
(r >= 0x200c && r <= 0x200d) || (r >= 0x203f && r <= 0x2040) ||
|
||||||
|
(r >= 0x2070 && r <= 0x218f) || (r >= 0x2460 && r <= 0x24ff) ||
|
||||||
|
(r >= 0x2c00 && r <= 0x2fef) || (r >= 0x3001 && r <= 0xd7ff) ||
|
||||||
|
(r >= 0xf900 && r <= 0xfdcf) || (r >= 0xfdf0 && r <= 0xfffd) ||
|
||||||
|
(r >= 0x10000 && r <= 0xeffff)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (r >= 'A' && r <= 'Z') ||
|
||||||
|
(r >= 'a' && r <= 'z') ||
|
||||||
|
(r >= '0' && r <= '9') ||
|
||||||
|
r == '_' || r == '-'
|
||||||
}
|
}
|
||||||
|
3
vendor/github.com/BurntSushi/toml/meta.go
generated
vendored
3
vendor/github.com/BurntSushi/toml/meta.go
generated
vendored
@ -135,6 +135,9 @@ func (k Key) maybeQuoted(i int) string {
|
|||||||
|
|
||||||
// Like append(), but only increase the cap by 1.
|
// Like append(), but only increase the cap by 1.
|
||||||
func (k Key) add(piece string) Key {
|
func (k Key) add(piece string) Key {
|
||||||
|
if cap(k) > len(k) {
|
||||||
|
return append(k, piece)
|
||||||
|
}
|
||||||
newKey := make(Key, len(k)+1)
|
newKey := make(Key, len(k)+1)
|
||||||
copy(newKey, k)
|
copy(newKey, k)
|
||||||
newKey[len(k)] = piece
|
newKey[len(k)] = piece
|
||||||
|
17
vendor/github.com/BurntSushi/toml/parse.go
generated
vendored
17
vendor/github.com/BurntSushi/toml/parse.go
generated
vendored
@ -50,6 +50,7 @@ func parse(data string) (p *parser, err error) {
|
|||||||
// it anyway.
|
// it anyway.
|
||||||
if strings.HasPrefix(data, "\xff\xfe") || strings.HasPrefix(data, "\xfe\xff") { // UTF-16
|
if strings.HasPrefix(data, "\xff\xfe") || strings.HasPrefix(data, "\xfe\xff") { // UTF-16
|
||||||
data = data[2:]
|
data = data[2:]
|
||||||
|
//lint:ignore S1017 https://github.com/dominikh/go-tools/issues/1447
|
||||||
} else if strings.HasPrefix(data, "\xef\xbb\xbf") { // UTF-8
|
} else if strings.HasPrefix(data, "\xef\xbb\xbf") { // UTF-8
|
||||||
data = data[3:]
|
data = data[3:]
|
||||||
}
|
}
|
||||||
@ -64,7 +65,7 @@ func parse(data string) (p *parser, err error) {
|
|||||||
if i := strings.IndexRune(data[:ex], 0); i > -1 {
|
if i := strings.IndexRune(data[:ex], 0); i > -1 {
|
||||||
return nil, ParseError{
|
return nil, ParseError{
|
||||||
Message: "files cannot contain NULL bytes; probably using UTF-16; TOML files must be UTF-8",
|
Message: "files cannot contain NULL bytes; probably using UTF-16; TOML files must be UTF-8",
|
||||||
Position: Position{Line: 1, Col: 1, Start: i, Len: 1},
|
Position: Position{Line: 1, Start: i, Len: 1},
|
||||||
Line: 1,
|
Line: 1,
|
||||||
input: data,
|
input: data,
|
||||||
}
|
}
|
||||||
@ -91,9 +92,8 @@ func parse(data string) (p *parser, err error) {
|
|||||||
|
|
||||||
func (p *parser) panicErr(it item, err error) {
|
func (p *parser) panicErr(it item, err error) {
|
||||||
panic(ParseError{
|
panic(ParseError{
|
||||||
Message: err.Error(),
|
|
||||||
err: err,
|
err: err,
|
||||||
Position: it.pos.withCol(p.lx.input),
|
Position: it.pos,
|
||||||
Line: it.pos.Len,
|
Line: it.pos.Len,
|
||||||
LastKey: p.current(),
|
LastKey: p.current(),
|
||||||
})
|
})
|
||||||
@ -102,7 +102,7 @@ func (p *parser) panicErr(it item, err error) {
|
|||||||
func (p *parser) panicItemf(it item, format string, v ...any) {
|
func (p *parser) panicItemf(it item, format string, v ...any) {
|
||||||
panic(ParseError{
|
panic(ParseError{
|
||||||
Message: fmt.Sprintf(format, v...),
|
Message: fmt.Sprintf(format, v...),
|
||||||
Position: it.pos.withCol(p.lx.input),
|
Position: it.pos,
|
||||||
Line: it.pos.Len,
|
Line: it.pos.Len,
|
||||||
LastKey: p.current(),
|
LastKey: p.current(),
|
||||||
})
|
})
|
||||||
@ -111,7 +111,7 @@ func (p *parser) panicItemf(it item, format string, v ...any) {
|
|||||||
func (p *parser) panicf(format string, v ...any) {
|
func (p *parser) panicf(format string, v ...any) {
|
||||||
panic(ParseError{
|
panic(ParseError{
|
||||||
Message: fmt.Sprintf(format, v...),
|
Message: fmt.Sprintf(format, v...),
|
||||||
Position: p.pos.withCol(p.lx.input),
|
Position: p.pos,
|
||||||
Line: p.pos.Line,
|
Line: p.pos.Line,
|
||||||
LastKey: p.current(),
|
LastKey: p.current(),
|
||||||
})
|
})
|
||||||
@ -123,11 +123,10 @@ func (p *parser) next() item {
|
|||||||
if it.typ == itemError {
|
if it.typ == itemError {
|
||||||
if it.err != nil {
|
if it.err != nil {
|
||||||
panic(ParseError{
|
panic(ParseError{
|
||||||
Message: it.err.Error(),
|
Position: it.pos,
|
||||||
err: it.err,
|
|
||||||
Position: it.pos.withCol(p.lx.input),
|
|
||||||
Line: it.pos.Line,
|
Line: it.pos.Line,
|
||||||
LastKey: p.current(),
|
LastKey: p.current(),
|
||||||
|
err: it.err,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -528,7 +527,7 @@ func numUnderscoresOK(s string) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// isHex is a superset of all the permissible characters surrounding an
|
// isHexis a superset of all the permissable characters surrounding an
|
||||||
// underscore.
|
// underscore.
|
||||||
accept = isHex(r)
|
accept = isHex(r)
|
||||||
}
|
}
|
||||||
|
10
vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go
generated
vendored
10
vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go
generated
vendored
@ -180,16 +180,6 @@ func (dke ErrMalformedMessage) Error() string {
|
|||||||
return "openpgp: malformed message " + string(dke)
|
return "openpgp: malformed message " + string(dke)
|
||||||
}
|
}
|
||||||
|
|
||||||
type messageTooLargeError int
|
|
||||||
|
|
||||||
func (e messageTooLargeError) Error() string {
|
|
||||||
return "openpgp: decompressed message size exceeds provided limit"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrMessageTooLarge is returned if the read data from
|
|
||||||
// a compressed packet exceeds the provided limit.
|
|
||||||
var ErrMessageTooLarge error = messageTooLargeError(0)
|
|
||||||
|
|
||||||
// ErrEncryptionKeySelection is returned if encryption key selection fails (v2 API).
|
// ErrEncryptionKeySelection is returned if encryption key selection fails (v2 API).
|
||||||
type ErrEncryptionKeySelection struct {
|
type ErrEncryptionKeySelection struct {
|
||||||
PrimaryKeyId string
|
PrimaryKeyId string
|
||||||
|
6
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_config.go
generated
vendored
6
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_config.go
generated
vendored
@ -37,7 +37,7 @@ func (conf *AEADConfig) Mode() AEADMode {
|
|||||||
|
|
||||||
// ChunkSizeByte returns the byte indicating the chunk size. The effective
|
// ChunkSizeByte returns the byte indicating the chunk size. The effective
|
||||||
// chunk size is computed with the formula uint64(1) << (chunkSizeByte + 6)
|
// chunk size is computed with the formula uint64(1) << (chunkSizeByte + 6)
|
||||||
// limit chunkSizeByte to 16 which equals to 2^22 = 4 MiB
|
// limit to 16 = 4 MiB
|
||||||
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-5.13.2
|
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-5.13.2
|
||||||
func (conf *AEADConfig) ChunkSizeByte() byte {
|
func (conf *AEADConfig) ChunkSizeByte() byte {
|
||||||
if conf == nil || conf.ChunkSize == 0 {
|
if conf == nil || conf.ChunkSize == 0 {
|
||||||
@ -49,8 +49,8 @@ func (conf *AEADConfig) ChunkSizeByte() byte {
|
|||||||
switch {
|
switch {
|
||||||
case exponent < 6:
|
case exponent < 6:
|
||||||
exponent = 6
|
exponent = 6
|
||||||
case exponent > 22:
|
case exponent > 16:
|
||||||
exponent = 22
|
exponent = 16
|
||||||
}
|
}
|
||||||
|
|
||||||
return byte(exponent - 6)
|
return byte(exponent - 6)
|
||||||
|
31
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/compressed.go
generated
vendored
31
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/compressed.go
generated
vendored
@ -98,16 +98,6 @@ func (c *Compressed) parse(r io.Reader) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// LimitedBodyReader wraps the provided body reader with a limiter that restricts
|
|
||||||
// the number of bytes read to the specified limit.
|
|
||||||
// If limit is nil, the reader is unbounded.
|
|
||||||
func (c *Compressed) LimitedBodyReader(limit *int64) io.Reader {
|
|
||||||
if limit == nil {
|
|
||||||
return c.Body
|
|
||||||
}
|
|
||||||
return &LimitReader{R: c.Body, N: *limit}
|
|
||||||
}
|
|
||||||
|
|
||||||
// compressedWriterCloser represents the serialized compression stream
|
// compressedWriterCloser represents the serialized compression stream
|
||||||
// header and the compressor. Its Close() method ensures that both the
|
// header and the compressor. Its Close() method ensures that both the
|
||||||
// compressor and serialized stream header are closed. Its Write()
|
// compressor and serialized stream header are closed. Its Write()
|
||||||
@ -169,24 +159,3 @@ func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *Compression
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// LimitReader is an io.Reader that fails with MessageToLarge if read bytes exceed N.
|
|
||||||
type LimitReader struct {
|
|
||||||
R io.Reader // underlying reader
|
|
||||||
N int64 // max bytes allowed
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LimitReader) Read(p []byte) (int, error) {
|
|
||||||
if l.N <= 0 {
|
|
||||||
return 0, errors.ErrMessageTooLarge
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err := l.R.Read(p)
|
|
||||||
l.N -= int64(n)
|
|
||||||
|
|
||||||
if err == nil && l.N <= 0 {
|
|
||||||
err = errors.ErrMessageTooLarge
|
|
||||||
}
|
|
||||||
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
12
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go
generated
vendored
12
vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go
generated
vendored
@ -178,11 +178,6 @@ type Config struct {
|
|||||||
// When set to true, a key without flags is treated as if all flags are enabled.
|
// When set to true, a key without flags is treated as if all flags are enabled.
|
||||||
// This behavior is consistent with GPG.
|
// This behavior is consistent with GPG.
|
||||||
InsecureAllowAllKeyFlagsWhenMissing bool
|
InsecureAllowAllKeyFlagsWhenMissing bool
|
||||||
|
|
||||||
// MaxDecompressedMessageSize specifies the maximum number of bytes that can be
|
|
||||||
// read from a compressed packet. This serves as an upper limit to prevent
|
|
||||||
// excessively large decompressed messages.
|
|
||||||
MaxDecompressedMessageSize *int64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Random() io.Reader {
|
func (c *Config) Random() io.Reader {
|
||||||
@ -420,13 +415,6 @@ func (c *Config) AllowAllKeyFlagsWhenMissing() bool {
|
|||||||
return c.InsecureAllowAllKeyFlagsWhenMissing
|
return c.InsecureAllowAllKeyFlagsWhenMissing
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) DecompressedMessageSizeLimit() *int64 {
|
|
||||||
if c == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return c.MaxDecompressedMessageSize
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolPointer is a helper function to set a boolean pointer in the Config.
|
// BoolPointer is a helper function to set a boolean pointer in the Config.
|
||||||
// e.g., config.CheckPacketSequence = BoolPointer(true)
|
// e.g., config.CheckPacketSequence = BoolPointer(true)
|
||||||
func BoolPointer(value bool) *bool {
|
func BoolPointer(value bool) *bool {
|
||||||
|
2
vendor/github.com/ProtonMail/go-crypto/openpgp/read.go
generated
vendored
2
vendor/github.com/ProtonMail/go-crypto/openpgp/read.go
generated
vendored
@ -259,7 +259,7 @@ FindLiteralData:
|
|||||||
}
|
}
|
||||||
switch p := p.(type) {
|
switch p := p.(type) {
|
||||||
case *packet.Compressed:
|
case *packet.Compressed:
|
||||||
if err := packets.Push(p.LimitedBodyReader(config.DecompressedMessageSizeLimit())); err != nil {
|
if err := packets.Push(p.Body); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
case *packet.OnePassSignature:
|
case *packet.OnePassSignature:
|
||||||
|
124
vendor/github.com/ProtonMail/go-crypto/openpgp/write.go
generated
vendored
124
vendor/github.com/ProtonMail/go-crypto/openpgp/write.go
generated
vendored
@ -253,12 +253,34 @@ func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entit
|
|||||||
}
|
}
|
||||||
|
|
||||||
var hash crypto.Hash
|
var hash crypto.Hash
|
||||||
var salt []byte
|
for _, hashId := range candidateHashes {
|
||||||
if signer != nil {
|
if h, ok := algorithm.HashIdToHash(hashId); ok && h.Available() {
|
||||||
if hash, err = selectHash(candidateHashes, config.Hash(), signer); err != nil {
|
hash = h
|
||||||
return nil, err
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the hash specified by config is a candidate, we'll use that.
|
||||||
|
if configuredHash := config.Hash(); configuredHash.Available() {
|
||||||
|
for _, hashId := range candidateHashes {
|
||||||
|
if h, ok := algorithm.HashIdToHash(hashId); ok && h == configuredHash {
|
||||||
|
hash = h
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if hash == 0 {
|
||||||
|
hashId := candidateHashes[0]
|
||||||
|
name, ok := algorithm.HashIdToString(hashId)
|
||||||
|
if !ok {
|
||||||
|
name = "#" + strconv.Itoa(int(hashId))
|
||||||
|
}
|
||||||
|
return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)")
|
||||||
|
}
|
||||||
|
|
||||||
|
var salt []byte
|
||||||
|
if signer != nil {
|
||||||
var opsVersion = 3
|
var opsVersion = 3
|
||||||
if signer.Version == 6 {
|
if signer.Version == 6 {
|
||||||
opsVersion = signer.Version
|
opsVersion = signer.Version
|
||||||
@ -536,34 +558,13 @@ func (s signatureWriter) Close() error {
|
|||||||
return s.encryptedData.Close()
|
return s.encryptedData.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func selectHashForSigningKey(config *packet.Config, signer *packet.PublicKey) crypto.Hash {
|
|
||||||
acceptableHashes := acceptableHashesToWrite(signer)
|
|
||||||
hash, ok := algorithm.HashToHashId(config.Hash())
|
|
||||||
if !ok {
|
|
||||||
return config.Hash()
|
|
||||||
}
|
|
||||||
for _, acceptableHashes := range acceptableHashes {
|
|
||||||
if acceptableHashes == hash {
|
|
||||||
return config.Hash()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(acceptableHashes) > 0 {
|
|
||||||
defaultAcceptedHash, ok := algorithm.HashIdToHash(acceptableHashes[0])
|
|
||||||
if ok {
|
|
||||||
return defaultAcceptedHash
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return config.Hash()
|
|
||||||
}
|
|
||||||
|
|
||||||
func createSignaturePacket(signer *packet.PublicKey, sigType packet.SignatureType, config *packet.Config) *packet.Signature {
|
func createSignaturePacket(signer *packet.PublicKey, sigType packet.SignatureType, config *packet.Config) *packet.Signature {
|
||||||
sigLifetimeSecs := config.SigLifetime()
|
sigLifetimeSecs := config.SigLifetime()
|
||||||
hash := selectHashForSigningKey(config, signer)
|
|
||||||
return &packet.Signature{
|
return &packet.Signature{
|
||||||
Version: signer.Version,
|
Version: signer.Version,
|
||||||
SigType: sigType,
|
SigType: sigType,
|
||||||
PubKeyAlgo: signer.PubKeyAlgo,
|
PubKeyAlgo: signer.PubKeyAlgo,
|
||||||
Hash: hash,
|
Hash: config.Hash(),
|
||||||
CreationTime: config.Now(),
|
CreationTime: config.Now(),
|
||||||
IssuerKeyId: &signer.KeyId,
|
IssuerKeyId: &signer.KeyId,
|
||||||
IssuerFingerprint: signer.Fingerprint,
|
IssuerFingerprint: signer.Fingerprint,
|
||||||
@ -617,74 +618,3 @@ func handleCompression(compressed io.WriteCloser, candidateCompression []uint8,
|
|||||||
}
|
}
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// selectHash selects the preferred hash given the candidateHashes and the configuredHash
|
|
||||||
func selectHash(candidateHashes []byte, configuredHash crypto.Hash, signer *packet.PrivateKey) (hash crypto.Hash, err error) {
|
|
||||||
acceptableHashes := acceptableHashesToWrite(&signer.PublicKey)
|
|
||||||
candidateHashes = intersectPreferences(acceptableHashes, candidateHashes)
|
|
||||||
|
|
||||||
for _, hashId := range candidateHashes {
|
|
||||||
if h, ok := algorithm.HashIdToHash(hashId); ok && h.Available() {
|
|
||||||
hash = h
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the hash specified by config is a candidate, we'll use that.
|
|
||||||
if configuredHash.Available() {
|
|
||||||
for _, hashId := range candidateHashes {
|
|
||||||
if h, ok := algorithm.HashIdToHash(hashId); ok && h == configuredHash {
|
|
||||||
hash = h
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if hash == 0 {
|
|
||||||
if len(acceptableHashes) > 0 {
|
|
||||||
if h, ok := algorithm.HashIdToHash(acceptableHashes[0]); ok {
|
|
||||||
hash = h
|
|
||||||
} else {
|
|
||||||
return 0, errors.UnsupportedError("no candidate hash functions are compiled in.")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return 0, errors.UnsupportedError("no candidate hash functions are compiled in.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func acceptableHashesToWrite(singingKey *packet.PublicKey) []uint8 {
|
|
||||||
switch singingKey.PubKeyAlgo {
|
|
||||||
case packet.PubKeyAlgoEd448:
|
|
||||||
return []uint8{
|
|
||||||
hashToHashId(crypto.SHA512),
|
|
||||||
hashToHashId(crypto.SHA3_512),
|
|
||||||
}
|
|
||||||
case packet.PubKeyAlgoECDSA, packet.PubKeyAlgoEdDSA:
|
|
||||||
if curve, err := singingKey.Curve(); err == nil {
|
|
||||||
if curve == packet.Curve448 ||
|
|
||||||
curve == packet.CurveNistP521 ||
|
|
||||||
curve == packet.CurveBrainpoolP512 {
|
|
||||||
return []uint8{
|
|
||||||
hashToHashId(crypto.SHA512),
|
|
||||||
hashToHashId(crypto.SHA3_512),
|
|
||||||
}
|
|
||||||
} else if curve == packet.CurveBrainpoolP384 ||
|
|
||||||
curve == packet.CurveNistP384 {
|
|
||||||
return []uint8{
|
|
||||||
hashToHashId(crypto.SHA384),
|
|
||||||
hashToHashId(crypto.SHA512),
|
|
||||||
hashToHashId(crypto.SHA3_512),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []uint8{
|
|
||||||
hashToHashId(crypto.SHA256),
|
|
||||||
hashToHashId(crypto.SHA384),
|
|
||||||
hashToHashId(crypto.SHA512),
|
|
||||||
hashToHashId(crypto.SHA3_256),
|
|
||||||
hashToHashId(crypto.SHA3_512),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Exponential Backoff [![GoDoc][godoc image]][godoc]
|
# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Coverage Status][coveralls image]][coveralls]
|
||||||
|
|
||||||
This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client].
|
This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client].
|
||||||
|
|
||||||
@ -9,11 +9,9 @@ The retries exponentially increase and stop increasing when a certain threshold
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Import path is `github.com/cenkalti/backoff/v5`. Please note the version part at the end.
|
Import path is `github.com/cenkalti/backoff/v4`. Please note the version part at the end.
|
||||||
|
|
||||||
For most cases, use `Retry` function. See [example_test.go][example] for an example.
|
Use https://pkg.go.dev/github.com/cenkalti/backoff/v4 to view the documentation.
|
||||||
|
|
||||||
If you have specific needs, copy `Retry` function (from [retry.go][retry-src]) into your code and modify it as needed.
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
@ -21,11 +19,12 @@ If you have specific needs, copy `Retry` function (from [retry.go][retry-src]) i
|
|||||||
* Please don't send a PR without opening an issue and discussing it first.
|
* Please don't send a PR without opening an issue and discussing it first.
|
||||||
* If proposed change is not a common use case, I will probably not accept it.
|
* If proposed change is not a common use case, I will probably not accept it.
|
||||||
|
|
||||||
[godoc]: https://pkg.go.dev/github.com/cenkalti/backoff/v5
|
[godoc]: https://pkg.go.dev/github.com/cenkalti/backoff/v4
|
||||||
[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png
|
[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png
|
||||||
|
[coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master
|
||||||
|
[coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master
|
||||||
|
|
||||||
[google-http-java-client]: https://github.com/google/google-http-java-client/blob/da1aa993e90285ec18579f1553339b00e19b3ab5/google-http-client/src/main/java/com/google/api/client/util/ExponentialBackOff.java
|
[google-http-java-client]: https://github.com/google/google-http-java-client/blob/da1aa993e90285ec18579f1553339b00e19b3ab5/google-http-client/src/main/java/com/google/api/client/util/ExponentialBackOff.java
|
||||||
[exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff
|
[exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff
|
||||||
|
|
||||||
[retry-src]: https://github.com/cenkalti/backoff/blob/v5/retry.go
|
[advanced example]: https://pkg.go.dev/github.com/cenkalti/backoff/v4?tab=doc#pkg-examples
|
||||||
[example]: https://github.com/cenkalti/backoff/blob/v5/example_test.go
|
|
@ -15,12 +15,12 @@ import "time"
|
|||||||
// BackOff is a backoff policy for retrying an operation.
|
// BackOff is a backoff policy for retrying an operation.
|
||||||
type BackOff interface {
|
type BackOff interface {
|
||||||
// NextBackOff returns the duration to wait before retrying the operation,
|
// NextBackOff returns the duration to wait before retrying the operation,
|
||||||
// backoff.Stop to indicate that no more retries should be made.
|
// or backoff. Stop to indicate that no more retries should be made.
|
||||||
//
|
//
|
||||||
// Example usage:
|
// Example usage:
|
||||||
//
|
//
|
||||||
// duration := backoff.NextBackOff()
|
// duration := backoff.NextBackOff();
|
||||||
// if duration == backoff.Stop {
|
// if (duration == backoff.Stop) {
|
||||||
// // Do not retry operation.
|
// // Do not retry operation.
|
||||||
// } else {
|
// } else {
|
||||||
// // Sleep for duration and retry operation.
|
// // Sleep for duration and retry operation.
|
62
vendor/github.com/cenkalti/backoff/v4/context.go
generated
vendored
Normal file
62
vendor/github.com/cenkalti/backoff/v4/context.go
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package backoff
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BackOffContext is a backoff policy that stops retrying after the context
|
||||||
|
// is canceled.
|
||||||
|
type BackOffContext interface { // nolint: golint
|
||||||
|
BackOff
|
||||||
|
Context() context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
type backOffContext struct {
|
||||||
|
BackOff
|
||||||
|
ctx context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithContext returns a BackOffContext with context ctx
|
||||||
|
//
|
||||||
|
// ctx must not be nil
|
||||||
|
func WithContext(b BackOff, ctx context.Context) BackOffContext { // nolint: golint
|
||||||
|
if ctx == nil {
|
||||||
|
panic("nil context")
|
||||||
|
}
|
||||||
|
|
||||||
|
if b, ok := b.(*backOffContext); ok {
|
||||||
|
return &backOffContext{
|
||||||
|
BackOff: b.BackOff,
|
||||||
|
ctx: ctx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &backOffContext{
|
||||||
|
BackOff: b,
|
||||||
|
ctx: ctx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getContext(b BackOff) context.Context {
|
||||||
|
if cb, ok := b.(BackOffContext); ok {
|
||||||
|
return cb.Context()
|
||||||
|
}
|
||||||
|
if tb, ok := b.(*backOffTries); ok {
|
||||||
|
return getContext(tb.delegate)
|
||||||
|
}
|
||||||
|
return context.Background()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *backOffContext) Context() context.Context {
|
||||||
|
return b.ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *backOffContext) NextBackOff() time.Duration {
|
||||||
|
select {
|
||||||
|
case <-b.ctx.Done():
|
||||||
|
return Stop
|
||||||
|
default:
|
||||||
|
return b.BackOff.NextBackOff()
|
||||||
|
}
|
||||||
|
}
|
216
vendor/github.com/cenkalti/backoff/v4/exponential.go
generated
vendored
Normal file
216
vendor/github.com/cenkalti/backoff/v4/exponential.go
generated
vendored
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
package backoff
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
ExponentialBackOff is a backoff implementation that increases the backoff
|
||||||
|
period for each retry attempt using a randomization function that grows exponentially.
|
||||||
|
|
||||||
|
NextBackOff() is calculated using the following formula:
|
||||||
|
|
||||||
|
randomized interval =
|
||||||
|
RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor])
|
||||||
|
|
||||||
|
In other words NextBackOff() will range between the randomization factor
|
||||||
|
percentage below and above the retry interval.
|
||||||
|
|
||||||
|
For example, given the following parameters:
|
||||||
|
|
||||||
|
RetryInterval = 2
|
||||||
|
RandomizationFactor = 0.5
|
||||||
|
Multiplier = 2
|
||||||
|
|
||||||
|
the actual backoff period used in the next retry attempt will range between 1 and 3 seconds,
|
||||||
|
multiplied by the exponential, that is, between 2 and 6 seconds.
|
||||||
|
|
||||||
|
Note: MaxInterval caps the RetryInterval and not the randomized interval.
|
||||||
|
|
||||||
|
If the time elapsed since an ExponentialBackOff instance is created goes past the
|
||||||
|
MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop.
|
||||||
|
|
||||||
|
The elapsed time can be reset by calling Reset().
|
||||||
|
|
||||||
|
Example: Given the following default arguments, for 10 tries the sequence will be,
|
||||||
|
and assuming we go over the MaxElapsedTime on the 10th try:
|
||||||
|
|
||||||
|
Request # RetryInterval (seconds) Randomized Interval (seconds)
|
||||||
|
|
||||||
|
1 0.5 [0.25, 0.75]
|
||||||
|
2 0.75 [0.375, 1.125]
|
||||||
|
3 1.125 [0.562, 1.687]
|
||||||
|
4 1.687 [0.8435, 2.53]
|
||||||
|
5 2.53 [1.265, 3.795]
|
||||||
|
6 3.795 [1.897, 5.692]
|
||||||
|
7 5.692 [2.846, 8.538]
|
||||||
|
8 8.538 [4.269, 12.807]
|
||||||
|
9 12.807 [6.403, 19.210]
|
||||||
|
10 19.210 backoff.Stop
|
||||||
|
|
||||||
|
Note: Implementation is not thread-safe.
|
||||||
|
*/
|
||||||
|
type ExponentialBackOff struct {
|
||||||
|
InitialInterval time.Duration
|
||||||
|
RandomizationFactor float64
|
||||||
|
Multiplier float64
|
||||||
|
MaxInterval time.Duration
|
||||||
|
// After MaxElapsedTime the ExponentialBackOff returns Stop.
|
||||||
|
// It never stops if MaxElapsedTime == 0.
|
||||||
|
MaxElapsedTime time.Duration
|
||||||
|
Stop time.Duration
|
||||||
|
Clock Clock
|
||||||
|
|
||||||
|
currentInterval time.Duration
|
||||||
|
startTime time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clock is an interface that returns current time for BackOff.
|
||||||
|
type Clock interface {
|
||||||
|
Now() time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExponentialBackOffOpts is a function type used to configure ExponentialBackOff options.
|
||||||
|
type ExponentialBackOffOpts func(*ExponentialBackOff)
|
||||||
|
|
||||||
|
// Default values for ExponentialBackOff.
|
||||||
|
const (
|
||||||
|
DefaultInitialInterval = 500 * time.Millisecond
|
||||||
|
DefaultRandomizationFactor = 0.5
|
||||||
|
DefaultMultiplier = 1.5
|
||||||
|
DefaultMaxInterval = 60 * time.Second
|
||||||
|
DefaultMaxElapsedTime = 15 * time.Minute
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
|
||||||
|
func NewExponentialBackOff(opts ...ExponentialBackOffOpts) *ExponentialBackOff {
|
||||||
|
b := &ExponentialBackOff{
|
||||||
|
InitialInterval: DefaultInitialInterval,
|
||||||
|
RandomizationFactor: DefaultRandomizationFactor,
|
||||||
|
Multiplier: DefaultMultiplier,
|
||||||
|
MaxInterval: DefaultMaxInterval,
|
||||||
|
MaxElapsedTime: DefaultMaxElapsedTime,
|
||||||
|
Stop: Stop,
|
||||||
|
Clock: SystemClock,
|
||||||
|
}
|
||||||
|
for _, fn := range opts {
|
||||||
|
fn(b)
|
||||||
|
}
|
||||||
|
b.Reset()
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithInitialInterval sets the initial interval between retries.
|
||||||
|
func WithInitialInterval(duration time.Duration) ExponentialBackOffOpts {
|
||||||
|
return func(ebo *ExponentialBackOff) {
|
||||||
|
ebo.InitialInterval = duration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithRandomizationFactor sets the randomization factor to add jitter to intervals.
|
||||||
|
func WithRandomizationFactor(randomizationFactor float64) ExponentialBackOffOpts {
|
||||||
|
return func(ebo *ExponentialBackOff) {
|
||||||
|
ebo.RandomizationFactor = randomizationFactor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMultiplier sets the multiplier for increasing the interval after each retry.
|
||||||
|
func WithMultiplier(multiplier float64) ExponentialBackOffOpts {
|
||||||
|
return func(ebo *ExponentialBackOff) {
|
||||||
|
ebo.Multiplier = multiplier
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMaxInterval sets the maximum interval between retries.
|
||||||
|
func WithMaxInterval(duration time.Duration) ExponentialBackOffOpts {
|
||||||
|
return func(ebo *ExponentialBackOff) {
|
||||||
|
ebo.MaxInterval = duration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMaxElapsedTime sets the maximum total time for retries.
|
||||||
|
func WithMaxElapsedTime(duration time.Duration) ExponentialBackOffOpts {
|
||||||
|
return func(ebo *ExponentialBackOff) {
|
||||||
|
ebo.MaxElapsedTime = duration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithRetryStopDuration sets the duration after which retries should stop.
|
||||||
|
func WithRetryStopDuration(duration time.Duration) ExponentialBackOffOpts {
|
||||||
|
return func(ebo *ExponentialBackOff) {
|
||||||
|
ebo.Stop = duration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithClockProvider sets the clock used to measure time.
|
||||||
|
func WithClockProvider(clock Clock) ExponentialBackOffOpts {
|
||||||
|
return func(ebo *ExponentialBackOff) {
|
||||||
|
ebo.Clock = clock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type systemClock struct{}
|
||||||
|
|
||||||
|
func (t systemClock) Now() time.Time {
|
||||||
|
return time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SystemClock implements Clock interface that uses time.Now().
|
||||||
|
var SystemClock = systemClock{}
|
||||||
|
|
||||||
|
// Reset the interval back to the initial retry interval and restarts the timer.
|
||||||
|
// Reset must be called before using b.
|
||||||
|
func (b *ExponentialBackOff) Reset() {
|
||||||
|
b.currentInterval = b.InitialInterval
|
||||||
|
b.startTime = b.Clock.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextBackOff calculates the next backoff interval using the formula:
|
||||||
|
// Randomized interval = RetryInterval * (1 ± RandomizationFactor)
|
||||||
|
func (b *ExponentialBackOff) NextBackOff() time.Duration {
|
||||||
|
// Make sure we have not gone over the maximum elapsed time.
|
||||||
|
elapsed := b.GetElapsedTime()
|
||||||
|
next := getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval)
|
||||||
|
b.incrementCurrentInterval()
|
||||||
|
if b.MaxElapsedTime != 0 && elapsed+next > b.MaxElapsedTime {
|
||||||
|
return b.Stop
|
||||||
|
}
|
||||||
|
return next
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance
|
||||||
|
// is created and is reset when Reset() is called.
|
||||||
|
//
|
||||||
|
// The elapsed time is computed using time.Now().UnixNano(). It is
|
||||||
|
// safe to call even while the backoff policy is used by a running
|
||||||
|
// ticker.
|
||||||
|
func (b *ExponentialBackOff) GetElapsedTime() time.Duration {
|
||||||
|
return b.Clock.Now().Sub(b.startTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increments the current interval by multiplying it with the multiplier.
|
||||||
|
func (b *ExponentialBackOff) incrementCurrentInterval() {
|
||||||
|
// Check for overflow, if overflow is detected set the current interval to the max interval.
|
||||||
|
if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier {
|
||||||
|
b.currentInterval = b.MaxInterval
|
||||||
|
} else {
|
||||||
|
b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a random value from the following interval:
|
||||||
|
// [currentInterval - randomizationFactor * currentInterval, currentInterval + randomizationFactor * currentInterval].
|
||||||
|
func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration {
|
||||||
|
if randomizationFactor == 0 {
|
||||||
|
return currentInterval // make sure no randomness is used when randomizationFactor is 0.
|
||||||
|
}
|
||||||
|
var delta = randomizationFactor * float64(currentInterval)
|
||||||
|
var minInterval = float64(currentInterval) - delta
|
||||||
|
var maxInterval = float64(currentInterval) + delta
|
||||||
|
|
||||||
|
// Get a random value from the range [minInterval, maxInterval].
|
||||||
|
// The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then
|
||||||
|
// we want a 33% chance for selecting either 1, 2 or 3.
|
||||||
|
return time.Duration(minInterval + (random * (maxInterval - minInterval + 1)))
|
||||||
|
}
|
146
vendor/github.com/cenkalti/backoff/v4/retry.go
generated
vendored
Normal file
146
vendor/github.com/cenkalti/backoff/v4/retry.go
generated
vendored
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
package backoff
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// An OperationWithData is executing by RetryWithData() or RetryNotifyWithData().
|
||||||
|
// The operation will be retried using a backoff policy if it returns an error.
|
||||||
|
type OperationWithData[T any] func() (T, error)
|
||||||
|
|
||||||
|
// An Operation is executing by Retry() or RetryNotify().
|
||||||
|
// The operation will be retried using a backoff policy if it returns an error.
|
||||||
|
type Operation func() error
|
||||||
|
|
||||||
|
func (o Operation) withEmptyData() OperationWithData[struct{}] {
|
||||||
|
return func() (struct{}, error) {
|
||||||
|
return struct{}{}, o()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify is a notify-on-error function. It receives an operation error and
|
||||||
|
// backoff delay if the operation failed (with an error).
|
||||||
|
//
|
||||||
|
// NOTE that if the backoff policy stated to stop retrying,
|
||||||
|
// the notify function isn't called.
|
||||||
|
type Notify func(error, time.Duration)
|
||||||
|
|
||||||
|
// Retry the operation o until it does not return error or BackOff stops.
|
||||||
|
// o is guaranteed to be run at least once.
|
||||||
|
//
|
||||||
|
// If o returns a *PermanentError, the operation is not retried, and the
|
||||||
|
// wrapped error is returned.
|
||||||
|
//
|
||||||
|
// Retry sleeps the goroutine for the duration returned by BackOff after a
|
||||||
|
// failed operation returns.
|
||||||
|
func Retry(o Operation, b BackOff) error {
|
||||||
|
return RetryNotify(o, b, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RetryWithData is like Retry but returns data in the response too.
|
||||||
|
func RetryWithData[T any](o OperationWithData[T], b BackOff) (T, error) {
|
||||||
|
return RetryNotifyWithData(o, b, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RetryNotify calls notify function with the error and wait duration
|
||||||
|
// for each failed attempt before sleep.
|
||||||
|
func RetryNotify(operation Operation, b BackOff, notify Notify) error {
|
||||||
|
return RetryNotifyWithTimer(operation, b, notify, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RetryNotifyWithData is like RetryNotify but returns data in the response too.
|
||||||
|
func RetryNotifyWithData[T any](operation OperationWithData[T], b BackOff, notify Notify) (T, error) {
|
||||||
|
return doRetryNotify(operation, b, notify, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RetryNotifyWithTimer calls notify function with the error and wait duration using the given Timer
|
||||||
|
// for each failed attempt before sleep.
|
||||||
|
// A default timer that uses system timer is used when nil is passed.
|
||||||
|
func RetryNotifyWithTimer(operation Operation, b BackOff, notify Notify, t Timer) error {
|
||||||
|
_, err := doRetryNotify(operation.withEmptyData(), b, notify, t)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RetryNotifyWithTimerAndData is like RetryNotifyWithTimer but returns data in the response too.
|
||||||
|
func RetryNotifyWithTimerAndData[T any](operation OperationWithData[T], b BackOff, notify Notify, t Timer) (T, error) {
|
||||||
|
return doRetryNotify(operation, b, notify, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func doRetryNotify[T any](operation OperationWithData[T], b BackOff, notify Notify, t Timer) (T, error) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
next time.Duration
|
||||||
|
res T
|
||||||
|
)
|
||||||
|
if t == nil {
|
||||||
|
t = &defaultTimer{}
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
t.Stop()
|
||||||
|
}()
|
||||||
|
|
||||||
|
ctx := getContext(b)
|
||||||
|
|
||||||
|
b.Reset()
|
||||||
|
for {
|
||||||
|
res, err = operation()
|
||||||
|
if err == nil {
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var permanent *PermanentError
|
||||||
|
if errors.As(err, &permanent) {
|
||||||
|
return res, permanent.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
if next = b.NextBackOff(); next == Stop {
|
||||||
|
if cerr := ctx.Err(); cerr != nil {
|
||||||
|
return res, cerr
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if notify != nil {
|
||||||
|
notify(err, next)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Start(next)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return res, ctx.Err()
|
||||||
|
case <-t.C():
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PermanentError signals that the operation should not be retried.
|
||||||
|
type PermanentError struct {
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *PermanentError) Error() string {
|
||||||
|
return e.Err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *PermanentError) Unwrap() error {
|
||||||
|
return e.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *PermanentError) Is(target error) bool {
|
||||||
|
_, ok := target.(*PermanentError)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// Permanent wraps the given err in a *PermanentError.
|
||||||
|
func Permanent(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &PermanentError{
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package backoff
|
package backoff
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -13,7 +14,8 @@ type Ticker struct {
|
|||||||
C <-chan time.Time
|
C <-chan time.Time
|
||||||
c chan time.Time
|
c chan time.Time
|
||||||
b BackOff
|
b BackOff
|
||||||
timer timer
|
ctx context.Context
|
||||||
|
timer Timer
|
||||||
stop chan struct{}
|
stop chan struct{}
|
||||||
stopOnce sync.Once
|
stopOnce sync.Once
|
||||||
}
|
}
|
||||||
@ -25,12 +27,22 @@ type Ticker struct {
|
|||||||
// provided backoff policy (notably calling NextBackOff or Reset)
|
// provided backoff policy (notably calling NextBackOff or Reset)
|
||||||
// while the ticker is running.
|
// while the ticker is running.
|
||||||
func NewTicker(b BackOff) *Ticker {
|
func NewTicker(b BackOff) *Ticker {
|
||||||
|
return NewTickerWithTimer(b, &defaultTimer{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTickerWithTimer returns a new Ticker with a custom timer.
|
||||||
|
// A default timer that uses system timer is used when nil is passed.
|
||||||
|
func NewTickerWithTimer(b BackOff, timer Timer) *Ticker {
|
||||||
|
if timer == nil {
|
||||||
|
timer = &defaultTimer{}
|
||||||
|
}
|
||||||
c := make(chan time.Time)
|
c := make(chan time.Time)
|
||||||
t := &Ticker{
|
t := &Ticker{
|
||||||
C: c,
|
C: c,
|
||||||
c: c,
|
c: c,
|
||||||
b: b,
|
b: b,
|
||||||
timer: &defaultTimer{},
|
ctx: getContext(b),
|
||||||
|
timer: timer,
|
||||||
stop: make(chan struct{}),
|
stop: make(chan struct{}),
|
||||||
}
|
}
|
||||||
t.b.Reset()
|
t.b.Reset()
|
||||||
@ -61,6 +73,8 @@ func (t *Ticker) run() {
|
|||||||
case <-t.stop:
|
case <-t.stop:
|
||||||
t.c = nil // Prevent future ticks from being sent to the channel.
|
t.c = nil // Prevent future ticks from being sent to the channel.
|
||||||
return
|
return
|
||||||
|
case <-t.ctx.Done():
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,7 +2,7 @@ package backoff
|
|||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type timer interface {
|
type Timer interface {
|
||||||
Start(duration time.Duration)
|
Start(duration time.Duration)
|
||||||
Stop()
|
Stop()
|
||||||
C() <-chan time.Time
|
C() <-chan time.Time
|
38
vendor/github.com/cenkalti/backoff/v4/tries.go
generated
vendored
Normal file
38
vendor/github.com/cenkalti/backoff/v4/tries.go
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package backoff
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
/*
|
||||||
|
WithMaxRetries creates a wrapper around another BackOff, which will
|
||||||
|
return Stop if NextBackOff() has been called too many times since
|
||||||
|
the last time Reset() was called
|
||||||
|
|
||||||
|
Note: Implementation is not thread-safe.
|
||||||
|
*/
|
||||||
|
func WithMaxRetries(b BackOff, max uint64) BackOff {
|
||||||
|
return &backOffTries{delegate: b, maxTries: max}
|
||||||
|
}
|
||||||
|
|
||||||
|
type backOffTries struct {
|
||||||
|
delegate BackOff
|
||||||
|
maxTries uint64
|
||||||
|
numTries uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *backOffTries) NextBackOff() time.Duration {
|
||||||
|
if b.maxTries == 0 {
|
||||||
|
return Stop
|
||||||
|
}
|
||||||
|
if b.maxTries > 0 {
|
||||||
|
if b.maxTries <= b.numTries {
|
||||||
|
return Stop
|
||||||
|
}
|
||||||
|
b.numTries++
|
||||||
|
}
|
||||||
|
return b.delegate.NextBackOff()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *backOffTries) Reset() {
|
||||||
|
b.numTries = 0
|
||||||
|
b.delegate.Reset()
|
||||||
|
}
|
29
vendor/github.com/cenkalti/backoff/v5/CHANGELOG.md
generated
vendored
29
vendor/github.com/cenkalti/backoff/v5/CHANGELOG.md
generated
vendored
@ -1,29 +0,0 @@
|
|||||||
# Changelog
|
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
||||||
|
|
||||||
## [5.0.0] - 2024-12-19
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- RetryAfterError can be returned from an operation to indicate how long to wait before the next retry.
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Retry function now accepts additional options for specifying max number of tries and max elapsed time.
|
|
||||||
- Retry function now accepts a context.Context.
|
|
||||||
- Operation function signature changed to return result (any type) and error.
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
|
|
||||||
- RetryNotify* and RetryWithData functions. Only single Retry function remains.
|
|
||||||
- Optional arguments from ExponentialBackoff constructor.
|
|
||||||
- Clock and Timer interfaces.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- The original error is returned from Retry if there's a PermanentError. (#144)
|
|
||||||
- The Retry function respects the wrapped PermanentError. (#140)
|
|
46
vendor/github.com/cenkalti/backoff/v5/error.go
generated
vendored
46
vendor/github.com/cenkalti/backoff/v5/error.go
generated
vendored
@ -1,46 +0,0 @@
|
|||||||
package backoff
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PermanentError signals that the operation should not be retried.
|
|
||||||
type PermanentError struct {
|
|
||||||
Err error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Permanent wraps the given err in a *PermanentError.
|
|
||||||
func Permanent(err error) error {
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return &PermanentError{
|
|
||||||
Err: err,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns a string representation of the Permanent error.
|
|
||||||
func (e *PermanentError) Error() string {
|
|
||||||
return e.Err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unwrap returns the wrapped error.
|
|
||||||
func (e *PermanentError) Unwrap() error {
|
|
||||||
return e.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
// RetryAfterError signals that the operation should be retried after the given duration.
|
|
||||||
type RetryAfterError struct {
|
|
||||||
Duration time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
// RetryAfter returns a RetryAfter error that specifies how long to wait before retrying.
|
|
||||||
func RetryAfter(seconds int) error {
|
|
||||||
return &RetryAfterError{Duration: time.Duration(seconds) * time.Second}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns a string representation of the RetryAfter error.
|
|
||||||
func (e *RetryAfterError) Error() string {
|
|
||||||
return fmt.Sprintf("retry after %s", e.Duration)
|
|
||||||
}
|
|
118
vendor/github.com/cenkalti/backoff/v5/exponential.go
generated
vendored
118
vendor/github.com/cenkalti/backoff/v5/exponential.go
generated
vendored
@ -1,118 +0,0 @@
|
|||||||
package backoff
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/rand/v2"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
|
||||||
ExponentialBackOff is a backoff implementation that increases the backoff
|
|
||||||
period for each retry attempt using a randomization function that grows exponentially.
|
|
||||||
|
|
||||||
NextBackOff() is calculated using the following formula:
|
|
||||||
|
|
||||||
randomized interval =
|
|
||||||
RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor])
|
|
||||||
|
|
||||||
In other words NextBackOff() will range between the randomization factor
|
|
||||||
percentage below and above the retry interval.
|
|
||||||
|
|
||||||
For example, given the following parameters:
|
|
||||||
|
|
||||||
RetryInterval = 2
|
|
||||||
RandomizationFactor = 0.5
|
|
||||||
Multiplier = 2
|
|
||||||
|
|
||||||
the actual backoff period used in the next retry attempt will range between 1 and 3 seconds,
|
|
||||||
multiplied by the exponential, that is, between 2 and 6 seconds.
|
|
||||||
|
|
||||||
Note: MaxInterval caps the RetryInterval and not the randomized interval.
|
|
||||||
|
|
||||||
Example: Given the following default arguments, for 9 tries the sequence will be:
|
|
||||||
|
|
||||||
Request # RetryInterval (seconds) Randomized Interval (seconds)
|
|
||||||
|
|
||||||
1 0.5 [0.25, 0.75]
|
|
||||||
2 0.75 [0.375, 1.125]
|
|
||||||
3 1.125 [0.562, 1.687]
|
|
||||||
4 1.687 [0.8435, 2.53]
|
|
||||||
5 2.53 [1.265, 3.795]
|
|
||||||
6 3.795 [1.897, 5.692]
|
|
||||||
7 5.692 [2.846, 8.538]
|
|
||||||
8 8.538 [4.269, 12.807]
|
|
||||||
9 12.807 [6.403, 19.210]
|
|
||||||
|
|
||||||
Note: Implementation is not thread-safe.
|
|
||||||
*/
|
|
||||||
type ExponentialBackOff struct {
|
|
||||||
InitialInterval time.Duration
|
|
||||||
RandomizationFactor float64
|
|
||||||
Multiplier float64
|
|
||||||
MaxInterval time.Duration
|
|
||||||
|
|
||||||
currentInterval time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default values for ExponentialBackOff.
|
|
||||||
const (
|
|
||||||
DefaultInitialInterval = 500 * time.Millisecond
|
|
||||||
DefaultRandomizationFactor = 0.5
|
|
||||||
DefaultMultiplier = 1.5
|
|
||||||
DefaultMaxInterval = 60 * time.Second
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
|
|
||||||
func NewExponentialBackOff() *ExponentialBackOff {
|
|
||||||
return &ExponentialBackOff{
|
|
||||||
InitialInterval: DefaultInitialInterval,
|
|
||||||
RandomizationFactor: DefaultRandomizationFactor,
|
|
||||||
Multiplier: DefaultMultiplier,
|
|
||||||
MaxInterval: DefaultMaxInterval,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset the interval back to the initial retry interval and restarts the timer.
|
|
||||||
// Reset must be called before using b.
|
|
||||||
func (b *ExponentialBackOff) Reset() {
|
|
||||||
b.currentInterval = b.InitialInterval
|
|
||||||
}
|
|
||||||
|
|
||||||
// NextBackOff calculates the next backoff interval using the formula:
|
|
||||||
//
|
|
||||||
// Randomized interval = RetryInterval * (1 ± RandomizationFactor)
|
|
||||||
func (b *ExponentialBackOff) NextBackOff() time.Duration {
|
|
||||||
if b.currentInterval == 0 {
|
|
||||||
b.currentInterval = b.InitialInterval
|
|
||||||
}
|
|
||||||
|
|
||||||
next := getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval)
|
|
||||||
b.incrementCurrentInterval()
|
|
||||||
return next
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increments the current interval by multiplying it with the multiplier.
|
|
||||||
func (b *ExponentialBackOff) incrementCurrentInterval() {
|
|
||||||
// Check for overflow, if overflow is detected set the current interval to the max interval.
|
|
||||||
if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier {
|
|
||||||
b.currentInterval = b.MaxInterval
|
|
||||||
} else {
|
|
||||||
b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a random value from the following interval:
|
|
||||||
//
|
|
||||||
// [currentInterval - randomizationFactor * currentInterval, currentInterval + randomizationFactor * currentInterval].
|
|
||||||
func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration {
|
|
||||||
if randomizationFactor == 0 {
|
|
||||||
return currentInterval // make sure no randomness is used when randomizationFactor is 0.
|
|
||||||
}
|
|
||||||
var delta = randomizationFactor * float64(currentInterval)
|
|
||||||
var minInterval = float64(currentInterval) - delta
|
|
||||||
var maxInterval = float64(currentInterval) + delta
|
|
||||||
|
|
||||||
// Get a random value from the range [minInterval, maxInterval].
|
|
||||||
// The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then
|
|
||||||
// we want a 33% chance for selecting either 1, 2 or 3.
|
|
||||||
return time.Duration(minInterval + (random * (maxInterval - minInterval + 1)))
|
|
||||||
}
|
|
139
vendor/github.com/cenkalti/backoff/v5/retry.go
generated
vendored
139
vendor/github.com/cenkalti/backoff/v5/retry.go
generated
vendored
@ -1,139 +0,0 @@
|
|||||||
package backoff
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DefaultMaxElapsedTime sets a default limit for the total retry duration.
|
|
||||||
const DefaultMaxElapsedTime = 15 * time.Minute
|
|
||||||
|
|
||||||
// Operation is a function that attempts an operation and may be retried.
|
|
||||||
type Operation[T any] func() (T, error)
|
|
||||||
|
|
||||||
// Notify is a function called on operation error with the error and backoff duration.
|
|
||||||
type Notify func(error, time.Duration)
|
|
||||||
|
|
||||||
// retryOptions holds configuration settings for the retry mechanism.
|
|
||||||
type retryOptions struct {
|
|
||||||
BackOff BackOff // Strategy for calculating backoff periods.
|
|
||||||
Timer timer // Timer to manage retry delays.
|
|
||||||
Notify Notify // Optional function to notify on each retry error.
|
|
||||||
MaxTries uint // Maximum number of retry attempts.
|
|
||||||
MaxElapsedTime time.Duration // Maximum total time for all retries.
|
|
||||||
}
|
|
||||||
|
|
||||||
type RetryOption func(*retryOptions)
|
|
||||||
|
|
||||||
// WithBackOff configures a custom backoff strategy.
|
|
||||||
func WithBackOff(b BackOff) RetryOption {
|
|
||||||
return func(args *retryOptions) {
|
|
||||||
args.BackOff = b
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// withTimer sets a custom timer for managing delays between retries.
|
|
||||||
func withTimer(t timer) RetryOption {
|
|
||||||
return func(args *retryOptions) {
|
|
||||||
args.Timer = t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithNotify sets a notification function to handle retry errors.
|
|
||||||
func WithNotify(n Notify) RetryOption {
|
|
||||||
return func(args *retryOptions) {
|
|
||||||
args.Notify = n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithMaxTries limits the number of all attempts.
|
|
||||||
func WithMaxTries(n uint) RetryOption {
|
|
||||||
return func(args *retryOptions) {
|
|
||||||
args.MaxTries = n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithMaxElapsedTime limits the total duration for retry attempts.
|
|
||||||
func WithMaxElapsedTime(d time.Duration) RetryOption {
|
|
||||||
return func(args *retryOptions) {
|
|
||||||
args.MaxElapsedTime = d
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retry attempts the operation until success, a permanent error, or backoff completion.
|
|
||||||
// It ensures the operation is executed at least once.
|
|
||||||
//
|
|
||||||
// Returns the operation result or error if retries are exhausted or context is cancelled.
|
|
||||||
func Retry[T any](ctx context.Context, operation Operation[T], opts ...RetryOption) (T, error) {
|
|
||||||
// Initialize default retry options.
|
|
||||||
args := &retryOptions{
|
|
||||||
BackOff: NewExponentialBackOff(),
|
|
||||||
Timer: &defaultTimer{},
|
|
||||||
MaxElapsedTime: DefaultMaxElapsedTime,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply user-provided options to the default settings.
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(args)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer args.Timer.Stop()
|
|
||||||
|
|
||||||
startedAt := time.Now()
|
|
||||||
args.BackOff.Reset()
|
|
||||||
for numTries := uint(1); ; numTries++ {
|
|
||||||
// Execute the operation.
|
|
||||||
res, err := operation()
|
|
||||||
if err == nil {
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop retrying if maximum tries exceeded.
|
|
||||||
if args.MaxTries > 0 && numTries >= args.MaxTries {
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle permanent errors without retrying.
|
|
||||||
var permanent *PermanentError
|
|
||||||
if errors.As(err, &permanent) {
|
|
||||||
return res, permanent.Unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop retrying if context is cancelled.
|
|
||||||
if cerr := context.Cause(ctx); cerr != nil {
|
|
||||||
return res, cerr
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate next backoff duration.
|
|
||||||
next := args.BackOff.NextBackOff()
|
|
||||||
if next == Stop {
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset backoff if RetryAfterError is encountered.
|
|
||||||
var retryAfter *RetryAfterError
|
|
||||||
if errors.As(err, &retryAfter) {
|
|
||||||
next = retryAfter.Duration
|
|
||||||
args.BackOff.Reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop retrying if maximum elapsed time exceeded.
|
|
||||||
if args.MaxElapsedTime > 0 && time.Since(startedAt)+next > args.MaxElapsedTime {
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify on error if a notifier function is provided.
|
|
||||||
if args.Notify != nil {
|
|
||||||
args.Notify(err, next)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for the next backoff period or context cancellation.
|
|
||||||
args.Timer.Start(next)
|
|
||||||
select {
|
|
||||||
case <-args.Timer.C():
|
|
||||||
case <-ctx.Done():
|
|
||||||
return res, context.Cause(ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
40
vendor/github.com/charmbracelet/bubbletea/.golangci-soft.yml
generated
vendored
Normal file
40
vendor/github.com/charmbracelet/bubbletea/.golangci-soft.yml
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
run:
|
||||||
|
tests: false
|
||||||
|
issues-exit-code: 0
|
||||||
|
|
||||||
|
issues:
|
||||||
|
include:
|
||||||
|
- EXC0001
|
||||||
|
- EXC0005
|
||||||
|
- EXC0011
|
||||||
|
- EXC0012
|
||||||
|
- EXC0013
|
||||||
|
|
||||||
|
max-issues-per-linter: 0
|
||||||
|
max-same-issues: 0
|
||||||
|
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
- exhaustive
|
||||||
|
- goconst
|
||||||
|
- godot
|
||||||
|
- godox
|
||||||
|
- mnd
|
||||||
|
- gomoddirectives
|
||||||
|
- goprintffuncname
|
||||||
|
- misspell
|
||||||
|
- nakedret
|
||||||
|
- nestif
|
||||||
|
- noctx
|
||||||
|
- nolintlint
|
||||||
|
- prealloc
|
||||||
|
- wrapcheck
|
||||||
|
|
||||||
|
# disable default linters, they are already enabled in .golangci.yml
|
||||||
|
disable:
|
||||||
|
- errcheck
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- staticcheck
|
||||||
|
- unused
|
40
vendor/github.com/charmbracelet/bubbletea/.golangci.yml
generated
vendored
40
vendor/github.com/charmbracelet/bubbletea/.golangci.yml
generated
vendored
@ -1,22 +1,24 @@
|
|||||||
version: "2"
|
|
||||||
run:
|
run:
|
||||||
tests: false
|
tests: false
|
||||||
|
|
||||||
|
issues:
|
||||||
|
include:
|
||||||
|
- EXC0001
|
||||||
|
- EXC0005
|
||||||
|
- EXC0011
|
||||||
|
- EXC0012
|
||||||
|
- EXC0013
|
||||||
|
|
||||||
|
max-issues-per-linter: 0
|
||||||
|
max-same-issues: 0
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable:
|
enable:
|
||||||
- bodyclose
|
- bodyclose
|
||||||
- exhaustive
|
- gofumpt
|
||||||
- goconst
|
- goimports
|
||||||
- godot
|
|
||||||
- gomoddirectives
|
|
||||||
- goprintffuncname
|
|
||||||
- gosec
|
- gosec
|
||||||
- misspell
|
|
||||||
- nakedret
|
|
||||||
- nestif
|
|
||||||
- nilerr
|
- nilerr
|
||||||
- noctx
|
|
||||||
- nolintlint
|
|
||||||
- prealloc
|
|
||||||
- revive
|
- revive
|
||||||
- rowserrcheck
|
- rowserrcheck
|
||||||
- sqlclosecheck
|
- sqlclosecheck
|
||||||
@ -24,17 +26,3 @@ linters:
|
|||||||
- unconvert
|
- unconvert
|
||||||
- unparam
|
- unparam
|
||||||
- whitespace
|
- whitespace
|
||||||
- wrapcheck
|
|
||||||
exclusions:
|
|
||||||
generated: lax
|
|
||||||
presets:
|
|
||||||
- common-false-positives
|
|
||||||
issues:
|
|
||||||
max-issues-per-linter: 0
|
|
||||||
max-same-issues: 0
|
|
||||||
formatters:
|
|
||||||
enable:
|
|
||||||
- gofumpt
|
|
||||||
- goimports
|
|
||||||
exclusions:
|
|
||||||
generated: lax
|
|
||||||
|
8
vendor/github.com/charmbracelet/bubbletea/README.md
generated
vendored
8
vendor/github.com/charmbracelet/bubbletea/README.md
generated
vendored
@ -1,15 +1,11 @@
|
|||||||
# Bubble Tea
|
# Bubble Tea
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<picture>
|
<a href="https://stuff.charm.sh/bubbletea/bubbletea-4k.png"><img src="https://github.com/charmbracelet/bubbletea/assets/25087/108d4fdb-d554-4910-abed-2a5f5586a60e" width="313" alt="Bubble Tea Title Treatment"></a><br>
|
||||||
<source media="(prefers-color-scheme: light)" srcset="https://stuff.charm.sh/bubbletea/bubble-tea-v2-light.png" width="308">
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="https://stuff.charm.sh/bubbletea/bubble-tea-v2-dark.png" width="312">
|
|
||||||
<img src="https://stuff.charm.sh/bubbletea/bubble-tea-v2-light.png" width="308" />
|
|
||||||
</picture>
|
|
||||||
<br>
|
|
||||||
<a href="https://github.com/charmbracelet/bubbletea/releases"><img src="https://img.shields.io/github/release/charmbracelet/bubbletea.svg" alt="Latest Release"></a>
|
<a href="https://github.com/charmbracelet/bubbletea/releases"><img src="https://img.shields.io/github/release/charmbracelet/bubbletea.svg" alt="Latest Release"></a>
|
||||||
<a href="https://pkg.go.dev/github.com/charmbracelet/bubbletea?tab=doc"><img src="https://godoc.org/github.com/charmbracelet/bubbletea?status.svg" alt="GoDoc"></a>
|
<a href="https://pkg.go.dev/github.com/charmbracelet/bubbletea?tab=doc"><img src="https://godoc.org/github.com/charmbracelet/bubbletea?status.svg" alt="GoDoc"></a>
|
||||||
<a href="https://github.com/charmbracelet/bubbletea/actions"><img src="https://github.com/charmbracelet/bubbletea/actions/workflows/build.yml/badge.svg" alt="Build Status"></a>
|
<a href="https://github.com/charmbracelet/bubbletea/actions"><img src="https://github.com/charmbracelet/bubbletea/actions/workflows/build.yml/badge.svg" alt="Build Status"></a>
|
||||||
|
<a href="https://www.phorm.ai/query?projectId=a0e324b6-b706-4546-b951-6671ea60c13f"><img src="https://stuff.charm.sh/misc/phorm-badge.svg" alt="phorm.ai"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
The fun, functional and stateful way to build terminal apps. A Go framework
|
The fun, functional and stateful way to build terminal apps. A Go framework
|
||||||
|
14
vendor/github.com/charmbracelet/bubbletea/Taskfile.yaml
generated
vendored
14
vendor/github.com/charmbracelet/bubbletea/Taskfile.yaml
generated
vendored
@ -1,14 +0,0 @@
|
|||||||
# https://taskfile.dev
|
|
||||||
|
|
||||||
version: '3'
|
|
||||||
|
|
||||||
tasks:
|
|
||||||
lint:
|
|
||||||
desc: Run lint
|
|
||||||
cmds:
|
|
||||||
- golangci-lint run
|
|
||||||
|
|
||||||
test:
|
|
||||||
desc: Run tests
|
|
||||||
cmds:
|
|
||||||
- go test ./... {{.CLI_ARGS}}
|
|
4
vendor/github.com/charmbracelet/bubbletea/exec.go
generated
vendored
4
vendor/github.com/charmbracelet/bubbletea/exec.go
generated
vendored
@ -114,7 +114,6 @@ func (p *Program) exec(c ExecCommand, fn ExecCallback) {
|
|||||||
|
|
||||||
// Execute system command.
|
// Execute system command.
|
||||||
if err := c.Run(); err != nil {
|
if err := c.Run(); err != nil {
|
||||||
p.renderer.resetLinesRendered()
|
|
||||||
_ = p.RestoreTerminal() // also try to restore the terminal.
|
_ = p.RestoreTerminal() // also try to restore the terminal.
|
||||||
if fn != nil {
|
if fn != nil {
|
||||||
go p.Send(fn(err))
|
go p.Send(fn(err))
|
||||||
@ -122,9 +121,6 @@ func (p *Program) exec(c ExecCommand, fn ExecCallback) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maintain the existing output from the command
|
|
||||||
p.renderer.resetLinesRendered()
|
|
||||||
|
|
||||||
// Have the program re-capture input.
|
// Have the program re-capture input.
|
||||||
err := p.RestoreTerminal()
|
err := p.RestoreTerminal()
|
||||||
if fn != nil {
|
if fn != nil {
|
||||||
|
7
vendor/github.com/charmbracelet/bubbletea/inputreader_other.go
generated
vendored
7
vendor/github.com/charmbracelet/bubbletea/inputreader_other.go
generated
vendored
@ -4,16 +4,11 @@
|
|||||||
package tea
|
package tea
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/muesli/cancelreader"
|
"github.com/muesli/cancelreader"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newInputReader(r io.Reader, _ bool) (cancelreader.CancelReader, error) {
|
func newInputReader(r io.Reader, _ bool) (cancelreader.CancelReader, error) {
|
||||||
cr, err := cancelreader.NewReader(r)
|
return cancelreader.NewReader(r)
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("bubbletea: error creating cancel reader: %w", err)
|
|
||||||
}
|
|
||||||
return cr, nil
|
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/charmbracelet/bubbletea/inputreader_windows.go
generated
vendored
2
vendor/github.com/charmbracelet/bubbletea/inputreader_windows.go
generated
vendored
@ -67,8 +67,6 @@ func newInputReader(r io.Reader, enableMouse bool) (cancelreader.CancelReader, e
|
|||||||
func (r *conInputReader) Cancel() bool {
|
func (r *conInputReader) Cancel() bool {
|
||||||
r.setCanceled()
|
r.setCanceled()
|
||||||
|
|
||||||
// Warning: These cancel methods do not reliably work on console input
|
|
||||||
// and should not be counted on.
|
|
||||||
return windows.CancelIoEx(r.conin, nil) == nil || windows.CancelIo(r.conin) == nil
|
return windows.CancelIoEx(r.conin, nil) == nil || windows.CancelIo(r.conin) == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
vendor/github.com/charmbracelet/bubbletea/key.go
generated
vendored
2
vendor/github.com/charmbracelet/bubbletea/key.go
generated
vendored
@ -622,7 +622,7 @@ func detectOneMsg(b []byte, canHaveMoreData bool) (w int, msg Msg) {
|
|||||||
case '<':
|
case '<':
|
||||||
if matchIndices := mouseSGRRegex.FindSubmatchIndex(b[3:]); matchIndices != nil {
|
if matchIndices := mouseSGRRegex.FindSubmatchIndex(b[3:]); matchIndices != nil {
|
||||||
// SGR mouse events length is the length of the match plus the length of the escape sequence
|
// SGR mouse events length is the length of the match plus the length of the escape sequence
|
||||||
mouseEventSGRLen := matchIndices[1] + 3 //nolint:mnd
|
mouseEventSGRLen := matchIndices[1] + 3 //nolint:gomnd
|
||||||
return mouseEventSGRLen, MouseMsg(parseSGRMouseEvent(b))
|
return mouseEventSGRLen, MouseMsg(parseSGRMouseEvent(b))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
5
vendor/github.com/charmbracelet/bubbletea/key_sequences.go
generated
vendored
5
vendor/github.com/charmbracelet/bubbletea/key_sequences.go
generated
vendored
@ -119,12 +119,13 @@ func detectBracketedPaste(input []byte) (hasBp bool, width int, msg Msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// detectReportFocus detects a focus report sequence.
|
// detectReportFocus detects a focus report sequence.
|
||||||
|
// nolint: gomnd
|
||||||
func detectReportFocus(input []byte) (hasRF bool, width int, msg Msg) {
|
func detectReportFocus(input []byte) (hasRF bool, width int, msg Msg) {
|
||||||
switch {
|
switch {
|
||||||
case bytes.Equal(input, []byte("\x1b[I")):
|
case bytes.Equal(input, []byte("\x1b[I")):
|
||||||
return true, 3, FocusMsg{} //nolint:mnd
|
return true, 3, FocusMsg{}
|
||||||
case bytes.Equal(input, []byte("\x1b[O")):
|
case bytes.Equal(input, []byte("\x1b[O")):
|
||||||
return true, 3, BlurMsg{} //nolint:mnd
|
return true, 3, BlurMsg{}
|
||||||
}
|
}
|
||||||
return false, 0, nil
|
return false, 0, nil
|
||||||
}
|
}
|
||||||
|
103
vendor/github.com/charmbracelet/bubbletea/key_windows.go
generated
vendored
103
vendor/github.com/charmbracelet/bubbletea/key_windows.go
generated
vendored
@ -7,7 +7,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/erikgeiser/coninput"
|
"github.com/erikgeiser/coninput"
|
||||||
localereader "github.com/mattn/go-localereader"
|
localereader "github.com/mattn/go-localereader"
|
||||||
@ -26,10 +25,14 @@ func readConInputs(ctx context.Context, msgsch chan<- Msg, con *conInputReader)
|
|||||||
var ps coninput.ButtonState // keep track of previous mouse state
|
var ps coninput.ButtonState // keep track of previous mouse state
|
||||||
var ws coninput.WindowBufferSizeEventRecord // keep track of the last window size event
|
var ws coninput.WindowBufferSizeEventRecord // keep track of the last window size event
|
||||||
for {
|
for {
|
||||||
events, err := peekAndReadConsInput(con)
|
events, err := coninput.ReadNConsoleInputs(con.conin, 16)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
if con.isCanceled() {
|
||||||
|
return cancelreader.ErrCanceled
|
||||||
}
|
}
|
||||||
|
return fmt.Errorf("read coninput events: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
for _, event := range events {
|
for _, event := range events {
|
||||||
var msgs []Msg
|
var msgs []Msg
|
||||||
switch e := event.Unwrap().(type) {
|
switch e := event.Unwrap().(type) {
|
||||||
@ -84,57 +87,13 @@ func readConInputs(ctx context.Context, msgsch chan<- Msg, con *conInputReader)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("coninput context error: %w", err)
|
return fmt.Errorf("coninput context error: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Peek for new input in a tight loop and then read the input.
|
|
||||||
// windows.CancelIo* does not work reliably so peek first and only use the data if
|
|
||||||
// the console input is not cancelled.
|
|
||||||
func peekAndReadConsInput(con *conInputReader) ([]coninput.InputRecord, error) {
|
|
||||||
events, err := peekConsInput(con)
|
|
||||||
if err != nil {
|
|
||||||
return events, err
|
|
||||||
}
|
|
||||||
events, err = coninput.ReadNConsoleInputs(con.conin, intToUint32OrDie(len(events)))
|
|
||||||
if con.isCanceled() {
|
|
||||||
return events, cancelreader.ErrCanceled
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return events, fmt.Errorf("read coninput events: %w", err)
|
|
||||||
}
|
|
||||||
return events, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert i to unit32 or panic if it cannot be converted. Check satisifes lint G115.
|
|
||||||
func intToUint32OrDie(i int) uint32 {
|
|
||||||
if i < 0 {
|
|
||||||
panic("cannot convert numEvents " + fmt.Sprint(i) + " to uint32")
|
|
||||||
}
|
|
||||||
return uint32(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keeps peeking until there is data or the input is cancelled.
|
|
||||||
func peekConsInput(con *conInputReader) ([]coninput.InputRecord, error) {
|
|
||||||
for {
|
|
||||||
events, err := coninput.PeekNConsoleInputs(con.conin, 16)
|
|
||||||
if con.isCanceled() {
|
|
||||||
return events, cancelreader.ErrCanceled
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return events, fmt.Errorf("peek coninput events: %w", err)
|
|
||||||
}
|
|
||||||
if len(events) > 0 {
|
|
||||||
return events, nil
|
|
||||||
}
|
|
||||||
// Sleep for a bit to avoid busy waiting.
|
|
||||||
time.Sleep(16 * time.Millisecond)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func mouseEventButton(p, s coninput.ButtonState) (button MouseButton, action MouseAction) {
|
func mouseEventButton(p, s coninput.ButtonState) (button MouseButton, action MouseAction) {
|
||||||
btn := p ^ s
|
btn := p ^ s
|
||||||
action = MouseActionPress
|
action = MouseActionPress
|
||||||
@ -155,7 +114,7 @@ func mouseEventButton(p, s coninput.ButtonState) (button MouseButton, action Mou
|
|||||||
case s&coninput.FROM_LEFT_4TH_BUTTON_PRESSED > 0:
|
case s&coninput.FROM_LEFT_4TH_BUTTON_PRESSED > 0:
|
||||||
button = MouseButtonForward
|
button = MouseButtonForward
|
||||||
}
|
}
|
||||||
return button, action
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
@ -188,7 +147,7 @@ func mouseEvent(p coninput.ButtonState, e coninput.MouseEventRecord) MouseMsg {
|
|||||||
if ev.Action == MouseActionRelease {
|
if ev.Action == MouseActionRelease {
|
||||||
ev.Type = MouseRelease
|
ev.Type = MouseRelease
|
||||||
}
|
}
|
||||||
switch ev.Button { //nolint:exhaustive
|
switch ev.Button {
|
||||||
case MouseButtonLeft:
|
case MouseButtonLeft:
|
||||||
ev.Type = MouseLeft
|
ev.Type = MouseLeft
|
||||||
case MouseButtonMiddle:
|
case MouseButtonMiddle:
|
||||||
@ -231,7 +190,7 @@ func keyType(e coninput.KeyEventRecord) KeyType {
|
|||||||
shiftPressed := e.ControlKeyState.Contains(coninput.SHIFT_PRESSED)
|
shiftPressed := e.ControlKeyState.Contains(coninput.SHIFT_PRESSED)
|
||||||
ctrlPressed := e.ControlKeyState.Contains(coninput.LEFT_CTRL_PRESSED | coninput.RIGHT_CTRL_PRESSED)
|
ctrlPressed := e.ControlKeyState.Contains(coninput.LEFT_CTRL_PRESSED | coninput.RIGHT_CTRL_PRESSED)
|
||||||
|
|
||||||
switch code { //nolint:exhaustive
|
switch code {
|
||||||
case coninput.VK_RETURN:
|
case coninput.VK_RETURN:
|
||||||
return KeyEnter
|
return KeyEnter
|
||||||
case coninput.VK_BACK:
|
case coninput.VK_BACK:
|
||||||
@ -317,46 +276,6 @@ func keyType(e coninput.KeyEventRecord) KeyType {
|
|||||||
return KeyPgDown
|
return KeyPgDown
|
||||||
case coninput.VK_DELETE:
|
case coninput.VK_DELETE:
|
||||||
return KeyDelete
|
return KeyDelete
|
||||||
case coninput.VK_F1:
|
|
||||||
return KeyF1
|
|
||||||
case coninput.VK_F2:
|
|
||||||
return KeyF2
|
|
||||||
case coninput.VK_F3:
|
|
||||||
return KeyF3
|
|
||||||
case coninput.VK_F4:
|
|
||||||
return KeyF4
|
|
||||||
case coninput.VK_F5:
|
|
||||||
return KeyF5
|
|
||||||
case coninput.VK_F6:
|
|
||||||
return KeyF6
|
|
||||||
case coninput.VK_F7:
|
|
||||||
return KeyF7
|
|
||||||
case coninput.VK_F8:
|
|
||||||
return KeyF8
|
|
||||||
case coninput.VK_F9:
|
|
||||||
return KeyF9
|
|
||||||
case coninput.VK_F10:
|
|
||||||
return KeyF10
|
|
||||||
case coninput.VK_F11:
|
|
||||||
return KeyF11
|
|
||||||
case coninput.VK_F12:
|
|
||||||
return KeyF12
|
|
||||||
case coninput.VK_F13:
|
|
||||||
return KeyF13
|
|
||||||
case coninput.VK_F14:
|
|
||||||
return KeyF14
|
|
||||||
case coninput.VK_F15:
|
|
||||||
return KeyF15
|
|
||||||
case coninput.VK_F16:
|
|
||||||
return KeyF16
|
|
||||||
case coninput.VK_F17:
|
|
||||||
return KeyF17
|
|
||||||
case coninput.VK_F18:
|
|
||||||
return KeyF18
|
|
||||||
case coninput.VK_F19:
|
|
||||||
return KeyF19
|
|
||||||
case coninput.VK_F20:
|
|
||||||
return KeyF20
|
|
||||||
default:
|
default:
|
||||||
switch {
|
switch {
|
||||||
case e.ControlKeyState.Contains(coninput.LEFT_CTRL_PRESSED) && e.ControlKeyState.Contains(coninput.RIGHT_ALT_PRESSED):
|
case e.ControlKeyState.Contains(coninput.LEFT_CTRL_PRESSED) && e.ControlKeyState.Contains(coninput.RIGHT_ALT_PRESSED):
|
||||||
@ -429,7 +348,7 @@ func keyType(e coninput.KeyEventRecord) KeyType {
|
|||||||
return KeyCtrlUnderscore
|
return KeyCtrlUnderscore
|
||||||
}
|
}
|
||||||
|
|
||||||
switch code { //nolint:exhaustive
|
switch code {
|
||||||
case coninput.VK_OEM_4:
|
case coninput.VK_OEM_4:
|
||||||
return KeyCtrlOpenBracket
|
return KeyCtrlOpenBracket
|
||||||
case coninput.VK_OEM_6:
|
case coninput.VK_OEM_6:
|
||||||
|
2
vendor/github.com/charmbracelet/bubbletea/logging.go
generated
vendored
2
vendor/github.com/charmbracelet/bubbletea/logging.go
generated
vendored
@ -33,7 +33,7 @@ type LogOptionsSetter interface {
|
|||||||
|
|
||||||
// LogToFileWith does allows to call LogToFile with a custom LogOptionsSetter.
|
// LogToFileWith does allows to call LogToFile with a custom LogOptionsSetter.
|
||||||
func LogToFileWith(path string, prefix string, log LogOptionsSetter) (*os.File, error) {
|
func LogToFileWith(path string, prefix string, log LogOptionsSetter) (*os.File, error) {
|
||||||
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o600) //nolint:mnd
|
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o600) //nolint:gomnd
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error opening file for logging: %w", err)
|
return nil, fmt.Errorf("error opening file for logging: %w", err)
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/charmbracelet/bubbletea/mouse.go
generated
vendored
2
vendor/github.com/charmbracelet/bubbletea/mouse.go
generated
vendored
@ -172,7 +172,7 @@ const (
|
|||||||
func parseSGRMouseEvent(buf []byte) MouseEvent {
|
func parseSGRMouseEvent(buf []byte) MouseEvent {
|
||||||
str := string(buf[3:])
|
str := string(buf[3:])
|
||||||
matches := mouseSGRRegex.FindStringSubmatch(str)
|
matches := mouseSGRRegex.FindStringSubmatch(str)
|
||||||
if len(matches) != 5 { //nolint:mnd
|
if len(matches) != 5 { //nolint:gomnd
|
||||||
// Unreachable, we already checked the regex in `detectOneMsg`.
|
// Unreachable, we already checked the regex in `detectOneMsg`.
|
||||||
panic("invalid mouse event")
|
panic("invalid mouse event")
|
||||||
}
|
}
|
||||||
|
1
vendor/github.com/charmbracelet/bubbletea/nil_renderer.go
generated
vendored
1
vendor/github.com/charmbracelet/bubbletea/nil_renderer.go
generated
vendored
@ -26,4 +26,3 @@ func (n nilRenderer) setWindowTitle(_ string) {}
|
|||||||
func (n nilRenderer) reportFocus() bool { return false }
|
func (n nilRenderer) reportFocus() bool { return false }
|
||||||
func (n nilRenderer) enableReportFocus() {}
|
func (n nilRenderer) enableReportFocus() {}
|
||||||
func (n nilRenderer) disableReportFocus() {}
|
func (n nilRenderer) disableReportFocus() {}
|
||||||
func (n nilRenderer) resetLinesRendered() {}
|
|
||||||
|
2
vendor/github.com/charmbracelet/bubbletea/options.go
generated
vendored
2
vendor/github.com/charmbracelet/bubbletea/options.go
generated
vendored
@ -19,7 +19,7 @@ type ProgramOption func(*Program)
|
|||||||
// cancelled it will exit with an error ErrProgramKilled.
|
// cancelled it will exit with an error ErrProgramKilled.
|
||||||
func WithContext(ctx context.Context) ProgramOption {
|
func WithContext(ctx context.Context) ProgramOption {
|
||||||
return func(p *Program) {
|
return func(p *Program) {
|
||||||
p.externalCtx = ctx
|
p.ctx = ctx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
vendor/github.com/charmbracelet/bubbletea/renderer.go
generated
vendored
3
vendor/github.com/charmbracelet/bubbletea/renderer.go
generated
vendored
@ -79,9 +79,6 @@ type renderer interface {
|
|||||||
|
|
||||||
// disableReportFocus stops reporting focus events to the program.
|
// disableReportFocus stops reporting focus events to the program.
|
||||||
disableReportFocus()
|
disableReportFocus()
|
||||||
|
|
||||||
// resetLinesRendered ensures exec output remains on screen on exit
|
|
||||||
resetLinesRendered()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// repaintMsg forces a full repaint.
|
// repaintMsg forces a full repaint.
|
||||||
|
4
vendor/github.com/charmbracelet/bubbletea/standard_renderer.go
generated
vendored
4
vendor/github.com/charmbracelet/bubbletea/standard_renderer.go
generated
vendored
@ -545,10 +545,6 @@ func (r *standardRenderer) clearIgnoredLines() {
|
|||||||
r.ignoreLines = nil
|
r.ignoreLines = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *standardRenderer) resetLinesRendered() {
|
|
||||||
r.linesRendered = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// insertTop effectively scrolls up. It inserts lines at the top of a given
|
// insertTop effectively scrolls up. It inserts lines at the top of a given
|
||||||
// area designated to be a scrollable region, pushing everything else down.
|
// area designated to be a scrollable region, pushing everything else down.
|
||||||
// This is roughly how ncurses does it.
|
// This is roughly how ncurses does it.
|
||||||
|
115
vendor/github.com/charmbracelet/bubbletea/tea.go
generated
vendored
115
vendor/github.com/charmbracelet/bubbletea/tea.go
generated
vendored
@ -27,9 +27,6 @@ import (
|
|||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrProgramPanic is returned by [Program.Run] when the program recovers from a panic.
|
|
||||||
var ErrProgramPanic = errors.New("program experienced a panic")
|
|
||||||
|
|
||||||
// ErrProgramKilled is returned by [Program.Run] when the program gets killed.
|
// ErrProgramKilled is returned by [Program.Run] when the program gets killed.
|
||||||
var ErrProgramKilled = errors.New("program was killed")
|
var ErrProgramKilled = errors.New("program was killed")
|
||||||
|
|
||||||
@ -150,12 +147,6 @@ type Program struct {
|
|||||||
|
|
||||||
inputType inputType
|
inputType inputType
|
||||||
|
|
||||||
// externalCtx is a context that was passed in via WithContext, otherwise defaulting
|
|
||||||
// to ctx.Background() (in case it was not), the internal context is derived from it.
|
|
||||||
externalCtx context.Context
|
|
||||||
|
|
||||||
// ctx is the programs's internal context for signalling internal teardown.
|
|
||||||
// It is built and derived from the externalCtx in NewProgram().
|
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
|
|
||||||
@ -252,11 +243,11 @@ func NewProgram(model Model, opts ...ProgramOption) *Program {
|
|||||||
|
|
||||||
// A context can be provided with a ProgramOption, but if none was provided
|
// A context can be provided with a ProgramOption, but if none was provided
|
||||||
// we'll use the default background context.
|
// we'll use the default background context.
|
||||||
if p.externalCtx == nil {
|
if p.ctx == nil {
|
||||||
p.externalCtx = context.Background()
|
p.ctx = context.Background()
|
||||||
}
|
}
|
||||||
// Initialize context and teardown channel.
|
// Initialize context and teardown channel.
|
||||||
p.ctx, p.cancel = context.WithCancel(p.externalCtx)
|
p.ctx, p.cancel = context.WithCancel(p.ctx)
|
||||||
|
|
||||||
// if no output was set, set it to stdout
|
// if no output was set, set it to stdout
|
||||||
if p.output == nil {
|
if p.output == nil {
|
||||||
@ -355,11 +346,7 @@ func (p *Program) handleCommands(cmds chan Cmd) chan struct{} {
|
|||||||
go func() {
|
go func() {
|
||||||
// Recover from panics.
|
// Recover from panics.
|
||||||
if !p.startupOptions.has(withoutCatchPanics) {
|
if !p.startupOptions.has(withoutCatchPanics) {
|
||||||
defer func() {
|
defer p.recoverFromPanic()
|
||||||
if r := recover(); r != nil {
|
|
||||||
p.recoverFromGoPanic(r)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := cmd() // this can be long.
|
msg := cmd() // this can be long.
|
||||||
@ -435,7 +422,7 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) {
|
|||||||
// work.
|
// work.
|
||||||
if runtime.GOOS == "windows" && !p.mouseMode {
|
if runtime.GOOS == "windows" && !p.mouseMode {
|
||||||
p.mouseMode = true
|
p.mouseMode = true
|
||||||
p.initCancelReader(true) //nolint:errcheck,gosec
|
p.initCancelReader(true) //nolint:errcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
case disableMouseMsg:
|
case disableMouseMsg:
|
||||||
@ -446,7 +433,7 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) {
|
|||||||
// mouse events.
|
// mouse events.
|
||||||
if runtime.GOOS == "windows" && p.mouseMode {
|
if runtime.GOOS == "windows" && p.mouseMode {
|
||||||
p.mouseMode = false
|
p.mouseMode = false
|
||||||
p.initCancelReader(true) //nolint:errcheck,gosec
|
p.initCancelReader(true) //nolint:errcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
case showCursorMsg:
|
case showCursorMsg:
|
||||||
@ -473,11 +460,7 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) {
|
|||||||
|
|
||||||
case BatchMsg:
|
case BatchMsg:
|
||||||
for _, cmd := range msg {
|
for _, cmd := range msg {
|
||||||
select {
|
cmds <- cmd
|
||||||
case <-p.ctx.Done():
|
|
||||||
return model, nil
|
|
||||||
case cmds <- cmd:
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -500,7 +483,7 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:errcheck,gosec
|
//nolint:errcheck
|
||||||
g.Wait() // wait for all commands from batch msg to finish
|
g.Wait() // wait for all commands from batch msg to finish
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -523,13 +506,7 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) {
|
|||||||
|
|
||||||
var cmd Cmd
|
var cmd Cmd
|
||||||
model, cmd = model.Update(msg) // run update
|
model, cmd = model.Update(msg) // run update
|
||||||
|
cmds <- cmd // process command (if any)
|
||||||
select {
|
|
||||||
case <-p.ctx.Done():
|
|
||||||
return model, nil
|
|
||||||
case cmds <- cmd: // process command (if any)
|
|
||||||
}
|
|
||||||
|
|
||||||
p.renderer.write(model.View()) // send view to renderer
|
p.renderer.write(model.View()) // send view to renderer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -538,15 +515,11 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) {
|
|||||||
// Run initializes the program and runs its event loops, blocking until it gets
|
// Run initializes the program and runs its event loops, blocking until it gets
|
||||||
// terminated by either [Program.Quit], [Program.Kill], or its signal handler.
|
// terminated by either [Program.Quit], [Program.Kill], or its signal handler.
|
||||||
// Returns the final model.
|
// Returns the final model.
|
||||||
func (p *Program) Run() (returnModel Model, returnErr error) {
|
func (p *Program) Run() (Model, error) {
|
||||||
p.handlers = channelHandlers{}
|
p.handlers = channelHandlers{}
|
||||||
cmds := make(chan Cmd)
|
cmds := make(chan Cmd)
|
||||||
p.errs = make(chan error, 1)
|
p.errs = make(chan error)
|
||||||
|
p.finished = make(chan struct{}, 1)
|
||||||
p.finished = make(chan struct{})
|
|
||||||
defer func() {
|
|
||||||
close(p.finished)
|
|
||||||
}()
|
|
||||||
|
|
||||||
defer p.cancel()
|
defer p.cancel()
|
||||||
|
|
||||||
@ -595,12 +568,7 @@ func (p *Program) Run() (returnModel Model, returnErr error) {
|
|||||||
|
|
||||||
// Recover from panics.
|
// Recover from panics.
|
||||||
if !p.startupOptions.has(withoutCatchPanics) {
|
if !p.startupOptions.has(withoutCatchPanics) {
|
||||||
defer func() {
|
defer p.recoverFromPanic()
|
||||||
if r := recover(); r != nil {
|
|
||||||
returnErr = fmt.Errorf("%w: %w", ErrProgramKilled, ErrProgramPanic)
|
|
||||||
p.recoverFromPanic(r)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no renderer is set use the standard one.
|
// If no renderer is set use the standard one.
|
||||||
@ -677,27 +645,11 @@ func (p *Program) Run() (returnModel Model, returnErr error) {
|
|||||||
|
|
||||||
// Run event loop, handle updates and draw.
|
// Run event loop, handle updates and draw.
|
||||||
model, err := p.eventLoop(model, cmds)
|
model, err := p.eventLoop(model, cmds)
|
||||||
|
killed := p.ctx.Err() != nil || err != nil
|
||||||
if err == nil && len(p.errs) > 0 {
|
if killed && err == nil {
|
||||||
err = <-p.errs // Drain a leftover error in case eventLoop crashed
|
err = fmt.Errorf("%w: %s", ErrProgramKilled, p.ctx.Err())
|
||||||
}
|
}
|
||||||
|
if err == nil {
|
||||||
killed := p.externalCtx.Err() != nil || p.ctx.Err() != nil || err != nil
|
|
||||||
if killed {
|
|
||||||
if err == nil && p.externalCtx.Err() != nil {
|
|
||||||
// Return also as context error the cancellation of an external context.
|
|
||||||
// This is the context the user knows about and should be able to act on.
|
|
||||||
err = fmt.Errorf("%w: %w", ErrProgramKilled, p.externalCtx.Err())
|
|
||||||
} else if err == nil && p.ctx.Err() != nil {
|
|
||||||
// Return only that the program was killed (not the internal mechanism).
|
|
||||||
// The user does not know or need to care about the internal program context.
|
|
||||||
err = ErrProgramKilled
|
|
||||||
} else {
|
|
||||||
// Return that the program was killed and also the error that caused it.
|
|
||||||
err = fmt.Errorf("%w: %w", ErrProgramKilled, err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Graceful shutdown of the program (not killed):
|
|
||||||
// Ensure we rendered the final state of the model.
|
// Ensure we rendered the final state of the model.
|
||||||
p.renderer.write(model.View())
|
p.renderer.write(model.View())
|
||||||
}
|
}
|
||||||
@ -752,11 +704,11 @@ func (p *Program) Quit() {
|
|||||||
p.Send(Quit())
|
p.Send(Quit())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kill signals the program to stop immediately and restore the former terminal state.
|
// Kill stops the program immediately and restores the former terminal state.
|
||||||
// The final render that you would normally see when quitting will be skipped.
|
// The final render that you would normally see when quitting will be skipped.
|
||||||
// [program.Run] returns a [ErrProgramKilled] error.
|
// [program.Run] returns a [ErrProgramKilled] error.
|
||||||
func (p *Program) Kill() {
|
func (p *Program) Kill() {
|
||||||
p.cancel()
|
p.shutdown(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait waits/blocks until the underlying Program finished shutting down.
|
// Wait waits/blocks until the underlying Program finished shutting down.
|
||||||
@ -765,11 +717,7 @@ func (p *Program) Wait() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// shutdown performs operations to free up resources and restore the terminal
|
// shutdown performs operations to free up resources and restore the terminal
|
||||||
// to its original state. It is called once at the end of the program's lifetime.
|
// to its original state.
|
||||||
//
|
|
||||||
// This method should not be called to signal the program to be killed/shutdown.
|
|
||||||
// Doing so can lead to race conditions with the eventual call at the program's end.
|
|
||||||
// As alternatives, the [Quit] or [Kill] convenience methods should be used instead.
|
|
||||||
func (p *Program) shutdown(kill bool) {
|
func (p *Program) shutdown(kill bool) {
|
||||||
p.cancel()
|
p.cancel()
|
||||||
|
|
||||||
@ -796,30 +744,19 @@ func (p *Program) shutdown(kill bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ = p.restoreTerminalState()
|
_ = p.restoreTerminalState()
|
||||||
|
if !kill {
|
||||||
|
p.finished <- struct{}{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// recoverFromPanic recovers from a panic, prints the stack trace, and restores
|
// recoverFromPanic recovers from a panic, prints the stack trace, and restores
|
||||||
// the terminal to a usable state.
|
// the terminal to a usable state.
|
||||||
func (p *Program) recoverFromPanic(r interface{}) {
|
func (p *Program) recoverFromPanic() {
|
||||||
select {
|
if r := recover(); r != nil {
|
||||||
case p.errs <- ErrProgramPanic:
|
p.shutdown(true)
|
||||||
default:
|
|
||||||
}
|
|
||||||
p.shutdown(true) // Ok to call here, p.Run() cannot do it anymore.
|
|
||||||
fmt.Printf("Caught panic:\n\n%s\n\nRestoring terminal...\n\n", r)
|
fmt.Printf("Caught panic:\n\n%s\n\nRestoring terminal...\n\n", r)
|
||||||
debug.PrintStack()
|
debug.PrintStack()
|
||||||
}
|
|
||||||
|
|
||||||
// recoverFromGoPanic recovers from a goroutine panic, prints a stack trace and
|
|
||||||
// signals for the program to be killed and terminal restored to a usable state.
|
|
||||||
func (p *Program) recoverFromGoPanic(r interface{}) {
|
|
||||||
select {
|
|
||||||
case p.errs <- ErrProgramPanic:
|
|
||||||
default:
|
|
||||||
}
|
}
|
||||||
p.cancel()
|
|
||||||
fmt.Printf("Caught goroutine panic:\n\n%s\n\nRestoring terminal...\n\n", r)
|
|
||||||
debug.PrintStack()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReleaseTerminal restores the original terminal state and cancels the input
|
// ReleaseTerminal restores the original terminal state and cancels the input
|
||||||
|
4
vendor/github.com/charmbracelet/bubbletea/tty.go
generated
vendored
4
vendor/github.com/charmbracelet/bubbletea/tty.go
generated
vendored
@ -52,7 +52,7 @@ func (p *Program) restoreTerminalState() error {
|
|||||||
p.renderer.exitAltScreen()
|
p.renderer.exitAltScreen()
|
||||||
|
|
||||||
// give the terminal a moment to catch up
|
// give the terminal a moment to catch up
|
||||||
time.Sleep(time.Millisecond * 10) //nolint:mnd
|
time.Sleep(time.Millisecond * 10) //nolint:gomnd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ func (p *Program) readLoop() {
|
|||||||
func (p *Program) waitForReadLoop() {
|
func (p *Program) waitForReadLoop() {
|
||||||
select {
|
select {
|
||||||
case <-p.readLoopDone:
|
case <-p.readLoopDone:
|
||||||
case <-time.After(500 * time.Millisecond): //nolint:mnd
|
case <-time.After(500 * time.Millisecond): //nolint:gomnd
|
||||||
// The read loop hangs, which means the input
|
// The read loop hangs, which means the input
|
||||||
// cancelReader's cancel function has returned true even
|
// cancelReader's cancel function has returned true even
|
||||||
// though it was not able to cancel the read.
|
// though it was not able to cancel the read.
|
||||||
|
8
vendor/github.com/charmbracelet/bubbletea/tty_windows.go
generated
vendored
8
vendor/github.com/charmbracelet/bubbletea/tty_windows.go
generated
vendored
@ -19,7 +19,7 @@ func (p *Program) initInput() (err error) {
|
|||||||
p.ttyInput = f
|
p.ttyInput = f
|
||||||
p.previousTtyInputState, err = term.MakeRaw(p.ttyInput.Fd())
|
p.previousTtyInputState, err = term.MakeRaw(p.ttyInput.Fd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error making raw: %w", err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable VT input
|
// Enable VT input
|
||||||
@ -38,7 +38,7 @@ func (p *Program) initInput() (err error) {
|
|||||||
p.ttyOutput = f
|
p.ttyOutput = f
|
||||||
p.previousOutputState, err = term.GetState(f.Fd())
|
p.previousOutputState, err = term.GetState(f.Fd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error getting state: %w", err)
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var mode uint32
|
var mode uint32
|
||||||
@ -51,14 +51,14 @@ func (p *Program) initInput() (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open the Windows equivalent of a TTY.
|
// Open the Windows equivalent of a TTY.
|
||||||
func openInputTTY() (*os.File, error) {
|
func openInputTTY() (*os.File, error) {
|
||||||
f, err := os.OpenFile("CONIN$", os.O_RDWR, 0o644)
|
f, err := os.OpenFile("CONIN$", os.O_RDWR, 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error opening file: %w", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
40
vendor/github.com/charmbracelet/colorprofile/.golangci-soft.yml
generated
vendored
Normal file
40
vendor/github.com/charmbracelet/colorprofile/.golangci-soft.yml
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
run:
|
||||||
|
tests: false
|
||||||
|
issues-exit-code: 0
|
||||||
|
|
||||||
|
issues:
|
||||||
|
include:
|
||||||
|
- EXC0001
|
||||||
|
- EXC0005
|
||||||
|
- EXC0011
|
||||||
|
- EXC0012
|
||||||
|
- EXC0013
|
||||||
|
|
||||||
|
max-issues-per-linter: 0
|
||||||
|
max-same-issues: 0
|
||||||
|
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
- exhaustive
|
||||||
|
- goconst
|
||||||
|
- godot
|
||||||
|
- godox
|
||||||
|
- mnd
|
||||||
|
- gomoddirectives
|
||||||
|
- goprintffuncname
|
||||||
|
- misspell
|
||||||
|
- nakedret
|
||||||
|
- nestif
|
||||||
|
- noctx
|
||||||
|
- nolintlint
|
||||||
|
- prealloc
|
||||||
|
- wrapcheck
|
||||||
|
|
||||||
|
# disable default linters, they are already enabled in .golangci.yml
|
||||||
|
disable:
|
||||||
|
- errcheck
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- staticcheck
|
||||||
|
- unused
|
44
vendor/github.com/charmbracelet/colorprofile/.golangci.yml
generated
vendored
44
vendor/github.com/charmbracelet/colorprofile/.golangci.yml
generated
vendored
@ -1,22 +1,24 @@
|
|||||||
version: "2"
|
|
||||||
run:
|
run:
|
||||||
tests: false
|
tests: false
|
||||||
|
|
||||||
|
issues:
|
||||||
|
include:
|
||||||
|
- EXC0001
|
||||||
|
- EXC0005
|
||||||
|
- EXC0011
|
||||||
|
- EXC0012
|
||||||
|
- EXC0013
|
||||||
|
|
||||||
|
max-issues-per-linter: 0
|
||||||
|
max-same-issues: 0
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable:
|
enable:
|
||||||
- bodyclose
|
- bodyclose
|
||||||
- exhaustive
|
- gofumpt
|
||||||
- goconst
|
- goimports
|
||||||
- godot
|
|
||||||
- gomoddirectives
|
|
||||||
- goprintffuncname
|
|
||||||
- gosec
|
- gosec
|
||||||
- misspell
|
|
||||||
- nakedret
|
|
||||||
- nestif
|
|
||||||
- nilerr
|
- nilerr
|
||||||
- noctx
|
|
||||||
- nolintlint
|
|
||||||
- prealloc
|
|
||||||
- revive
|
- revive
|
||||||
- rowserrcheck
|
- rowserrcheck
|
||||||
- sqlclosecheck
|
- sqlclosecheck
|
||||||
@ -24,21 +26,3 @@ linters:
|
|||||||
- unconvert
|
- unconvert
|
||||||
- unparam
|
- unparam
|
||||||
- whitespace
|
- whitespace
|
||||||
- wrapcheck
|
|
||||||
exclusions:
|
|
||||||
rules:
|
|
||||||
- text: '(slog|log)\.\w+'
|
|
||||||
linters:
|
|
||||||
- noctx
|
|
||||||
generated: lax
|
|
||||||
presets:
|
|
||||||
- common-false-positives
|
|
||||||
issues:
|
|
||||||
max-issues-per-linter: 0
|
|
||||||
max-same-issues: 0
|
|
||||||
formatters:
|
|
||||||
enable:
|
|
||||||
- gofumpt
|
|
||||||
- goimports
|
|
||||||
exclusions:
|
|
||||||
generated: lax
|
|
||||||
|
6
vendor/github.com/charmbracelet/colorprofile/README.md
generated
vendored
6
vendor/github.com/charmbracelet/colorprofile/README.md
generated
vendored
@ -82,12 +82,6 @@ w.Profile = colorprofile.NoTTY
|
|||||||
fmt.Fprintf(w, myFancyANSI) // not as fancy
|
fmt.Fprintf(w, myFancyANSI) // not as fancy
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
See [contributing][contribute].
|
|
||||||
|
|
||||||
[contribute]: https://github.com/charmbracelet/colorprofile/contribute
|
|
||||||
|
|
||||||
## Feedback
|
## Feedback
|
||||||
|
|
||||||
We’d love to hear your thoughts on this project. Feel free to drop us a note!
|
We’d love to hear your thoughts on this project. Feel free to drop us a note!
|
||||||
|
4
vendor/github.com/charmbracelet/colorprofile/doc.go
generated
vendored
4
vendor/github.com/charmbracelet/colorprofile/doc.go
generated
vendored
@ -1,4 +0,0 @@
|
|||||||
// Package colorprofile provides a way to downsample ANSI escape sequence
|
|
||||||
// colors and styles automatically based on output, environment variables, and
|
|
||||||
// Terminfo databases.
|
|
||||||
package colorprofile
|
|
36
vendor/github.com/charmbracelet/colorprofile/env.go
generated
vendored
36
vendor/github.com/charmbracelet/colorprofile/env.go
generated
vendored
@ -12,8 +12,6 @@ import (
|
|||||||
"github.com/xo/terminfo"
|
"github.com/xo/terminfo"
|
||||||
)
|
)
|
||||||
|
|
||||||
const dumbTerm = "dumb"
|
|
||||||
|
|
||||||
// Detect returns the color profile based on the terminal output, and
|
// Detect returns the color profile based on the terminal output, and
|
||||||
// environment variables. This respects NO_COLOR, CLICOLOR, and CLICOLOR_FORCE
|
// environment variables. This respects NO_COLOR, CLICOLOR, and CLICOLOR_FORCE
|
||||||
// environment variables.
|
// environment variables.
|
||||||
@ -31,10 +29,10 @@ const dumbTerm = "dumb"
|
|||||||
// See https://no-color.org/ and https://bixense.com/clicolors/ for more information.
|
// See https://no-color.org/ and https://bixense.com/clicolors/ for more information.
|
||||||
func Detect(output io.Writer, env []string) Profile {
|
func Detect(output io.Writer, env []string) Profile {
|
||||||
out, ok := output.(term.File)
|
out, ok := output.(term.File)
|
||||||
|
isatty := ok && term.IsTerminal(out.Fd())
|
||||||
environ := newEnviron(env)
|
environ := newEnviron(env)
|
||||||
isatty := isTTYForced(environ) || (ok && term.IsTerminal(out.Fd()))
|
term := environ.get("TERM")
|
||||||
term, ok := environ.lookup("TERM")
|
isDumb := term == "dumb"
|
||||||
isDumb := !ok || term == dumbTerm
|
|
||||||
envp := colorProfile(isatty, environ)
|
envp := colorProfile(isatty, environ)
|
||||||
if envp == TrueColor || envNoColor(environ) {
|
if envp == TrueColor || envNoColor(environ) {
|
||||||
// We already know we have TrueColor, or NO_COLOR is set.
|
// We already know we have TrueColor, or NO_COLOR is set.
|
||||||
@ -71,8 +69,7 @@ func Env(env []string) (p Profile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func colorProfile(isatty bool, env environ) (p Profile) {
|
func colorProfile(isatty bool, env environ) (p Profile) {
|
||||||
term, ok := env.lookup("TERM")
|
isDumb := env.get("TERM") == "dumb"
|
||||||
isDumb := (!ok && runtime.GOOS != "windows") || term == dumbTerm
|
|
||||||
envp := envColorProfile(env)
|
envp := envColorProfile(env)
|
||||||
if !isatty || isDumb {
|
if !isatty || isDumb {
|
||||||
// Check if the output is a terminal.
|
// Check if the output is a terminal.
|
||||||
@ -86,7 +83,7 @@ func colorProfile(isatty bool, env environ) (p Profile) {
|
|||||||
if p > Ascii {
|
if p > Ascii {
|
||||||
p = Ascii
|
p = Ascii
|
||||||
}
|
}
|
||||||
return //nolint:nakedret
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if cliColorForced(env) {
|
if cliColorForced(env) {
|
||||||
@ -97,7 +94,7 @@ func colorProfile(isatty bool, env environ) (p Profile) {
|
|||||||
p = envp
|
p = envp
|
||||||
}
|
}
|
||||||
|
|
||||||
return //nolint:nakedret
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if cliColor(env) {
|
if cliColor(env) {
|
||||||
@ -126,11 +123,6 @@ func cliColorForced(env environ) bool {
|
|||||||
return cliColorForce
|
return cliColorForce
|
||||||
}
|
}
|
||||||
|
|
||||||
func isTTYForced(env environ) bool {
|
|
||||||
skip, _ := strconv.ParseBool(env.get("TTY_FORCE"))
|
|
||||||
return skip
|
|
||||||
}
|
|
||||||
|
|
||||||
func colorTerm(env environ) bool {
|
func colorTerm(env environ) bool {
|
||||||
colorTerm := strings.ToLower(env.get("COLORTERM"))
|
colorTerm := strings.ToLower(env.get("COLORTERM"))
|
||||||
return colorTerm == "truecolor" || colorTerm == "24bit" ||
|
return colorTerm == "truecolor" || colorTerm == "24bit" ||
|
||||||
@ -140,7 +132,7 @@ func colorTerm(env environ) bool {
|
|||||||
// envColorProfile returns infers the color profile from the environment.
|
// envColorProfile returns infers the color profile from the environment.
|
||||||
func envColorProfile(env environ) (p Profile) {
|
func envColorProfile(env environ) (p Profile) {
|
||||||
term, ok := env.lookup("TERM")
|
term, ok := env.lookup("TERM")
|
||||||
if !ok || len(term) == 0 || term == dumbTerm {
|
if !ok || len(term) == 0 || term == "dumb" {
|
||||||
p = NoTTY
|
p = NoTTY
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
// Use Windows API to detect color profile. Windows Terminal and
|
// Use Windows API to detect color profile. Windows Terminal and
|
||||||
@ -192,12 +184,7 @@ func envColorProfile(env environ) (p Profile) {
|
|||||||
p = ANSI256
|
p = ANSI256
|
||||||
}
|
}
|
||||||
|
|
||||||
// Direct color terminals support true colors.
|
return
|
||||||
if strings.HasSuffix(term, "direct") {
|
|
||||||
return TrueColor
|
|
||||||
}
|
|
||||||
|
|
||||||
return //nolint:nakedret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Terminfo returns the color profile based on the terminal's terminfo
|
// Terminfo returns the color profile based on the terminal's terminfo
|
||||||
@ -291,3 +278,10 @@ func (e environ) get(key string) string {
|
|||||||
v, _ := e.lookup(key)
|
v, _ := e.lookup(key)
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func max[T ~byte | ~int](a, b T) T {
|
||||||
|
if a > b {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
395
vendor/github.com/charmbracelet/colorprofile/profile.go
generated
vendored
395
vendor/github.com/charmbracelet/colorprofile/profile.go
generated
vendored
@ -2,24 +2,25 @@ package colorprofile
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"image/color"
|
"image/color"
|
||||||
"sync"
|
"math"
|
||||||
|
|
||||||
"github.com/charmbracelet/x/ansi"
|
"github.com/charmbracelet/x/ansi"
|
||||||
|
"github.com/lucasb-eyer/go-colorful"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Profile is a color profile: NoTTY, Ascii, ANSI, ANSI256, or TrueColor.
|
// Profile is a color profile: NoTTY, Ascii, ANSI, ANSI256, or TrueColor.
|
||||||
type Profile byte
|
type Profile byte
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// NoTTY is a profile with no terminal support.
|
// NoTTY, not a terminal profile.
|
||||||
NoTTY Profile = iota
|
NoTTY Profile = iota
|
||||||
// Ascii is a profile with no color support.
|
// Ascii, uncolored profile.
|
||||||
Ascii //nolint:revive
|
Ascii //nolint:revive
|
||||||
// ANSI is a profile with 16 colors (4-bit).
|
// ANSI, 4-bit color profile.
|
||||||
ANSI
|
ANSI
|
||||||
// ANSI256 is a profile with 256 colors (8-bit).
|
// ANSI256, 8-bit color profile.
|
||||||
ANSI256
|
ANSI256
|
||||||
// TrueColor is a profile with 16 million colors (24-bit).
|
// TrueColor, 24-bit color profile.
|
||||||
TrueColor
|
TrueColor
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -40,61 +41,359 @@ func (p Profile) String() string {
|
|||||||
return "Unknown"
|
return "Unknown"
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
cache = map[Profile]map[color.Color]color.Color{
|
|
||||||
ANSI256: {},
|
|
||||||
ANSI: {},
|
|
||||||
}
|
|
||||||
mu sync.RWMutex
|
|
||||||
)
|
|
||||||
|
|
||||||
// Convert transforms a given Color to a Color supported within the Profile.
|
// Convert transforms a given Color to a Color supported within the Profile.
|
||||||
func (p Profile) Convert(c color.Color) (cc color.Color) {
|
func (p Profile) Convert(c color.Color) color.Color {
|
||||||
if p <= Ascii {
|
if p <= Ascii {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if p == TrueColor {
|
|
||||||
// TrueColor is a passthrough.
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do we have a cached color for this profile and color?
|
switch c := c.(type) {
|
||||||
mu.RLock()
|
|
||||||
if c != nil && cache[p] != nil {
|
|
||||||
if cc, ok := cache[p][c]; ok {
|
|
||||||
mu.RUnlock()
|
|
||||||
return cc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mu.RUnlock()
|
|
||||||
|
|
||||||
// If we don't have a cached color, we need to convert it and cache it.
|
|
||||||
defer func() {
|
|
||||||
mu.Lock()
|
|
||||||
if cc != nil && cache[p] != nil {
|
|
||||||
if _, ok := cache[p][c]; !ok {
|
|
||||||
cache[p][c] = cc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mu.Unlock()
|
|
||||||
}()
|
|
||||||
|
|
||||||
switch c.(type) {
|
|
||||||
case ansi.BasicColor:
|
case ansi.BasicColor:
|
||||||
return c
|
return c
|
||||||
|
|
||||||
case ansi.IndexedColor:
|
case ansi.ExtendedColor:
|
||||||
if p == ANSI {
|
if p == ANSI {
|
||||||
return ansi.Convert16(c)
|
return ansi256ToANSIColor(c)
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
|
|
||||||
default:
|
case ansi.TrueColor, color.Color:
|
||||||
if p == ANSI256 {
|
h, ok := colorful.MakeColor(c)
|
||||||
return ansi.Convert256(c)
|
if !ok {
|
||||||
} else if p == ANSI {
|
return nil
|
||||||
return ansi.Convert16(c)
|
}
|
||||||
|
if p != TrueColor {
|
||||||
|
ac := hexToANSI256Color(h)
|
||||||
|
if p == ANSI {
|
||||||
|
return ansi256ToANSIColor(ac)
|
||||||
|
}
|
||||||
|
return ac
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func hexToANSI256Color(c colorful.Color) ansi.ExtendedColor {
|
||||||
|
v2ci := func(v float64) int {
|
||||||
|
if v < 48 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if v < 115 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return int((v - 35) / 40)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the nearest 0-based color index at 16..231
|
||||||
|
r := v2ci(c.R * 255.0) // 0..5 each
|
||||||
|
g := v2ci(c.G * 255.0)
|
||||||
|
b := v2ci(c.B * 255.0)
|
||||||
|
ci := 36*r + 6*g + b /* 0..215 */
|
||||||
|
|
||||||
|
// Calculate the represented colors back from the index
|
||||||
|
i2cv := [6]int{0, 0x5f, 0x87, 0xaf, 0xd7, 0xff}
|
||||||
|
cr := i2cv[r] // r/g/b, 0..255 each
|
||||||
|
cg := i2cv[g]
|
||||||
|
cb := i2cv[b]
|
||||||
|
|
||||||
|
// Calculate the nearest 0-based gray index at 232..255
|
||||||
|
var grayIdx int
|
||||||
|
average := (cr + cg + cb) / 3
|
||||||
|
if average > 238 {
|
||||||
|
grayIdx = 23
|
||||||
|
} else {
|
||||||
|
grayIdx = (average - 3) / 10 // 0..23
|
||||||
|
}
|
||||||
|
gv := 8 + 10*grayIdx // same value for r/g/b, 0..255
|
||||||
|
|
||||||
|
// Return the one which is nearer to the original input rgb value
|
||||||
|
c2 := colorful.Color{R: float64(cr) / 255.0, G: float64(cg) / 255.0, B: float64(cb) / 255.0}
|
||||||
|
g2 := colorful.Color{R: float64(gv) / 255.0, G: float64(gv) / 255.0, B: float64(gv) / 255.0}
|
||||||
|
colorDist := c.DistanceHSLuv(c2)
|
||||||
|
grayDist := c.DistanceHSLuv(g2)
|
||||||
|
|
||||||
|
if colorDist <= grayDist {
|
||||||
|
return ansi.ExtendedColor(16 + ci) //nolint:gosec
|
||||||
|
}
|
||||||
|
return ansi.ExtendedColor(232 + grayIdx) //nolint:gosec
|
||||||
|
}
|
||||||
|
|
||||||
|
func ansi256ToANSIColor(c ansi.ExtendedColor) ansi.BasicColor {
|
||||||
|
var r int
|
||||||
|
md := math.MaxFloat64
|
||||||
|
|
||||||
|
h, _ := colorful.Hex(ansiHex[c])
|
||||||
|
for i := 0; i <= 15; i++ {
|
||||||
|
hb, _ := colorful.Hex(ansiHex[i])
|
||||||
|
d := h.DistanceHSLuv(hb)
|
||||||
|
|
||||||
|
if d < md {
|
||||||
|
md = d
|
||||||
|
r = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ansi.BasicColor(r) //nolint:gosec
|
||||||
|
}
|
||||||
|
|
||||||
|
// RGB values of ANSI colors (0-255).
|
||||||
|
var ansiHex = []string{
|
||||||
|
"#000000",
|
||||||
|
"#800000",
|
||||||
|
"#008000",
|
||||||
|
"#808000",
|
||||||
|
"#000080",
|
||||||
|
"#800080",
|
||||||
|
"#008080",
|
||||||
|
"#c0c0c0",
|
||||||
|
"#808080",
|
||||||
|
"#ff0000",
|
||||||
|
"#00ff00",
|
||||||
|
"#ffff00",
|
||||||
|
"#0000ff",
|
||||||
|
"#ff00ff",
|
||||||
|
"#00ffff",
|
||||||
|
"#ffffff",
|
||||||
|
"#000000",
|
||||||
|
"#00005f",
|
||||||
|
"#000087",
|
||||||
|
"#0000af",
|
||||||
|
"#0000d7",
|
||||||
|
"#0000ff",
|
||||||
|
"#005f00",
|
||||||
|
"#005f5f",
|
||||||
|
"#005f87",
|
||||||
|
"#005faf",
|
||||||
|
"#005fd7",
|
||||||
|
"#005fff",
|
||||||
|
"#008700",
|
||||||
|
"#00875f",
|
||||||
|
"#008787",
|
||||||
|
"#0087af",
|
||||||
|
"#0087d7",
|
||||||
|
"#0087ff",
|
||||||
|
"#00af00",
|
||||||
|
"#00af5f",
|
||||||
|
"#00af87",
|
||||||
|
"#00afaf",
|
||||||
|
"#00afd7",
|
||||||
|
"#00afff",
|
||||||
|
"#00d700",
|
||||||
|
"#00d75f",
|
||||||
|
"#00d787",
|
||||||
|
"#00d7af",
|
||||||
|
"#00d7d7",
|
||||||
|
"#00d7ff",
|
||||||
|
"#00ff00",
|
||||||
|
"#00ff5f",
|
||||||
|
"#00ff87",
|
||||||
|
"#00ffaf",
|
||||||
|
"#00ffd7",
|
||||||
|
"#00ffff",
|
||||||
|
"#5f0000",
|
||||||
|
"#5f005f",
|
||||||
|
"#5f0087",
|
||||||
|
"#5f00af",
|
||||||
|
"#5f00d7",
|
||||||
|
"#5f00ff",
|
||||||
|
"#5f5f00",
|
||||||
|
"#5f5f5f",
|
||||||
|
"#5f5f87",
|
||||||
|
"#5f5faf",
|
||||||
|
"#5f5fd7",
|
||||||
|
"#5f5fff",
|
||||||
|
"#5f8700",
|
||||||
|
"#5f875f",
|
||||||
|
"#5f8787",
|
||||||
|
"#5f87af",
|
||||||
|
"#5f87d7",
|
||||||
|
"#5f87ff",
|
||||||
|
"#5faf00",
|
||||||
|
"#5faf5f",
|
||||||
|
"#5faf87",
|
||||||
|
"#5fafaf",
|
||||||
|
"#5fafd7",
|
||||||
|
"#5fafff",
|
||||||
|
"#5fd700",
|
||||||
|
"#5fd75f",
|
||||||
|
"#5fd787",
|
||||||
|
"#5fd7af",
|
||||||
|
"#5fd7d7",
|
||||||
|
"#5fd7ff",
|
||||||
|
"#5fff00",
|
||||||
|
"#5fff5f",
|
||||||
|
"#5fff87",
|
||||||
|
"#5fffaf",
|
||||||
|
"#5fffd7",
|
||||||
|
"#5fffff",
|
||||||
|
"#870000",
|
||||||
|
"#87005f",
|
||||||
|
"#870087",
|
||||||
|
"#8700af",
|
||||||
|
"#8700d7",
|
||||||
|
"#8700ff",
|
||||||
|
"#875f00",
|
||||||
|
"#875f5f",
|
||||||
|
"#875f87",
|
||||||
|
"#875faf",
|
||||||
|
"#875fd7",
|
||||||
|
"#875fff",
|
||||||
|
"#878700",
|
||||||
|
"#87875f",
|
||||||
|
"#878787",
|
||||||
|
"#8787af",
|
||||||
|
"#8787d7",
|
||||||
|
"#8787ff",
|
||||||
|
"#87af00",
|
||||||
|
"#87af5f",
|
||||||
|
"#87af87",
|
||||||
|
"#87afaf",
|
||||||
|
"#87afd7",
|
||||||
|
"#87afff",
|
||||||
|
"#87d700",
|
||||||
|
"#87d75f",
|
||||||
|
"#87d787",
|
||||||
|
"#87d7af",
|
||||||
|
"#87d7d7",
|
||||||
|
"#87d7ff",
|
||||||
|
"#87ff00",
|
||||||
|
"#87ff5f",
|
||||||
|
"#87ff87",
|
||||||
|
"#87ffaf",
|
||||||
|
"#87ffd7",
|
||||||
|
"#87ffff",
|
||||||
|
"#af0000",
|
||||||
|
"#af005f",
|
||||||
|
"#af0087",
|
||||||
|
"#af00af",
|
||||||
|
"#af00d7",
|
||||||
|
"#af00ff",
|
||||||
|
"#af5f00",
|
||||||
|
"#af5f5f",
|
||||||
|
"#af5f87",
|
||||||
|
"#af5faf",
|
||||||
|
"#af5fd7",
|
||||||
|
"#af5fff",
|
||||||
|
"#af8700",
|
||||||
|
"#af875f",
|
||||||
|
"#af8787",
|
||||||
|
"#af87af",
|
||||||
|
"#af87d7",
|
||||||
|
"#af87ff",
|
||||||
|
"#afaf00",
|
||||||
|
"#afaf5f",
|
||||||
|
"#afaf87",
|
||||||
|
"#afafaf",
|
||||||
|
"#afafd7",
|
||||||
|
"#afafff",
|
||||||
|
"#afd700",
|
||||||
|
"#afd75f",
|
||||||
|
"#afd787",
|
||||||
|
"#afd7af",
|
||||||
|
"#afd7d7",
|
||||||
|
"#afd7ff",
|
||||||
|
"#afff00",
|
||||||
|
"#afff5f",
|
||||||
|
"#afff87",
|
||||||
|
"#afffaf",
|
||||||
|
"#afffd7",
|
||||||
|
"#afffff",
|
||||||
|
"#d70000",
|
||||||
|
"#d7005f",
|
||||||
|
"#d70087",
|
||||||
|
"#d700af",
|
||||||
|
"#d700d7",
|
||||||
|
"#d700ff",
|
||||||
|
"#d75f00",
|
||||||
|
"#d75f5f",
|
||||||
|
"#d75f87",
|
||||||
|
"#d75faf",
|
||||||
|
"#d75fd7",
|
||||||
|
"#d75fff",
|
||||||
|
"#d78700",
|
||||||
|
"#d7875f",
|
||||||
|
"#d78787",
|
||||||
|
"#d787af",
|
||||||
|
"#d787d7",
|
||||||
|
"#d787ff",
|
||||||
|
"#d7af00",
|
||||||
|
"#d7af5f",
|
||||||
|
"#d7af87",
|
||||||
|
"#d7afaf",
|
||||||
|
"#d7afd7",
|
||||||
|
"#d7afff",
|
||||||
|
"#d7d700",
|
||||||
|
"#d7d75f",
|
||||||
|
"#d7d787",
|
||||||
|
"#d7d7af",
|
||||||
|
"#d7d7d7",
|
||||||
|
"#d7d7ff",
|
||||||
|
"#d7ff00",
|
||||||
|
"#d7ff5f",
|
||||||
|
"#d7ff87",
|
||||||
|
"#d7ffaf",
|
||||||
|
"#d7ffd7",
|
||||||
|
"#d7ffff",
|
||||||
|
"#ff0000",
|
||||||
|
"#ff005f",
|
||||||
|
"#ff0087",
|
||||||
|
"#ff00af",
|
||||||
|
"#ff00d7",
|
||||||
|
"#ff00ff",
|
||||||
|
"#ff5f00",
|
||||||
|
"#ff5f5f",
|
||||||
|
"#ff5f87",
|
||||||
|
"#ff5faf",
|
||||||
|
"#ff5fd7",
|
||||||
|
"#ff5fff",
|
||||||
|
"#ff8700",
|
||||||
|
"#ff875f",
|
||||||
|
"#ff8787",
|
||||||
|
"#ff87af",
|
||||||
|
"#ff87d7",
|
||||||
|
"#ff87ff",
|
||||||
|
"#ffaf00",
|
||||||
|
"#ffaf5f",
|
||||||
|
"#ffaf87",
|
||||||
|
"#ffafaf",
|
||||||
|
"#ffafd7",
|
||||||
|
"#ffafff",
|
||||||
|
"#ffd700",
|
||||||
|
"#ffd75f",
|
||||||
|
"#ffd787",
|
||||||
|
"#ffd7af",
|
||||||
|
"#ffd7d7",
|
||||||
|
"#ffd7ff",
|
||||||
|
"#ffff00",
|
||||||
|
"#ffff5f",
|
||||||
|
"#ffff87",
|
||||||
|
"#ffffaf",
|
||||||
|
"#ffffd7",
|
||||||
|
"#ffffff",
|
||||||
|
"#080808",
|
||||||
|
"#121212",
|
||||||
|
"#1c1c1c",
|
||||||
|
"#262626",
|
||||||
|
"#303030",
|
||||||
|
"#3a3a3a",
|
||||||
|
"#444444",
|
||||||
|
"#4e4e4e",
|
||||||
|
"#585858",
|
||||||
|
"#626262",
|
||||||
|
"#6c6c6c",
|
||||||
|
"#767676",
|
||||||
|
"#808080",
|
||||||
|
"#8a8a8a",
|
||||||
|
"#949494",
|
||||||
|
"#9e9e9e",
|
||||||
|
"#a8a8a8",
|
||||||
|
"#b2b2b2",
|
||||||
|
"#bcbcbc",
|
||||||
|
"#c6c6c6",
|
||||||
|
"#d0d0d0",
|
||||||
|
"#dadada",
|
||||||
|
"#e4e4e4",
|
||||||
|
"#eeeeee",
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user