mirror of
https://github.com/ipfs/kubo.git
synced 2025-05-17 23:16:11 +08:00
feat: periodic version check and json config (#10438)
Co-authored-by: Lucas Molas <schomatis@gmail.com> Co-authored-by: Marcin Rataj <lidel@lidel.org>
This commit is contained in:
@ -1,9 +1,11 @@
|
|||||||
package kubo
|
package kubo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
_ "expvar"
|
_ "expvar"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
_ "net/http/pprof"
|
_ "net/http/pprof"
|
||||||
@ -438,9 +440,11 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment
|
|||||||
return fmt.Errorf("unrecognized routing option: %s", routingOption)
|
return fmt.Errorf("unrecognized routing option: %s", routingOption)
|
||||||
}
|
}
|
||||||
|
|
||||||
agentVersionSuffixString, _ := req.Options[agentVersionSuffix].(string)
|
// Set optional agent version suffix
|
||||||
if agentVersionSuffixString != "" {
|
versionSuffixFromCli, _ := req.Options[agentVersionSuffix].(string)
|
||||||
version.SetUserAgentSuffix(agentVersionSuffixString)
|
versionSuffix := cfg.Version.AgentSuffix.WithDefault(versionSuffixFromCli)
|
||||||
|
if versionSuffix != "" {
|
||||||
|
version.SetUserAgentSuffix(versionSuffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
node, err := core.NewNode(req.Context, ncfg)
|
node, err := core.NewNode(req.Context, ncfg)
|
||||||
@ -610,6 +614,15 @@ take effect.
|
|||||||
}
|
}
|
||||||
if len(peers) == 0 {
|
if len(peers) == 0 {
|
||||||
log.Error("failed to bootstrap (no peers found): consider updating Bootstrap or Peering section of your config")
|
log.Error("failed to bootstrap (no peers found): consider updating Bootstrap or Peering section of your config")
|
||||||
|
} else {
|
||||||
|
// After 1 minute we should have enough peers
|
||||||
|
// to run informed version check
|
||||||
|
startVersionChecker(
|
||||||
|
cctx.Context(),
|
||||||
|
node,
|
||||||
|
cfg.Version.SwarmCheckEnabled.WithDefault(true),
|
||||||
|
cfg.Version.SwarmCheckPercentThreshold.WithDefault(config.DefaultSwarmCheckPercentThreshold),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1056,3 +1069,41 @@ func printVersion() {
|
|||||||
fmt.Printf("System version: %s\n", runtime.GOARCH+"/"+runtime.GOOS)
|
fmt.Printf("System version: %s\n", runtime.GOARCH+"/"+runtime.GOOS)
|
||||||
fmt.Printf("Golang version: %s\n", runtime.Version())
|
fmt.Printf("Golang version: %s\n", runtime.Version())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func startVersionChecker(ctx context.Context, nd *core.IpfsNode, enabled bool, percentThreshold int64) {
|
||||||
|
if !enabled {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ticker := time.NewTicker(time.Hour)
|
||||||
|
defer ticker.Stop()
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
o, err := commands.DetectNewKuboVersion(nd, percentThreshold)
|
||||||
|
if err != nil {
|
||||||
|
// The version check is best-effort, and may fail in custom
|
||||||
|
// configurations that do not run standard WAN DHT. If it
|
||||||
|
// errors here, no point in spamming logs: og once and exit.
|
||||||
|
log.Errorw("initial version check failed, will not be run again", "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if o.UpdateAvailable {
|
||||||
|
newerPercent := fmt.Sprintf("%.0f%%", math.Round(float64(o.WithGreaterVersion)/float64(o.PeersSampled)*100))
|
||||||
|
log.Errorf(`
|
||||||
|
⚠️ A NEW VERSION OF KUBO DETECTED
|
||||||
|
|
||||||
|
This Kubo node is running an outdated version (%s).
|
||||||
|
%s of the sampled Kubo peers are running a higher version.
|
||||||
|
Visit https://github.com/ipfs/kubo/releases or https://dist.ipfs.tech/#kubo and update to version %s or later.`,
|
||||||
|
o.RunningVersion, newerPercent, o.GreatestVersion)
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case <-nd.Process.Closing():
|
||||||
|
return
|
||||||
|
case <-ticker.C:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
@ -37,6 +37,7 @@ type Config struct {
|
|||||||
Plugins Plugins
|
Plugins Plugins
|
||||||
Pinning Pinning
|
Pinning Pinning
|
||||||
Import Import
|
Import Import
|
||||||
|
Version Version
|
||||||
|
|
||||||
Internal Internal // experimental/unstable options
|
Internal Internal // experimental/unstable options
|
||||||
}
|
}
|
||||||
|
14
config/version.go
Normal file
14
config/version.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
const DefaultSwarmCheckPercentThreshold = 5
|
||||||
|
|
||||||
|
// Version allows controling things like custom user agent and update checks.
|
||||||
|
type Version struct {
|
||||||
|
// Optional suffix to the AgentVersion presented by `ipfs id` and exposed
|
||||||
|
// via libp2p identify protocol.
|
||||||
|
AgentSuffix *OptionalString `json:",omitempty"`
|
||||||
|
|
||||||
|
// Detect when to warn about new version when observed via libp2p identify
|
||||||
|
SwarmCheckEnabled Flag `json:",omitempty"`
|
||||||
|
SwarmCheckPercentThreshold *OptionalInteger `json:",omitempty"`
|
||||||
|
}
|
@ -199,6 +199,7 @@ func TestCommands(t *testing.T) {
|
|||||||
"/swarm/resources",
|
"/swarm/resources",
|
||||||
"/update",
|
"/update",
|
||||||
"/version",
|
"/version",
|
||||||
|
"/version/check",
|
||||||
"/version/deps",
|
"/version/deps",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,17 +5,25 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
|
"strings"
|
||||||
|
|
||||||
version "github.com/ipfs/kubo"
|
versioncmp "github.com/hashicorp/go-version"
|
||||||
|
|
||||||
cmds "github.com/ipfs/go-ipfs-cmds"
|
cmds "github.com/ipfs/go-ipfs-cmds"
|
||||||
|
version "github.com/ipfs/kubo"
|
||||||
|
"github.com/ipfs/kubo/config"
|
||||||
|
"github.com/ipfs/kubo/core"
|
||||||
|
"github.com/ipfs/kubo/core/commands/cmdenv"
|
||||||
|
"github.com/libp2p/go-libp2p-kad-dht/fullrt"
|
||||||
|
peer "github.com/libp2p/go-libp2p/core/peer"
|
||||||
|
pstore "github.com/libp2p/go-libp2p/core/peerstore"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
versionNumberOptionName = "number"
|
versionNumberOptionName = "number"
|
||||||
versionCommitOptionName = "commit"
|
versionCommitOptionName = "commit"
|
||||||
versionRepoOptionName = "repo"
|
versionRepoOptionName = "repo"
|
||||||
versionAllOptionName = "all"
|
versionAllOptionName = "all"
|
||||||
|
versionCheckThresholdOptionName = "min-percent"
|
||||||
)
|
)
|
||||||
|
|
||||||
var VersionCmd = &cmds.Command{
|
var VersionCmd = &cmds.Command{
|
||||||
@ -24,7 +32,8 @@ var VersionCmd = &cmds.Command{
|
|||||||
ShortDescription: "Returns the current version of IPFS and exits.",
|
ShortDescription: "Returns the current version of IPFS and exits.",
|
||||||
},
|
},
|
||||||
Subcommands: map[string]*cmds.Command{
|
Subcommands: map[string]*cmds.Command{
|
||||||
"deps": depsVersionCommand,
|
"deps": depsVersionCommand,
|
||||||
|
"check": checkVersionCommand,
|
||||||
},
|
},
|
||||||
|
|
||||||
Options: []cmds.Option{
|
Options: []cmds.Option{
|
||||||
@ -130,3 +139,161 @@ Print out all dependencies and their versions.`,
|
|||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DefaultMinimalVersionFraction = 0.05 // 5%
|
||||||
|
|
||||||
|
type VersionCheckOutput struct {
|
||||||
|
UpdateAvailable bool
|
||||||
|
RunningVersion string
|
||||||
|
GreatestVersion string
|
||||||
|
PeersSampled int
|
||||||
|
WithGreaterVersion int
|
||||||
|
}
|
||||||
|
|
||||||
|
var checkVersionCommand = &cmds.Command{
|
||||||
|
Helptext: cmds.HelpText{
|
||||||
|
Tagline: "Checks Kubo version against connected peers.",
|
||||||
|
ShortDescription: `
|
||||||
|
This command uses the libp2p identify protocol to check the 'AgentVersion'
|
||||||
|
of connected peers and see if the Kubo version we're running is outdated.
|
||||||
|
|
||||||
|
Peers with an AgentVersion that doesn't start with 'kubo/' are ignored.
|
||||||
|
'UpdateAvailable' is set to true only if the 'min-fraction' criteria are met.
|
||||||
|
|
||||||
|
The 'ipfs daemon' does the same check regularly and logs when a new version
|
||||||
|
is available. You can stop these regular checks by setting
|
||||||
|
Version.SwarmCheckEnabled:false in the config.
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
Options: []cmds.Option{
|
||||||
|
cmds.IntOption(versionCheckThresholdOptionName, "t", "Percentage (1-100) of sampled peers with the new Kubo version needed to trigger an update warning.").WithDefault(config.DefaultSwarmCheckPercentThreshold),
|
||||||
|
},
|
||||||
|
Type: VersionCheckOutput{},
|
||||||
|
|
||||||
|
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
|
||||||
|
nd, err := cmdenv.GetNode(env)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !nd.IsOnline {
|
||||||
|
return ErrNotOnline
|
||||||
|
}
|
||||||
|
|
||||||
|
minPercent, _ := req.Options[versionCheckThresholdOptionName].(int64)
|
||||||
|
output, err := DetectNewKuboVersion(nd, minPercent)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cmds.EmitOnce(res, output); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// DetectNewKuboVersion observers kubo version reported by other peers via
|
||||||
|
// libp2p identify protocol and notifies when threshold fraction of seen swarm
|
||||||
|
// is running updated Kubo. It is used by RPC and CLI at 'ipfs version check'
|
||||||
|
// and also periodically when 'ipfs daemon' is running.
|
||||||
|
func DetectNewKuboVersion(nd *core.IpfsNode, minPercent int64) (VersionCheckOutput, error) {
|
||||||
|
ourVersion, err := versioncmp.NewVersion(version.CurrentVersionNumber)
|
||||||
|
if err != nil {
|
||||||
|
return VersionCheckOutput{}, fmt.Errorf("could not parse our own version %q: %w",
|
||||||
|
version.CurrentVersionNumber, err)
|
||||||
|
}
|
||||||
|
// MAJOR.MINOR.PATCH without any suffix
|
||||||
|
ourVersion = ourVersion.Core()
|
||||||
|
|
||||||
|
greatestVersionSeen := ourVersion
|
||||||
|
totalPeersSampled := 1 // Us (and to avoid division-by-zero edge case)
|
||||||
|
withGreaterVersion := 0
|
||||||
|
|
||||||
|
recordPeerVersion := func(agentVersion string) {
|
||||||
|
// We process the version as is it assembled in GetUserAgentVersion
|
||||||
|
segments := strings.Split(agentVersion, "/")
|
||||||
|
if len(segments) < 2 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if segments[0] != "kubo" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
versionNumber := segments[1] // As in our CurrentVersionNumber
|
||||||
|
|
||||||
|
peerVersion, err := versioncmp.NewVersion(versionNumber)
|
||||||
|
if err != nil {
|
||||||
|
// Do not error on invalid remote versions, just ignore
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore prerelases and development releases (-dev, -rcX)
|
||||||
|
if peerVersion.Metadata() != "" || peerVersion.Prerelease() != "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// MAJOR.MINOR.PATCH without any suffix
|
||||||
|
peerVersion = peerVersion.Core()
|
||||||
|
|
||||||
|
// Valid peer version number
|
||||||
|
totalPeersSampled += 1
|
||||||
|
if ourVersion.LessThan(peerVersion) {
|
||||||
|
withGreaterVersion += 1
|
||||||
|
}
|
||||||
|
if peerVersion.GreaterThan(greatestVersionSeen) {
|
||||||
|
greatestVersionSeen = peerVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processPeerstoreEntry := func(id peer.ID) {
|
||||||
|
if v, err := nd.Peerstore.Get(id, "AgentVersion"); err == nil {
|
||||||
|
recordPeerVersion(v.(string))
|
||||||
|
} else if errors.Is(err, pstore.ErrNotFound) { // ignore noop
|
||||||
|
} else { // a bug, usually.
|
||||||
|
log.Errorw("failed to get agent version from peerstore", "error", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Amino DHT client keeps information about previously seen peers
|
||||||
|
if nd.DHTClient != nd.DHT && nd.DHTClient != nil {
|
||||||
|
client, ok := nd.DHTClient.(*fullrt.FullRT)
|
||||||
|
if !ok {
|
||||||
|
return VersionCheckOutput{}, errors.New("could not perform version check due to missing or incompatible DHT configuration")
|
||||||
|
}
|
||||||
|
for _, p := range client.Stat() {
|
||||||
|
processPeerstoreEntry(p)
|
||||||
|
}
|
||||||
|
} else if nd.DHT != nil && nd.DHT.WAN != nil {
|
||||||
|
for _, pi := range nd.DHT.WAN.RoutingTable().GetPeerInfos() {
|
||||||
|
processPeerstoreEntry(pi.Id)
|
||||||
|
}
|
||||||
|
} else if nd.DHT != nil && nd.DHT.LAN != nil {
|
||||||
|
for _, pi := range nd.DHT.LAN.RoutingTable().GetPeerInfos() {
|
||||||
|
processPeerstoreEntry(pi.Id)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return VersionCheckOutput{}, errors.New("could not perform version check due to missing or incompatible DHT configuration")
|
||||||
|
}
|
||||||
|
|
||||||
|
if minPercent < 1 || minPercent > 100 {
|
||||||
|
if minPercent == 0 {
|
||||||
|
minPercent = config.DefaultSwarmCheckPercentThreshold
|
||||||
|
} else {
|
||||||
|
return VersionCheckOutput{}, errors.New("Version.SwarmCheckPercentThreshold must be between 1 and 100")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
minFraction := float64(minPercent) / 100.0
|
||||||
|
|
||||||
|
// UpdateAvailable flag is set only if minFraction was reached
|
||||||
|
greaterFraction := float64(withGreaterVersion) / float64(totalPeersSampled)
|
||||||
|
|
||||||
|
// Gathered metric are returned every time
|
||||||
|
return VersionCheckOutput{
|
||||||
|
UpdateAvailable: (greaterFraction >= minFraction),
|
||||||
|
RunningVersion: ourVersion.String(),
|
||||||
|
GreatestVersion: greatestVersionSeen.String(),
|
||||||
|
PeersSampled: totalPeersSampled,
|
||||||
|
WithGreaterVersion: withGreaterVersion,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
- [Overview](#overview)
|
- [Overview](#overview)
|
||||||
- [🔦 Highlights](#-highlights)
|
- [🔦 Highlights](#-highlights)
|
||||||
|
- [Automated `ipfs version check`](#automated-ipfs-version-check)
|
||||||
|
- [Version Suffix Configuration](#version-suffix-configuration)
|
||||||
- [📝 Changelog](#-changelog)
|
- [📝 Changelog](#-changelog)
|
||||||
- [👨👩👧👦 Contributors](#-contributors)
|
- [👨👩👧👦 Contributors](#-contributors)
|
||||||
|
|
||||||
@ -13,6 +15,21 @@
|
|||||||
|
|
||||||
### 🔦 Highlights
|
### 🔦 Highlights
|
||||||
|
|
||||||
|
#### Automated `ipfs version check`
|
||||||
|
|
||||||
|
Kubo now performs privacy-preserving version checks using the [libp2p identify protocol](https://github.com/libp2p/specs/blob/master/identify/README.md) on peers detected by the Amino DHT client.
|
||||||
|
If more than 5% of Kubo peers seen by your node are running a newer version, you will receive a log message notification.
|
||||||
|
|
||||||
|
- For manual checks, refer to `ipfs version check --help` for details.
|
||||||
|
- To disable automated checks, set [`Version.SwarmCheckEnabled`](https://github.com/ipfs/kubo/blob/master/docs/config.md#versionswarmcheckenabled) to `false`.
|
||||||
|
|
||||||
|
#### Version Suffix Configuration
|
||||||
|
|
||||||
|
Defining the optional agent version suffix is now simpler. The [`Version.AgentSuffix`](https://github.com/ipfs/kubo/blob/master/docs/config.md#agentsuffix) value from the Kubo config takes precedence over any value provided via `ipfs daemon --agent-version-suffix` (which is still supported).
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Setting a custom version suffix helps with ecosystem analysis, such as Amino DHT reports published at https://stats.ipfs.network
|
||||||
|
|
||||||
### 📝 Changelog
|
### 📝 Changelog
|
||||||
|
|
||||||
### 👨👩👧👦 Contributors
|
### 👨👩👧👦 Contributors
|
||||||
|
@ -180,6 +180,10 @@ config file at runtime.
|
|||||||
- [`Import.UnixFSRawLeaves`](#importunixfsrawleaves)
|
- [`Import.UnixFSRawLeaves`](#importunixfsrawleaves)
|
||||||
- [`Import.UnixFSChunker`](#importunixfschunker)
|
- [`Import.UnixFSChunker`](#importunixfschunker)
|
||||||
- [`Import.HashFunction`](#importhashfunction)
|
- [`Import.HashFunction`](#importhashfunction)
|
||||||
|
- [`Version`](#version)
|
||||||
|
- [`Version.AgentSuffix`](#versionagentsuffix)
|
||||||
|
- [`Version.SwarmCheckEnabled`](#versionswarmcheckenabled)
|
||||||
|
- [`Version.SwarmCheckPercentThreshold`](#versionswarmcheckpercentthreshold)
|
||||||
|
|
||||||
## Profiles
|
## Profiles
|
||||||
|
|
||||||
@ -2435,3 +2439,39 @@ The default hash function. Commands affected: `ipfs add`, `ipfs block put`, `ipf
|
|||||||
Default: `sha2-256`
|
Default: `sha2-256`
|
||||||
|
|
||||||
Type: `optionalString`
|
Type: `optionalString`
|
||||||
|
|
||||||
|
## `Version`
|
||||||
|
|
||||||
|
Options to configure agent version announced to the swarm, and leveraging
|
||||||
|
other peers version for detecting when there is time to update.
|
||||||
|
|
||||||
|
### `Version.AgentSuffix`
|
||||||
|
|
||||||
|
Optional suffix to the AgentVersion presented by `ipfs id` and exposed via [libp2p identify protocol](https://github.com/libp2p/specs/blob/master/identify/README.md#agentversion).
|
||||||
|
|
||||||
|
The value from config takes precedence over value passed via `ipfs daemon --agent-version-suffix`.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Setting a custom version suffix helps with ecosystem analysis, such as Amino DHT reports published at https://stats.ipfs.network
|
||||||
|
|
||||||
|
Default: `""` (no suffix, or value from `ipfs daemon --agent-version-suffix=`)
|
||||||
|
|
||||||
|
Type: `optionalString`
|
||||||
|
|
||||||
|
### `Version.SwarmCheckEnabled`
|
||||||
|
|
||||||
|
Observe the AgentVersion of swarm peers and log warning when
|
||||||
|
`SwarmCheckPercentThreshold` of peers runs version higher than this node.
|
||||||
|
|
||||||
|
Default: `true`
|
||||||
|
|
||||||
|
Type: `flag`
|
||||||
|
|
||||||
|
### `Version.SwarmCheckPercentThreshold`
|
||||||
|
|
||||||
|
Control the percentage of `kubo/` peers running new version required to
|
||||||
|
trigger update warning.
|
||||||
|
|
||||||
|
Default: `5`
|
||||||
|
|
||||||
|
Type: `optionalInteger` (1-100)
|
||||||
|
1
go.mod
1
go.mod
@ -15,6 +15,7 @@ require (
|
|||||||
github.com/fsnotify/fsnotify v1.6.0
|
github.com/fsnotify/fsnotify v1.6.0
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/hashicorp/go-multierror v1.1.1
|
github.com/hashicorp/go-multierror v1.1.1
|
||||||
|
github.com/hashicorp/go-version v1.6.0
|
||||||
github.com/ipfs-shipyard/nopfs v0.0.12
|
github.com/ipfs-shipyard/nopfs v0.0.12
|
||||||
github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c
|
github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c
|
||||||
github.com/ipfs/boxo v0.21.0
|
github.com/ipfs/boxo v0.21.0
|
||||||
|
2
go.sum
2
go.sum
@ -310,6 +310,8 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY
|
|||||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||||
|
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
|
||||||
|
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
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/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
|
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
|
||||||
|
@ -65,5 +65,16 @@ iptb stop
|
|||||||
|
|
||||||
test_kill_ipfs_daemon
|
test_kill_ipfs_daemon
|
||||||
|
|
||||||
|
# Version.AgentSuffix overrides --agent-version-suffix (local, offline)
|
||||||
|
test_expect_success "setting Version.AgentSuffix in config" '
|
||||||
|
ipfs config Version.AgentSuffix json-config-suffix
|
||||||
|
'
|
||||||
|
test_launch_ipfs_daemon --agent-version-suffix=ignored-cli-suffix
|
||||||
|
test_expect_success "checking AgentVersion with suffix set via JSON config" '
|
||||||
|
test_id_compute_agent json-config-suffix > expected-agent-version &&
|
||||||
|
ipfs id -f "<aver>\n" > actual-agent-version &&
|
||||||
|
test_cmp expected-agent-version actual-agent-version
|
||||||
|
'
|
||||||
|
test_kill_ipfs_daemon
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Reference in New Issue
Block a user