-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(worker): get available workers #773
base: main
Are you sure you want to change the base?
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -178,6 +178,34 @@ func GetWorkers(c *gin.Context) { | |
c.JSON(http.StatusOK, w) | ||
} | ||
|
||
// GetWorkersByStatus represents the API handler to capture a | ||
// list of workers with specified status from the configured backend. | ||
func GetWorkersByStatus(c *gin.Context) { | ||
s := c.Param("status") | ||
// capture middleware values | ||
u := user.Retrieve(c) | ||
|
||
// TODO message/error if not valid status or empty string, or they get back all the workers (GetWorkers), how do other endpoints do it? prob use regex to confirm alpha charas only | ||
|
||
// update engine logger with API metadata | ||
// | ||
// https://pkg.go.dev/github.com/sirupsen/logrus?tab=doc#Entry.WithFields | ||
logrus.WithFields(logrus.Fields{ | ||
"user": u.GetName(), | ||
}).Info("reading workers") | ||
|
||
w, err := database.FromContext(c).ListWorkersByStatus(s) | ||
if err != nil { | ||
retErr := fmt.Errorf("unable to get workers: %w", err) | ||
|
||
util.HandleError(c, http.StatusInternalServerError, retErr) | ||
|
||
return | ||
} | ||
|
||
c.JSON(http.StatusOK, w) | ||
} | ||
|
||
// swagger:operation GET /api/v1/workers/{worker} workers GetWorker | ||
// | ||
// Retrieve a worker for the configured backend | ||
|
@@ -311,6 +339,31 @@ func UpdateWorker(c *gin.Context) { | |
w.SetActive(input.GetActive()) | ||
} | ||
|
||
if len(input.GetStatus()) > 0 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 |
||
// update status if set | ||
w.SetStatus(input.GetStatus()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 |
||
} | ||
|
||
if input.GetLastStatusUpdateAt() > 0 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 |
||
// update LastStatusUpdateAt if set | ||
w.SetLastStatusUpdateAt(input.GetLastStatusUpdateAt()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 |
||
} | ||
|
||
if len(input.GetRunningBuildIDs()) > 0 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 |
||
// update RunningBuildIDs if set | ||
w.SetRunningBuildIDs(input.GetRunningBuildIDs()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 |
||
} | ||
|
||
if input.GetLastBuildFinishedAt() > 0 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 |
||
// update LastBuildFinishedAt if set | ||
w.SetLastBuildFinishedAt(input.GetLastBuildFinishedAt()) | ||
} | ||
|
||
if input.GetLastCheckedIn() > 0 { | ||
// update LastCheckedIn if set | ||
w.SetLastCheckedIn(input.GetLastCheckedIn()) | ||
} | ||
|
||
// send API call to update the worker | ||
err = database.FromContext(c).UpdateWorker(w) | ||
if err != nil { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Copyright (c) 2022 Target Brands, Inc. All rights reserved. | ||
// | ||
// Use of this source code is governed by the LICENSE file in this repository. | ||
|
||
package worker | ||
|
||
import ( | ||
"github.com/go-vela/types/constants" | ||
) | ||
|
||
// CountWorkersByStatus gets the count of all workers from the database with the specified status. | ||
func (e *engine) CountWorkersByStatus(status string) (int64, error) { | ||
e.logger.Tracef("getting count of all workers from the database with the specified status") | ||
|
||
// variable to store query results | ||
var w int64 | ||
|
||
// send query to the database and store result in variable | ||
err := e.client. | ||
Table(constants.TableWorker). | ||
Where("status = ?", status). | ||
Count(&w). | ||
Error | ||
|
||
return w, err | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// Copyright (c) 2022 Target Brands, Inc. All rights reserved. | ||
// | ||
// Use of this source code is governed by the LICENSE file in this repository. | ||
|
||
package worker | ||
|
||
import ( | ||
"github.com/go-vela/types/constants" | ||
"github.com/go-vela/types/database" | ||
"github.com/go-vela/types/library" | ||
) | ||
|
||
// ListWorkersByStatus gets a list of all workers from the database with the specified status. | ||
func (e *engine) ListWorkersByStatus(status string) ([]*library.Worker, error) { | ||
e.logger.Trace("listing all workers from the database") | ||
|
||
// variables to store query results and return value | ||
count := int64(0) | ||
w := new([]database.Worker) | ||
workers := []*library.Worker{} | ||
|
||
// count the results | ||
count, err := e.CountWorkersByStatus(status) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// short-circuit if there are no results | ||
if count == 0 { | ||
return workers, nil | ||
} | ||
|
||
// send query to the database and store result in variable | ||
err = e.client. | ||
Table(constants.TableWorker). | ||
Where("status = ?", status). | ||
Find(&w). | ||
Error | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// iterate through all query results | ||
for _, worker := range *w { | ||
// https://golang.org/doc/faq#closures_and_goroutines | ||
tmp := worker | ||
|
||
// convert query result to library type | ||
// | ||
// https://pkg.go.dev/github.com/go-vela/types/database#Worker.ToLibrary | ||
workers = append(workers, tmp.ToLibrary()) | ||
} | ||
|
||
return workers, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
// Copyright (c) 2022 Target Brands, Inc. All rights reserved. | ||
// | ||
// Use of this source code is governed by the LICENSE file in this repository. | ||
|
||
package worker | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
|
||
"github.com/DATA-DOG/go-sqlmock" | ||
"github.com/go-vela/types/library" | ||
) | ||
|
||
func TestWorker_Engine_GetWorkersByStatus(t *testing.T) { | ||
// setup types | ||
_workerOne := testWorker() | ||
_workerOne.SetID(1) | ||
_workerOne.SetHostname("worker_0") | ||
_workerOne.SetAddress("localhost") | ||
_workerOne.SetActive(true) | ||
_workerOne.SetStatus("available") | ||
|
||
_workerTwo := testWorker() | ||
_workerTwo.SetID(2) | ||
_workerTwo.SetHostname("worker_1") | ||
_workerTwo.SetAddress("localhost") | ||
_workerTwo.SetActive(true) | ||
_workerTwo.SetStatus("busy") | ||
|
||
_workerThree := testWorker() | ||
_workerThree.SetID(3) | ||
_workerThree.SetHostname("worker_2") | ||
_workerThree.SetAddress("localhost") | ||
_workerThree.SetActive(true) | ||
_workerThree.SetStatus("available") | ||
|
||
_postgres, _mock := testPostgres(t) | ||
defer func() { _sql, _ := _postgres.client.DB(); _sql.Close() }() | ||
|
||
// create expected result in mock | ||
_rows := sqlmock.NewRows([]string{"count"}).AddRow(2) | ||
|
||
// ensure the mock expects the query | ||
_mock.ExpectQuery(`SELECT count(*) FROM "workers" WHERE status = $1`).WithArgs("available").WillReturnRows(_rows) | ||
|
||
// create expected result in mock | ||
_rows = sqlmock.NewRows( | ||
[]string{"id", "hostname", "address", "routes", "active", "status", "last_checked_in", "build_limit"}). | ||
AddRow(1, "worker_0", "localhost", nil, true, "available", 0, 0). | ||
AddRow(3, "worker_2", "localhost", nil, true, "available", 0, 0) | ||
|
||
// ensure the mock expects the query | ||
_mock.ExpectQuery(`SELECT * FROM "workers" WHERE status = $1`).WithArgs("available").WillReturnRows(_rows) | ||
|
||
_sqlite := testSqlite(t) | ||
defer func() { _sql, _ := _sqlite.client.DB(); _sql.Close() }() | ||
|
||
err := _sqlite.CreateWorker(_workerOne) | ||
if err != nil { | ||
t.Errorf("unable to create test worker one for sqlite: %v", err) | ||
} | ||
|
||
err = _sqlite.CreateWorker(_workerTwo) | ||
if err != nil { | ||
t.Errorf("unable to create test worker two for sqlite: %v", err) | ||
} | ||
|
||
err = _sqlite.CreateWorker(_workerThree) | ||
if err != nil { | ||
t.Errorf("unable to create test worker three for sqlite: %v", err) | ||
} | ||
|
||
// setup tests | ||
tests := []struct { | ||
failure bool | ||
name string | ||
database *engine | ||
want []*library.Worker | ||
}{ | ||
{ | ||
failure: false, | ||
name: "postgres", | ||
database: _postgres, | ||
want: []*library.Worker{_workerOne, _workerThree}, | ||
}, | ||
{ | ||
failure: false, | ||
name: "sqlite3", | ||
database: _sqlite, | ||
want: []*library.Worker{_workerOne, _workerThree}, | ||
}, | ||
} | ||
|
||
// run tests | ||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
got, err := test.database.ListWorkersByStatus("available") | ||
|
||
if test.failure { | ||
if err == nil { | ||
t.Errorf("ListWorkersByStatus for %s should have returned err", test.name) | ||
} | ||
|
||
return | ||
} | ||
|
||
if err != nil { | ||
t.Errorf("ListWorkersByStatus for %s returned err: %v", test.name, err) | ||
} | ||
|
||
if !reflect.DeepEqual(got, test.want) { | ||
t.Errorf("ListWorkersByStatus for %s is %v, want %v", test.name, got, test.want) | ||
} | ||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚫 [golangci] reported by reviewdog 🐶
input.GetStatus undefined (type *library.Worker has no field or method GetStatus)