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