From 316ca44667126f7d14624c5df5e9fd02eca20827 Mon Sep 17 00:00:00 2001 From: Chris Baker <1675087+cgbaker@users.noreply.github.com> Date: Wed, 11 Nov 2020 10:29:42 +0000 Subject: [PATCH 1/3] auto-complete for recommendations CLI, plus OSS components of recommendations prefix search --- api/contexts/contexts.go | 21 ++++----- command/recommendation_apply.go | 17 +++++++ command/recommendation_apply_test.go | 45 +++++++++++++++++++ command/recommendation_dismiss.go | 17 +++++++ command/recommendation_dismiss_test.go | 45 +++++++++++++++++++ command/recommendation_info.go | 17 +++++++ command/recommendation_info_test.go | 45 +++++++++++++++++++ command/recommendation_list_test.go | 22 ++------- nomad/structs/structs.go | 21 ++++----- .../hashicorp/nomad/api/contexts/contexts.go | 21 ++++----- 10 files changed, 222 insertions(+), 49 deletions(-) diff --git a/api/contexts/contexts.go b/api/contexts/contexts.go index ae40db3f81ba..ea4ea1309509 100644 --- a/api/contexts/contexts.go +++ b/api/contexts/contexts.go @@ -4,14 +4,15 @@ package contexts type Context string const ( - Allocs Context = "allocs" - Deployments Context = "deployment" - Evals Context = "evals" - Jobs Context = "jobs" - Nodes Context = "nodes" - Namespaces Context = "namespaces" - Quotas Context = "quotas" - Plugins Context = "plugins" - Volumes Context = "volumes" - All Context = "all" + Allocs Context = "allocs" + Deployments Context = "deployment" + Evals Context = "evals" + Jobs Context = "jobs" + Nodes Context = "nodes" + Namespaces Context = "namespaces" + Quotas Context = "quotas" + Recommendations Context = "recommendations" + Plugins Context = "plugins" + Volumes Context = "volumes" + All Context = "all" ) diff --git a/command/recommendation_apply.go b/command/recommendation_apply.go index 980746b4dc0f..ee6b316743c7 100644 --- a/command/recommendation_apply.go +++ b/command/recommendation_apply.go @@ -5,6 +5,8 @@ import ( "strings" "github.com/hashicorp/nomad/api" + "github.com/hashicorp/nomad/api/contexts" + "github.com/mitchellh/cli" "github.com/posener/complete" ) @@ -60,6 +62,21 @@ func (r *RecommendationApplyCommand) AutocompleteFlags() complete.Flags { }) } +func (r *RecommendationApplyCommand) AutocompleteArgs() complete.Predictor { + return complete.PredictFunc(func(a complete.Args) []string { + client, err := r.Meta.Client() + if err != nil { + return nil + } + + resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Recommendations, nil) + if err != nil { + return []string{} + } + return resp.Matches[contexts.Recommendations] + }) +} + // Name returns the name of this command. func (r *RecommendationApplyCommand) Name() string { return "recommendation apply" } diff --git a/command/recommendation_apply_test.go b/command/recommendation_apply_test.go index cc8f9e19cc1d..e8656b3d58a9 100644 --- a/command/recommendation_apply_test.go +++ b/command/recommendation_apply_test.go @@ -7,6 +7,8 @@ import ( "github.com/hashicorp/nomad/api" "github.com/hashicorp/nomad/testutil" "github.com/mitchellh/cli" + "github.com/posener/complete" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -83,3 +85,46 @@ func TestRecommendationApplyCommand_Run(t *testing.T) { require.NoError(err) require.Equal(1, *jobResp.TaskGroups[0].Tasks[0].Resources.CPU) } + +func TestRecommendationApplyCommand_AutocompleteArgs(t *testing.T) { + assert := assert.New(t) + t.Parallel() + + srv, client, url := testServer(t, true, nil) + defer srv.Shutdown() + + // Register a test job to write a recommendation against. + ui := cli.NewMockUi() + testJob := testJob("recommendation_list") + regResp, _, err := client.Jobs().Register(testJob, nil) + require.NoError(t, err) + registerCode := waitForSuccess(ui, client, fullId, t, regResp.EvalID) + require.Equal(t, 0, registerCode) + + // Write a recommendation. + rec := &api.Recommendation{ + JobID: *testJob.ID, + Group: *testJob.TaskGroups[0].Name, + Task: testJob.TaskGroups[0].Tasks[0].Name, + Resource: "CPU", + Value: 1050, + Meta: map[string]interface{}{"test-meta-entry": "test-meta-value"}, + Stats: map[string]float64{"p13": 1.13}, + } + rec, _, err = client.Recommendations().Upsert(rec, nil) + if srv.Enterprise { + require.NoError(t, err) + } else { + require.Error(t, err, "Nomad Enterprise only endpoint") + return + } + + cmd := &RecommendationApplyCommand{Meta: Meta{Ui: ui, flagAddress: url}} + prefix := rec.ID[:5] + args := complete.Args{Last: prefix} + predictor := cmd.AutocompleteArgs() + + res := predictor.Predict(args) + assert.Equal(1, len(res)) + assert.Equal(rec.ID, res[0]) +} diff --git a/command/recommendation_dismiss.go b/command/recommendation_dismiss.go index bb362cd8b45b..636ce898f040 100644 --- a/command/recommendation_dismiss.go +++ b/command/recommendation_dismiss.go @@ -6,6 +6,8 @@ import ( "github.com/mitchellh/cli" "github.com/posener/complete" + + "github.com/hashicorp/nomad/api/contexts" ) // Ensure RecommendationDismissCommand satisfies the cli.Command interface. @@ -39,6 +41,21 @@ func (r *RecommendationDismissCommand) AutocompleteFlags() complete.Flags { complete.Flags{}) } +func (r *RecommendationDismissCommand) AutocompleteArgs() complete.Predictor { + return complete.PredictFunc(func(a complete.Args) []string { + client, err := r.Meta.Client() + if err != nil { + return nil + } + + resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Recommendations, nil) + if err != nil { + return []string{} + } + return resp.Matches[contexts.Recommendations] + }) +} + // Name returns the name of this command. func (r *RecommendationDismissCommand) Name() string { return "recommendation dismiss" } diff --git a/command/recommendation_dismiss_test.go b/command/recommendation_dismiss_test.go index 77e8f3ba38c0..ea4a5bc155b5 100644 --- a/command/recommendation_dismiss_test.go +++ b/command/recommendation_dismiss_test.go @@ -7,6 +7,8 @@ import ( "github.com/hashicorp/nomad/api" "github.com/hashicorp/nomad/testutil" "github.com/mitchellh/cli" + "github.com/posener/complete" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -80,3 +82,46 @@ func TestRecommendationDismissCommand_Run(t *testing.T) { require.Error(err, "not found") require.Nil(recInfo) } + +func TestRecommendationDismissCommand_AutocompleteArgs(t *testing.T) { + assert := assert.New(t) + t.Parallel() + + srv, client, url := testServer(t, true, nil) + defer srv.Shutdown() + + // Register a test job to write a recommendation against. + ui := cli.NewMockUi() + testJob := testJob("recommendation_list") + regResp, _, err := client.Jobs().Register(testJob, nil) + require.NoError(t, err) + registerCode := waitForSuccess(ui, client, fullId, t, regResp.EvalID) + require.Equal(t, 0, registerCode) + + // Write a recommendation. + rec := &api.Recommendation{ + JobID: *testJob.ID, + Group: *testJob.TaskGroups[0].Name, + Task: testJob.TaskGroups[0].Tasks[0].Name, + Resource: "CPU", + Value: 1050, + Meta: map[string]interface{}{"test-meta-entry": "test-meta-value"}, + Stats: map[string]float64{"p13": 1.13}, + } + rec, _, err = client.Recommendations().Upsert(rec, nil) + if srv.Enterprise { + require.NoError(t, err) + } else { + require.Error(t, err, "Nomad Enterprise only endpoint") + return + } + + cmd := &RecommendationDismissCommand{Meta: Meta{Ui: ui, flagAddress: url}} + prefix := rec.ID[:5] + args := complete.Args{Last: prefix} + predictor := cmd.AutocompleteArgs() + + res := predictor.Predict(args) + assert.Equal(1, len(res)) + assert.Equal(rec.ID, res[0]) +} diff --git a/command/recommendation_info.go b/command/recommendation_info.go index 42c822c02626..9045445abfea 100644 --- a/command/recommendation_info.go +++ b/command/recommendation_info.go @@ -7,6 +7,8 @@ import ( "github.com/mitchellh/cli" "github.com/posener/complete" + + "github.com/hashicorp/nomad/api/contexts" ) // Ensure RecommendationInfoCommand satisfies the cli.Command interface. @@ -52,6 +54,21 @@ func (r *RecommendationInfoCommand) AutocompleteFlags() complete.Flags { }) } +func (r *RecommendationInfoCommand) AutocompleteArgs() complete.Predictor { + return complete.PredictFunc(func(a complete.Args) []string { + client, err := r.Meta.Client() + if err != nil { + return nil + } + + resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Recommendations, nil) + if err != nil { + return []string{} + } + return resp.Matches[contexts.Recommendations] + }) +} + // Name returns the name of this command. func (r *RecommendationInfoCommand) Name() string { return "recommendation info" } diff --git a/command/recommendation_info_test.go b/command/recommendation_info_test.go index b56bea86feca..614d7ef8789a 100644 --- a/command/recommendation_info_test.go +++ b/command/recommendation_info_test.go @@ -7,6 +7,8 @@ import ( "github.com/hashicorp/nomad/api" "github.com/hashicorp/nomad/testutil" "github.com/mitchellh/cli" + "github.com/posener/complete" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -81,3 +83,46 @@ func TestRecommendationInfoCommand_Run(t *testing.T) { require.Contains(out, recResp.ID) } } + +func TestRecommendationInfoCommand_AutocompleteArgs(t *testing.T) { + assert := assert.New(t) + t.Parallel() + + srv, client, url := testServer(t, true, nil) + defer srv.Shutdown() + + // Register a test job to write a recommendation against. + ui := cli.NewMockUi() + testJob := testJob("recommendation_list") + regResp, _, err := client.Jobs().Register(testJob, nil) + require.NoError(t, err) + registerCode := waitForSuccess(ui, client, fullId, t, regResp.EvalID) + require.Equal(t, 0, registerCode) + + // Write a recommendation. + rec := &api.Recommendation{ + JobID: *testJob.ID, + Group: *testJob.TaskGroups[0].Name, + Task: testJob.TaskGroups[0].Tasks[0].Name, + Resource: "CPU", + Value: 1050, + Meta: map[string]interface{}{"test-meta-entry": "test-meta-value"}, + Stats: map[string]float64{"p13": 1.13}, + } + rec, _, err = client.Recommendations().Upsert(rec, nil) + if srv.Enterprise { + require.NoError(t, err) + } else { + require.Error(t, err, "Nomad Enterprise only endpoint") + return + } + + cmd := &RecommendationInfoCommand{Meta: Meta{Ui: ui, flagAddress: url}} + prefix := rec.ID[:5] + args := complete.Args{Last: prefix} + predictor := cmd.AutocompleteArgs() + + res := predictor.Predict(args) + assert.Equal(1, len(res)) + assert.Equal(rec.ID, res[0]) +} diff --git a/command/recommendation_list_test.go b/command/recommendation_list_test.go index d09c67eb84e6..c7234bd7c50e 100644 --- a/command/recommendation_list_test.go +++ b/command/recommendation_list_test.go @@ -1,15 +1,14 @@ package command import ( - "fmt" "sort" "testing" - "github.com/hashicorp/nomad/api" - "github.com/hashicorp/nomad/testutil" "github.com/mitchellh/cli" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/hashicorp/nomad/api" ) func TestRecommendationListCommand_Run(t *testing.T) { @@ -17,21 +16,6 @@ func TestRecommendationListCommand_Run(t *testing.T) { t.Parallel() srv, client, url := testServer(t, true, nil) defer srv.Shutdown() - testutil.WaitForResult(func() (bool, error) { - nodes, _, err := client.Nodes().List(nil) - if err != nil { - return false, err - } - if len(nodes) == 0 { - return false, fmt.Errorf("missing node") - } - if _, ok := nodes[0].Drivers["mock_driver"]; !ok { - return false, fmt.Errorf("mock_driver not ready") - } - return true, nil - }, func(err error) { - t.Fatalf("err: %s", err) - }) ui := cli.NewMockUi() cmd := &RecommendationListCommand{Meta: Meta{Ui: ui}} @@ -89,7 +73,7 @@ func TestRecommendationListCommand_Run(t *testing.T) { } } -func TestRecommendationList_Sort(t *testing.T) { +func TestRecommendationListCommand_Sort(t *testing.T) { testCases := []struct { inputRecommendationList []*api.Recommendation expectedOutputList []*api.Recommendation diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index 58049ef70c18..95869e8cc2e3 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -193,16 +193,17 @@ var ( type Context string const ( - Allocs Context = "allocs" - Deployments Context = "deployment" - Evals Context = "evals" - Jobs Context = "jobs" - Nodes Context = "nodes" - Namespaces Context = "namespaces" - Quotas Context = "quotas" - All Context = "all" - Plugins Context = "plugins" - Volumes Context = "volumes" + Allocs Context = "allocs" + Deployments Context = "deployment" + Evals Context = "evals" + Jobs Context = "jobs" + Nodes Context = "nodes" + Namespaces Context = "namespaces" + Quotas Context = "quotas" + Recommendations Context = "recommendations" + All Context = "all" + Plugins Context = "plugins" + Volumes Context = "volumes" ) // NamespacedID is a tuple of an ID and a namespace diff --git a/vendor/github.com/hashicorp/nomad/api/contexts/contexts.go b/vendor/github.com/hashicorp/nomad/api/contexts/contexts.go index ae40db3f81ba..ea4ea1309509 100644 --- a/vendor/github.com/hashicorp/nomad/api/contexts/contexts.go +++ b/vendor/github.com/hashicorp/nomad/api/contexts/contexts.go @@ -4,14 +4,15 @@ package contexts type Context string const ( - Allocs Context = "allocs" - Deployments Context = "deployment" - Evals Context = "evals" - Jobs Context = "jobs" - Nodes Context = "nodes" - Namespaces Context = "namespaces" - Quotas Context = "quotas" - Plugins Context = "plugins" - Volumes Context = "volumes" - All Context = "all" + Allocs Context = "allocs" + Deployments Context = "deployment" + Evals Context = "evals" + Jobs Context = "jobs" + Nodes Context = "nodes" + Namespaces Context = "namespaces" + Quotas Context = "quotas" + Recommendations Context = "recommendations" + Plugins Context = "plugins" + Volumes Context = "volumes" + All Context = "all" ) From 8b0d273dd97e2c85ae6b0d2b713d408a891b1b3e Mon Sep 17 00:00:00 2001 From: Chris Baker <1675087+cgbaker@users.noreply.github.com> Date: Wed, 11 Nov 2020 11:39:26 +0000 Subject: [PATCH 2/3] cli: updated recommendation commands and test to remove duplication of autocompletion code --- command/recommendation_apply.go | 17 +--------- command/recommendation_apply_test.go | 45 +++----------------------- command/recommendation_dismiss.go | 37 ++++++++++++--------- command/recommendation_dismiss_test.go | 18 +++++++---- command/recommendation_info.go | 18 +---------- command/recommendation_info_test.go | 45 +++----------------------- 6 files changed, 46 insertions(+), 134 deletions(-) diff --git a/command/recommendation_apply.go b/command/recommendation_apply.go index ee6b316743c7..6482013e4863 100644 --- a/command/recommendation_apply.go +++ b/command/recommendation_apply.go @@ -5,7 +5,6 @@ import ( "strings" "github.com/hashicorp/nomad/api" - "github.com/hashicorp/nomad/api/contexts" "github.com/mitchellh/cli" "github.com/posener/complete" @@ -17,6 +16,7 @@ var _ cli.Command = &RecommendationApplyCommand{} // RecommendationApplyCommand implements cli.Command. type RecommendationApplyCommand struct { Meta + RecommendationAutocompleteCommand } // Help satisfies the cli.Command Help function. @@ -62,21 +62,6 @@ func (r *RecommendationApplyCommand) AutocompleteFlags() complete.Flags { }) } -func (r *RecommendationApplyCommand) AutocompleteArgs() complete.Predictor { - return complete.PredictFunc(func(a complete.Args) []string { - client, err := r.Meta.Client() - if err != nil { - return nil - } - - resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Recommendations, nil) - if err != nil { - return []string{} - } - return resp.Matches[contexts.Recommendations] - }) -} - // Name returns the name of this command. func (r *RecommendationApplyCommand) Name() string { return "recommendation apply" } diff --git a/command/recommendation_apply_test.go b/command/recommendation_apply_test.go index e8656b3d58a9..b2f051ff1eaa 100644 --- a/command/recommendation_apply_test.go +++ b/command/recommendation_apply_test.go @@ -4,12 +4,11 @@ import ( "fmt" "testing" - "github.com/hashicorp/nomad/api" - "github.com/hashicorp/nomad/testutil" "github.com/mitchellh/cli" - "github.com/posener/complete" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/hashicorp/nomad/api" + "github.com/hashicorp/nomad/testutil" ) func TestRecommendationApplyCommand_Run(t *testing.T) { @@ -87,44 +86,10 @@ func TestRecommendationApplyCommand_Run(t *testing.T) { } func TestRecommendationApplyCommand_AutocompleteArgs(t *testing.T) { - assert := assert.New(t) - t.Parallel() - srv, client, url := testServer(t, true, nil) defer srv.Shutdown() - // Register a test job to write a recommendation against. ui := cli.NewMockUi() - testJob := testJob("recommendation_list") - regResp, _, err := client.Jobs().Register(testJob, nil) - require.NoError(t, err) - registerCode := waitForSuccess(ui, client, fullId, t, regResp.EvalID) - require.Equal(t, 0, registerCode) - - // Write a recommendation. - rec := &api.Recommendation{ - JobID: *testJob.ID, - Group: *testJob.TaskGroups[0].Name, - Task: testJob.TaskGroups[0].Tasks[0].Name, - Resource: "CPU", - Value: 1050, - Meta: map[string]interface{}{"test-meta-entry": "test-meta-value"}, - Stats: map[string]float64{"p13": 1.13}, - } - rec, _, err = client.Recommendations().Upsert(rec, nil) - if srv.Enterprise { - require.NoError(t, err) - } else { - require.Error(t, err, "Nomad Enterprise only endpoint") - return - } - - cmd := &RecommendationApplyCommand{Meta: Meta{Ui: ui, flagAddress: url}} - prefix := rec.ID[:5] - args := complete.Args{Last: prefix} - predictor := cmd.AutocompleteArgs() - - res := predictor.Predict(args) - assert.Equal(1, len(res)) - assert.Equal(rec.ID, res[0]) + cmd := RecommendationApplyCommand{Meta: Meta{Ui: ui, flagAddress: url}} + testRecommendationAutocompleteCommand(t, client, srv, ui, &cmd.RecommendationAutocompleteCommand) } diff --git a/command/recommendation_dismiss.go b/command/recommendation_dismiss.go index 636ce898f040..66bc9b626517 100644 --- a/command/recommendation_dismiss.go +++ b/command/recommendation_dismiss.go @@ -13,9 +13,31 @@ import ( // Ensure RecommendationDismissCommand satisfies the cli.Command interface. var _ cli.Command = &RecommendationDismissCommand{} +// RecommendationAutocompleteCommand provides AutocompleteArgs for all +// recommendation commands that support prefix-search autocompletion +type RecommendationAutocompleteCommand struct { + Meta +} + +func (r *RecommendationAutocompleteCommand) AutocompleteArgs() complete.Predictor { + return complete.PredictFunc(func(a complete.Args) []string { + client, err := r.Meta.Client() + if err != nil { + return nil + } + + resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Recommendations, nil) + if err != nil { + return []string{} + } + return resp.Matches[contexts.Recommendations] + }) +} + // RecommendationDismissCommand implements cli.Command. type RecommendationDismissCommand struct { Meta + RecommendationAutocompleteCommand } // Help satisfies the cli.Command Help function. @@ -41,21 +63,6 @@ func (r *RecommendationDismissCommand) AutocompleteFlags() complete.Flags { complete.Flags{}) } -func (r *RecommendationDismissCommand) AutocompleteArgs() complete.Predictor { - return complete.PredictFunc(func(a complete.Args) []string { - client, err := r.Meta.Client() - if err != nil { - return nil - } - - resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Recommendations, nil) - if err != nil { - return []string{} - } - return resp.Matches[contexts.Recommendations] - }) -} - // Name returns the name of this command. func (r *RecommendationDismissCommand) Name() string { return "recommendation dismiss" } diff --git a/command/recommendation_dismiss_test.go b/command/recommendation_dismiss_test.go index ea4a5bc155b5..bcd10638953a 100644 --- a/command/recommendation_dismiss_test.go +++ b/command/recommendation_dismiss_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/hashicorp/nomad/api" + "github.com/hashicorp/nomad/command/agent" "github.com/hashicorp/nomad/testutil" "github.com/mitchellh/cli" "github.com/posener/complete" @@ -84,15 +85,21 @@ func TestRecommendationDismissCommand_Run(t *testing.T) { } func TestRecommendationDismissCommand_AutocompleteArgs(t *testing.T) { - assert := assert.New(t) - t.Parallel() - srv, client, url := testServer(t, true, nil) defer srv.Shutdown() - // Register a test job to write a recommendation against. ui := cli.NewMockUi() - testJob := testJob("recommendation_list") + cmd := &RecommendationDismissCommand{Meta: Meta{Ui: ui, flagAddress: url}} + + testRecommendationAutocompleteCommand(t, client, srv, ui, &cmd.RecommendationAutocompleteCommand) +} + +func testRecommendationAutocompleteCommand(t *testing.T, client *api.Client, srv *agent.TestAgent, ui *cli.MockUi, cmd *RecommendationAutocompleteCommand) { + assert := assert.New(t) + t.Parallel() + + // Register a test job to write a recommendation against. + testJob := testJob("recommendation_autocomplete") regResp, _, err := client.Jobs().Register(testJob, nil) require.NoError(t, err) registerCode := waitForSuccess(ui, client, fullId, t, regResp.EvalID) @@ -116,7 +123,6 @@ func TestRecommendationDismissCommand_AutocompleteArgs(t *testing.T) { return } - cmd := &RecommendationDismissCommand{Meta: Meta{Ui: ui, flagAddress: url}} prefix := rec.ID[:5] args := complete.Args{Last: prefix} predictor := cmd.AutocompleteArgs() diff --git a/command/recommendation_info.go b/command/recommendation_info.go index 9045445abfea..2105f1b70627 100644 --- a/command/recommendation_info.go +++ b/command/recommendation_info.go @@ -7,8 +7,6 @@ import ( "github.com/mitchellh/cli" "github.com/posener/complete" - - "github.com/hashicorp/nomad/api/contexts" ) // Ensure RecommendationInfoCommand satisfies the cli.Command interface. @@ -17,6 +15,7 @@ var _ cli.Command = &RecommendationInfoCommand{} // RecommendationInfoCommand implements cli.Command. type RecommendationInfoCommand struct { Meta + RecommendationAutocompleteCommand } // Help satisfies the cli.Command Help function. @@ -54,21 +53,6 @@ func (r *RecommendationInfoCommand) AutocompleteFlags() complete.Flags { }) } -func (r *RecommendationInfoCommand) AutocompleteArgs() complete.Predictor { - return complete.PredictFunc(func(a complete.Args) []string { - client, err := r.Meta.Client() - if err != nil { - return nil - } - - resp, _, err := client.Search().PrefixSearch(a.Last, contexts.Recommendations, nil) - if err != nil { - return []string{} - } - return resp.Matches[contexts.Recommendations] - }) -} - // Name returns the name of this command. func (r *RecommendationInfoCommand) Name() string { return "recommendation info" } diff --git a/command/recommendation_info_test.go b/command/recommendation_info_test.go index 614d7ef8789a..29e564fe18df 100644 --- a/command/recommendation_info_test.go +++ b/command/recommendation_info_test.go @@ -4,12 +4,11 @@ import ( "fmt" "testing" - "github.com/hashicorp/nomad/api" - "github.com/hashicorp/nomad/testutil" "github.com/mitchellh/cli" - "github.com/posener/complete" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/hashicorp/nomad/api" + "github.com/hashicorp/nomad/testutil" ) func TestRecommendationInfoCommand_Run(t *testing.T) { @@ -85,44 +84,10 @@ func TestRecommendationInfoCommand_Run(t *testing.T) { } func TestRecommendationInfoCommand_AutocompleteArgs(t *testing.T) { - assert := assert.New(t) - t.Parallel() - srv, client, url := testServer(t, true, nil) defer srv.Shutdown() - // Register a test job to write a recommendation against. ui := cli.NewMockUi() - testJob := testJob("recommendation_list") - regResp, _, err := client.Jobs().Register(testJob, nil) - require.NoError(t, err) - registerCode := waitForSuccess(ui, client, fullId, t, regResp.EvalID) - require.Equal(t, 0, registerCode) - - // Write a recommendation. - rec := &api.Recommendation{ - JobID: *testJob.ID, - Group: *testJob.TaskGroups[0].Name, - Task: testJob.TaskGroups[0].Tasks[0].Name, - Resource: "CPU", - Value: 1050, - Meta: map[string]interface{}{"test-meta-entry": "test-meta-value"}, - Stats: map[string]float64{"p13": 1.13}, - } - rec, _, err = client.Recommendations().Upsert(rec, nil) - if srv.Enterprise { - require.NoError(t, err) - } else { - require.Error(t, err, "Nomad Enterprise only endpoint") - return - } - - cmd := &RecommendationInfoCommand{Meta: Meta{Ui: ui, flagAddress: url}} - prefix := rec.ID[:5] - args := complete.Args{Last: prefix} - predictor := cmd.AutocompleteArgs() - - res := predictor.Predict(args) - assert.Equal(1, len(res)) - assert.Equal(rec.ID, res[0]) + cmd := RecommendationInfoCommand{Meta: Meta{Ui: ui, flagAddress: url}} + testRecommendationAutocompleteCommand(t, client, srv, ui, &cmd.RecommendationAutocompleteCommand) } From f2e8df397691dc20dc37dd0ed3786a3aed7447b5 Mon Sep 17 00:00:00 2001 From: Chris Baker <1675087+cgbaker@users.noreply.github.com> Date: Wed, 11 Nov 2020 11:57:04 +0000 Subject: [PATCH 3/3] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7270ead4496..14523de13287 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ IMPROVEMENTS: * api: Added ?resources=true query parameter to /v1/nodes and /v1/allocations to include resource allocations in listings. [[GH-9055](https://github.com/hashicorp/nomad/issues/9055)] * api: Added ?task_states=false query parameter to /v1/allocations to remove TaskStates from listings. Defaults to being included as before. [[GH-9055](https://github.com/hashicorp/nomad/issues/9055)] * build: Updated to Go 1.15.4. [[GH-9305](https://github.com/hashicorp/nomad/issues/9305)] + * cli: Added autocompletion for `recommendation` commands [[GH-9317](https://github.com/hashicorp/nomad/issues/9317)] * cli: Added `scale` and `scaling-events` subcommands to the `job` command. [[GH-9023](https://github.com/hashicorp/nomad/pull/9023)] * cli: Added `scaling` command for interaction with the scaling API endpoint. [[GH-9025](https://github.com/hashicorp/nomad/pull/9025)] * client: Batch state store writes to reduce disk IO. [[GH-9093](https://github.com/hashicorp/nomad/issues/9093)]