check / check (push) Failing after 3s
REPO_POLICIES.md requires the module root sneak.berlin/go/<name>. go.mod, every import (rewritten with gofmt -r), the -X flags in script/build and the examples in the pkg READMEs now use the new path. go mod tidy lists go-humanize and fatih/color as direct requirements, since internal/cli imports them. This breaks anyone who fetched or imported git.eeqj.de/sneak/secret: they must switch to sneak.berlin/go/secret, which resolves to this repository. Model: opus-5-5
75 lines
2.4 KiB
Go
75 lines
2.4 KiB
Go
package cli_test
|
|
|
|
import (
|
|
"io"
|
|
"testing"
|
|
|
|
"github.com/spf13/afero"
|
|
"github.com/spf13/cobra"
|
|
"github.com/stretchr/testify/require"
|
|
"sneak.berlin/go/secret/internal/cli"
|
|
"sneak.berlin/go/secret/internal/secret"
|
|
"sneak.berlin/go/secret/internal/vault"
|
|
)
|
|
|
|
// TestLeftoversRemovedByNextChangingCommand is a regression test for
|
|
// https://git.eeqj.de/sneak/secret/issues/75. It plants what a command
|
|
// killed part-way leaves in each directory where secret.TempDirFor and
|
|
// secret.WriteFileAtomic make temporary entries: a temporary directory
|
|
// holding a vault, secret, unlocker or version being added or removed, and
|
|
// a temporary file beside a file being replaced. `secret list` must leave
|
|
// them all, and the next command that takes the state directory lock, here
|
|
// `secret vault select` of the vault already current, must delete exactly
|
|
// them: a vault named like a temporary directory stays. The copy has no
|
|
// lock file yet, so that command, as after a killed one, finds no mark that
|
|
// the last holder of the lock finished.
|
|
func TestLeftoversRemovedByNextChangingCommand(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
fs := newTwoVaultFs(t)
|
|
|
|
_, err := vault.CreateVault(fs, testStateDir, ".tmp-0", nil, nil)
|
|
require.NoError(t, err)
|
|
require.NoError(t, vault.SelectVault(fs, testStateDir, "default"))
|
|
|
|
before := snapshotStateDir(t, fs)
|
|
|
|
vaultDir := testStateDir + "/vaults.d/default"
|
|
secretDir := vaultDir + "/secrets.d/x"
|
|
|
|
versions, err := secret.ListVersions(fs, secretDir)
|
|
require.NoError(t, err)
|
|
require.Len(t, versions, 1)
|
|
|
|
for _, dir := range []string{
|
|
testStateDir + "/.tmp-1/default",
|
|
vaultDir + "/.tmp-2/x",
|
|
secretDir + "/.tmp-3/" + testVersion,
|
|
} {
|
|
require.NoError(t, fs.MkdirAll(dir, secret.DirPerms))
|
|
require.NoError(t, afero.WriteFile(fs, dir+"/value.age",
|
|
[]byte("encrypted"), secret.FilePerms))
|
|
}
|
|
|
|
for _, file := range []string{
|
|
testStateDir + "/.currentvault.tmp-4",
|
|
vaultDir + "/.current-unlocker.tmp-5",
|
|
secretDir + "/.current.tmp-6",
|
|
secretDir + "/versions/" + versions[0] + "/.metadata.age.tmp-7",
|
|
} {
|
|
require.NoError(t, afero.WriteFile(fs, file,
|
|
[]byte("partial"), secret.FilePerms))
|
|
}
|
|
|
|
planted := snapshotStateDir(t, fs)
|
|
c := cli.NewCLIInstanceWithStateDir(fs, testStateDir)
|
|
cmd := &cobra.Command{}
|
|
cmd.SetOut(io.Discard)
|
|
|
|
require.NoError(t, c.ListSecrets(cmd, false, false, ""))
|
|
require.Equal(t, planted, snapshotStateDir(t, fs))
|
|
|
|
require.NoError(t, c.SelectVault(cmd, "default"))
|
|
require.Equal(t, before, snapshotStateDir(t, fs))
|
|
}
|