Skip to content

Commit

Permalink
feat(cli): Implement --all-namespaces flag (#129)
Browse files Browse the repository at this point in the history
  • Loading branch information
irvinlim authored Feb 11, 2023
1 parent 77c961f commit 1e86f73
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 16 deletions.
30 changes: 30 additions & 0 deletions pkg/cli/cmd/cmd_get_job_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,36 @@ var (
State: execution.JobStateQueued,
},
}

prodJobRunning = &execution.Job{
ObjectMeta: metav1.ObjectMeta{
Name: "job-running",
Namespace: ProdNamespace,
UID: testutils.MakeUID("prod/job-running"),
},
Status: execution.JobStatus{
Phase: execution.JobRunning,
State: execution.JobStateRunning,
Condition: execution.JobCondition{
Running: &execution.JobConditionRunning{
LatestCreationTimestamp: testutils.Mkmtime(taskCreateTime),
LatestRunningTimestamp: testutils.Mkmtime(taskLaunchTime),
},
},
StartTime: testutils.Mkmtimep(startTime),
CreatedTasks: 1,
Tasks: []execution.TaskRef{
{
Name: "job-running.1",
CreationTimestamp: testutils.Mkmtime(taskCreateTime),
RunningTimestamp: testutils.Mkmtimep(taskLaunchTime),
Status: execution.TaskStatus{
State: execution.TaskRunning,
},
},
},
},
}
)

func TestGetJobCommand(t *testing.T) {
Expand Down
22 changes: 22 additions & 0 deletions pkg/cli/cmd/cmd_get_jobconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,28 @@ var (
State: execution.JobConfigReadyEnabled,
},
}

prodJobConfig = &execution.JobConfig{
ObjectMeta: metav1.ObjectMeta{
Name: "periodic-jobconfig",
Namespace: ProdNamespace,
UID: testutils.MakeUID("prod/periodic-jobconfig"),
},
Spec: execution.JobConfigSpec{
Concurrency: execution.ConcurrencySpec{
Policy: execution.ConcurrencyPolicyForbid,
},
Schedule: &execution.ScheduleSpec{
Cron: &execution.CronSchedule{
Expression: "H/5 * * * *",
Timezone: "Asia/Singapore",
},
},
},
Status: execution.JobConfigStatus{
State: execution.JobConfigReadyEnabled,
},
}
)

