From 130e800252147bd1c6bb935b9d36df59a4920eeb Mon Sep 17 00:00:00 2001 From: Anis Elleuch Date: Sat, 21 Mar 2020 13:10:41 +0100 Subject: [PATCH] Add global context and adapt context change in admin API This commit adds a new global context, monitors os signals and cancels the global context in such cases to exit on going process gracefully. It will also update minio-go and adapts the code with the new context changes in the admin API. --- cmd/admin-config-export.go | 2 +- cmd/admin-config-get.go | 4 ++-- cmd/admin-config-history.go | 4 ++-- cmd/admin-config-import.go | 2 +- cmd/admin-config-reset.go | 4 ++-- cmd/admin-config-restore.go | 2 +- cmd/admin-config-set.go | 4 ++-- cmd/admin-console.go | 8 +++++--- cmd/admin-group-add.go | 2 +- cmd/admin-group-enable.go | 2 +- cmd/admin-group-info.go | 2 +- cmd/admin-group-list.go | 2 +- cmd/admin-group-remove.go | 2 +- cmd/admin-heal-ui.go | 11 ++++------- cmd/admin-heal.go | 6 +++--- cmd/admin-info.go | 2 +- cmd/admin-kms-key-status.go | 2 +- cmd/admin-policy-add.go | 2 +- cmd/admin-policy-info.go | 2 +- cmd/admin-policy-list.go | 2 +- cmd/admin-policy-remove.go | 2 +- cmd/admin-policy-set.go | 2 +- cmd/admin-profile-start.go | 2 +- cmd/admin-profile-stop.go | 2 +- cmd/admin-service-restart.go | 4 ++-- cmd/admin-service-stop.go | 2 +- cmd/admin-top-locks.go | 2 +- cmd/admin-trace.go | 8 +++++--- cmd/admin-update.go | 2 +- cmd/admin-user-add.go | 2 +- cmd/admin-user-disable.go | 2 +- cmd/admin-user-enable.go | 2 +- cmd/admin-user-info.go | 2 +- cmd/admin-user-list.go | 2 +- cmd/admin-user-remove.go | 2 +- cmd/auto-complete.go | 2 +- cmd/cp-main.go | 13 +++++-------- cmd/find.go | 5 +---- cmd/globals.go | 5 +++-- cmd/main.go | 5 +++++ cmd/mirror-main.go | 10 +++------- cmd/signals.go | 35 ++++++++++++++--------------------- cmd/watch-main.go | 6 +----- go.mod | 2 +- go.sum | 10 ++++++++++ 45 files changed, 97 insertions(+), 101 deletions(-) diff --git a/cmd/admin-config-export.go b/cmd/admin-config-export.go index 76ca40cedb..7fd0e573f9 100644 --- a/cmd/admin-config-export.go +++ b/cmd/admin-config-export.go @@ -84,7 +84,7 @@ func mainAdminConfigExport(ctx *cli.Context) error { fatalIf(err, "Unable to initialize admin connection.") // Call get config API - buf, e := client.GetConfig() + buf, e := client.GetConfig(globalContext) fatalIf(probe.NewError(e), "Cannot get server config") // Print diff --git a/cmd/admin-config-get.go b/cmd/admin-config-get.go index 70792cb2f8..effd025b5d 100644 --- a/cmd/admin-config-get.go +++ b/cmd/admin-config-get.go @@ -96,7 +96,7 @@ func mainAdminConfigGet(ctx *cli.Context) error { if len(ctx.Args()) == 1 { // Call get config API - hr, e := client.HelpConfigKV("", "", false) + hr, e := client.HelpConfigKV(globalContext, "", "", false) fatalIf(probe.NewError(e), "Cannot get help for the sub-system") // Print @@ -109,7 +109,7 @@ func mainAdminConfigGet(ctx *cli.Context) error { } // Call get config API - buf, e := client.GetConfigKV(strings.Join(args.Tail(), " ")) + buf, e := client.GetConfigKV(globalContext, strings.Join(args.Tail(), " ")) fatalIf(probe.NewError(e), "Cannot get server '%s' config", args.Tail()) // Print diff --git a/cmd/admin-config-history.go b/cmd/admin-config-history.go index 3174f8c498..1e767aa078 100644 --- a/cmd/admin-config-history.go +++ b/cmd/admin-config-history.go @@ -127,14 +127,14 @@ func mainAdminConfigHistory(ctx *cli.Context) error { fatalIf(err, "Unable to initialize admin connection.") if ctx.IsSet("clear") { - fatalIf(probe.NewError(client.ClearConfigHistoryKV("all")), "Cannot clear server configuration.") + fatalIf(probe.NewError(client.ClearConfigHistoryKV(globalContext, "all")), "Cannot clear server configuration.") // Print printMsg(configHistoryMessage{}) return nil } - chEntries, e := client.ListConfigHistoryKV(ctx.Int("count")) + chEntries, e := client.ListConfigHistoryKV(globalContext, ctx.Int("count")) fatalIf(probe.NewError(e), "Cannot list server history configuration.") hentries := make([]historyEntry, len(chEntries)) diff --git a/cmd/admin-config-import.go b/cmd/admin-config-import.go index e67e634343..255008007d 100644 --- a/cmd/admin-config-import.go +++ b/cmd/admin-config-import.go @@ -96,7 +96,7 @@ func mainAdminConfigImport(ctx *cli.Context) error { fatalIf(err, "Unable to initialize admin connection.") // Call set config API - fatalIf(probe.NewError(client.SetConfig(os.Stdin)), "Cannot set server config") + fatalIf(probe.NewError(client.SetConfig(globalContext, os.Stdin)), "Cannot set server config") // Print printMsg(configImportMessage{ diff --git a/cmd/admin-config-reset.go b/cmd/admin-config-reset.go index a260cb48bb..46039d2975 100644 --- a/cmd/admin-config-reset.go +++ b/cmd/admin-config-reset.go @@ -107,7 +107,7 @@ func mainAdminConfigReset(ctx *cli.Context) error { if len(ctx.Args()) == 1 { // Call get config API - hr, e := client.HelpConfigKV("", "", ctx.IsSet("env")) + hr, e := client.HelpConfigKV(globalContext, "", "", ctx.IsSet("env")) fatalIf(probe.NewError(e), "Cannot get help for the sub-system") // Print @@ -121,7 +121,7 @@ func mainAdminConfigReset(ctx *cli.Context) error { // Call reset config API input := strings.Join(args.Tail(), " ") - fatalIf(probe.NewError(client.DelConfigKV(input)), + fatalIf(probe.NewError(client.DelConfigKV(globalContext, input)), "Cannot reset '%s' on the server", input) // Print set config result diff --git a/cmd/admin-config-restore.go b/cmd/admin-config-restore.go index 488b320c9e..a14af902fb 100644 --- a/cmd/admin-config-restore.go +++ b/cmd/admin-config-restore.go @@ -94,7 +94,7 @@ func mainAdminConfigRestore(ctx *cli.Context) error { fatalIf(err, "Unable to initialize admin connection.") // Call get config API - fatalIf(probe.NewError(client.RestoreConfigHistoryKV(args.Get(1))), "Cannot restore server configuration.") + fatalIf(probe.NewError(client.RestoreConfigHistoryKV(globalContext, args.Get(1))), "Cannot restore server configuration.") // Print printMsg(configRestoreMessage{ diff --git a/cmd/admin-config-set.go b/cmd/admin-config-set.go index 0a159debf6..02d9636a7e 100644 --- a/cmd/admin-config-set.go +++ b/cmd/admin-config-set.go @@ -105,7 +105,7 @@ func mainAdminConfigSet(ctx *cli.Context) error { if !strings.Contains(input, madmin.KvSeparator) { // Call get config API - hr, e := client.HelpConfigKV(args.Get(1), args.Get(2), ctx.IsSet("env")) + hr, e := client.HelpConfigKV(globalContext, args.Get(1), args.Get(2), ctx.IsSet("env")) fatalIf(probe.NewError(e), "Cannot get help for the sub-system") // Print @@ -119,7 +119,7 @@ func mainAdminConfigSet(ctx *cli.Context) error { } // Call set config API - fatalIf(probe.NewError(client.SetConfigKV(input)), + fatalIf(probe.NewError(client.SetConfigKV(globalContext, input)), "Cannot set '%s' to server", input) // Print set config result diff --git a/cmd/admin-console.go b/cmd/admin-console.go index 5c17ada3a3..38f425da4b 100644 --- a/cmd/admin-console.go +++ b/cmd/admin-console.go @@ -17,6 +17,7 @@ package cmd import ( + "context" "fmt" "strings" "time" @@ -195,11 +196,12 @@ func mainAdminConsole(ctx *cli.Context) error { fatalIf(err.Trace(aliasedURL), "Cannot initialize admin client.") return nil } - doneCh := make(chan struct{}) - defer close(doneCh) + + ctxt, cancel := context.WithCancel(globalContext) + defer cancel() // Start listening on all console log activity. - logCh := client.GetLogs(node, limit, logType, doneCh) + logCh := client.GetLogs(ctxt, node, limit, logType) for logInfo := range logCh { if logInfo.Err != nil { fatalIf(probe.NewError(logInfo.Err), "Cannot listen to console logs") diff --git a/cmd/admin-group-add.go b/cmd/admin-group-add.go index b5f5a09241..91c8af1fc3 100644 --- a/cmd/admin-group-add.go +++ b/cmd/admin-group-add.go @@ -131,7 +131,7 @@ func mainAdminGroupAdd(ctx *cli.Context) error { Members: members, IsRemove: false, } - fatalIf(probe.NewError(client.UpdateGroupMembers(gAddRemove)).Trace(args...), "Cannot add new group") + fatalIf(probe.NewError(client.UpdateGroupMembers(globalContext, gAddRemove)).Trace(args...), "Cannot add new group") printMsg(groupMessage{ op: "add", diff --git a/cmd/admin-group-enable.go b/cmd/admin-group-enable.go index 0e2c955155..4b362046f9 100644 --- a/cmd/admin-group-enable.go +++ b/cmd/admin-group-enable.go @@ -79,7 +79,7 @@ func mainAdminGroupEnableDisable(ctx *cli.Context) error { err1 = errors.New("cannot happen") fatalIf(probe.NewError(err1).Trace(args...), "Could not get group enable") } - err1 = client.SetGroupStatus(group, status) + err1 = client.SetGroupStatus(globalContext, group, status) fatalIf(probe.NewError(err1).Trace(args...), "Could not get group enable") printMsg(groupMessage{ diff --git a/cmd/admin-group-info.go b/cmd/admin-group-info.go index fb180226d6..4720a532bc 100644 --- a/cmd/admin-group-info.go +++ b/cmd/admin-group-info.go @@ -66,7 +66,7 @@ func mainAdminGroupInfo(ctx *cli.Context) error { fatalIf(err, "Unable to initialize admin connection.") group := args.Get(1) - gd, err1 := client.GetGroupDescription(group) + gd, err1 := client.GetGroupDescription(globalContext, group) fatalIf(probe.NewError(err1).Trace(args...), "Could not get group info") printMsg(groupMessage{ diff --git a/cmd/admin-group-list.go b/cmd/admin-group-list.go index 3b3e32f961..ff03be5b42 100644 --- a/cmd/admin-group-list.go +++ b/cmd/admin-group-list.go @@ -65,7 +65,7 @@ func mainAdminGroupList(ctx *cli.Context) error { client, err := newAdminClient(aliasedURL) fatalIf(err, "Unable to initialize admin connection.") - gs, err1 := client.ListGroups() + gs, err1 := client.ListGroups(globalContext) fatalIf(probe.NewError(err1).Trace(args...), "Could not get group list") printMsg(groupMessage{ diff --git a/cmd/admin-group-remove.go b/cmd/admin-group-remove.go index db5529b231..f96b00f472 100644 --- a/cmd/admin-group-remove.go +++ b/cmd/admin-group-remove.go @@ -79,7 +79,7 @@ func mainAdminGroupRemove(ctx *cli.Context) error { IsRemove: true, } - e := client.UpdateGroupMembers(gAddRemove) + e := client.UpdateGroupMembers(globalContext, gAddRemove) fatalIf(probe.NewError(e).Trace(args...), "Could not perform remove operation") printMsg(groupMessage{ diff --git a/cmd/admin-heal-ui.go b/cmd/admin-heal-ui.go index 2f6f89239a..07953ec01d 100644 --- a/cmd/admin-heal-ui.go +++ b/cmd/admin-heal-ui.go @@ -20,9 +20,7 @@ import ( "errors" "fmt" "math" - "os" "strings" - "syscall" "time" humanize "github.com/dustin/go-humanize" @@ -404,16 +402,15 @@ func (ui *uiData) healResumeMsg(aliasedURL string) string { } func (ui *uiData) DisplayAndFollowHealStatus(aliasedURL string) (res madmin.HealTaskStatus, err error) { - trapCh := signalTrap(os.Interrupt, syscall.SIGTERM, syscall.SIGKILL) - trapMsg := ui.healResumeMsg(aliasedURL) + quitMsg := ui.healResumeMsg(aliasedURL) firstIter := true for { select { - case <-trapCh: - return res, errors.New(trapMsg) + case <-globalContext.Done(): + return res, errors.New(quitMsg) default: - _, res, err = ui.Client.Heal(ui.Bucket, ui.Prefix, *ui.HealOpts, + _, res, err = ui.Client.Heal(globalContext, ui.Bucket, ui.Prefix, *ui.HealOpts, ui.ClientToken, ui.ForceStart, false) if err != nil { return res, err diff --git a/cmd/admin-heal.go b/cmd/admin-heal.go index 6862886da7..0d0731d481 100644 --- a/cmd/admin-heal.go +++ b/cmd/admin-heal.go @@ -231,7 +231,7 @@ func mainAdminHeal(ctx *cli.Context) error { // Return the background heal status when the user // doesn't pass a bucket or --recursive flag. if bucket == "" && !ctx.Bool("recursive") { - bgHealStatus, berr := client.BackgroundHealStatus() + bgHealStatus, berr := client.BackgroundHealStatus(globalContext) fatalIf(probe.NewError(berr), "Failed to get the status of the background heal.") printMsg(backgroundHealStatusMessage{Status: "success", HealInfo: bgHealStatus}) return nil @@ -247,13 +247,13 @@ func mainAdminHeal(ctx *cli.Context) error { forceStart := ctx.Bool("force-start") forceStop := ctx.Bool("force-stop") if forceStop { - _, _, herr := client.Heal(bucket, prefix, opts, "", forceStart, forceStop) + _, _, herr := client.Heal(globalContext, bucket, prefix, opts, "", forceStart, forceStop) fatalIf(probe.NewError(herr), "Failed to stop heal sequence.") printMsg(stopHealMessage{Status: "success", Alias: aliasedURL}) return nil } - healStart, _, herr := client.Heal(bucket, prefix, opts, "", forceStart, false) + healStart, _, herr := client.Heal(globalContext, bucket, prefix, opts, "", forceStart, false) fatalIf(probe.NewError(herr), "Failed to start heal sequence.") ui := uiData{ diff --git a/cmd/admin-info.go b/cmd/admin-info.go index 5597998778..f31ae0b1a4 100644 --- a/cmd/admin-info.go +++ b/cmd/admin-info.go @@ -224,7 +224,7 @@ func mainAdminInfo(ctx *cli.Context) error { var clusterInfo clusterStruct // Fetch info of all servers (cluster or single server) - admInfo, e := client.ServerInfo() + admInfo, e := client.ServerInfo(globalContext) if e != nil { clusterInfo.Status = "error" clusterInfo.Error = e.Error() diff --git a/cmd/admin-kms-key-status.go b/cmd/admin-kms-key-status.go index 4482fccdfe..a643b9b3b7 100644 --- a/cmd/admin-kms-key-status.go +++ b/cmd/admin-kms-key-status.go @@ -60,7 +60,7 @@ func mainAdminKMSKeyStatus(ctx *cli.Context) error { if len(ctx.Args()) == 2 { keyID = ctx.Args().Get(1) } - status, e := client.GetKeyStatus(keyID) + status, e := client.GetKeyStatus(globalContext, keyID) fatalIf(probe.NewError(e), "Failed to get status information") printMsg(kmsKeyStatusMsg(*status)) diff --git a/cmd/admin-policy-add.go b/cmd/admin-policy-add.go index a21318f7ad..88ea47e560 100644 --- a/cmd/admin-policy-add.go +++ b/cmd/admin-policy-add.go @@ -121,7 +121,7 @@ func mainAdminPolicyAdd(ctx *cli.Context) error { client, err := newAdminClient(aliasedURL) fatalIf(err, "Unable to initialize admin connection.") - fatalIf(probe.NewError(client.AddCannedPolicy(args.Get(1), string(policy))).Trace(args...), "Cannot add new policy") + fatalIf(probe.NewError(client.AddCannedPolicy(globalContext, args.Get(1), string(policy))).Trace(args...), "Cannot add new policy") printMsg(userPolicyMessage{ op: "add", diff --git a/cmd/admin-policy-info.go b/cmd/admin-policy-info.go index dc665ab0eb..23ed5e8747 100644 --- a/cmd/admin-policy-info.go +++ b/cmd/admin-policy-info.go @@ -72,7 +72,7 @@ func mainAdminPolicyInfo(ctx *cli.Context) error { client, err := newAdminClient(aliasedURL) fatalIf(err, "Unable to initialize admin connection.") - policies, e := client.ListCannedPolicies() + policies, e := client.ListCannedPolicies(globalContext) fatalIf(probe.NewError(e).Trace(args...), "Cannot list policy") if len(policies[policyName]) != 0 { diff --git a/cmd/admin-policy-list.go b/cmd/admin-policy-list.go index 328e1ba5a0..1cc979ee3b 100644 --- a/cmd/admin-policy-list.go +++ b/cmd/admin-policy-list.go @@ -66,7 +66,7 @@ func mainAdminPolicyList(ctx *cli.Context) error { client, err := newAdminClient(aliasedURL) fatalIf(err, "Unable to initialize admin connection.") - policies, e := client.ListCannedPolicies() + policies, e := client.ListCannedPolicies(globalContext) fatalIf(probe.NewError(e).Trace(args...), "Cannot list policy") for k := range policies { diff --git a/cmd/admin-policy-remove.go b/cmd/admin-policy-remove.go index c91259c273..d9f237e969 100644 --- a/cmd/admin-policy-remove.go +++ b/cmd/admin-policy-remove.go @@ -68,7 +68,7 @@ func mainAdminPolicyRemove(ctx *cli.Context) error { client, err := newAdminClient(aliasedURL) fatalIf(err, "Unable to initialize admin connection.") - fatalIf(probe.NewError(client.RemoveCannedPolicy(args.Get(1))).Trace(args...), "Cannot remove policy") + fatalIf(probe.NewError(client.RemoveCannedPolicy(globalContext, args.Get(1))).Trace(args...), "Cannot remove policy") printMsg(userPolicyMessage{ op: "remove", diff --git a/cmd/admin-policy-set.go b/cmd/admin-policy-set.go index 12c87b73fd..b9f51e4793 100644 --- a/cmd/admin-policy-set.go +++ b/cmd/admin-policy-set.go @@ -103,7 +103,7 @@ func mainAdminPolicySet(ctx *cli.Context) error { client, err := newAdminClient(aliasedURL) fatalIf(err, "Unable to initialize admin connection.") - e := client.SetPolicy(policyName, userOrGroup, isGroup) + e := client.SetPolicy(globalContext, policyName, userOrGroup, isGroup) if e == nil { printMsg(userPolicyMessage{ diff --git a/cmd/admin-profile-start.go b/cmd/admin-profile-start.go index c87d39c60c..3c79401adb 100644 --- a/cmd/admin-profile-start.go +++ b/cmd/admin-profile-start.go @@ -114,7 +114,7 @@ func mainAdminProfileStart(ctx *cli.Context) error { } // Start profile - _, cmdErr := client.StartProfiling(madmin.ProfilerType(profilers)) + _, cmdErr := client.StartProfiling(globalContext, madmin.ProfilerType(profilers)) fatalIf(probe.NewError(cmdErr), "Unable to start profile.") console.Infoln("Profile data successfully started.") diff --git a/cmd/admin-profile-stop.go b/cmd/admin-profile-stop.go index 9868bc0fda..1a839f2690 100644 --- a/cmd/admin-profile-stop.go +++ b/cmd/admin-profile-stop.go @@ -103,7 +103,7 @@ func mainAdminProfileStop(ctx *cli.Context) error { fatalIf(probe.NewError(e), "Unable to download profile data.") // Ask for profile data, which will come compressed with zip format - zippedData, adminErr := client.DownloadProfilingData() + zippedData, adminErr := client.DownloadProfilingData(globalContext) fatalIf(probe.NewError(adminErr), "Unable to download profile data.") // Copy zip content to target download file diff --git a/cmd/admin-service-restart.go b/cmd/admin-service-restart.go index 16014f4f7f..349213a079 100644 --- a/cmd/admin-service-restart.go +++ b/cmd/admin-service-restart.go @@ -113,7 +113,7 @@ func mainAdminServiceRestart(ctx *cli.Context) error { fatalIf(err, "Unable to initialize admin connection.") // Restart the specified MinIO server - fatalIf(probe.NewError(client.ServiceRestart()), "Cannot restart the server.") + fatalIf(probe.NewError(client.ServiceRestart(globalContext)), "Cannot restart the server.") // Success.. printMsg(serviceRestartCommand{Status: "success", ServerURL: aliasedURL}) @@ -125,7 +125,7 @@ func mainAdminServiceRestart(ctx *cli.Context) error { time.Sleep(6 * time.Second) // Fetch the service status of the specified MinIO server - _, e := client.ServerInfo() + _, e := client.ServerInfo(globalContext) if e != nil { printMsg(serviceRestartMessage{Status: "failure", Err: e, ServerURL: aliasedURL}) diff --git a/cmd/admin-service-stop.go b/cmd/admin-service-stop.go index c3850caf51..c2b98d42b3 100644 --- a/cmd/admin-service-stop.go +++ b/cmd/admin-service-stop.go @@ -87,7 +87,7 @@ func mainAdminServiceStop(ctx *cli.Context) error { fatalIf(err, "Unable to initialize admin connection.") // Stop the specified MinIO server - fatalIf(probe.NewError(client.ServiceStop()), "Unable to stop the server.") + fatalIf(probe.NewError(client.ServiceStop(globalContext)), "Unable to stop the server.") // Success.. printMsg(serviceStopMessage{Status: "success", ServerURL: aliasedURL}) diff --git a/cmd/admin-top-locks.go b/cmd/admin-top-locks.go index 12a7204f38..9635457af7 100644 --- a/cmd/admin-top-locks.go +++ b/cmd/admin-top-locks.go @@ -114,7 +114,7 @@ func mainAdminTopLocks(ctx *cli.Context) error { fatalIf(err, "Unable to initialize admin connection.") // Call top locks API - entries, e := client.TopLocks() + entries, e := client.TopLocks(globalContext) fatalIf(probe.NewError(e), "Cannot get server locks list.") console.SetColor("StaleLock", color.New(color.FgRed, color.Bold)) diff --git a/cmd/admin-trace.go b/cmd/admin-trace.go index 6fb444e691..9437ac589e 100644 --- a/cmd/admin-trace.go +++ b/cmd/admin-trace.go @@ -18,6 +18,7 @@ package cmd import ( "bytes" + "context" "fmt" "hash/fnv" "net/http" @@ -117,11 +118,12 @@ func mainAdminTrace(ctx *cli.Context) error { fatalIf(err.Trace(aliasedURL), "Cannot initialize admin client.") return nil } - doneCh := make(chan struct{}) - defer close(doneCh) + + ctxt, cancel := context.WithCancel(globalContext) + defer cancel() // Start listening on all trace activity. - traceCh := client.ServiceTrace(all, errfltr, doneCh) + traceCh := client.ServiceTrace(ctxt, all, errfltr) for traceInfo := range traceCh { if traceInfo.Err != nil { fatalIf(probe.NewError(traceInfo.Err), "Cannot listen to http trace") diff --git a/cmd/admin-update.go b/cmd/admin-update.go index 10c87789a5..90cb45f3f6 100644 --- a/cmd/admin-update.go +++ b/cmd/admin-update.go @@ -103,7 +103,7 @@ func mainAdminServerUpdate(ctx *cli.Context) error { // Update the specified MinIO server, optionally also // with the provided update URL. - us, e := client.ServerUpdate(updateURL) + us, e := client.ServerUpdate(globalContext, updateURL) fatalIf(probe.NewError(e), "Unable to update the server.") // Success.. diff --git a/cmd/admin-user-add.go b/cmd/admin-user-add.go index 1d7d6b09ff..4dceccfc73 100644 --- a/cmd/admin-user-add.go +++ b/cmd/admin-user-add.go @@ -180,7 +180,7 @@ func mainAdminUserAdd(ctx *cli.Context) error { client, err := newAdminClient(aliasedURL) fatalIf(err, "Unable to initialize admin connection.") - fatalIf(probe.NewError(client.AddUser(accessKey, secretKey)).Trace(args...), "Cannot add new user") + fatalIf(probe.NewError(client.AddUser(globalContext, accessKey, secretKey)).Trace(args...), "Cannot add new user") printMsg(userMessage{ op: "add", diff --git a/cmd/admin-user-disable.go b/cmd/admin-user-disable.go index 52937ec3f0..6a70315c65 100644 --- a/cmd/admin-user-disable.go +++ b/cmd/admin-user-disable.go @@ -66,7 +66,7 @@ func mainAdminUserDisable(ctx *cli.Context) error { client, err := newAdminClient(aliasedURL) fatalIf(err, "Unable to initialize admin connection.") - e := client.SetUserStatus(args.Get(1), madmin.AccountDisabled) + e := client.SetUserStatus(globalContext, args.Get(1), madmin.AccountDisabled) fatalIf(probe.NewError(e).Trace(args...), "Cannot disable user") printMsg(userMessage{ diff --git a/cmd/admin-user-enable.go b/cmd/admin-user-enable.go index 65d816b267..637c958c37 100644 --- a/cmd/admin-user-enable.go +++ b/cmd/admin-user-enable.go @@ -66,7 +66,7 @@ func mainAdminUserEnable(ctx *cli.Context) error { client, err := newAdminClient(aliasedURL) fatalIf(err, "Unable to initialize admin connection.") - e := client.SetUserStatus(args.Get(1), madmin.AccountEnabled) + e := client.SetUserStatus(globalContext, args.Get(1), madmin.AccountEnabled) fatalIf(probe.NewError(e).Trace(args...), "Cannot enable user") printMsg(userMessage{ diff --git a/cmd/admin-user-info.go b/cmd/admin-user-info.go index 4107c43987..b432aeca05 100644 --- a/cmd/admin-user-info.go +++ b/cmd/admin-user-info.go @@ -65,7 +65,7 @@ func mainAdminUserInfo(ctx *cli.Context) error { client, err := newAdminClient(aliasedURL) fatalIf(err, "Unable to initialize admin connection.") - user, e := client.GetUserInfo(args.Get(1)) + user, e := client.GetUserInfo(globalContext, args.Get(1)) fatalIf(probe.NewError(e).Trace(args...), "Cannot get user info") printMsg(userMessage{ diff --git a/cmd/admin-user-list.go b/cmd/admin-user-list.go index 53f548d724..5e2dc39eb8 100644 --- a/cmd/admin-user-list.go +++ b/cmd/admin-user-list.go @@ -69,7 +69,7 @@ func mainAdminUserList(ctx *cli.Context) error { client, err := newAdminClient(aliasedURL) fatalIf(err, "Unable to initialize admin connection.") - users, e := client.ListUsers() + users, e := client.ListUsers(globalContext) fatalIf(probe.NewError(e).Trace(args...), "Cannot list user") for k, v := range users { diff --git a/cmd/admin-user-remove.go b/cmd/admin-user-remove.go index 9609c09ea8..f40a13eac9 100644 --- a/cmd/admin-user-remove.go +++ b/cmd/admin-user-remove.go @@ -65,7 +65,7 @@ func mainAdminUserRemove(ctx *cli.Context) error { client, err := newAdminClient(aliasedURL) fatalIf(err, "Unable to initialize admin connection.") - e := client.RemoveUser(args.Get(1)) + e := client.RemoveUser(globalContext, args.Get(1)) fatalIf(probe.NewError(e).Trace(args...), "Cannot remove %s", args.Get(1)) printMsg(userMessage{ diff --git a/cmd/auto-complete.go b/cmd/auto-complete.go index b0e5e459c9..44afb8e6e8 100644 --- a/cmd/auto-complete.go +++ b/cmd/auto-complete.go @@ -41,7 +41,7 @@ func completeAdminConfigKeys(aliasPath string, keyPrefix string) (prediction []s return nil } - h, e := clnt.HelpConfigKV("", "", false) + h, e := clnt.HelpConfigKV(globalContext, "", "", false) if e != nil { return nil } diff --git a/cmd/cp-main.go b/cmd/cp-main.go index a1bbdf606e..e2c257d9ec 100644 --- a/cmd/cp-main.go +++ b/cmd/cp-main.go @@ -27,7 +27,6 @@ import ( "os" "path/filepath" "strings" - "syscall" "github.com/fatih/color" "github.com/minio/cli" @@ -224,7 +223,7 @@ func doCopyFake(cpURLs URLs, pg Progress) URLs { } // doPrepareCopyURLs scans the source URL and prepares a list of objects for copying. -func doPrepareCopyURLs(session *sessionV8, trapCh <-chan bool, cancelCopy context.CancelFunc) (totalBytes, totalObjects int64) { +func doPrepareCopyURLs(session *sessionV8, cancelCopy context.CancelFunc) (totalBytes, totalObjects int64) { // Separate source and target. 'cp' can take only one target, // but any number of sources. sourceURLs := session.Header.CommandArgs[:len(session.Header.CommandArgs)-1] @@ -283,7 +282,7 @@ func doPrepareCopyURLs(session *sessionV8, trapCh <-chan bool, cancelCopy contex totalBytes += cpURLs.SourceContent.Size totalObjects++ - case <-trapCh: + case <-globalContext.Done(): cancelCopy() // Print in new line and adjust to top so that we don't print over the ongoing scan bar if !globalQuiet && !globalJSON { @@ -301,9 +300,7 @@ func doPrepareCopyURLs(session *sessionV8, trapCh <-chan bool, cancelCopy contex } func doCopySession(cli *cli.Context, session *sessionV8, encKeyDB map[string][]prefixSSEPair) error { - trapCh := signalTrap(os.Interrupt, syscall.SIGTERM, syscall.SIGKILL) - - ctx, cancelCopy := context.WithCancel(context.Background()) + ctx, cancelCopy := context.WithCancel(globalContext) defer cancelCopy() var isCopied func(string) bool @@ -327,7 +324,7 @@ func doCopySession(cli *cli.Context, session *sessionV8, encKeyDB map[string][]p isCopied = isLastFactory(session.Header.LastCopied) if !session.HasData() { - totalBytes, totalObjects = doPrepareCopyURLs(session, trapCh, cancelCopy) + totalBytes, totalObjects = doPrepareCopyURLs(session, cancelCopy) } else { totalBytes, totalObjects = session.Header.TotalBytes, session.Header.TotalObjects } @@ -469,7 +466,7 @@ func doCopySession(cli *cli.Context, session *sessionV8, encKeyDB map[string][]p loop: for { select { - case <-trapCh: + case <-globalContext.Done(): close(quitCh) cancelCopy() // Receive interrupt notification. diff --git a/cmd/find.go b/cmd/find.go index 345a32d8f7..7771fc3ef6 100644 --- a/cmd/find.go +++ b/cmd/find.go @@ -143,13 +143,10 @@ func watchFind(ctx *findContext) { watchObj, err := ctx.clnt.Watch(params) fatalIf(err.Trace(ctx.targetAlias), "Cannot watch with given params.") - // Enables users to kill using the control + c - trapCh := signalTrap(os.Interrupt, syscall.SIGTERM) - // Loop until user CTRL-C the command line. for { select { - case <-trapCh: + case <-globalContext.Done(): console.Println() close(watchObj.doneChan) return diff --git a/cmd/globals.go b/cmd/globals.go index 17fd9c4a95..458846f11e 100644 --- a/cmd/globals.go +++ b/cmd/globals.go @@ -1,5 +1,5 @@ /* - * MinIO Client (C) 2015 MinIO, Inc. + * MinIO Client (C) 2015-2020 MinIO, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ package cmd import ( + "context" "crypto/x509" "github.com/minio/cli" @@ -50,7 +51,7 @@ var ( globalNoColor = false // No Color flag set via command line globalInsecure = false // Insecure flag set via command line - // WHEN YOU ADD NEXT GLOBAL FLAG, MAKE SURE TO ALSO UPDATE SESSION CODE AND CODE BELOW. + globalContext, globalCancel = context.WithCancel(context.Background()) ) var ( diff --git a/cmd/main.go b/cmd/main.go index 93f9fc67bf..9258b78088 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -25,6 +25,7 @@ import ( "sort" "strconv" "strings" + "syscall" "time" "github.com/cheggaaa/pb" @@ -109,6 +110,10 @@ func Main(args []string) { // Trim ".exe" from Windows executable. appName = appName[:strings.LastIndex(appName, ".")] } + + // Monitor OS exit signals and cancel the global context in such case + go trapSignals(os.Interrupt, syscall.SIGTERM, syscall.SIGKILL) + // Run the app - exit on error. if err := registerApp(appName).Run(args); err != nil { os.Exit(1) diff --git a/cmd/mirror-main.go b/cmd/mirror-main.go index b85b0b7e25..e79d8680b6 100644 --- a/cmd/mirror-main.go +++ b/cmd/mirror-main.go @@ -25,7 +25,6 @@ import ( "runtime" "strings" "sync" - "syscall" "time" "github.com/fatih/color" @@ -175,8 +174,6 @@ EXAMPLES: const uaMirrorAppName = "mc-mirror" type mirrorJob struct { - // the channel to trap SIGKILL signals - trapCh <-chan bool stopCh chan struct{} // mutex for shutdown, this prevents the shutdown @@ -529,7 +526,7 @@ func (mj *mirrorJob) watchMirror(ctx context.Context, cancelMirror context.Cance } mj.statusCh <- URLs{Error: err} return - case <-mj.trapCh: + case <-globalContext.Done(): return case <-mj.stopCh: return @@ -593,7 +590,7 @@ func (mj *mirrorJob) startMirror(ctx context.Context, cancelMirror context.Cance return mj.doRemove(sURLs) } } - case <-mj.trapCh: + case <-globalContext.Done(): if stopParallel != nil { stopParallel() } @@ -649,7 +646,6 @@ func newMirrorJob(srcURL, dstURL string, isFake, isRemove, isOverwrite, isWatch, isPreserve = true } mj := mirrorJob{ - trapCh: signalTrap(os.Interrupt, syscall.SIGTERM, syscall.SIGKILL), stopCh: make(chan struct{}), sourceURL: srcURL, @@ -772,7 +768,7 @@ func runMirror(srcURL, dstURL string, ctx *cli.Context, encKeyDB map[string][]pr encKeyDB) go func() { - <-mj.trapCh + <-globalContext.Done() os.Exit(globalErrorExitStatus) }() diff --git a/cmd/signals.go b/cmd/signals.go index 49185e76d0..b3471bce0f 100644 --- a/cmd/signals.go +++ b/cmd/signals.go @@ -21,29 +21,22 @@ import ( "os/signal" ) -// signalTrap traps the registered signals and notifies the caller. -func signalTrap(sig ...os.Signal) <-chan bool { - // channel to notify the caller. - trapCh := make(chan bool, 1) +// trapSignals traps the registered signals and cancel the global context. +func trapSignals(sig ...os.Signal) { + // channel to receive signals. + sigCh := make(chan os.Signal, 1) + defer close(sigCh) - go func(chan<- bool) { - // channel to receive signals. - sigCh := make(chan os.Signal, 1) - defer close(sigCh) + // `signal.Notify` registers the given channel to + // receive notifications of the specified signals. + signal.Notify(sigCh, sig...) - // `signal.Notify` registers the given channel to - // receive notifications of the specified signals. - signal.Notify(sigCh, sig...) + // Wait for the signal. + <-sigCh - // Wait for the signal. - <-sigCh + // Once signal has been received stop signal Notify handler. + signal.Stop(sigCh) - // Once signal has been received stop signal Notify handler. - signal.Stop(sigCh) - - // Notify the caller. - trapCh <- true - }(trapCh) - - return trapCh + // Cancel the global context + globalCancel() } diff --git a/cmd/watch-main.go b/cmd/watch-main.go index fdd0b5f9a1..9741be904a 100644 --- a/cmd/watch-main.go +++ b/cmd/watch-main.go @@ -18,10 +18,8 @@ package cmd import ( "fmt" - "os" "strings" "sync" - "syscall" humanize "github.com/dustin/go-humanize" "github.com/fatih/color" @@ -163,8 +161,6 @@ func mainWatch(ctx *cli.Context) error { wo, err := s3Client.Watch(params) fatalIf(err, "Cannot watch on the specified bucket.") - trapCh := signalTrap(os.Interrupt, syscall.SIGTERM) - // Initialize.. waitgroup to track the go-routine. wg := sync.WaitGroup{} @@ -178,7 +174,7 @@ func mainWatch(ctx *cli.Context) error { // Wait for all events. for { select { - case <-trapCh: + case <-globalContext.Done(): // Signal received we are done. close(wo.doneChan) return diff --git a/go.mod b/go.mod index 5cf0528647..72e4251d2b 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/mattn/go-isatty v0.0.7 github.com/mattn/go-runewidth v0.0.5 // indirect github.com/minio/cli v1.22.0 - github.com/minio/minio v0.0.0-20200312144740-ed4bd20a7cfc + github.com/minio/minio v0.0.0-20200321002836-bf545dc3203b github.com/minio/minio-go/v6 v6.0.51-0.20200319192131-097caa7760c7 github.com/minio/sha256-simd v0.1.1 github.com/mitchellh/go-homedir v1.1.0 diff --git a/go.sum b/go.sum index 1f4029f198..b5f4fd7796 100644 --- a/go.sum +++ b/go.sum @@ -37,6 +37,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheggaaa/pb v1.0.28 h1:kWGpdAcSp3MxMU9CCHOwz/8V0kCHN4+9yQm2MzWuI98= github.com/cheggaaa/pb v1.0.28/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= @@ -253,6 +255,8 @@ github.com/minio/lsync v1.0.1 h1:AVvILxA976xc27hstd1oR+X9PQG0sPSom1MNb1ImfUs= github.com/minio/lsync v1.0.1/go.mod h1:tCFzfo0dlvdGl70IT4IAK/5Wtgb0/BrTmo/jE8pArKA= github.com/minio/minio v0.0.0-20200312144740-ed4bd20a7cfc h1:JvRNAEmHghf0mPluxNLnleD2LZz+fyew0ddf6Xt5gD8= github.com/minio/minio v0.0.0-20200312144740-ed4bd20a7cfc/go.mod h1:QbCnTGb/blyNjrkyxB9ecKxtuWWUdcHShqED1bItwa0= +github.com/minio/minio v0.0.0-20200321002836-bf545dc3203b h1:8TWH16dqfdsSddYC29tBgRpTLxITy0LN/Dg5VFZezdY= +github.com/minio/minio v0.0.0-20200321002836-bf545dc3203b/go.mod h1:cUjzu4ZZy1YdtUjCSBWsxoa+z2NqCRohj6EyFIQA3gE= github.com/minio/minio-go/v6 v6.0.45/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg= github.com/minio/minio-go/v6 v6.0.50-0.20200306231101-b882ba63d570 h1:GLTZoRC6rhCTucnkJAQ63LhMU2S4CM71MRc9gfX7ohE= github.com/minio/minio-go/v6 v6.0.50-0.20200306231101-b882ba63d570/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg= @@ -311,6 +315,8 @@ github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQ github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/getopt v0.0.0-20180729010549-6fdd0a2c7117/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= +github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ= +github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.2.6+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.4.0+incompatible h1:06usnXXDNcPvCHDkmPpkidf4jTc52UKld7UPfqKatY4= @@ -387,6 +393,8 @@ github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/sjson v1.0.4 h1:UcdIRXff12Lpnu3OLtZvnc03g4vH2suXDXhBwBqmzYg= github.com/tidwall/sjson v1.0.4/go.mod h1:bURseu1nuBkFpIES5cz6zBtjmYeOQmEESshn7VpF15Y= +github.com/tinylib/msgp v1.1.1 h1:TnCZ3FIuKeaIy+F45+Cnp+caqdXGy4z74HvwXN+570Y= +github.com/tinylib/msgp v1.1.1/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= @@ -398,7 +406,9 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a h1:0R4NLDRDZX6JcmhJgXi5E4b8Wg84ihbmUKp/GvSPEzc= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0= github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=