예제 #1
0
// 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
}
예제 #2
0
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)
}