github.com/ryanslade/nomad@v0.2.4-0.20160128061903-fc95782f2089/command/fs_cat.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"strings"
     8  )
     9  
    10  type FSCatCommand struct {
    11  	Meta
    12  }
    13  
    14  func (f *FSCatCommand) Help() string {
    15  	helpText := `
    16  	Usage: nomad fs-cat <alloc-id> <path>
    17  
    18  	Dispays a file in an allocation directory at the given path.
    19  	The path is relative to the allocation directory and defaults to root if unspecified.
    20  
    21  	General Options:
    22  
    23    ` + generalOptionsUsage() + `
    24  
    25    -verbose
    26      Show full information.
    27  `
    28  	return strings.TrimSpace(helpText)
    29  }
    30  
    31  func (f *FSCatCommand) Synopsis() string {
    32  	return "displays a file at a given location"
    33  }
    34  
    35  func (f *FSCatCommand) Run(args []string) int {
    36  	var verbose bool
    37  	flags := f.Meta.FlagSet("fs-list", FlagSetClient)
    38  	flags.Usage = func() { f.Ui.Output(f.Help()) }
    39  	flags.BoolVar(&verbose, "verbose", false, "")
    40  
    41  	if err := flags.Parse(args); err != nil {
    42  		return 1
    43  	}
    44  	args = flags.Args()
    45  
    46  	if len(args) < 1 {
    47  		f.Ui.Error("allocation id is a required parameter")
    48  		return 1
    49  	}
    50  
    51  	allocID := args[0]
    52  	path := "/"
    53  	if len(args) == 2 {
    54  		path = args[1]
    55  	}
    56  
    57  	client, err := f.Meta.Client()
    58  	if err != nil {
    59  		f.Ui.Error(fmt.Sprintf("Error inititalizing client: %v", err))
    60  		return 1
    61  	}
    62  
    63  	// Truncate the id unless full length is requested
    64  	length := shortId
    65  	if verbose {
    66  		length = fullId
    67  	}
    68  	// Query the allocation info
    69  	alloc, _, err := client.Allocations().Info(allocID, nil)
    70  	if err != nil {
    71  		if len(allocID) == 1 {
    72  			f.Ui.Error(fmt.Sprintf("Alloc ID must contain at least two characters."))
    73  			return 1
    74  		}
    75  		if len(allocID)%2 == 1 {
    76  			// Identifiers must be of even length, so we strip off the last byte
    77  			// to provide a consistent user experience.
    78  			allocID = allocID[:len(allocID)-1]
    79  		}
    80  
    81  		allocs, _, err := client.Allocations().PrefixList(allocID)
    82  		if err != nil {
    83  			f.Ui.Error(fmt.Sprintf("Error querying allocation: %v", err))
    84  			return 1
    85  		}
    86  		if len(allocs) == 0 {
    87  			f.Ui.Error(fmt.Sprintf("No allocation(s) with prefix or id %q found", allocID))
    88  			return 1
    89  		}
    90  		if len(allocs) > 1 {
    91  			// Format the allocs
    92  			out := make([]string, len(allocs)+1)
    93  			out[0] = "ID|Eval ID|Job ID|Task Group|Desired Status|Client Status"
    94  			for i, alloc := range allocs {
    95  				out[i+1] = fmt.Sprintf("%s|%s|%s|%s|%s|%s",
    96  					limit(alloc.ID, length),
    97  					limit(alloc.EvalID, length),
    98  					alloc.JobID,
    99  					alloc.TaskGroup,
   100  					alloc.DesiredStatus,
   101  					alloc.ClientStatus,
   102  				)
   103  			}
   104  			f.Ui.Output(fmt.Sprintf("Prefix matched multiple allocations\n\n%s", formatList(out)))
   105  			return 0
   106  		}
   107  		// Prefix lookup matched a single allocation
   108  		alloc, _, err = client.Allocations().Info(allocs[0].ID, nil)
   109  		if err != nil {
   110  			f.Ui.Error(fmt.Sprintf("Error querying allocation: %s", err))
   111  			return 1
   112  		}
   113  	}
   114  
   115  	// Stat the file to find it's size
   116  	file, _, err := client.AllocFS().Stat(alloc, path, nil)
   117  	if err != nil {
   118  		f.Ui.Error(err.Error())
   119  		return 1
   120  	}
   121  	if file.IsDir {
   122  		f.Ui.Error(fmt.Sprintf("The file %q is a directory", file.Name))
   123  		return 1
   124  	}
   125  
   126  	// Get the contents of the file
   127  	offset := 0
   128  	limit := file.Size
   129  	r, _, err := client.AllocFS().ReadAt(alloc, path, int64(offset), limit, nil)
   130  	if err != nil {
   131  		f.Ui.Error(fmt.Sprintf("Error reading file: %v", err))
   132  		return 1
   133  	}
   134  	io.Copy(os.Stdout, r)
   135  	return 0
   136  }