github.com/nicgrayson/terraform@v0.4.3-0.20150415203910-c4de50829380/panic.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"strings"
     8  
     9  	"github.com/mitchellh/panicwrap"
    10  )
    11  
    12  // This output is shown if a panic happens.
    13  const panicOutput = `
    14  
    15  !!!!!!!!!!!!!!!!!!!!!!!!!!! TERRAFORM CRASH !!!!!!!!!!!!!!!!!!!!!!!!!!!!
    16  
    17  Terraform crashed! This is always indicative of a bug within Terraform.
    18  A crash log has been placed at "crash.log" relative to your current
    19  working directory. It would be immensely helpful if you could please
    20  report the crash with Terraform[1] so that we can fix this.
    21  
    22  [1]: https://github.com/hashicorp/terraform/issues
    23  
    24  !!!!!!!!!!!!!!!!!!!!!!!!!!! TERRAFORM CRASH !!!!!!!!!!!!!!!!!!!!!!!!!!!!
    25  `
    26  
    27  // panicHandler is what is called by panicwrap when a panic is encountered
    28  // within Terraform. It is guaranteed to run after the resulting process has
    29  // exited so we can take the log file, add in the panic, and store it
    30  // somewhere locally.
    31  func panicHandler(logF *os.File) panicwrap.HandlerFunc {
    32  	return func(m string) {
    33  		// Right away just output this thing on stderr so that it gets
    34  		// shown in case anything below fails.
    35  		fmt.Fprintf(os.Stderr, fmt.Sprintf("%s\n", m))
    36  
    37  		// Create the crash log file where we'll write the logs
    38  		f, err := os.Create("crash.log")
    39  		if err != nil {
    40  			fmt.Fprintf(os.Stderr, "Failed to create crash log file: %s", err)
    41  			return
    42  		}
    43  		defer f.Close()
    44  
    45  		// Seek the log file back to the beginning
    46  		if _, err = logF.Seek(0, 0); err != nil {
    47  			fmt.Fprintf(os.Stderr, "Failed to seek log file for crash: %s", err)
    48  			return
    49  		}
    50  
    51  		// Copy the contents to the crash file. This will include
    52  		// the panic that just happened.
    53  		if _, err = io.Copy(f, logF); err != nil {
    54  			fmt.Fprintf(os.Stderr, "Failed to write crash log: %s", err)
    55  			return
    56  		}
    57  
    58  		// Tell the user a crash occurred in some helpful way that
    59  		// they'll hopefully notice.
    60  		fmt.Printf("\n\n")
    61  		fmt.Println(strings.TrimSpace(panicOutput))
    62  	}
    63  }