Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add spinner at preparing Kubernetes... #9855

Merged
merged 33 commits into from
Dec 11, 2020
Merged
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
df37c78
change config func call
ruben-baez-seagull-com Dec 2, 2020
2e3e0ab
add new method to print spinner
ruben-baez-seagull-com Dec 2, 2020
7a0a2b0
remove break line in spinner line
ruben-baez-seagull-com Dec 2, 2020
65dc5b8
add spinner library to mod
ruben-baez-seagull-com Dec 2, 2020
88947d6
add break line in windows case
ruben-baez-seagull-com Dec 4, 2020
ead02fd
remove unnecesary file
ruben-baez-seagull-com Dec 4, 2020
f37a4aa
remove windows break line
ruben-baez-seagull-com Dec 4, 2020
6e37ffb
change spinner module version
ruben-baez-seagull-com Dec 4, 2020
994ff36
restore break line
ruben-baez-seagull-com Dec 4, 2020
b6ee8f2
remove old versions of the spinner
ruben-baez-seagull-com Dec 4, 2020
33b6e9a
add spinner param in step func
ruben-baez-seagull-com Dec 7, 2020
f7abca6
remove comment line
ruben-baez-seagull-com Dec 7, 2020
23dc03c
fix delete unittest
ruben-baez-seagull-com Dec 7, 2020
64f4895
fix lint if statement
ruben-baez-seagull-com Dec 7, 2020
32bb174
fix lint goimports
ruben-baez-seagull-com Dec 7, 2020
7a9979b
restore go sum
ruben-baez-seagull-com Dec 7, 2020
6b89930
add older lines in go sum
ruben-baez-seagull-com Dec 8, 2020
b330cdb
Merge branch 'master' into w/add-spinner
ruben-baez-seagull-com Dec 8, 2020
a763e05
change bool to second parameter
ruben-baez-seagull-com Dec 8, 2020
e09dcaa
Merge branch 'w/add-spinner' of https://github.com/alonyb/minikube in…
ruben-baez-seagull-com Dec 8, 2020
8d11d8b
Merge branch 'master' of https://github.com/alonyb/minikube into w/ad…
ruben-baez-seagull-com Dec 9, 2020
291ea78
fix repo with upstream
ruben-baez-seagull-com Dec 9, 2020
73ea4f2
add comment and fix bool param
ruben-baez-seagull-com Dec 9, 2020
032b43c
fix lint
ruben-baez-seagull-com Dec 9, 2020
e45b42f
fix unittest
ruben-baez-seagull-com Dec 9, 2020
c24eda6
change false to constant
ruben-baez-seagull-com Dec 9, 2020
42aac91
remove bool var from String func
ruben-baez-seagull-com Dec 9, 2020
e7ca292
change more false by constant
ruben-baez-seagull-com Dec 9, 2020
f729145
fix lint
ruben-baez-seagull-com Dec 9, 2020
277e096
remove param && add spin bool to style enum
ruben-baez-seagull-com Dec 10, 2020
d474058
restore unittest
ruben-baez-seagull-com Dec 10, 2020
8ee8989
move spinner character const to style
ruben-baez-seagull-com Dec 10, 2020
2d80cfc
fix lint
ruben-baez-seagull-com Dec 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cmd/minikube/cmd/config/addons_list.go
Original file line number Diff line number Diff line change
@@ -117,7 +117,7 @@ var printAddonsList = func(cc *config.ClusterConfig) {
klog.Errorf("list profiles returned error: %v", err)
}
if len(v) > 1 {
out.Step(style.Tip, "To see addons list for other profiles use: `minikube addons -p name list`")
out.Step(style.Tip, "To see addons list for other profiles use: `minikube addons -p name list`", false)
}
}

@@ -141,5 +141,5 @@ var printAddonsJSON = func(cc *config.ClusterConfig) {
}
jsonString, _ := json.Marshal(addonsMap)

