-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor fs subcommands into fs command #1150
Merged
Merged
Changes from 2 commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,27 +2,222 @@ package command | |
|
||
import ( | ||
"fmt" | ||
"io" | ||
"math/rand" | ||
"os" | ||
"strings" | ||
"time" | ||
|
||
humanize "github.com/dustin/go-humanize" | ||
"github.com/hashicorp/nomad/api" | ||
"github.com/mitchellh/cli" | ||
) | ||
|
||
type FSCommand struct { | ||
Meta | ||
} | ||
|
||
func (f *FSCommand) Help() string { | ||
return "This command is accessed by using one of the subcommands below." | ||
helpText := ` | ||
Usage: nomad fs <alloc-id> <path> | ||
|
||
fs displays either the contents of an allocation directory for the passed allocation, | ||
or displays the file at the given path. The path is relative to the root of the alloc | ||
dir and defaults to root if unspecified. | ||
|
||
General Options: | ||
|
||
` + generalOptionsUsage() + ` | ||
|
||
Fs Options: | ||
|
||
-H | ||
Machine friendly output. | ||
|
||
-verbose | ||
Show full information. | ||
|
||
-job <job-id> | ||
Use a random allocation from a specified job-id. | ||
|
||
-stat | ||
Show file stat information instead of displaying the file, or listing the directory. | ||
|
||
` | ||
return strings.TrimSpace(helpText) | ||
} | ||
|
||
func (f *FSCommand) Synopsis() string { | ||
return "Inspect the contents of an allocation directory" | ||
} | ||
|
||
func (f *FSCommand) Run(args []string) int { | ||
return cli.RunResultHelp | ||
var verbose, machine, job, stat bool | ||
flags := f.Meta.FlagSet("fs-list", FlagSetClient) | ||
flags.Usage = func() { f.Ui.Output(f.Help()) } | ||
flags.BoolVar(&verbose, "verbose", false, "") | ||
flags.BoolVar(&machine, "H", false, "") | ||
flags.BoolVar(&job, "job", false, "") | ||
flags.BoolVar(&stat, "stat", false, "") | ||
|
||
if err := flags.Parse(args); err != nil { | ||
return 1 | ||
} | ||
args = flags.Args() | ||
|
||
if len(args) < 1 { | ||
f.Ui.Error("allocation id is a required parameter") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This message isn't right if they set the job flag There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
return 1 | ||
} | ||
|
||
path := "/" | ||
if len(args) == 2 { | ||
path = args[1] | ||
} | ||
|
||
client, err := f.Meta.Client() | ||
if err != nil { | ||
f.Ui.Error(fmt.Sprintf("Error initializing client: %v", err)) | ||
return 1 | ||
} | ||
|
||
// If -job is specified, use random allocation, otherwise use provided allocation | ||
allocID := args[0] | ||
if job { | ||
allocID, err = getRandomJobAlloc(client, args[0]) | ||
if err != nil { | ||
f.Ui.Error(fmt.Sprintf("Error fetching allocations: %v", err)) | ||
return 1 | ||
} | ||
} | ||
|
||
// Truncate the id unless full length is requested | ||
length := shortId | ||
if verbose { | ||
length = fullId | ||
} | ||
// Query the allocation info | ||
if len(allocID) == 1 { | ||
f.Ui.Error(fmt.Sprintf("Alloc ID must contain at least two characters.")) | ||
return 1 | ||
} | ||
if len(allocID)%2 == 1 { | ||
// Identifiers must be of even length, so we strip off the last byte | ||
// to provide a consistent user experience. | ||
allocID = allocID[:len(allocID)-1] | ||
} | ||
|
||
allocs, _, err := client.Allocations().PrefixList(allocID) | ||
if err != nil { | ||
f.Ui.Error(fmt.Sprintf("Error querying allocation: %v", err)) | ||
return 1 | ||
} | ||
if len(allocs) == 0 { | ||
f.Ui.Error(fmt.Sprintf("No allocation(s) with prefix or id %q found", allocID)) | ||
return 1 | ||
} | ||
if len(allocs) > 1 { | ||
// Format the allocs | ||
out := make([]string, len(allocs)+1) | ||
out[0] = "ID|Eval ID|Job ID|Task Group|Desired Status|Client Status" | ||
for i, alloc := range allocs { | ||
out[i+1] = fmt.Sprintf("%s|%s|%s|%s|%s|%s", | ||
limit(alloc.ID, length), | ||
limit(alloc.EvalID, length), | ||
alloc.JobID, | ||
alloc.TaskGroup, | ||
alloc.DesiredStatus, | ||
alloc.ClientStatus, | ||
) | ||
} | ||
f.Ui.Output(fmt.Sprintf("Prefix matched multiple allocations\n\n%s", formatList(out))) | ||
return 0 | ||
} | ||
// Prefix lookup matched a single allocation | ||
alloc, _, err := client.Allocations().Info(allocs[0].ID, nil) | ||
if err != nil { | ||
f.Ui.Error(fmt.Sprintf("Error querying allocation: %s", err)) | ||
return 1 | ||
} | ||
|
||
if alloc.DesiredStatus == "failed" { | ||
allocID := limit(alloc.ID, length) | ||
msg := fmt.Sprintf(`The allocation %q failed to be placed. To see the cause, run: | ||
nomad alloc-status %s`, allocID, allocID) | ||
f.Ui.Error(msg) | ||
return 0 | ||
} | ||
|
||
// Get file stat info | ||
file, _, err := client.AllocFS().Stat(alloc, path, nil) | ||
if err != nil { | ||
f.Ui.Error(err.Error()) | ||
return 1 | ||
} | ||
|
||
// If we want file stats, print those and exit. | ||
if stat { | ||
// Display the file information | ||
out := make([]string, 2) | ||
out[0] = "Mode|Size|Modified Time|Name" | ||
if file != nil { | ||
fn := file.Name | ||
if file.IsDir { | ||
fn = fmt.Sprintf("%s/", fn) | ||
} | ||
var size string | ||
if machine { | ||
size = fmt.Sprintf("%d", file.Size) | ||
} else { | ||
size = humanize.Bytes(uint64(file.Size)) | ||
} | ||
out[1] = fmt.Sprintf("%s|%s|%s|%s", file.FileMode, size, | ||
formatTime(file.ModTime), fn) | ||
} | ||
f.Ui.Output(formatList(out)) | ||
return 0 | ||
} | ||
|
||
// Determine if the path is a file or a directory. | ||
if file.IsDir { | ||
// We have a directory, list it. | ||
files, _, err := client.AllocFS().List(alloc, path, nil) | ||
if err != nil { | ||
f.Ui.Error(fmt.Sprintf("Error listing alloc dir: %s", err)) | ||
return 1 | ||
} | ||
// Display the file information in a tabular format | ||
out := make([]string, len(files)+1) | ||
out[0] = "Mode|Size|Modfied Time|Name" | ||
for i, file := range files { | ||
fn := file.Name | ||
if file.IsDir { | ||
fn = fmt.Sprintf("%s/", fn) | ||
} | ||
var size string | ||
if machine { | ||
size = fmt.Sprintf("%d", file.Size) | ||
} else { | ||
size = humanize.Bytes(uint64(file.Size)) | ||
} | ||
out[i+1] = fmt.Sprintf("%s|%s|%s|%s", | ||
file.FileMode, | ||
size, | ||
formatTime(file.ModTime), | ||
fn, | ||
) | ||
} | ||
f.Ui.Output(formatList(out)) | ||
} else { | ||
// We have a file, cat it. | ||
r, _, err := client.AllocFS().Cat(alloc, path, nil) | ||
if err != nil { | ||
f.Ui.Error(fmt.Sprintf("Error reading file: %s", err)) | ||
return 1 | ||
} | ||
io.Copy(os.Stdout, r) | ||
} | ||
|
||
return 0 | ||
} | ||
|
||
// Get Random Allocation ID from a known jobID. Prefer to use a running allocation, | ||
|
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix indents to be in-line with the rest of the commands