func TestGetJobConfigCommand(t *testing.T) {
Expand Down
2 changes: 2 additions & 0 deletions pkg/cli/cmd/cmd_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ func (c *ListCommand) RegisterFlags(cmd *cobra.Command) {
cmd.Flags().String("field-selector", "",
"Selector (field query) to filter on, supports '=', '==', and '!=' (e.g. --field-selector key1=value1,key2=value2). "+
"The server only supports a limited number of field queries per type.")
cmd.Flags().BoolP("all-namespaces", "A", false,
"If specified, list the requested objects across all namespaces. Namespace in current context is ignored even if specified with --namespace.")

if err := completion.RegisterFlagCompletions(cmd, []completion.FlagCompletion{
{FlagName: "output", Completer: completion.NewSliceCompleter(printer.AllOutputFormats)},
Expand Down
35 changes: 25 additions & 10 deletions pkg/cli/cmd/cmd_list_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ var (
# List all Jobs in current namespace.
{{.CommandName}} list job
# List all Jobs across all namespaces.
{{.CommandName}} list job -A
# List all Jobs in current namespace belonging to JobConfig "daily-send-email".
{{.CommandName}} list job --for daily-send-email
Expand All @@ -50,12 +53,13 @@ var (
type ListJobCommand struct {
*baseListCommand

streams *streams.Streams
jobConfig string
states sets.Set[execution.JobState]
output printer.OutputFormat
noHeaders bool
watch bool
streams *streams.Streams
jobConfig string
states sets.Set[execution.JobState]
output printer.OutputFormat
noHeaders bool
watch bool
allNamespaces bool

// Cached set of job UIDs that were previously filtered in.
// If it was displayed before, we don't want to filter it out afterwards.
Expand Down Expand Up @@ -109,6 +113,7 @@ func (c *ListJobCommand) Complete(cmd *cobra.Command, args []string) error {
c.output = common.GetOutputFormat(cmd)
c.noHeaders = common.GetFlagBool(cmd, "no-headers")
c.watch = common.GetFlagBool(cmd, "watch")
c.allNamespaces = common.GetFlagBool(cmd, "all-namespaces")

// Handle --states.
if v := common.GetFlagString(cmd, "states"); v != "" {
Expand Down Expand Up @@ -242,13 +247,18 @@ func (c *ListJobCommand) PrintJob(p *printer.TablePrinter, job *execution.Job) e
}

func (c *ListJobCommand) makeJobHeader() []string {
return []string{
var columns []string
if c.allNamespaces {
columns = append(columns, "NAMESPACE")
}
columns = append(columns, []string{
"NAME",
"PHASE",
"START TIME",
"RUN TIME",
"FINISH TIME",
}
}...)
return columns
}

func (c *ListJobCommand) prettyPrint(p *printer.TablePrinter, jobs []*execution.Job) {
Expand Down Expand Up @@ -279,13 +289,18 @@ func (c *ListJobCommand) makeJobRow(job *execution.Job) []string {
finishTime = format.TimeAgo(&condition.FinishTimestamp)
}

return []string{
var row []string
if c.allNamespaces {
row = append(row, job.Namespace)
}
row = append(row, []string{
job.Name,
string(job.Status.Phase),
startTime,
runTime,
finishTime,
}
}...)
return row
}

// FilterJobs returns a filtered list of jobs.
Expand Down
53 changes: 53 additions & 0 deletions pkg/cli/cmd/cmd_list_job_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package cmd_test

import (
"regexp"
"testing"
"time"

Expand Down Expand Up @@ -55,6 +56,58 @@ func TestListJobCommand(t *testing.T) {
Contains: "job.execution.furiko.io/job-running",
},
},
{
Name: "only show jobs in the default namespace",
Args: []string{"list", "job", "-o", "yaml"},
Fixtures: []runtime.Object{
jobRunning,
prodJobRunning,
},
Stdout: runtimetesting.Output{
Contains: string(jobRunning.UID),
Excludes: string(prodJobRunning.UID),
},
},
{
Name: "use explicit namespace",
Args: []string{"list", "job", "-o", "yaml", "-n", ProdNamespace},
Fixtures: []runtime.Object{
jobRunning,
prodJobRunning,
},
Stdout: runtimetesting.Output{
Contains: string(prodJobRunning.UID),
Excludes: string(jobRunning.UID),
},
},
{
Name: "use all namespaces",
Args: []string{"list", "job", "-o", "yaml", "-A"},
Fixtures: []runtime.Object{
jobRunning,
prodJobRunning,
},
Stdout: runtimetesting.Output{
ContainsAll: []string{
string(prodJobRunning.UID),
string(jobRunning.UID),
},
},
},
{
Name: "use all namespaces, pretty print",
Args: []string{"list", "job", "-A"},
Fixtures: []runtime.Object{
jobRunning,
prodJobRunning,
},
Stdout: runtimetesting.Output{
MatchesAll: []*regexp.Regexp{
regexp.MustCompile(`default\s+job-running`),
regexp.MustCompile(`prod\s+job-running`),
},
},
},
{
Name: "can use alias",
Args: []string{"list", "jobs", "-o", "name"},
Expand Down
31 changes: 26 additions & 5 deletions pkg/cli/cmd/cmd_list_jobconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,16 @@ var (
# List all JobConfigs in current namespace.
{{.CommandName}} list jobconfig
# List all JobConfigs in JSON format.
# List all JobConfigs across all namespaces.
{{.CommandName}} list jobconfig -A
# List only JobConfigs with a schedule.
{{.CommandName}} list jobconfig --scheduled
# List adhoc-only JobConfigs (i.e. does not have a schedule).
{{.CommandName}} list jobconfig --adhoc-only
# List JobConfigs in JSON format.
{{.CommandName}} list jobconfig -o json`)
)

Expand All @@ -53,6 +62,7 @@ type ListJobConfigCommand struct {
adhocOnly bool
scheduleEnabled bool
watch bool
allNamespaces bool

// Cached cron parser.
cronParser *cron.Parser
Expand Down Expand Up @@ -99,6 +109,7 @@ func (c *ListJobConfigCommand) Complete(cmd *cobra.Command, args []string) error
c.output = common.GetOutputFormat(cmd)
c.noHeaders = common.GetFlagBool(cmd, "no-headers")
c.watch = common.GetFlagBool(cmd, "watch")
c.allNamespaces = common.GetFlagBool(cmd, "all-namespaces")

// Prepare parser.
c.cronParser = cron.NewParserFromConfig(common.GetCronDynamicConfig(cmd))
Expand Down Expand Up @@ -206,7 +217,11 @@ func (c *ListJobConfigCommand) prettyPrint(p *printer.TablePrinter, jobConfigs [
}

func (c *ListJobConfigCommand) makeJobHeader() []string {
return []string{
var columns []string
if c.allNamespaces {
columns = append(columns, "NAMESPACE")
}
columns = append(columns, []string{
"NAME",
"STATE",
"ACTIVE",
Expand All @@ -215,7 +230,8 @@ func (c *ListJobConfigCommand) makeJobHeader() []string {
"LAST SCHEDULED",
"CRON SCHEDULE",
"NEXT SCHEDULE",
}
}...)
return columns
}

func (c *ListJobConfigCommand) makeJobRows(jobConfigs []*execution.JobConfig) [][]string {
Expand All @@ -235,7 +251,11 @@ func (c *ListJobConfigCommand) makeJobRow(jobConfig *execution.JobConfig) []stri
}
}

return []string{
var row []string
if c.allNamespaces {
row = append(row, jobConfig.Namespace)
}
row = append(row, []string{
jobConfig.Name,
string(jobConfig.Status.State),
strconv.Itoa(int(jobConfig.Status.Active)),
Expand All @@ -244,7 +264,8 @@ func (c *ListJobConfigCommand) makeJobRow(jobConfig *execution.JobConfig) []stri
format.TimeAgo(jobConfig.Status.LastScheduled),
cronSchedule,
nextSchedule,
}
}...)
return row
}

// FilterJobConfigs returns a filtered list of job configs.
Expand Down
53 changes: 53 additions & 0 deletions pkg/cli/cmd/cmd_list_jobconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package cmd_test

import (
"regexp"
"testing"
"time"

Expand Down Expand Up @@ -54,6 +55,58 @@ func TestListJobConfigCommand(t *testing.T) {
Contains: "jobconfig.execution.furiko.io/periodic-jobconfig",
},
},
{
Name: "only show job configs in the default namespace",
Args: []string{"list", "jobconfig", "-o", "yaml"},
Fixtures: []runtime.Object{
periodicJobConfig,
prodJobConfig,
},
Stdout: runtimetesting.Output{
Contains: string(periodicJobConfig.UID),
Excludes: string(prodJobConfig.UID),
},
},
{
Name: "use explicit namespace",
Args: []string{"list", "jobconfig", "-o", "yaml", "-n", ProdNamespace},
Fixtures: []runtime.Object{
periodicJobConfig,
prodJobConfig,
},
Stdout: runtimetesting.Output{
Contains: string(prodJobConfig.UID),
Excludes: string(periodicJobConfig.UID),
},
},
{
Name: "use all namespaces",
Args: []string{"list", "jobconfig", "-o", "yaml", "-A"},
Fixtures: []runtime.Object{
periodicJobConfig,
prodJobConfig,
},
Stdout: runtimetesting.Output{
ContainsAll: []string{
string(prodJobConfig.UID),
string(periodicJobConfig.UID),
},
},
},
{
Name: "use all namespaces, pretty print",
Args: []string{"list", "jobconfig", "-A"},
Fixtures: []runtime.Object{
periodicJobConfig,
prodJobConfig,
},
Stdout: runtimetesting.Output{
MatchesAll: []*regexp.Regexp{
regexp.MustCompile(`default\s+periodic-jobconfig`),
regexp.MustCompile(`prod\s+periodic-jobconfig`),
},
},
},
{
Name: "can use alias",
Args: []string{"list", "jobconfigs", "-o", "name"},
Expand Down
1 change: 1 addition & 0 deletions pkg/cli/cmd/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ package cmd_test

const (
DefaultNamespace = "default"
ProdNamespace = "prod"
)
Loading

0 comments on commit 1e86f73

Please sign in to comment.