github.com/jcarley/cli@v0.0.0-20180201210820-966d90434c30/commands/logs/logs_test.go (about) 1 package logs 2 3 import ( 4 "errors" 5 "fmt" 6 "net/http" 7 "strings" 8 "testing" 9 "time" 10 11 "github.com/Sirupsen/logrus" 12 "github.com/daticahealth/cli/commands/environments" 13 "github.com/daticahealth/cli/commands/services" 14 "github.com/daticahealth/cli/commands/sites" 15 "github.com/daticahealth/cli/config" 16 "github.com/daticahealth/cli/lib/jobs" 17 "github.com/daticahealth/cli/models" 18 "github.com/daticahealth/cli/test" 19 ) 20 21 type SLogsMock struct { 22 Settings *models.Settings 23 } 24 25 func (l *SLogsMock) RetrieveElasticsearchVersion(domain string) (string, error) { 26 return "5", nil 27 } 28 29 func (l *SLogsMock) Output(queryString, domain string, generator queryGenerator, from int, startTimestamp, endTimestamp time.Time, hostNames []string, fileName string) (int, error) { 30 appLogsIdentifier := "source" 31 appLogsValue := "app" 32 if strings.HasPrefix(domain, "csb01") { 33 appLogsIdentifier = "syslog_program" 34 appLogsValue = "supervisord" 35 } 36 37 logrus.Println(" @timestamp - message") 38 for { 39 queryBytes, err := generator(queryString, appLogsIdentifier, appLogsValue, startTimestamp, from, hostNames, fileName) 40 if err != nil { 41 return -1, fmt.Errorf("Error generating query: %s", err) 42 } else if queryBytes == nil || len(queryBytes) == 0 { 43 return -1, errors.New("Error generating query") 44 } 45 46 var logs models.Logs 47 var hits models.Hits 48 logHits := []models.LogHits{} 49 for i := 0; i < 3; i++ { 50 var logHit models.LogHits 51 logHit.ID = fmt.Sprintf("log_%d", i) 52 logHit.Score = 2.3 53 logHit.Index = "1" 54 logHit.Type = "THeHittenistLogHit" 55 logHit.Fields = make(map[string][]string) 56 logHit.Fields["@timestamp"] = []string{fmt.Sprintf("2017-10-11T15:04:0%d.999999999Z07:00", i)} 57 logHit.Fields["message"] = []string{fmt.Sprintf("Wow so log %d", i)} 58 logHits = append(logHits, logHit) 59 } 60 hits.Hits = &logHits 61 hits.MaxScore = 2.3 62 hits.Total = 1 63 logs.Hits = &hits 64 65 end := time.Time{} 66 for _, lh := range *logs.Hits.Hits { 67 logrus.Printf("%s - %s", lh.Fields["@timestamp"][0], lh.Fields["message"][0]) 68 end, _ = time.Parse(time.RFC3339Nano, lh.Fields["@timestamp"][0]) 69 } 70 amount := len(*logs.Hits.Hits) 71 72 from += len(*logs.Hits.Hits) 73 // TODO this will infinite loop if it always retrieves `size` hits 74 // and it fails to parse the end timestamp. very small window of opportunity. 75 if amount < size || end.After(endTimestamp) { 76 break 77 } 78 time.Sleep(config.JobPollTime * time.Second) 79 } 80 return from, nil 81 } 82 83 func (l *SLogsMock) Stream(queryString, domain string, generator queryGenerator, from int, timestamp time.Time, hostNames []string, fileName string) error { 84 //Don't want to run stream forever in test 85 for i := 0; i < 2; i++ { 86 f, err := l.Output(queryString, domain, generator, from, timestamp, time.Now(), hostNames, fileName) 87 if err != nil { 88 return err 89 } 90 from = f 91 time.Sleep(config.LogPollTime * time.Second) 92 } 93 return nil 94 } 95 96 func (l *SLogsMock) Watch(queryString, domain string) error { 97 //TODO: Mock it better? 98 return errors.New("Run Stream") 99 } 100 101 func muxSetup(mux *http.ServeMux, t *testing.T, serviceType string, createdAt []string, query *CMDLogQuery) { 102 mux.HandleFunc("/environments/"+test.EnvID+"/services/", 103 // Retrieve services 104 func(w http.ResponseWriter, r *http.Request) { 105 test.AssertEquals(t, r.Method, "GET") 106 fmt.Fprint(w, fmt.Sprintf(`[{"id":"%s","label":"%s","name":"%s","type":"%s","redeployable":false},{"id":"%s","label":"service_proxy","name":"service proxy","redeployable":true}]`, test.SvcID, test.SvcLabel, serviceType, serviceType, test.SvcIDAlt)) 107 }, 108 ) 109 mux.HandleFunc("/environments/"+test.EnvID+"/services/"+test.SvcID+"/jobs/"+query.JobID, 110 //Retrieve job 111 func(w http.ResponseWriter, r *http.Request) { 112 test.AssertEquals(t, r.Method, "GET") 113 if query.JobID == test.JobID { 114 jobJSON := fmt.Sprintf(`{"id":"%s","type":"%s","target":"%s","status":"happy", "created_at":"%s"}`, test.JobID, "deploy", test.Target, createdAt[0]) 115 fmt.Fprint(w, jobJSON) 116 } else { 117 fmt.Fprint(w, "") 118 } 119 }, 120 ) 121 mux.HandleFunc("/environments/"+test.EnvID+"/services/"+test.SvcID+"/jobs", 122 // RetrieveByTarget/Type 123 func(w http.ResponseWriter, r *http.Request) { 124 test.AssertEquals(t, r.Method, "GET") 125 var jobs []string 126 for i, created := range createdAt { 127 jobID := test.JobID 128 if i > 0 { 129 jobID = test.JobIDAlt 130 } 131 jobs = append(jobs, fmt.Sprintf(`{"id":"%s","type":"%s","target":"%s","status":"happy","created_at":"%s"}`, jobID, "worker", test.Target, created)) 132 } 133 jobsJSON := fmt.Sprintf("[%s]", strings.Join(jobs, ",")) 134 fmt.Fprint(w, jobsJSON) 135 }, 136 ) 137 mux.HandleFunc("/environments", 138 // Retrieve environment list 139 func(w http.ResponseWriter, r *http.Request) { 140 test.AssertEquals(t, r.Method, "GET") 141 if r.Header.Get("X-Pod-ID") == test.Pod { 142 fmt.Fprint(w, fmt.Sprintf(`[{"id":"%s","name":"%s","namespace":"%s","organizationId":"%s"}]`, test.EnvID, test.EnvName, test.Namespace, test.OrgID)) 143 } else { 144 fmt.Fprint(w, fmt.Sprintf(`[{"id":"%s","name":"%s","namespace":"%s","organizationId":"%s"}]`, test.EnvIDAlt, test.EnvNameAlt, test.NamespaceAlt, test.OrgIDAlt)) 145 } 146 }, 147 ) 148 mux.HandleFunc("/environments/"+test.EnvID, 149 // Retrieve environment by ID 150 func(w http.ResponseWriter, r *http.Request) { 151 test.AssertEquals(t, r.Method, "GET") 152 fmt.Fprint(w, fmt.Sprintf(`{"id":"%s","name":"%s","namespace":"%s","organizationId":"%s"}`, test.EnvID, test.EnvName, test.Namespace, test.OrgID)) 153 }, 154 ) 155 mux.HandleFunc("/environments/"+test.EnvID+"/services/"+test.SvcIDAlt+"/sites", 156 // Retrieve site by ID 157 func(w http.ResponseWriter, r *http.Request) { 158 test.AssertEquals(t, r.Method, "GET") 159 fmt.Fprint(w, fmt.Sprintf(`[{"id":%d, "name":"%s"}]`, 123, test.Namespace+".supersite")) 160 }, 161 ) 162 } 163 164 func TestLogsService(t *testing.T) { 165 mux, server, baseURL := test.Setup() 166 defer test.Teardown(server) 167 settings := test.GetSettings(baseURL.String()) 168 cmdQuery := CMDLogQuery{ 169 Query: "", 170 Follow: false, 171 Service: test.SvcLabel, 172 } 173 muxSetup(mux, t, "code", []string{test.GoodDate}, &cmdQuery) 174 175 ilogs := &SLogsMock{ 176 Settings: settings, 177 } 178 err := CmdLogs(&cmdQuery, settings.EnvironmentID, settings, ilogs, &test.FakePrompts{}, environments.New(settings), services.New(settings), jobs.New(settings), sites.New(settings)) 179 if err != nil { 180 t.Fatalf("Unexpected error: %s", err) 181 } 182 } 183 184 func TestLogsJobID(t *testing.T) { 185 mux, server, baseURL := test.Setup() 186 defer test.Teardown(server) 187 settings := test.GetSettings(baseURL.String()) 188 cmdQuery := CMDLogQuery{ 189 Query: "", 190 Follow: false, 191 Service: test.SvcLabel, 192 JobID: test.JobID, 193 } 194 muxSetup(mux, t, "code", []string{test.GoodDate}, &cmdQuery) 195 196 ilogs := &SLogsMock{ 197 Settings: settings, 198 } 199 err := CmdLogs(&cmdQuery, settings.EnvironmentID, settings, ilogs, &test.FakePrompts{}, environments.New(settings), services.New(settings), jobs.New(settings), sites.New(settings)) 200 if err != nil { 201 t.Fatalf("Unexpected error: %s", err) 202 } 203 } 204 205 func TestLogsTarget(t *testing.T) { 206 mux, server, baseURL := test.Setup() 207 defer test.Teardown(server) 208 settings := test.GetSettings(baseURL.String()) 209 cmdQuery := CMDLogQuery{ 210 Query: "", 211 Follow: false, 212 Service: test.SvcLabel, 213 Target: test.Target, 214 } 215 muxSetup(mux, t, "code", []string{test.GoodDate, test.GoodDate}, &cmdQuery) 216 217 ilogs := &SLogsMock{ 218 Settings: settings, 219 } 220 err := CmdLogs(&cmdQuery, settings.EnvironmentID, settings, ilogs, &test.FakePrompts{}, environments.New(settings), services.New(settings), jobs.New(settings), sites.New(settings)) 221 if err != nil { 222 t.Fatalf("Unexpected error: %s", err) 223 } 224 } 225 226 func TestLogsStream(t *testing.T) { 227 mux, server, baseURL := test.Setup() 228 defer test.Teardown(server) 229 settings := test.GetSettings(baseURL.String()) 230 cmdQuery := CMDLogQuery{ 231 Query: "", 232 Follow: true, 233 Service: test.SvcLabel, 234 } 235 muxSetup(mux, t, "code", []string{test.GoodDate}, &cmdQuery) 236 237 ilogs := &SLogsMock{ 238 Settings: settings, 239 } 240 err := CmdLogs(&cmdQuery, settings.EnvironmentID, settings, ilogs, &test.FakePrompts{}, environments.New(settings), services.New(settings), jobs.New(settings), sites.New(settings)) 241 if err != nil { 242 t.Fatalf("Unexpected error: %s", err) 243 } 244 } 245 246 func TestLogsBadService(t *testing.T) { 247 mux, server, baseURL := test.Setup() 248 defer test.Teardown(server) 249 settings := test.GetSettings(baseURL.String()) 250 cmdQuery := CMDLogQuery{ 251 Query: "", 252 Follow: false, 253 Service: "BadServiceLabel", 254 } 255 muxSetup(mux, t, "code", []string{test.BadDate}, &cmdQuery) 256 257 ilogs := &SLogsMock{ 258 Settings: settings, 259 } 260 err := CmdLogs(&cmdQuery, settings.EnvironmentID, settings, ilogs, &test.FakePrompts{}, environments.New(settings), services.New(settings), jobs.New(settings), sites.New(settings)) 261 expectedErr := fmt.Sprintf("Cannot find the specified service \"%s\".", cmdQuery.Service) 262 if err == nil { 263 t.Fatalf("Expected: %s\n", expectedErr) 264 } else if err.Error() != expectedErr { 265 t.Fatalf("Expected: %s\nGot: %s", expectedErr, err) 266 } 267 } 268 269 func TestLogsBadRequestMissingService(t *testing.T) { 270 mux, server, baseURL := test.Setup() 271 defer test.Teardown(server) 272 settings := test.GetSettings(baseURL.String()) 273 cmdQuery := CMDLogQuery{ 274 Query: "", 275 Follow: false, 276 Target: test.Target, 277 } 278 muxSetup(mux, t, "code", []string{test.GoodDate}, &cmdQuery) 279 280 ilogs := &SLogsMock{ 281 Settings: settings, 282 } 283 err := CmdLogs(&cmdQuery, settings.EnvironmentID, settings, ilogs, &test.FakePrompts{}, environments.New(settings), services.New(settings), jobs.New(settings), sites.New(settings)) 284 expectedErr := "You must specify a code service to query the logs for a particular target" 285 if err == nil { 286 t.Fatalf("Expected: %s\n", expectedErr) 287 } else if err.Error() != expectedErr { 288 t.Fatalf("Expected: %s\nGot: %s", expectedErr, err) 289 } 290 } 291 292 func TestLogsBadRequestTargetAndJobID(t *testing.T) { 293 mux, server, baseURL := test.Setup() 294 defer test.Teardown(server) 295 settings := test.GetSettings(baseURL.String()) 296 cmdQuery := CMDLogQuery{ 297 Query: "", 298 Follow: false, 299 Target: test.Target, 300 JobID: test.JobID, 301 } 302 muxSetup(mux, t, "code", []string{test.GoodDate}, &cmdQuery) 303 304 ilogs := &SLogsMock{ 305 Settings: settings, 306 } 307 err := CmdLogs(&cmdQuery, settings.EnvironmentID, settings, ilogs, &test.FakePrompts{}, environments.New(settings), services.New(settings), jobs.New(settings), sites.New(settings)) 308 expectedErr := "Specifying \"--job-id\" in combination with \"--target\" is unsupported." 309 if err == nil { 310 t.Fatalf("Expected: %s\n", expectedErr) 311 } else if err.Error() != expectedErr { 312 t.Fatalf("Expected: %s\nGot: %s", expectedErr, err) 313 } 314 } 315 316 func TestLogsBadRequestTargetNonCodeService(t *testing.T) { 317 mux, server, baseURL := test.Setup() 318 defer test.Teardown(server) 319 settings := test.GetSettings(baseURL.String()) 320 cmdQuery := CMDLogQuery{ 321 Query: "", 322 Follow: false, 323 Service: test.SvcLabel, 324 Target: test.Target, 325 } 326 muxSetup(mux, t, "database", []string{test.GoodDate}, &cmdQuery) 327 328 ilogs := &SLogsMock{ 329 Settings: settings, 330 } 331 err := CmdLogs(&cmdQuery, settings.EnvironmentID, settings, ilogs, &test.FakePrompts{}, environments.New(settings), services.New(settings), jobs.New(settings), sites.New(settings)) 332 expectedErr := "Cannot specifiy a target for a non-code service type" 333 if err == nil { 334 t.Fatalf("Expected: %s\n", expectedErr) 335 } else if err.Error() != expectedErr { 336 t.Fatalf("Expected: %s\nGot: %s", expectedErr, err) 337 } 338 } 339 340 func TestLogsBadServiceWithTarget(t *testing.T) { 341 mux, server, baseURL := test.Setup() 342 defer test.Teardown(server) 343 settings := test.GetSettings(baseURL.String()) 344 cmdQuery := CMDLogQuery{ 345 Query: "", 346 Follow: false, 347 Service: "BadServiceLabel", 348 Target: test.Target, 349 } 350 muxSetup(mux, t, "code", []string{test.GoodDate}, &cmdQuery) 351 352 ilogs := &SLogsMock{ 353 Settings: settings, 354 } 355 err := CmdLogs(&cmdQuery, settings.EnvironmentID, settings, ilogs, &test.FakePrompts{}, environments.New(settings), services.New(settings), jobs.New(settings), sites.New(settings)) 356 expectedErr := fmt.Sprintf("Cannot find the specified service \"%s\".", cmdQuery.Service) 357 if err == nil { 358 t.Fatalf("Expected: %s\n", expectedErr) 359 } else if err.Error() != expectedErr { 360 t.Fatalf("Expected: %s\nGot: %s", expectedErr, err) 361 } 362 } 363 364 func TestLogsBadJobID(t *testing.T) { 365 mux, server, baseURL := test.Setup() 366 defer test.Teardown(server) 367 settings := test.GetSettings(baseURL.String()) 368 cmdQuery := CMDLogQuery{ 369 Query: "", 370 Follow: false, 371 Service: test.SvcLabel, 372 JobID: "BadJobID", 373 } 374 muxSetup(mux, t, "code", []string{test.GoodDate}, &cmdQuery) 375 376 ilogs := &SLogsMock{ 377 Settings: settings, 378 } 379 err := CmdLogs(&cmdQuery, settings.EnvironmentID, settings, ilogs, &test.FakePrompts{}, environments.New(settings), services.New(settings), jobs.New(settings), sites.New(settings)) 380 expectedErr := fmt.Sprintf("Cannot find the specified job \"%s\".", cmdQuery.JobID) 381 if err == nil { 382 t.Fatalf("Expected: %s\n", expectedErr) 383 } else if err.Error() != expectedErr { 384 t.Fatalf("Expected: %s\nGot: %s", expectedErr, err) 385 } 386 } 387 388 func TestLogsBadTarget(t *testing.T) { 389 mux, server, baseURL := test.Setup() 390 defer test.Teardown(server) 391 settings := test.GetSettings(baseURL.String()) 392 cmdQuery := CMDLogQuery{ 393 Query: "", 394 Follow: false, 395 Service: test.SvcLabel, 396 Target: "BadTarget", 397 } 398 muxSetup(mux, t, "code", []string{test.GoodDate}, &cmdQuery) 399 400 ilogs := &SLogsMock{ 401 Settings: settings, 402 } 403 err := CmdLogs(&cmdQuery, settings.EnvironmentID, settings, ilogs, &test.FakePrompts{}, environments.New(settings), services.New(settings), jobs.New(settings), sites.New(settings)) 404 expectedErr := fmt.Sprintf("Cannot find any jobs with target \"%s\" for service \"%s\"", cmdQuery.Target, test.SvcID) 405 if err == nil { 406 t.Fatalf("Expected: %s\n", expectedErr) 407 } else if err.Error() != expectedErr { 408 t.Fatalf("Expected: %s\nGot: %s", expectedErr, err) 409 } 410 } 411 412 func TestLogsNoValidHostNames(t *testing.T) { 413 mux, server, baseURL := test.Setup() 414 defer test.Teardown(server) 415 settings := test.GetSettings(baseURL.String()) 416 cmdQuery := CMDLogQuery{ 417 Query: "", 418 Follow: false, 419 Service: test.SvcLabel, 420 Target: test.Target, 421 } 422 muxSetup(mux, t, "code", []string{test.BadDate, test.BadDate}, &cmdQuery) 423 424 ilogs := &SLogsMock{ 425 Settings: settings, 426 } 427 err := CmdLogs(&cmdQuery, settings.EnvironmentID, settings, ilogs, &test.FakePrompts{}, environments.New(settings), services.New(settings), jobs.New(settings), sites.New(settings)) 428 expectedErr := fmt.Sprintf(`All %d jobs for the service "%s"%s do not have valid hostnames to allow their logs to be queried. Redeploy the service if you would like to use this functionality.`, 2, cmdQuery.Service, fmt.Sprintf(` that have a target of "%s"`, cmdQuery.Target)) 429 if err == nil || err.Error() != expectedErr { 430 t.Fatalf("Expected: %s\nGot: %s", expectedErr, err) 431 } 432 } 433 434 func TestLogsOneValidHostName(t *testing.T) { 435 mux, server, baseURL := test.Setup() 436 defer test.Teardown(server) 437 settings := test.GetSettings(baseURL.String()) 438 cmdQuery := CMDLogQuery{ 439 Query: "", 440 Follow: false, 441 Service: test.SvcLabel, 442 Target: test.Target, 443 } 444 muxSetup(mux, t, "code", []string{test.BadDate, test.GoodDate, test.BadDate, test.BadDate}, &cmdQuery) 445 446 ilogs := &SLogsMock{ 447 Settings: settings, 448 } 449 450 err := CmdLogs(&cmdQuery, settings.EnvironmentID, settings, ilogs, &test.FakePrompts{}, environments.New(settings), services.New(settings), jobs.New(settings), sites.New(settings)) 451 if err != nil { 452 t.Fatalf("Unexpected error: %s", err) 453 } 454 }