1
0

ssh_reload_test.go 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. package nebula
  2. import (
  3. "errors"
  4. "io"
  5. "os"
  6. "path/filepath"
  7. "testing"
  8. "github.com/slackhq/nebula/commands"
  9. "github.com/slackhq/nebula/config"
  10. "github.com/slackhq/nebula/test"
  11. "github.com/stretchr/testify/assert"
  12. "github.com/stretchr/testify/require"
  13. )
  14. type lineWriter struct {
  15. lines []string
  16. err error
  17. }
  18. func (w *lineWriter) WriteLine(s string) error {
  19. w.lines = append(w.lines, s)
  20. return w.err
  21. }
  22. func (w *lineWriter) Write(s string) error { return w.WriteLine(s) }
  23. func (w *lineWriter) WriteBytes(b []byte) error { return w.WriteLine(string(b)) }
  24. func (w *lineWriter) GetWriter() io.Writer { return io.Discard }
  25. func TestReloadCommandReportsTheResult(t *testing.T) {
  26. dir := t.TempDir()
  27. write := func(body string) {
  28. require.NoError(t, os.WriteFile(filepath.Join(dir, "config.yml"), []byte(body), 0o600))
  29. }
  30. write("a: 1\nb: 1")
  31. l := test.NewLogger()
  32. c := config.NewC(l)
  33. require.NoError(t, c.Load(dir))
  34. fail := false
  35. c.RegisterReloadCallback(func(c *config.C, r *config.Reload) {
  36. r.RestartRequiredIfChanged("b")
  37. if fail {
  38. r.Failed()
  39. }
  40. })
  41. // reload returns what the client was told. A reload that failed is a commands.Failure
  42. // to the surface, exit 1 over ssh, with the result line as its message; one that
  43. // merely needs a restart is not.
  44. reload := func(failed bool) []string {
  45. w := &lineWriter{}
  46. err := reloadCommand(l, c, w)
  47. if failed {
  48. var f *commands.Failure
  49. require.ErrorAs(t, err, &f)
  50. assert.Equal(t, w.lines[len(w.lines)-1], f.Msg)
  51. } else {
  52. require.NoError(t, err)
  53. }
  54. return w.lines
  55. }
  56. write("a: 2\nb: 1")
  57. assert.Equal(t, []string{"Reloading config", "Config reload complete"}, reload(false))
  58. fail = true
  59. write("a: 3\nb: 1")
  60. assert.Equal(t, []string{"Reloading config", "Config reload completed with errors, review the logs"}, reload(true))
  61. fail = false
  62. write("a: 3\nb: 2")
  63. assert.Equal(t, []string{"Reloading config", "Config reload was completed but requires a restart to fully apply, keys [b]"}, reload(false))
  64. write("a: [")
  65. lines := reload(true)
  66. require.Len(t, lines, 2)
  67. assert.Contains(t, lines[1], "Config reload failed, the new config did not load")
  68. assert.Contains(t, lines[1], dir, "names the config that did not load")
  69. }
  70. // A client that went away still gets the reload it asked for
  71. func TestReloadCommandReloadsWhenTheClientIsGone(t *testing.T) {
  72. dir := t.TempDir()
  73. require.NoError(t, os.WriteFile(filepath.Join(dir, "config.yml"), []byte("a: 1"), 0o600))
  74. l := test.NewLogger()
  75. c := config.NewC(l)
  76. require.NoError(t, c.Load(dir))
  77. reloaded := false
  78. c.RegisterReloadCallback(func(*config.C, *config.Reload) { reloaded = true })
  79. gone := errors.New("client is gone")
  80. require.ErrorIs(t, reloadCommand(l, c, &lineWriter{err: gone}), gone)
  81. assert.True(t, reloaded)
  82. }