Skip to content
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 3 commits into from
May 16, 2016
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
201 changes: 198 additions & 3 deletions command/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Copy link
Contributor

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


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")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This message isn't right if they set the job flag

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-> % nomad fs -job example
Mode        Size  Modfied Time           Name
drwxrwxr-x  22 B  16/05/16 13:10:58 EDT  alloc/
drwxrwxr-x  16 B  16/05/16 13:10:58 EDT  redis/

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,
Expand Down
143 changes: 0 additions & 143 deletions command/fs_cat.go

This file was deleted.

Loading