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 }