@cryptotaxi247 / kubo / commits / 2e3cbe3e2

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

License: MIT Signed-off-by: chenminjian <727180553@qq.com>

chenminjian committed Sep 13, 2018 at 16:39 UTC 2e3cbe3e27a2db90a1b99080af3c7847f0f0d930
3 files changed +111 -11
core/commands/config.go
+63 -11
@@ -16,10 +16,17 @@ import (
16 repo "github.com/ipfs/go-ipfs/repo"
17 fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo"
18
19 + "gx/ipfs/QmP2i47tnU23ijdshrZtuvrSkQPtf9HhsMb9fwGVe8owj2/jsondiff"
20 config "gx/ipfs/QmSoYrBMibm2T3LupaLuez7LPGnyrJwdRxvTfPUyCp691u/go-ipfs-config"
21 "gx/ipfs/Qmde5VP1qUkyQXKCfmEUA7bP64V2HAptbJ7phuPp7jXWwg/go-ipfs-cmdkit"
22 )
23
24 +// ConfigUpdateOutput is config profile apply command's output
25 +type ConfigUpdateOutput struct {
26 + Old config.Config
27 + New config.Config
28 +}
29 +
30 type ConfigField struct {
31 Key string
32 Value interface{}
@@ -333,6 +340,9 @@ var configProfileApplyCmd = &cmds.Command{
340 Helptext: cmdkit.HelpText{
341 Tagline: "Apply profile to config.",
342 },
343 + Options: []cmdkit.Option{
344 + cmdkit.BoolOption("dry-run", "print difference between the current config and the config that would be generated"),
345 + },
346 Arguments: []cmdkit.Argument{
347 cmdkit.StringArg("profile", true, false, "The profile to apply to the config."),
348 },
@@ -343,13 +353,40 @@ var configProfileApplyCmd = &cmds.Command{
353 return
354 }
355
346 - err := transformConfig(req.InvocContext().ConfigRoot, req.Arguments()[0], profile.Transform)
356 + dryRun, _, _ := req.Option("dry-run").Bool()
357 + oldCfg, newCfg, err := transformConfig(req.InvocContext().ConfigRoot, req.Arguments()[0], profile.Transform, dryRun)
358 if err != nil {
359 res.SetError(err, cmdkit.ErrNormal)
360 return
361 }
351 - res.SetOutput(nil)
362 + res.SetOutput(&ConfigUpdateOutput{
363 + Old: *oldCfg,
364 + New: *newCfg,
365 + })
366 + },
367 + Marshalers: cmds.MarshalerMap{
368 + cmds.Text: func(res cmds.Response) (io.Reader, error) {
369 + if res.Error() != nil {
370 + return nil, res.Error()
371 + }
372 +
373 + v, err := unwrapOutput(res.Output())
374 + if err != nil {
375 + return nil, err
376 + }
377 +
378 + apply, ok := v.(*ConfigUpdateOutput)
379 + if !ok {
380 + return nil, e.TypeErr(apply, v)
381 + }
382 +
383 + diff := jsondiff.Compare(apply.Old, apply.New)
384 + buf := jsondiff.Format(diff)
385 +
386 + return strings.NewReader(string(buf)), nil
387 + },
388 },
389 + Type: ConfigUpdateOutput{},
390 }
391
392 func buildProfileHelp() string {
@@ -367,29 +404,44 @@ func buildProfileHelp() string {
404 return out
405 }
406
370 -func transformConfig(configRoot string, configName string, transformer config.Transformer) error {
407 +// transformConfig returns old config and new config instead of difference between they,
408 +// because apply command can provide stable API through this way.
409 +// If dryRun is true, repo's config should not be updated and persisted
410 +// to storage. Otherwise, repo's config should be updated and persisted
411 +// to storage.
412 +func transformConfig(configRoot string, configName string, transformer config.Transformer, dryRun bool) (*config.Config, *config.Config, error) {
413 r, err := fsrepo.Open(configRoot)
414 if err != nil {
373 - return err
415 + return nil, nil, err
416 }
417 defer r.Close()
418
419 cfg, err := r.Config()
420 if err != nil {
379 - return err
421 + return nil, nil, err
422 }
423
382 - err = transformer(cfg)
424 + // make a copy to avoid updating repo's config unintentionally
425 + oldCfg := *cfg
426 + newCfg := oldCfg
427 + err = transformer(&newCfg)
428 if err != nil {
384 - return err
429 + return nil, nil, err
430 }
431
387 - _, err = r.BackupConfig("pre-" + configName + "-")
388 - if err != nil {
389 - return err
432 + if !dryRun {
433 + _, err = r.BackupConfig("pre-" + configName + "-")
434 + if err != nil {
435 + return nil, nil, err
436 + }
437 +
438 + err = r.SetConfig(&newCfg)
439 + if err != nil {
440 + return nil, nil, err
441 + }
442 }
443
392 - return r.SetConfig(cfg)
444 + return &oldCfg, &newCfg, nil
445 }
446
447 func getConfig(r repo.Repo, key string) (*ConfigField, error) {
package.json
+6
@@ -552,6 +552,12 @@
552 "name": "go-multiaddr-dns",
553 "version": "0.2.4"
554 },
555 + {
556 + "author": "elgris",
557 + "hash": "QmP2i47tnU23ijdshrZtuvrSkQPtf9HhsMb9fwGVe8owj2",
558 + "name": "jsondiff",
559 + "version": "0.0.0"
560 + },
561 {
562 "author": "marten-seemann",
563 "hash": "QmNtLLJMc7TDMSaNuJVFipxLji9NL56QyMnBBPk2X58Mno",
test/sharness/t0021-config.sh
+42
@@ -75,6 +75,17 @@ test_profile_apply_revert() {
75 '
76 }
77
78 +test_profile_apply_dry_run_not_alter() {
79 + profile=$1
80 +
81 + test_expect_success "'ipfs config profile apply ${profile} --dry-run' doesn't alter config" '
82 + cat "$IPFS_PATH/config" >expected &&
83 + ipfs config profile apply '${profile}' --dry-run &&
84 + cat "$IPFS_PATH/config" >actual &&
85 + test_cmp expected actual
86 + '
87 +}
88 +
89 test_config_cmd() {
90 test_config_cmd_set "beep" "boop"
91 test_config_cmd_set "beep1" "boop2"
@@ -220,6 +231,37 @@ test_config_cmd() {
231 # need to do this in reverse as the test profile is already applied in sharness
232 test_profile_apply_revert default-networking test
233
234 + test_profile_apply_dry_run_not_alter server
235 +
236 + test_profile_apply_dry_run_not_alter local-discovery
237 +
238 + test_profile_apply_dry_run_not_alter test
239 +
240 + test_expect_success "'ipfs config profile apply local-discovery --dry-run' looks good with different profile info" '
241 + ipfs config profile apply local-discovery --dry-run > diff_info &&
242 + test `grep "DisableNatPortMap" diff_info | wc -l` = 2
243 + '
244 +
245 + test_expect_success "'ipfs config profile apply server --dry-run' looks good with same profile info" '
246 + ipfs config profile apply server --dry-run > diff_info &&
247 + test `grep "DisableNatPortMap" diff_info | wc -l` = 1
248 + '
249 +
250 + test_expect_success "'ipfs config profile apply server' looks good with same profile info" '
251 + ipfs config profile apply server > diff_info &&
252 + test `grep "DisableNatPortMap" diff_info | wc -l` = 1
253 + '
254 +
255 + test_expect_success "'ipfs config profile apply local-discovery' looks good with different profile info" '
256 + ipfs config profile apply local-discovery > diff_info &&
257 + test `grep "DisableNatPortMap" diff_info | wc -l` = 2
258 + '
259 +
260 + test_expect_success "'ipfs config profile apply test' looks good with different profile info" '
261 + ipfs config profile apply test > diff_info &&
262 + test `grep "DisableNatPortMap" diff_info | wc -l` = 2
263 + '
264 +
265 # won't work as it changes datastore definition, which makes ipfs not launch
266 # without converting first
267 # test_profile_apply_revert badgerds