1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-07-01 10:49:24 +08:00

feat: add dry-run flag for config profile apply command

License: MIT
Signed-off-by: chenminjian <727180553@qq.com>
This commit is contained in:
chenminjian
2018-09-13 16:39:28 +08:00
committed by Steven Allen
parent dcecab6854
commit 2e3cbe3e27
3 changed files with 111 additions and 11 deletions

View File

@ -16,10 +16,17 @@ import (
repo "github.com/ipfs/go-ipfs/repo" repo "github.com/ipfs/go-ipfs/repo"
fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo" fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo"
"gx/ipfs/QmP2i47tnU23ijdshrZtuvrSkQPtf9HhsMb9fwGVe8owj2/jsondiff"
config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config" config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config"
"gx/ipfs/Qmde5VP1qUkyQXKCfmEUA7bP64V2HAptbJ7phuPp7jXWwg/go-ipfs-cmdkit" "gx/ipfs/Qmde5VP1qUkyQXKCfmEUA7bP64V2HAptbJ7phuPp7jXWwg/go-ipfs-cmdkit"
) )
// ConfigUpdateOutput is config profile apply command's output
type ConfigUpdateOutput struct {
Old config.Config
New config.Config
}
type ConfigField struct { type ConfigField struct {
Key string Key string
Value interface{} Value interface{}
@ -333,6 +340,9 @@ var configProfileApplyCmd = &cmds.Command{
Helptext: cmdkit.HelpText{ Helptext: cmdkit.HelpText{
Tagline: "Apply profile to config.", Tagline: "Apply profile to config.",
}, },
Options: []cmdkit.Option{
cmdkit.BoolOption("dry-run", "print difference between the current config and the config that would be generated"),
},
Arguments: []cmdkit.Argument{ Arguments: []cmdkit.Argument{
cmdkit.StringArg("profile", true, false, "The profile to apply to the config."), cmdkit.StringArg("profile", true, false, "The profile to apply to the config."),
}, },
@ -343,13 +353,40 @@ var configProfileApplyCmd = &cmds.Command{
return return
} }
err := transformConfig(req.InvocContext().ConfigRoot, req.Arguments()[0], profile.Transform) dryRun, _, _ := req.Option("dry-run").Bool()
oldCfg, newCfg, err := transformConfig(req.InvocContext().ConfigRoot, req.Arguments()[0], profile.Transform, dryRun)
if err != nil { if err != nil {
res.SetError(err, cmdkit.ErrNormal) res.SetError(err, cmdkit.ErrNormal)
return return
} }
res.SetOutput(nil) res.SetOutput(&ConfigUpdateOutput{
Old: *oldCfg,
New: *newCfg,
})
}, },
Marshalers: cmds.MarshalerMap{
cmds.Text: func(res cmds.Response) (io.Reader, error) {
if res.Error() != nil {
return nil, res.Error()
}
v, err := unwrapOutput(res.Output())
if err != nil {
return nil, err
}
apply, ok := v.(*ConfigUpdateOutput)
if !ok {
return nil, e.TypeErr(apply, v)
}
diff := jsondiff.Compare(apply.Old, apply.New)
buf := jsondiff.Format(diff)
return strings.NewReader(string(buf)), nil
},
},
Type: ConfigUpdateOutput{},
} }
func buildProfileHelp() string { func buildProfileHelp() string {
@ -367,29 +404,44 @@ func buildProfileHelp() string {
return out return out
} }
func transformConfig(configRoot string, configName string, transformer config.Transformer) error { // transformConfig returns old config and new config instead of difference between they,
// because apply command can provide stable API through this way.
// If dryRun is true, repo's config should not be updated and persisted
// to storage. Otherwise, repo's config should be updated and persisted
// to storage.
func transformConfig(configRoot string, configName string, transformer config.Transformer, dryRun bool) (*config.Config, *config.Config, error) {
r, err := fsrepo.Open(configRoot) r, err := fsrepo.Open(configRoot)
if err != nil { if err != nil {
return err return nil, nil, err
} }
defer r.Close() defer r.Close()
cfg, err := r.Config() cfg, err := r.Config()
if err != nil { if err != nil {
return err return nil, nil, err
} }
err = transformer(cfg) // make a copy to avoid updating repo's config unintentionally
oldCfg := *cfg
newCfg := oldCfg
err = transformer(&newCfg)
if err != nil { if err != nil {
return err return nil, nil, err
} }
_, err = r.BackupConfig("pre-" + configName + "-") if !dryRun {
if err != nil { _, err = r.BackupConfig("pre-" + configName + "-")
return err if err != nil {
return nil, nil, err
}
err = r.SetConfig(&newCfg)
if err != nil {
return nil, nil, err
}
} }
return r.SetConfig(cfg) return &oldCfg, &newCfg, nil
} }
func getConfig(r repo.Repo, key string) (*ConfigField, error) { func getConfig(r repo.Repo, key string) (*ConfigField, error) {

View File

@ -552,6 +552,12 @@
"name": "go-multiaddr-dns", "name": "go-multiaddr-dns",
"version": "0.2.4" "version": "0.2.4"
}, },
{
"author": "elgris",
"hash": "QmP2i47tnU23ijdshrZtuvrSkQPtf9HhsMb9fwGVe8owj2",
"name": "jsondiff",
"version": "0.0.0"
},
{ {
"author": "marten-seemann", "author": "marten-seemann",
"hash": "QmNtLLJMc7TDMSaNuJVFipxLji9NL56QyMnBBPk2X58Mno", "hash": "QmNtLLJMc7TDMSaNuJVFipxLji9NL56QyMnBBPk2X58Mno",

View File

@ -75,6 +75,17 @@ test_profile_apply_revert() {
' '
} }
test_profile_apply_dry_run_not_alter() {
profile=$1
test_expect_success "'ipfs config profile apply ${profile} --dry-run' doesn't alter config" '
cat "$IPFS_PATH/config" >expected &&
ipfs config profile apply '${profile}' --dry-run &&
cat "$IPFS_PATH/config" >actual &&
test_cmp expected actual
'
}
test_config_cmd() { test_config_cmd() {
test_config_cmd_set "beep" "boop" test_config_cmd_set "beep" "boop"
test_config_cmd_set "beep1" "boop2" test_config_cmd_set "beep1" "boop2"
@ -220,6 +231,37 @@ test_config_cmd() {
# need to do this in reverse as the test profile is already applied in sharness # need to do this in reverse as the test profile is already applied in sharness
test_profile_apply_revert default-networking test test_profile_apply_revert default-networking test
test_profile_apply_dry_run_not_alter server
test_profile_apply_dry_run_not_alter local-discovery
test_profile_apply_dry_run_not_alter test
test_expect_success "'ipfs config profile apply local-discovery --dry-run' looks good with different profile info" '
ipfs config profile apply local-discovery --dry-run > diff_info &&
test `grep "DisableNatPortMap" diff_info | wc -l` = 2
'
test_expect_success "'ipfs config profile apply server --dry-run' looks good with same profile info" '
ipfs config profile apply server --dry-run > diff_info &&
test `grep "DisableNatPortMap" diff_info | wc -l` = 1
'
test_expect_success "'ipfs config profile apply server' looks good with same profile info" '
ipfs config profile apply server > diff_info &&
test `grep "DisableNatPortMap" diff_info | wc -l` = 1
'
test_expect_success "'ipfs config profile apply local-discovery' looks good with different profile info" '
ipfs config profile apply local-discovery > diff_info &&
test `grep "DisableNatPortMap" diff_info | wc -l` = 2
'
test_expect_success "'ipfs config profile apply test' looks good with different profile info" '
ipfs config profile apply test > diff_info &&
test `grep "DisableNatPortMap" diff_info | wc -l` = 2
'
# won't work as it changes datastore definition, which makes ipfs not launch # won't work as it changes datastore definition, which makes ipfs not launch
# without converting first # without converting first
# test_profile_apply_revert badgerds # test_profile_apply_revert badgerds