1package agent 2 3import ( 4 "encoding/json" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "reflect" 9 "strings" 10 "testing" 11 12 "github.com/hashicorp/serf/serf" 13 "github.com/hashicorp/serf/testutil" 14) 15 16func TestAgent_eventHandler(t *testing.T) { 17 a1 := testAgent(nil) 18 defer a1.Shutdown() 19 defer a1.Leave() 20 21 handler := new(MockEventHandler) 22 a1.RegisterEventHandler(handler) 23 24 if err := a1.Start(); err != nil { 25 t.Fatalf("err: %s", err) 26 } 27 28 testutil.Yield() 29 30 if len(handler.Events) != 1 { 31 t.Fatalf("bad: %#v", handler.Events) 32 } 33 34 if handler.Events[0].EventType() != serf.EventMemberJoin { 35 t.Fatalf("bad: %#v", handler.Events[0]) 36 } 37} 38 39func TestAgentShutdown_multiple(t *testing.T) { 40 a := testAgent(nil) 41 if err := a.Start(); err != nil { 42 t.Fatalf("err: %s", err) 43 } 44 45 for i := 0; i < 5; i++ { 46 if err := a.Shutdown(); err != nil { 47 t.Fatalf("err: %s", err) 48 } 49 } 50} 51 52func TestAgentUserEvent(t *testing.T) { 53 a1 := testAgent(nil) 54 defer a1.Shutdown() 55 defer a1.Leave() 56 57 handler := new(MockEventHandler) 58 a1.RegisterEventHandler(handler) 59 60 if err := a1.Start(); err != nil { 61 t.Fatalf("err: %s", err) 62 } 63 64 testutil.Yield() 65 66 if err := a1.UserEvent("deploy", []byte("foo"), false); err != nil { 67 t.Fatalf("err: %s", err) 68 } 69 70 testutil.Yield() 71 72 handler.Lock() 73 defer handler.Unlock() 74 75 if len(handler.Events) == 0 { 76 t.Fatal("no events") 77 } 78 79 e, ok := handler.Events[len(handler.Events)-1].(serf.UserEvent) 80 if !ok { 81 t.Fatalf("bad: %#v", e) 82 } 83 84 if e.Name != "deploy" { 85 t.Fatalf("bad: %#v", e) 86 } 87 88 if string(e.Payload) != "foo" { 89 t.Fatalf("bad: %#v", e) 90 } 91} 92 93func TestAgentQuery_BadPrefix(t *testing.T) { 94 a1 := testAgent(nil) 95 defer a1.Shutdown() 96 defer a1.Leave() 97 98 if err := a1.Start(); err != nil { 99 t.Fatalf("err: %s", err) 100 } 101 102 testutil.Yield() 103 104 _, err := a1.Query("_serf_test", nil, nil) 105 if err == nil || !strings.Contains(err.Error(), "cannot contain") { 106 t.Fatalf("err: %s", err) 107 } 108} 109 110func TestAgentTagsFile(t *testing.T) { 111 tags := map[string]string{ 112 "role": "webserver", 113 "datacenter": "us-east", 114 } 115 116 td, err := ioutil.TempDir("", "serf") 117 if err != nil { 118 t.Fatalf("err: %s", err) 119 } 120 defer os.RemoveAll(td) 121 122 agentConfig := DefaultConfig() 123 agentConfig.TagsFile = filepath.Join(td, "tags.json") 124 125 a1 := testAgentWithConfig(agentConfig, serf.DefaultConfig(), nil) 126 127 if err := a1.Start(); err != nil { 128 t.Fatalf("err: %s", err) 129 } 130 defer a1.Shutdown() 131 defer a1.Leave() 132 133 testutil.Yield() 134 135 err = a1.SetTags(tags) 136 137 if err != nil { 138 t.Fatalf("err: %s", err) 139 } 140 141 testutil.Yield() 142 143 a2 := testAgentWithConfig(agentConfig, serf.DefaultConfig(), nil) 144 145 if err := a2.Start(); err != nil { 146 t.Fatalf("err: %s", err) 147 } 148 defer a2.Shutdown() 149 defer a2.Leave() 150 151 testutil.Yield() 152 153 m := a2.Serf().LocalMember() 154 155 if !reflect.DeepEqual(m.Tags, tags) { 156 t.Fatalf("tags not restored: %#v", m.Tags) 157 } 158} 159 160func TestAgentTagsFile_BadOptions(t *testing.T) { 161 agentConfig := DefaultConfig() 162 agentConfig.TagsFile = "/some/path" 163 agentConfig.Tags = map[string]string{ 164 "tag1": "val1", 165 } 166 167 _, err := Create(agentConfig, serf.DefaultConfig(), nil) 168 if err == nil || !strings.Contains(err.Error(), "not allowed") { 169 t.Fatalf("err: %s", err) 170 } 171} 172 173func TestAgent_MarshalTags(t *testing.T) { 174 tags := map[string]string{ 175 "tag1": "val1", 176 "tag2": "val2", 177 } 178 179 tagPairs := MarshalTags(tags) 180 181 if !containsKey(tagPairs, "tag1=val1") { 182 t.Fatalf("bad: %v", tagPairs) 183 } 184 if !containsKey(tagPairs, "tag2=val2") { 185 t.Fatalf("bad: %v", tagPairs) 186 } 187} 188 189func TestAgent_UnmarshalTags(t *testing.T) { 190 tagPairs := []string{ 191 "tag1=val1", 192 "tag2=val2", 193 } 194 195 tags, err := UnmarshalTags(tagPairs) 196 197 if err != nil { 198 t.Fatalf("err: %s", err) 199 } 200 201 if v, ok := tags["tag1"]; !ok || v != "val1" { 202 t.Fatalf("bad: %v", tags) 203 } 204 if v, ok := tags["tag2"]; !ok || v != "val2" { 205 t.Fatalf("bad: %v", tags) 206 } 207} 208 209func TestAgent_UnmarshalTagsError(t *testing.T) { 210 tagSets := [][]string{ 211 []string{"="}, 212 []string{"=x"}, 213 []string{""}, 214 []string{"x"}, 215 } 216 for _, tagPairs := range tagSets { 217 if _, err := UnmarshalTags(tagPairs); err == nil { 218 t.Fatalf("Expected tag error: %s", tagPairs[0]) 219 } 220 } 221} 222 223func TestAgentKeyringFile(t *testing.T) { 224 keys := []string{ 225 "HvY8ubRZMgafUOWvrOadwOckVa1wN3QWAo46FVKbVN8=", 226 "T9jncgl9mbLus+baTTa7q7nPSUrXwbDi2dhbtqir37s=", 227 "5K9OtfP7efFrNKe5WCQvXvnaXJ5cWP0SvXiwe0kkjM4=", 228 } 229 230 td, err := ioutil.TempDir("", "serf") 231 if err != nil { 232 t.Fatalf("err: %s", err) 233 } 234 defer os.RemoveAll(td) 235 236 keyringFile := filepath.Join(td, "keyring.json") 237 238 serfConfig := serf.DefaultConfig() 239 agentConfig := DefaultConfig() 240 agentConfig.KeyringFile = keyringFile 241 242 encodedKeys, err := json.Marshal(keys) 243 if err != nil { 244 t.Fatalf("err: %s", err) 245 } 246 247 if err := ioutil.WriteFile(keyringFile, encodedKeys, 0600); err != nil { 248 t.Fatalf("err: %s", err) 249 } 250 251 a1 := testAgentWithConfig(agentConfig, serfConfig, nil) 252 253 if err := a1.Start(); err != nil { 254 t.Fatalf("err: %s", err) 255 } 256 defer a1.Shutdown() 257 258 testutil.Yield() 259 260 totalLoadedKeys := len(serfConfig.MemberlistConfig.Keyring.GetKeys()) 261 if totalLoadedKeys != 3 { 262 t.Fatalf("Expected to load 3 keys but got %d", totalLoadedKeys) 263 } 264} 265 266func TestAgentKeyringFile_BadOptions(t *testing.T) { 267 agentConfig := DefaultConfig() 268 agentConfig.KeyringFile = "/some/path" 269 agentConfig.EncryptKey = "5K9OtfP7efFrNKe5WCQvXvnaXJ5cWP0SvXiwe0kkjM4=" 270 271 _, err := Create(agentConfig, serf.DefaultConfig(), nil) 272 if err == nil || !strings.Contains(err.Error(), "not allowed") { 273 t.Fatalf("err: %s", err) 274 } 275} 276 277func TestAgentKeyringFile_NoKeys(t *testing.T) { 278 dir, err := ioutil.TempDir("", "serf") 279 if err != nil { 280 t.Fatalf("err: %s", err) 281 } 282 defer os.RemoveAll(dir) 283 284 keysFile := filepath.Join(dir, "keyring") 285 if err := ioutil.WriteFile(keysFile, []byte("[]"), 0600); err != nil { 286 t.Fatalf("err: %s", err) 287 } 288 289 agentConfig := DefaultConfig() 290 agentConfig.KeyringFile = keysFile 291 292 _, err = Create(agentConfig, serf.DefaultConfig(), nil) 293 if err == nil { 294 t.Fatalf("should have errored") 295 } 296 if !strings.Contains(err.Error(), "contains no keys") { 297 t.Fatalf("bad: %s", err) 298 } 299} 300