out.String(string(jsonString))
out.String(string(jsonString), false)
}
2 changes: 1 addition & 1 deletion cmd/minikube/cmd/config/disable.go
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@ var addonsDisableCmd = &cobra.Command{
if err != nil {
exit.Error(reason.InternalDisable, "disable failed", err)
}
out.Step(style.AddonDisable, `"The '{{.minikube_addon}}' addon is disabled`, out.V{"minikube_addon": addon})
out.Step(style.AddonDisable, `"The '{{.minikube_addon}}' addon is disabled`, false, out.V{"minikube_addon": addon})
},
}

6 changes: 3 additions & 3 deletions cmd/minikube/cmd/config/enable.go
Original file line number Diff line number Diff line change
@@ -39,7 +39,7 @@ var addonsEnableCmd = &cobra.Command{
addon := args[0]
// replace heapster as metrics-server because heapster is deprecated
if addon == "heapster" {
out.Step(style.Waiting, "enable metrics-server addon instead of heapster addon because heapster is deprecated")
out.Step(style.Waiting, "enable metrics-server addon instead of heapster addon because heapster is deprecated", false)
addon = "metrics-server"
}
err := addons.SetAndSave(ClusterFlagValue(), addon, "true")
@@ -55,11 +55,11 @@ var addonsEnableCmd = &cobra.Command{

minikube{{.profileArg}} addons enable metrics-server

`, out.V{"profileArg": tipProfileArg})
`, false, out.V{"profileArg": tipProfileArg})

}

out.Step(style.AddonEnable, "The '{{.addonName}}' addon is enabled", out.V{"addonName": addon})
out.Step(style.AddonEnable, "The '{{.addonName}}' addon is enabled", false, out.V{"addonName": addon})
},
}

