github.com/ferranbt/nomad@v0.9.3-0.20190607002617-85c449b7667c/command/job_periodic_force_test.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/hashicorp/nomad/api"
     8  	"github.com/hashicorp/nomad/helper"
     9  	"github.com/hashicorp/nomad/nomad/mock"
    10  	"github.com/hashicorp/nomad/nomad/structs"
    11  	"github.com/hashicorp/nomad/testutil"
    12  	"github.com/mitchellh/cli"
    13  	"github.com/posener/complete"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  func TestJobPeriodicForceCommand_Implements(t *testing.T) {
    18  	t.Parallel()
    19  	var _ cli.Command = &JobPeriodicForceCommand{}
    20  }
    21  
    22  func TestJobPeriodicForceCommand_Fails(t *testing.T) {
    23  	t.Parallel()
    24  	ui := new(cli.MockUi)
    25  	cmd := &JobPeriodicForceCommand{Meta: Meta{Ui: ui}}
    26  
    27  	// Fails on misuse
    28  	code := cmd.Run([]string{"some", "bad", "args"})
    29  	require.Equal(t, code, 1, "expected error")
    30  	out := ui.ErrorWriter.String()
    31  	require.Contains(t, out, commandErrorText(cmd), "expected help output")
    32  	ui.ErrorWriter.Reset()
    33  
    34  	code = cmd.Run([]string{"-address=nope", "12"})
    35  	require.Equal(t, code, 1, "expected error")
    36  	out = ui.ErrorWriter.String()
    37  	require.Contains(t, out, "Error forcing periodic job", "expected force error")
    38  }
    39  
    40  func TestJobPeriodicForceCommand_AutocompleteArgs(t *testing.T) {
    41  	t.Parallel()
    42  
    43  	srv, _, url := testServer(t, true, nil)
    44  	defer srv.Shutdown()
    45  
    46  	ui := new(cli.MockUi)
    47  	cmd := &JobPeriodicForceCommand{Meta: Meta{Ui: ui, flagAddress: url}}
    48  
    49  	// Create a fake job, not periodic
    50  	state := srv.Agent.Server().State()
    51  	j := mock.Job()
    52  	require.NoError(t, state.UpsertJob(1000, j))
    53  
    54  	predictor := cmd.AutocompleteArgs()
    55  
    56  	res := predictor.Predict(complete.Args{Last: j.ID[:len(j.ID)-5]})
    57  	require.Empty(t, res)
    58  
    59  	// Create another fake job, periodic
    60  	state = srv.Agent.Server().State()
    61  	j2 := mock.Job()
    62  	j2.Periodic = &structs.PeriodicConfig{
    63  		Enabled:         true,
    64  		Spec:            "spec",
    65  		SpecType:        "cron",
    66  		ProhibitOverlap: true,
    67  		TimeZone:        "test zone",
    68  	}
    69  	require.NoError(t, state.UpsertJob(1000, j2))
    70  
    71  	res = predictor.Predict(complete.Args{Last: j2.ID[:len(j.ID)-5]})
    72  	require.Equal(t, []string{j2.ID}, res)
    73  
    74  	res = predictor.Predict(complete.Args{})
    75  	require.Equal(t, []string{j2.ID}, res)
    76  }
    77  
    78  func TestJobPeriodicForceCommand_NonPeriodicJob(t *testing.T) {
    79  	t.Parallel()
    80  	srv, client, url := testServer(t, true, nil)
    81  	defer srv.Shutdown()
    82  	testutil.WaitForResult(func() (bool, error) {
    83  		nodes, _, err := client.Nodes().List(nil)
    84  		if err != nil {
    85  			return false, err
    86  		}
    87  		if len(nodes) == 0 {
    88  			return false, fmt.Errorf("missing node")
    89  		}
    90  		if _, ok := nodes[0].Drivers["mock_driver"]; !ok {
    91  			return false, fmt.Errorf("mock_driver not ready")
    92  		}
    93  		return true, nil
    94  	}, func(err error) {
    95  		require.NoError(t, err)
    96  	})
    97  
    98  	// Register a job
    99  	j := testJob("job_not_periodic")
   100  
   101  	ui := new(cli.MockUi)
   102  	cmd := &JobPeriodicForceCommand{Meta: Meta{Ui: ui, flagAddress: url}}
   103  
   104  	resp, _, err := client.Jobs().Register(j, nil)
   105  	require.NoError(t, err)
   106  	code := waitForSuccess(ui, client, fullId, t, resp.EvalID)
   107  	require.Equal(t, 0, code)
   108  
   109  	code = cmd.Run([]string{"-address=" + url, "job_not_periodic"})
   110  	require.Equal(t, 1, code, "expected exit code")
   111  	out := ui.ErrorWriter.String()
   112  	require.Contains(t, out, "No periodic job(s)", "non-periodic error message")
   113  }
   114  
   115  func TestJobPeriodicForceCommand_SuccessfulPeriodicForceDetach(t *testing.T) {
   116  	t.Parallel()
   117  	srv, client, url := testServer(t, true, nil)
   118  	defer srv.Shutdown()
   119  	testutil.WaitForResult(func() (bool, error) {
   120  		nodes, _, err := client.Nodes().List(nil)
   121  		if err != nil {
   122  			return false, err
   123  		}
   124  		if len(nodes) == 0 {
   125  			return false, fmt.Errorf("missing node")
   126  		}
   127  		if _, ok := nodes[0].Drivers["mock_driver"]; !ok {
   128  			return false, fmt.Errorf("mock_driver not ready")
   129  		}
   130  		return true, nil
   131  	}, func(err error) {
   132  		require.NoError(t, err)
   133  	})
   134  
   135  	// Register a job
   136  	j := testJob("job1_is_periodic")
   137  	j.Periodic = &api.PeriodicConfig{
   138  		SpecType:        helper.StringToPtr(api.PeriodicSpecCron),
   139  		Spec:            helper.StringToPtr("*/15 * * * * *"),
   140  		ProhibitOverlap: helper.BoolToPtr(true),
   141  		TimeZone:        helper.StringToPtr("Europe/Minsk"),
   142  	}
   143  
   144  	ui := new(cli.MockUi)
   145  	cmd := &JobPeriodicForceCommand{Meta: Meta{Ui: ui, flagAddress: url}}
   146  
   147  	_, _, err := client.Jobs().Register(j, nil)
   148  	require.NoError(t, err)
   149  
   150  	code := cmd.Run([]string{"-address=" + url, "-detach", "job1_is_periodic"})
   151  	require.Equal(t, 0, code, "expected no error code")
   152  	out := ui.OutputWriter.String()
   153  	require.Contains(t, out, "Force periodic successful")
   154  	require.Contains(t, out, "Evaluation ID:")
   155  }
   156  
   157  func TestJobPeriodicForceCommand_SuccessfulPeriodicForce(t *testing.T) {
   158  	t.Parallel()
   159  	srv, client, url := testServer(t, true, nil)
   160  	defer srv.Shutdown()
   161  	testutil.WaitForResult(func() (bool, error) {
   162  		nodes, _, err := client.Nodes().List(nil)
   163  		if err != nil {
   164  			return false, err
   165  		}
   166  		if len(nodes) == 0 {
   167  			return false, fmt.Errorf("missing node")
   168  		}
   169  		if _, ok := nodes[0].Drivers["mock_driver"]; !ok {
   170  			return false, fmt.Errorf("mock_driver not ready")
   171  		}
   172  		return true, nil
   173  	}, func(err error) {
   174  		require.NoError(t, err)
   175  	})
   176  
   177  	// Register a job
   178  	j := testJob("job2_is_periodic")
   179  	j.Periodic = &api.PeriodicConfig{
   180  		SpecType:        helper.StringToPtr(api.PeriodicSpecCron),
   181  		Spec:            helper.StringToPtr("*/15 * * * * *"),
   182  		ProhibitOverlap: helper.BoolToPtr(true),
   183  		TimeZone:        helper.StringToPtr("Europe/Minsk"),
   184  	}
   185  
   186  	ui := new(cli.MockUi)
   187  	cmd := &JobPeriodicForceCommand{Meta: Meta{Ui: ui, flagAddress: url}}
   188  
   189  	_, _, err := client.Jobs().Register(j, nil)
   190  	require.NoError(t, err)
   191  
   192  	code := cmd.Run([]string{"-address=" + url, "job2_is_periodic"})
   193  	require.Equal(t, 0, code, "expected no error code")
   194  	out := ui.OutputWriter.String()
   195  	require.Contains(t, out, "Monitoring evaluation")
   196  	require.Contains(t, out, "finished with status \"complete\"")
   197  }