diff --git a/cmd/diagnostics.go b/cmd/diagnostics.go index e726d71..b487c9f 100644 --- a/cmd/diagnostics.go +++ b/cmd/diagnostics.go @@ -15,14 +15,15 @@ import ( "strings" "time" - "github.com/pterodactyl/wings/environment" - "github.com/AlecAivazis/survey/v2" "github.com/AlecAivazis/survey/v2/terminal" + "github.com/apex/log" "github.com/docker/docker/api/types" "github.com/docker/docker/pkg/parsers/kernel" "github.com/docker/docker/pkg/parsers/operatingsystem" "github.com/pterodactyl/wings/config" + "github.com/pterodactyl/wings/environment" + "github.com/pterodactyl/wings/loggers/cli" "github.com/pterodactyl/wings/system" "github.com/spf13/cobra" ) @@ -40,15 +41,21 @@ var ( } ) -var diagnosticsCmd = &cobra.Command{ - Use: "diagnostics", - Short: "Collect diagnostics information.", - Run: diagnosticsCmdRun, -} +func newDiagnosticsCommand() *cobra.Command { + command := &cobra.Command{ + Use: "diagnostics", + Short: "Collect and report information about this Wings instance to assist in debugging.", + PreRun: func(cmd *cobra.Command, args []string) { + initConfig() + log.SetHandler(cli.Default) + }, + Run: diagnosticsCmdRun, + } -func init() { - diagnosticsCmd.PersistentFlags().StringVar(&diagnosticsArgs.HastebinURL, "hastebin-url", DefaultHastebinUrl, "The url of the hastebin instance to use.") - diagnosticsCmd.PersistentFlags().IntVar(&diagnosticsArgs.LogLines, "log-lines", DefaultLogLines, "The number of log lines to include in the report") + command.Flags().StringVar(&diagnosticsArgs.HastebinURL, "hastebin-url", DefaultHastebinUrl, "the url of the hastebin instance to use") + command.Flags().IntVar(&diagnosticsArgs.LogLines, "log-lines", DefaultLogLines, "the number of log lines to include in the report") + + return command } // diagnosticsCmdRun collects diagnostics about wings, it's configuration and the node. @@ -85,7 +92,6 @@ func diagnosticsCmdRun(cmd *cobra.Command, args []string) { } dockerVersion, dockerInfo, dockerErr := getDockerInfo() - _ = dockerInfo output := &strings.Builder{} fmt.Fprintln(output, "Pterodactyl Wings - Diagnostics Report") @@ -102,50 +108,53 @@ func diagnosticsCmdRun(cmd *cobra.Command, args []string) { } printHeader(output, "Wings Configuration") - cfg, err := config.FromFile(config.DefaultLocation) - if cfg != nil { - fmt.Fprintln(output, " Panel Location:", redact(cfg.PanelLocation)) - fmt.Fprintln(output, "") - fmt.Fprintln(output, " Internal Webserver:", redact(cfg.Api.Host), ":", cfg.Api.Port) - fmt.Fprintln(output, " SSL Enabled:", cfg.Api.Ssl.Enabled) - fmt.Fprintln(output, " SSL Certificate:", redact(cfg.Api.Ssl.CertificateFile)) - fmt.Fprintln(output, " SSL Key:", redact(cfg.Api.Ssl.KeyFile)) - fmt.Fprintln(output, "") - fmt.Fprintln(output, " SFTP Server:", redact(cfg.System.Sftp.Address), ":", cfg.System.Sftp.Port) - fmt.Fprintln(output, " SFTP Read-Only:", cfg.System.Sftp.ReadOnly) - fmt.Fprintln(output, "") - fmt.Fprintln(output, " Root Directory:", cfg.System.RootDirectory) - fmt.Fprintln(output, " Logs Directory:", cfg.System.LogDirectory) - fmt.Fprintln(output, " Data Directory:", cfg.System.Data) - fmt.Fprintln(output, " Archive Directory:", cfg.System.ArchiveDirectory) - fmt.Fprintln(output, " Backup Directory:", cfg.System.BackupDirectory) - fmt.Fprintln(output, "") - fmt.Fprintln(output, " Username:", cfg.System.Username) - fmt.Fprintln(output, " Server Time:", time.Now().Format(time.RFC1123Z)) - fmt.Fprintln(output, " Debug Mode:", cfg.Debug) - } else { - fmt.Println("Failed to load configuration.", err) + if err := config.FromFile(config.DefaultLocation); err != nil { + } + cfg := config.Get() + fmt.Fprintln(output, " Panel Location:", redact(cfg.PanelLocation)) + fmt.Fprintln(output, "") + fmt.Fprintln(output, " Internal Webserver:", redact(cfg.Api.Host), ":", cfg.Api.Port) + fmt.Fprintln(output, " SSL Enabled:", cfg.Api.Ssl.Enabled) + fmt.Fprintln(output, " SSL Certificate:", redact(cfg.Api.Ssl.CertificateFile)) + fmt.Fprintln(output, " SSL Key:", redact(cfg.Api.Ssl.KeyFile)) + fmt.Fprintln(output, "") + fmt.Fprintln(output, " SFTP Server:", redact(cfg.System.Sftp.Address), ":", cfg.System.Sftp.Port) + fmt.Fprintln(output, " SFTP Read-Only:", cfg.System.Sftp.ReadOnly) + fmt.Fprintln(output, "") + fmt.Fprintln(output, " Root Directory:", cfg.System.RootDirectory) + fmt.Fprintln(output, " Logs Directory:", cfg.System.LogDirectory) + fmt.Fprintln(output, " Data Directory:", cfg.System.Data) + fmt.Fprintln(output, " Archive Directory:", cfg.System.ArchiveDirectory) + fmt.Fprintln(output, " Backup Directory:", cfg.System.BackupDirectory) + fmt.Fprintln(output, "") + fmt.Fprintln(output, " Username:", cfg.System.Username) + fmt.Fprintln(output, " Server Time:", time.Now().Format(time.RFC1123Z)) + fmt.Fprintln(output, " Debug Mode:", cfg.Debug) printHeader(output, "Docker: Info") - fmt.Fprintln(output, "Server Version:", dockerInfo.ServerVersion) - fmt.Fprintln(output, "Storage Driver:", dockerInfo.Driver) - if dockerInfo.DriverStatus != nil { - for _, pair := range dockerInfo.DriverStatus { - fmt.Fprintf(output, " %s: %s\n", pair[0], pair[1]) + if dockerErr == nil { + fmt.Fprintln(output, "Server Version:", dockerInfo.ServerVersion) + fmt.Fprintln(output, "Storage Driver:", dockerInfo.Driver) + if dockerInfo.DriverStatus != nil { + for _, pair := range dockerInfo.DriverStatus { + fmt.Fprintf(output, " %s: %s\n", pair[0], pair[1]) + } } - } - if dockerInfo.SystemStatus != nil { - for _, pair := range dockerInfo.SystemStatus { - fmt.Fprintf(output, " %s: %s\n", pair[0], pair[1]) + if dockerInfo.SystemStatus != nil { + for _, pair := range dockerInfo.SystemStatus { + fmt.Fprintf(output, " %s: %s\n", pair[0], pair[1]) + } } - } - fmt.Fprintln(output, "LoggingDriver:", dockerInfo.LoggingDriver) - fmt.Fprintln(output, " CgroupDriver:", dockerInfo.CgroupDriver) - if len(dockerInfo.Warnings) > 0 { - for _, w := range dockerInfo.Warnings { - fmt.Fprintln(output, w) + fmt.Fprintln(output, "LoggingDriver:", dockerInfo.LoggingDriver) + fmt.Fprintln(output, " CgroupDriver:", dockerInfo.CgroupDriver) + if len(dockerInfo.Warnings) > 0 { + for _, w := range dockerInfo.Warnings { + fmt.Fprintln(output, w) + } } + } else { + fmt.Fprintln(output, dockerErr.Error()) } printHeader(output, "Docker: Running Containers") @@ -180,23 +189,23 @@ func diagnosticsCmdRun(cmd *cobra.Command, args []string) { survey.AskOne(&survey.Confirm{Message: "Upload to " + diagnosticsArgs.HastebinURL + "?", Default: false}, &upload) } if upload { - url, err := uploadToHastebin(diagnosticsArgs.HastebinURL, output.String()) + u, err := uploadToHastebin(diagnosticsArgs.HastebinURL, output.String()) if err == nil { - fmt.Println("Your report is available here: ", url) + fmt.Println("Your report is available here: ", u) } } } func getDockerInfo() (types.Version, types.Info, error) { - cli, err := environment.Docker() + client, err := environment.Docker() if err != nil { return types.Version{}, types.Info{}, err } - dockerVersion, err := cli.ServerVersion(context.Background()) + dockerVersion, err := client.ServerVersion(context.Background()) if err != nil { return types.Version{}, types.Info{}, err } - dockerInfo, err := cli.Info(context.Background()) + dockerInfo, err := client.Info(context.Background()) if err != nil { return types.Version{}, types.Info{}, err } diff --git a/cmd/root.go b/cmd/root.go index 2d4e775..efc5b6a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -78,7 +78,7 @@ func init() { rootCommand.AddCommand(versionCommand) rootCommand.AddCommand(configureCmd) - rootCommand.AddCommand(diagnosticsCmd) + rootCommand.AddCommand(newDiagnosticsCommand()) } func rootCmdRun(cmd *cobra.Command, _ []string) { diff --git a/router/router_system.go b/router/router_system.go index 140decc..a3bad4d 100644 --- a/router/router_system.go +++ b/router/router_system.go @@ -72,37 +72,29 @@ func postCreateServer(c *gin.Context) { c.Status(http.StatusAccepted) } -// Updates the running configuration for this daemon instance. +// Updates the running configuration for this Wings instance. func postUpdateConfiguration(c *gin.Context) { - // A backup of the configuration for error purposes. - ccopy := *config.Get() - // A copy of the configuration we're using to bind the data received into. - cfg := *config.Get() - - // BindJSON sends 400 if the request fails, all we need to do is return + cfg := config.Get() if err := c.BindJSON(&cfg); err != nil { return } - // Keep the SSL certificates the same since the Panel will send through Lets Encrypt // default locations. However, if we picked a different location manually we don't // want to override that. // // If you pass through manual locations in the API call this logic will be skipped. if strings.HasPrefix(cfg.Api.Ssl.KeyFile, "/etc/letsencrypt/live/") { - cfg.Api.Ssl.KeyFile = strings.ToLower(ccopy.Api.Ssl.KeyFile) - cfg.Api.Ssl.CertificateFile = strings.ToLower(ccopy.Api.Ssl.CertificateFile) + cfg.Api.Ssl.KeyFile = strings.ToLower(config.Get().Api.Ssl.KeyFile) + cfg.Api.Ssl.CertificateFile = strings.ToLower(config.Get().Api.Ssl.CertificateFile) } - - config.Set(&cfg) - if err := config.Get().WriteToDisk(); err != nil { - // If there was an error writing to the disk, revert back to the configuration we had - // before this code was run. - config.Set(&ccopy) - - NewTrackedError(err).Abort(c) + // Try to write this new configuration to the disk before updating our global + // state with it. + if err := config.WriteToDisk(cfg); err != nil { + WithError(c, err) return } - + // Since we wrote it to the disk successfully now update the global configuration + // state to use this new configuration struct. + config.Set(cfg) c.Status(http.StatusNoContent) }