// handleLogs send the log message of an app. func handleLogs(request *api.Request) (interface{}, error) { // Map the data to the custom type. var data api.RequestLogs err := request.MapTo(&data) if err != nil { return nil, err } // Validate. if len(data.Name) == 0 { return nil, fmt.Errorf("missing or invalid data: %+v", data) } // Obtain the app with the given name. a, err := apps.Get(data.Name) if err != nil { return nil, fmt.Errorf("failed to get log message: %v", err) } // Create the response value. res := api.ResponseLogs{} // If no specific container is passed, // then send a list of all available containers. if len(data.Container) == 0 { res.Containers, err = a.Containers() if err != nil { return nil, fmt.Errorf("failed to get app containers: %v", err) } } else { var streamType docker.StdStream = docker.StdStreamCombined // Get the stream option. if len(data.Stream) > 0 { if data.Stream == "stderr" { streamType = docker.StdStreamError } else if data.Stream == "stdout" { streamType = docker.StdStreamOutput } else { return nil, fmt.Errorf("failed to get log messages: invalid stream option.") } } // Get the log messages. logs, err := docker.Logs(a.ContainerNamePrefix()+data.Container, streamType) if err != nil { return nil, fmt.Errorf("failed to get log messages: %v", err) } // Set the response log messages. res.LogMessages = logs } return res, nil }
func _checkRestart(app *App, retryCount int) (err error) { // Increment the retry count. retryCount++ var stoppedContainers []*d.Container // Get all containers which stopped running. for _, id := range app.containerIDs { // Obtain the container with its ID. c, err := docker.Client.InspectContainer(id) if err != nil { return err } // Check if not running. if !c.State.Running { // Append the stopped container to the slice. stoppedContainers = append(stoppedContainers, c) // Log log.WithFields( log.Fields{ "app": app.name, "container ID": c.ID, "container name": c.Name, }).Warning("app container stopped running!") } } // Return if everything is ok. if len(stoppedContainers) == 0 { return nil } // Abort and return an error if the retry count is reached. if retryCount > maximumRestartRetryCount { var errStr string // Obtain the error logs from the stopped containers. for _, c := range stoppedContainers { stderr, err := docker.Logs(c.ID, docker.StdStreamError) if err != nil { log.Errorln(err) continue } // Add a spacing to each error line. lines := strings.Split(stderr, "\n") for i := 0; i < len(lines); i++ { lines[i] = " " + lines[i] } stderr = " " + strings.TrimSpace(strings.Join(lines, "\n")) errStr += fmt.Sprintf("\n\nContainer '%s' error output:\n%s", c.Name, stderr) } return fmt.Errorf("failed to restart app: max restart retries reached! App '%s' stopped running!%s", app.name, errStr) } // Set the app state. app.setState("restarting app...") // Log. log.Infof("restarting app '%s'", app.name) // First stop and remove all app containers. if err = stopContainers(app); err != nil { return err } // Start the app containers again. if err = startContainers(app); err != nil { return err } // Recall this method to recheck the state. return _checkRestart(app, retryCount) }