2 changes: 1 addition & 1 deletion cmd/minikube/cmd/config/open.go
Original file line number Diff line number Diff line change
@@ -96,7 +96,7 @@ You can add one by annotating a service with the label {{.labelName}}:{{.addonNa
}

if len(urlString) != 0 {
out.Step(style.Celebrate, "Opening Kubernetes service {{.namespace_name}}/{{.service_name}} in default browser...", out.V{"namespace_name": namespace, "service_name": svc})
out.Step(style.Celebrate, "Opening Kubernetes service {{.namespace_name}}/{{.service_name}} in default browser...", false, out.V{"namespace_name": namespace, "service_name": svc})
for _, url := range urlString {
if err := browser.OpenURL(url); err != nil {
exit.Error(reason.HostBrowser, fmt.Sprintf("browser failed to open url %s", url), err)
2 changes: 1 addition & 1 deletion cmd/minikube/cmd/config/profile.go
Original file line number Diff line number Diff line change
@@ -37,7 +37,7 @@ var ProfileCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
profile := ClusterFlagValue()
out.Step(style.Empty, profile)
out.Step(style.Empty, profile, false)
os.Exit(0)
}

4 changes: 2 additions & 2 deletions cmd/minikube/cmd/config/profile_list.go
Original file line number Diff line number Diff line change
@@ -177,11 +177,11 @@ func printProfilesJSON() {
body["valid"] = profilesOrDefault(validProfiles)
body["invalid"] = profilesOrDefault(invalidProfiles)
jsonString, _ := json.Marshal(body)
out.String(string(jsonString))
out.String(string(jsonString), false)
} else {
body["error"] = err
jsonString, _ := json.Marshal(body)
out.String(string(jsonString))
out.String(string(jsonString), false)
os.Exit(reason.ExGuestError)
}
}
4 changes: 2 additions & 2 deletions cmd/minikube/cmd/config/prompt.go
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ func AskForYesNoConfirmation(s string, posResponses, negResponses []string) bool
reader := bufio.NewReader(os.Stdin)

for {
out.String("%s [y/n]: ", s)
out.String("%s [y/n]: ", false, s)

response, err := reader.ReadString('\n')
if err != nil {
@@ -78,7 +78,7 @@ func AskForStaticValueOptional(s string) string {
}

func getStaticValue(reader *bufio.Reader, s string) string {
out.String("%s", s)
out.String("%s", false, s)

response, err := reader.ReadString('\n')
if err != nil {
2 changes: 1 addition & 1 deletion cmd/minikube/cmd/dashboard.go
Original file line number Diff line number Diff line change
@@ -112,7 +112,7 @@ var dashboardCmd = &cobra.Command{
if dashboardURLMode || user.Uid == "0" {
out.Ln(url)
} else {
out.Step(style.Celebrate, "Opening {{.url}} in your default browser...", out.V{"url": url})
out.Step(style.Celebrate, "Opening {{.url}} in your default browser...", false, out.V{"url": url})
if err = browser.OpenURL(url); err != nil {
exit.Message(reason.HostBrowser, "failed to open browser: {{.error}}", out.V{"error": err})
}
20 changes: 10 additions & 10 deletions cmd/minikube/cmd/delete.go
Original file line number Diff line number Diff line change
@@ -142,7 +142,7 @@ func runDelete(cmd *cobra.Command, args []string) {
if purge && len(profilesToDelete) > 1 && !deleteAll {
out.ErrT(style.Notice, "Multiple minikube profiles were found - ")
for _, p := range profilesToDelete {
out.Step(style.Notice, " - {{.profile}}", out.V{"profile": p.Name})
out.Step(style.Notice, " - {{.profile}}", false, out.V{"profile": p.Name})
}
exit.Message(reason.Usage, "Usage: minikube delete --all --purge")
}
@@ -157,7 +157,7 @@ func runDelete(cmd *cobra.Command, args []string) {
if len(errs) > 0 {
HandleDeletionErrors(errs)
} else {
out.Step(style.DeletingHost, "Successfully deleted all profiles")
out.Step(style.DeletingHost, "Successfully deleted all profiles", false)
}
} else {
if len(args) > 0 {
@@ -198,7 +198,7 @@ func purgeMinikubeDirectory() {
if err := os.RemoveAll(localpath.MiniPath()); err != nil {
exit.Error(reason.HostPurge, "unable to delete minikube config folder", err)
}
out.Step(style.Deleted, "Successfully purged minikube directory located at - [{{.minikubeDirectory}}]", out.V{"minikubeDirectory": localpath.MiniPath()})
out.Step(style.Deleted, "Successfully purged minikube directory located at - [{{.minikubeDirectory}}]", false, out.V{"minikubeDirectory": localpath.MiniPath()})
}

// DeleteProfiles deletes one or more profiles
@@ -246,7 +246,7 @@ func deletePossibleKicLeftOver(cname string, driverName string) {
cs, err := oci.ListContainersByLabel(bin, delLabel)
if err == nil && len(cs) > 0 {
for _, c := range cs {
out.Step(style.DeletingHost, `Deleting container "{{.name}}" ...`, out.V{"name": cname})
out.Step(style.DeletingHost, `Deleting container "{{.name}}" ...`, false, out.V{"name": cname})
err := oci.DeleteContainer(bin, c)
if err != nil { // it will error if there is no container to delete
klog.Errorf("error deleting container %q. You may want to delete it manually :\n%v", cname, err)
@@ -286,7 +286,7 @@ func deleteProfile(profile *config.Profile) error {

// if driver is oci driver, delete containers and volumes
if driver.IsKIC(profile.Config.Driver) {
out.Step(style.DeletingHost, `Deleting "{{.profile_name}}" in {{.driver_name}} ...`, out.V{"profile_name": profile.Name, "driver_name": profile.Config.Driver})
out.Step(style.DeletingHost, `Deleting "{{.profile_name}}" in {{.driver_name}} ...`, false, out.V{"profile_name": profile.Name, "driver_name": profile.Config.Driver})
for _, n := range profile.Config.Nodes {
machineName := driver.MachineName(*profile.Config, n)
deletePossibleKicLeftOver(machineName, profile.Config.Driver)
@@ -337,7 +337,7 @@ func deleteProfile(profile *config.Profile) error {
if err := deleteContext(profile.Name); err != nil {
return err
}
out.Step(style.Deleted, `Removed all traces of the "{{.name}}" cluster.`, out.V{"name": profile.Name})
out.Step(style.Deleted, `Removed all traces of the "{{.name}}" cluster.`, false, out.V{"name": profile.Name})
return nil
}

@@ -353,7 +353,7 @@ func deleteHosts(api libmachine.API, cc *config.ClusterConfig) {
klog.Infof("Host %s does not exist. Proceeding ahead with cleanup.", machineName)
default:
out.FailureT("Failed to delete cluster: {{.error}}", out.V{"error": err})
out.Step(style.Notice, `You may need to manually remove the "{{.name}}" VM from your hypervisor`, out.V{"name": machineName})
out.Step(style.Notice, `You may need to manually remove the "{{.name}}" VM from your hypervisor`, false, out.V{"name": machineName})
}
}
}
@@ -384,7 +384,7 @@ func deleteContext(machineName string) error {
}

func deleteInvalidProfile(profile *config.Profile) []error {
out.Step(style.DeletingHost, "Trying to delete invalid profile {{.profile}}", out.V{"profile": profile.Name})
out.Step(style.DeletingHost, "Trying to delete invalid profile {{.profile}}", false, out.V{"profile": profile.Name})

var errs []error
pathToProfile := config.ProfileFolderPath(profile.Name, localpath.MiniPath())
@@ -410,7 +410,7 @@ func profileDeletionErr(cname string, additionalInfo string) error {
}

func uninstallKubernetes(api libmachine.API, cc config.ClusterConfig, n config.Node, bsName string) error {
out.Step(style.Resetting, "Uninstalling Kubernetes {{.kubernetes_version}} using {{.bootstrapper_name}} ...", out.V{"kubernetes_version": cc.KubernetesConfig.KubernetesVersion, "bootstrapper_name": bsName})
out.Step(style.Resetting, "Uninstalling Kubernetes {{.kubernetes_version}} using {{.bootstrapper_name}} ...", false, out.V{"kubernetes_version": cc.KubernetesConfig.KubernetesVersion, "bootstrapper_name": bsName})
host, err := machine.LoadHost(api, driver.MachineName(cc, n))
if err != nil {
return DeletionError{Err: fmt.Errorf("unable to load host: %v", err), Errtype: MissingCluster}
@@ -488,7 +488,7 @@ func handleMultipleDeletionErrors(errors []error) {
func deleteProfileDirectory(profile string) {
machineDir := filepath.Join(localpath.MiniPath(), "machines", profile)
if _, err := os.Stat(machineDir); err == nil {
out.Step(style.DeletingHost, `Removing {{.directory}} ...`, out.V{"directory": machineDir})
out.Step(style.DeletingHost, `Removing {{.directory}} ...`, false, out.V{"directory": machineDir})
err := os.RemoveAll(machineDir)
if err != nil {
exit.Error(reason.GuestProfileDeletion, "Unable to remove machine directory", err)
2 changes: 1 addition & 1 deletion cmd/minikube/cmd/generate-docs.go
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@ var generateDocs = &cobra.Command{
if err := generate.Docs(RootCmd, path); err != nil {
exit.Error(reason.InternalGenerateDocs, "Unable to generate docs", err)
}
out.Step(style.Documentation, "Docs have been saved at - {{.path}}", out.V{"path": path})
out.Step(style.Documentation, "Docs have been saved at - {{.path}}", false, out.V{"path": path})
},
}

12 changes: 6 additions & 6 deletions cmd/minikube/cmd/mount.go
Original file line number Diff line number Diff line change
@@ -154,7 +154,7 @@ var mountCmd = &cobra.Command{
if driver.IsKIC(co.CP.Host.Driver.DriverName()) && runtime.GOOS != "linux" {
bindIP = "127.0.0.1"
}
out.Step(style.Mounting, "Mounting host path {{.sourcePath}} into VM as {{.destinationPath}} ...", out.V{"sourcePath": hostPath, "destinationPath": vmPath})
out.Step(style.Mounting, "Mounting host path {{.sourcePath}} into VM as {{.destinationPath}} ...", false, out.V{"sourcePath": hostPath, "destinationPath": vmPath})
out.Infof("Mount type: {{.name}}", out.V{"type": cfg.Type})
out.Infof("User ID: {{.userID}}", out.V{"userID": cfg.UID})
out.Infof("Group ID: {{.groupID}}", out.V{"groupID": cfg.GID})
@@ -168,9 +168,9 @@ var mountCmd = &cobra.Command{
if cfg.Type == nineP {
wg.Add(1)
go func() {
out.Step(style.Fileserver, "Userspace file server: ")
out.Step(style.Fileserver, "Userspace file server: ", false)
ufs.StartServer(net.JoinHostPort(bindIP, strconv.Itoa(port)), debugVal, hostPath)
out.Step(style.Stopped, "Userspace file server is shutdown")
out.Step(style.Stopped, "Userspace file server is shutdown", false)
wg.Done()
}()
}
@@ -180,7 +180,7 @@ var mountCmd = &cobra.Command{
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
for sig := range c {
out.Step(style.Unmount, "Unmounting {{.path}} ...", out.V{"path": vmPath})
out.Step(style.Unmount, "Unmounting {{.path}} ...", false, out.V{"path": vmPath})
err := cluster.Unmount(co.CP.Runner, vmPath)
if err != nil {
out.FailureT("Failed unmount: {{.error}}", out.V{"error": err})
@@ -193,9 +193,9 @@ var mountCmd = &cobra.Command{
if err != nil {
exit.Error(reason.GuestMount, "mount failed", err)
}
out.Step(style.Success, "Successfully mounted {{.sourcePath}} to {{.destinationPath}}", out.V{"sourcePath": hostPath, "destinationPath": vmPath})
out.Step(style.Success, "Successfully mounted {{.sourcePath}} to {{.destinationPath}}", false, out.V{"sourcePath": hostPath, "destinationPath": vmPath})
out.Ln("")
out.Step(style.Notice, "NOTE: This process must stay alive for the mount to be accessible ...")
out.Step(style.Notice, "NOTE: This process must stay alive for the mount to be accessible ...", false)
wg.Wait()
},
}
4 changes: 2 additions & 2 deletions cmd/minikube/cmd/node_add.go
Original file line number Diff line number Diff line change
@@ -48,7 +48,7 @@ var nodeAddCmd = &cobra.Command{

name := node.Name(len(cc.Nodes) + 1)

out.Step(style.Happy, "Adding node {{.name}} to cluster {{.cluster}}", out.V{"name": name, "cluster": cc.Name})
out.Step(style.Happy, "Adding node {{.name}} to cluster {{.cluster}}", false, out.V{"name": name, "cluster": cc.Name})

// TODO: Deal with parameters better. Ideally we should be able to acceot any node-specific minikube start params here.
n := config.Node{
@@ -77,7 +77,7 @@ var nodeAddCmd = &cobra.Command{
exit.Error(reason.HostSaveProfile, "failed to save config", err)
}

out.Step(style.Ready, "Successfully added {{.name}} to {{.cluster}}!", out.V{"name": name, "cluster": cc.Name})
out.Step(style.Ready, "Successfully added {{.name}} to {{.cluster}}!", false, out.V{"name": name, "cluster": cc.Name})
},
}

4 changes: 2 additions & 2 deletions cmd/minikube/cmd/node_delete.go
Original file line number Diff line number Diff line change
@@ -38,7 +38,7 @@ var nodeDeleteCmd = &cobra.Command{
name := args[0]

co := mustload.Healthy(ClusterFlagValue())
out.Step(style.DeletingHost, "Deleting node {{.name}} from cluster {{.cluster}}", out.V{"name": name, "cluster": co.Config.Name})
out.Step(style.DeletingHost, "Deleting node {{.name}} from cluster {{.cluster}}", false, out.V{"name": name, "cluster": co.Config.Name})

n, err := node.Delete(*co.Config, name)
if err != nil {
@@ -50,7 +50,7 @@ var nodeDeleteCmd = &cobra.Command{
deletePossibleKicLeftOver(machineName, co.Config.Driver)
}

out.Step(style.Deleted, "Node {{.name}} was successfully deleted.", out.V{"name": name})
out.Step(style.Deleted, "Node {{.name}} was successfully deleted.", false, out.V{"name": name})
},
}

4 changes: 2 additions & 2 deletions cmd/minikube/cmd/node_start.go
Original file line number Diff line number Diff line change
@@ -50,7 +50,7 @@ var nodeStartCmd = &cobra.Command{

machineName := driver.MachineName(*cc, *n)
if machine.IsRunning(api, machineName) {
out.Step(style.Check, "{{.name}} is already running", out.V{"name": name})
out.Step(style.Check, "{{.name}} is already running", false, out.V{"name": name})
os.Exit(0)
}

@@ -77,7 +77,7 @@ var nodeStartCmd = &cobra.Command{
exit.Error(reason.GuestNodeStart, "failed to start node", err)
}
}
out.Step(style.Happy, "Successfully started node {{.name}}!", out.V{"name": machineName})
out.Step(style.Happy, "Successfully started node {{.name}}!", false, out.V{"name": machineName})
},
}

2 changes: 1 addition & 1 deletion cmd/minikube/cmd/node_stop.go
Original file line number Diff line number Diff line change
@@ -51,7 +51,7 @@ var nodeStopCmd = &cobra.Command{
if err != nil {
out.FatalT("Failed to stop node {{.name}}", out.V{"name": name})
}
out.Step(style.Stopped, "Successfully stopped node {{.name}}", out.V{"name": machineName})
out.Step(style.Stopped, "Successfully stopped node {{.name}}", false, out.V{"name": machineName})
},
}

4 changes: 2 additions & 2 deletions cmd/minikube/cmd/options.go
Original file line number Diff line number Diff line change
@@ -37,9 +37,9 @@ var optionsCmd = &cobra.Command{

// runOptions handles the executes the flow of "minikube options"
func runOptions(cmd *cobra.Command, args []string) {
out.String("The following options can be passed to any command:\n\n")
out.String("The following options can be passed to any command:\n\n", false)
cmd.Root().PersistentFlags().VisitAll(func(flag *pflag.Flag) {
out.String(flagUsage(flag))
out.String(flagUsage(flag), false)
})
}

6 changes: 3 additions & 3 deletions cmd/minikube/cmd/pause.go
Original file line number Diff line number Diff line change
@@ -71,7 +71,7 @@ func runPause(cmd *cobra.Command, args []string) {
name = co.Config.Name
}

out.Step(style.Pause, "Pausing node {{.name}} ... ", out.V{"name": name})
out.Step(style.Pause, "Pausing node {{.name}} ... ", false, out.V{"name": name})

host, err := machine.LoadHost(co.API, driver.MachineName(*co.Config, n))
if err != nil {
@@ -97,9 +97,9 @@ func runPause(cmd *cobra.Command, args []string) {

register.Reg.SetStep(register.Done)
if namespaces == nil {
out.Step(style.Unpause, "Paused {{.count}} containers", out.V{"count": len(ids)})
out.Step(style.Unpause, "Paused {{.count}} containers", false, out.V{"count": len(ids)})
} else {
out.Step(style.Unpause, "Paused {{.count}} containers in: {{.namespaces}}", out.V{"count": len(ids), "namespaces": strings.Join(namespaces, ", ")})
out.Step(style.Unpause, "Paused {{.count}} containers in: {{.namespaces}}", false, out.V{"count": len(ids), "namespaces": strings.Join(namespaces, ", ")})
}
}

6 changes: 3 additions & 3 deletions cmd/minikube/cmd/service.go
Original file line number Diff line number Diff line change
@@ -155,16 +155,16 @@ func openURLs(svc string, urls []string) {
_, err := url.Parse(u)
if err != nil {
klog.Warningf("failed to parse url %q: %v (will not open)", u, err)
out.String(fmt.Sprintf("%s\n", u))
out.String(fmt.Sprintf("%s\n", u), false)
continue
}

if serviceURLMode {
out.String(fmt.Sprintf("%s\n", u))
out.String(fmt.Sprintf("%s\n", u), false)
continue
}

out.Step(style.Celebrate, "Opening service {{.namespace_name}}/{{.service_name}} in default browser...", out.V{"namespace_name": namespace, "service_name": svc})
out.Step(style.Celebrate, "Opening service {{.namespace_name}}/{{.service_name}} in default browser...", false, out.V{"namespace_name": namespace, "service_name": svc})
if err := browser.OpenURL(u); err != nil {
exit.Error(reason.HostBrowser, fmt.Sprintf("open url failed: %s", u), err)
}
Loading