From 987704f6739249801681403cf807be34be23f103 Mon Sep 17 00:00:00 2001 From: dave vader <48764154+plyr4@users.noreply.github.com> Date: Fri, 1 Sep 2023 14:19:33 -0500 Subject: [PATCH] enhance: add context to Services (#942) --- api/admin/clean.go | 2 +- api/admin/service.go | 5 ++- api/build/cancel.go | 4 +- api/build/clean.go | 2 +- api/build/plan.go | 2 +- api/metrics.go | 4 +- api/service/create.go | 3 +- api/service/delete.go | 3 +- api/service/list.go | 3 +- api/service/plan.go | 5 ++- api/service/update.go | 3 +- database/integration_test.go | 22 +++++----- database/service/clean.go | 3 +- database/service/clean_test.go | 11 ++--- database/service/count.go | 4 +- database/service/count_build.go | 4 +- database/service/count_build_test.go | 7 ++-- database/service/count_test.go | 7 ++-- database/service/create.go | 4 +- database/service/create_test.go | 3 +- database/service/delete.go | 4 +- database/service/delete_test.go | 5 ++- database/service/get.go | 4 +- database/service/get_build.go | 4 +- database/service/get_build_test.go | 5 ++- database/service/get_test.go | 5 ++- database/service/interface.go | 28 +++++++------ database/service/list.go | 6 ++- database/service/list_build.go | 6 ++- database/service/list_build_test.go | 7 ++-- database/service/list_image.go | 3 +- database/service/list_image_test.go | 7 ++-- database/service/list_status.go | 3 +- database/service/list_status_test.go | 7 ++-- database/service/list_test.go | 7 ++-- database/service/opts.go | 11 +++++ database/service/opts_test.go | 50 +++++++++++++++++++++++ database/service/service.go | 5 ++- database/service/table.go | 4 +- database/service/table_test.go | 3 +- database/service/update.go | 4 +- database/service/update_test.go | 5 ++- router/middleware/service/service.go | 3 +- router/middleware/service/service_test.go | 4 +- 44 files changed, 201 insertions(+), 90 deletions(-) diff --git a/api/admin/clean.go b/api/admin/clean.go index 89884c8d5..6ee9e7056 100644 --- a/api/admin/clean.go +++ b/api/admin/clean.go @@ -111,7 +111,7 @@ func CleanResources(c *gin.Context) { logrus.Infof("platform admin %s: cleaned %d builds in database", u.GetName(), builds) // clean services - services, err := database.FromContext(c).CleanServices(msg, before) + services, err := database.FromContext(c).CleanServices(ctx, msg, before) if err != nil { retErr := fmt.Errorf("%d builds cleaned. unable to update services: %w", builds, err) diff --git a/api/admin/service.go b/api/admin/service.go index 24ddae3dc..b80c71a80 100644 --- a/api/admin/service.go +++ b/api/admin/service.go @@ -54,6 +54,9 @@ import ( func UpdateService(c *gin.Context) { logrus.Info("Admin: updating service in database") + // capture middleware values + ctx := c.Request.Context() + // capture body from API request input := new(library.Service) @@ -67,7 +70,7 @@ func UpdateService(c *gin.Context) { } // send API call to update the service - s, err := database.FromContext(c).UpdateService(input) + s, err := database.FromContext(c).UpdateService(ctx, input) if err != nil { retErr := fmt.Errorf("unable to update service %d: %w", input.GetID(), err) diff --git a/api/build/cancel.go b/api/build/cancel.go index 8b75dc470..7d5bff144 100644 --- a/api/build/cancel.go +++ b/api/build/cancel.go @@ -247,7 +247,7 @@ func CancelBuild(c *gin.Context) { for page > 0 { // retrieve build services (per page) from the database - servicesPart, _, err := database.FromContext(c).ListServicesForBuild(b, map[string]interface{}{}, page, perPage) + servicesPart, _, err := database.FromContext(c).ListServicesForBuild(ctx, b, map[string]interface{}{}, page, perPage) if err != nil { retErr := fmt.Errorf("unable to retrieve services for build %s: %w", entry, err) util.HandleError(c, http.StatusNotFound, retErr) @@ -272,7 +272,7 @@ func CancelBuild(c *gin.Context) { if service.GetStatus() == constants.StatusRunning || service.GetStatus() == constants.StatusPending { service.SetStatus(constants.StatusCanceled) - _, err = database.FromContext(c).UpdateService(service) + _, err = database.FromContext(c).UpdateService(ctx, service) if err != nil { retErr := fmt.Errorf("unable to update service %s for build %s: %w", service.GetName(), diff --git a/api/build/clean.go b/api/build/clean.go index 0dd9ea81e..475525f98 100644 --- a/api/build/clean.go +++ b/api/build/clean.go @@ -37,7 +37,7 @@ func CleanBuild(ctx context.Context, database database.Interface, b *library.Bui s.SetFinished(time.Now().UTC().Unix()) // send API call to update the service - _, err := database.UpdateService(s) + _, err := database.UpdateService(ctx, s) if err != nil { logrus.Errorf("unable to kill service %s for build %d: %v", s.GetName(), b.GetNumber(), err) } diff --git a/api/build/plan.go b/api/build/plan.go index 13080b40c..0916e8b50 100644 --- a/api/build/plan.go +++ b/api/build/plan.go @@ -42,7 +42,7 @@ func PlanBuild(ctx context.Context, database database.Interface, p *pipeline.Bui } // plan all services for the build - services, err := service.PlanServices(database, p, b) + services, err := service.PlanServices(ctx, database, p, b) if err != nil { // clean up the objects from the pipeline in the database CleanBuild(ctx, database, b, services, nil, err) diff --git a/api/metrics.go b/api/metrics.go index 3eb1f90e1..507753041 100644 --- a/api/metrics.go +++ b/api/metrics.go @@ -386,7 +386,7 @@ func recordGauges(c *gin.Context) { // service_image_count if q.ServiceImageCount { // send API call to capture the total number of service images - serviceImageMap, err := database.FromContext(c).ListServiceImageCount() + serviceImageMap, err := database.FromContext(c).ListServiceImageCount(ctx) if err != nil { logrus.Errorf("unable to get count of all service images: %v", err) } @@ -399,7 +399,7 @@ func recordGauges(c *gin.Context) { // service_status_count if q.ServiceStatusCount { // send API call to capture the total number of service statuses - serviceStatusMap, err := database.FromContext(c).ListServiceStatusCount() + serviceStatusMap, err := database.FromContext(c).ListServiceStatusCount(ctx) if err != nil { logrus.Errorf("unable to get count of all service statuses: %v", err) } diff --git a/api/service/create.go b/api/service/create.go index 2dcccbd26..b66e57c51 100644 --- a/api/service/create.go +++ b/api/service/create.go @@ -74,6 +74,7 @@ func CreateService(c *gin.Context) { o := org.Retrieve(c) r := repo.Retrieve(c) u := user.Retrieve(c) + ctx := c.Request.Context() entry := fmt.Sprintf("%s/%d", r.GetFullName(), b.GetNumber()) @@ -112,7 +113,7 @@ func CreateService(c *gin.Context) { } // send API call to create the service - s, err := database.FromContext(c).CreateService(input) + s, err := database.FromContext(c).CreateService(ctx, input) if err != nil { retErr := fmt.Errorf("unable to create service for build %s: %w", entry, err) diff --git a/api/service/delete.go b/api/service/delete.go index d85aa0fe8..24c0d7eb0 100644 --- a/api/service/delete.go +++ b/api/service/delete.go @@ -69,6 +69,7 @@ func DeleteService(c *gin.Context) { r := repo.Retrieve(c) s := service.Retrieve(c) u := user.Retrieve(c) + ctx := c.Request.Context() entry := fmt.Sprintf("%s/%d/%d", r.GetFullName(), b.GetNumber(), s.GetNumber()) @@ -84,7 +85,7 @@ func DeleteService(c *gin.Context) { }).Infof("deleting service %s", entry) // send API call to remove the service - err := database.FromContext(c).DeleteService(s) + err := database.FromContext(c).DeleteService(ctx, s) if err != nil { retErr := fmt.Errorf("unable to delete service %s: %w", entry, err) diff --git a/api/service/list.go b/api/service/list.go index 22a7b8be7..d91268092 100644 --- a/api/service/list.go +++ b/api/service/list.go @@ -87,6 +87,7 @@ func ListServices(c *gin.Context) { o := org.Retrieve(c) r := repo.Retrieve(c) u := user.Retrieve(c) + ctx := c.Request.Context() entry := fmt.Sprintf("%s/%d", r.GetFullName(), b.GetNumber()) @@ -124,7 +125,7 @@ func ListServices(c *gin.Context) { perPage = util.MaxInt(1, util.MinInt(100, perPage)) // send API call to capture the list of services for the build - s, t, err := database.FromContext(c).ListServicesForBuild(b, map[string]interface{}{}, page, perPage) + s, t, err := database.FromContext(c).ListServicesForBuild(ctx, b, map[string]interface{}{}, page, perPage) if err != nil { retErr := fmt.Errorf("unable to get services for build %s: %w", entry, err) diff --git a/api/service/plan.go b/api/service/plan.go index a0200767e..203be53aa 100644 --- a/api/service/plan.go +++ b/api/service/plan.go @@ -5,6 +5,7 @@ package service import ( + "context" "fmt" "time" @@ -17,7 +18,7 @@ import ( // PlanServices is a helper function to plan all services // in the build for execution. This creates the services // for the build in the configured backend. -func PlanServices(database database.Interface, p *pipeline.Build, b *library.Build) ([]*library.Service, error) { +func PlanServices(ctx context.Context, database database.Interface, p *pipeline.Build, b *library.Build) ([]*library.Service, error) { // variable to store planned services services := []*library.Service{} @@ -34,7 +35,7 @@ func PlanServices(database database.Interface, p *pipeline.Build, b *library.Bui s.SetCreated(time.Now().UTC().Unix()) // send API call to create the service - s, err := database.CreateService(s) + s, err := database.CreateService(ctx, s) if err != nil { return services, fmt.Errorf("unable to create service %s: %w", s.GetName(), err) } diff --git a/api/service/update.go b/api/service/update.go index 7c1a5859f..fda5d9676 100644 --- a/api/service/update.go +++ b/api/service/update.go @@ -80,6 +80,7 @@ func UpdateService(c *gin.Context) { r := repo.Retrieve(c) s := service.Retrieve(c) u := user.Retrieve(c) + ctx := c.Request.Context() entry := fmt.Sprintf("%s/%d/%d", r.GetFullName(), b.GetNumber(), s.GetNumber()) @@ -133,7 +134,7 @@ func UpdateService(c *gin.Context) { } // send API call to update the service - s, err = database.FromContext(c).UpdateService(s) + s, err = database.FromContext(c).UpdateService(ctx, s) if err != nil { retErr := fmt.Errorf("unable to update service %s: %w", entry, err) diff --git a/database/integration_test.go b/database/integration_test.go index 38f5387c0..a20f48d46 100644 --- a/database/integration_test.go +++ b/database/integration_test.go @@ -1326,7 +1326,7 @@ func testServices(t *testing.T, db Interface, resources *Resources) { // create the services for _, service := range resources.Services { - _, err := db.CreateService(service) + _, err := db.CreateService(context.TODO(), service) if err != nil { t.Errorf("unable to create service %d: %v", service.GetID(), err) } @@ -1334,7 +1334,7 @@ func testServices(t *testing.T, db Interface, resources *Resources) { methods["CreateService"] = true // count the services - count, err := db.CountServices() + count, err := db.CountServices(context.TODO()) if err != nil { t.Errorf("unable to count services: %v", err) } @@ -1344,7 +1344,7 @@ func testServices(t *testing.T, db Interface, resources *Resources) { methods["CountServices"] = true // count the services for a build - count, err = db.CountServicesForBuild(resources.Builds[0], nil) + count, err = db.CountServicesForBuild(context.TODO(), resources.Builds[0], nil) if err != nil { t.Errorf("unable to count services for build %d: %v", resources.Builds[0].GetID(), err) } @@ -1354,7 +1354,7 @@ func testServices(t *testing.T, db Interface, resources *Resources) { methods["CountServicesForBuild"] = true // list the services - list, err := db.ListServices() + list, err := db.ListServices(context.TODO()) if err != nil { t.Errorf("unable to list services: %v", err) } @@ -1364,7 +1364,7 @@ func testServices(t *testing.T, db Interface, resources *Resources) { methods["ListServices"] = true // list the services for a build - list, count, err = db.ListServicesForBuild(resources.Builds[0], nil, 1, 10) + list, count, err = db.ListServicesForBuild(context.TODO(), resources.Builds[0], nil, 1, 10) if err != nil { t.Errorf("unable to list services for build %d: %v", resources.Builds[0].GetID(), err) } @@ -1380,7 +1380,7 @@ func testServices(t *testing.T, db Interface, resources *Resources) { "#init": 1, "target/vela-git:v0.3.0": 1, } - images, err := db.ListServiceImageCount() + images, err := db.ListServiceImageCount(context.TODO()) if err != nil { t.Errorf("unable to list service image count: %v", err) } @@ -1396,7 +1396,7 @@ func testServices(t *testing.T, db Interface, resources *Resources) { "running": 1, "success": 0, } - statuses, err := db.ListServiceStatusCount() + statuses, err := db.ListServiceStatusCount(context.TODO()) if err != nil { t.Errorf("unable to list service status count: %v", err) } @@ -1408,7 +1408,7 @@ func testServices(t *testing.T, db Interface, resources *Resources) { // lookup the services by name for _, service := range resources.Services { build := resources.Builds[service.GetBuildID()-1] - got, err := db.GetServiceForBuild(build, service.GetNumber()) + got, err := db.GetServiceForBuild(context.TODO(), build, service.GetNumber()) if err != nil { t.Errorf("unable to get service %d for build %d: %v", service.GetID(), build.GetID(), err) } @@ -1419,7 +1419,7 @@ func testServices(t *testing.T, db Interface, resources *Resources) { methods["GetServiceForBuild"] = true // clean the services - count, err = db.CleanServices("integration testing", 1563474090) + count, err = db.CleanServices(context.TODO(), "integration testing", 1563474090) if err != nil { t.Errorf("unable to clean services: %v", err) } @@ -1431,7 +1431,7 @@ func testServices(t *testing.T, db Interface, resources *Resources) { // update the services for _, service := range resources.Services { service.SetStatus("success") - got, err := db.UpdateService(service) + got, err := db.UpdateService(context.TODO(), service) if err != nil { t.Errorf("unable to update service %d: %v", service.GetID(), err) } @@ -1445,7 +1445,7 @@ func testServices(t *testing.T, db Interface, resources *Resources) { // delete the services for _, service := range resources.Services { - err = db.DeleteService(service) + err = db.DeleteService(context.TODO(), service) if err != nil { t.Errorf("unable to delete service %d: %v", service.GetID(), err) } diff --git a/database/service/clean.go b/database/service/clean.go index e8bcac16d..aa3cda50a 100644 --- a/database/service/clean.go +++ b/database/service/clean.go @@ -5,6 +5,7 @@ package service import ( + "context" "time" "github.com/go-vela/types/constants" @@ -14,7 +15,7 @@ import ( ) // CleanServices updates services to an error with a created timestamp prior to a defined moment. -func (e *engine) CleanServices(msg string, before int64) (int64, error) { +func (e *engine) CleanServices(ctx context.Context, msg string, before int64) (int64, error) { logrus.Tracef("cleaning pending or running steps in the database created prior to %d", before) s := new(library.Service) diff --git a/database/service/clean_test.go b/database/service/clean_test.go index 17301e119..c469a3127 100644 --- a/database/service/clean_test.go +++ b/database/service/clean_test.go @@ -5,6 +5,7 @@ package service import ( + "context" "reflect" "testing" @@ -64,22 +65,22 @@ func TestService_Engine_CleanService(t *testing.T) { _sqlite := testSqlite(t) defer func() { _sql, _ := _sqlite.client.DB(); _sql.Close() }() - _, err := _sqlite.CreateService(_serviceOne) + _, err := _sqlite.CreateService(context.TODO(), _serviceOne) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } - _, err = _sqlite.CreateService(_serviceTwo) + _, err = _sqlite.CreateService(context.TODO(), _serviceTwo) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } - _, err = _sqlite.CreateService(_serviceThree) + _, err = _sqlite.CreateService(context.TODO(), _serviceThree) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } - _, err = _sqlite.CreateService(_serviceFour) + _, err = _sqlite.CreateService(context.TODO(), _serviceFour) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } @@ -108,7 +109,7 @@ func TestService_Engine_CleanService(t *testing.T) { // run tests for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, err := test.database.CleanServices("msg", 3) + got, err := test.database.CleanServices(context.TODO(), "msg", 3) if test.failure { if err == nil { diff --git a/database/service/count.go b/database/service/count.go index 08b488933..2ea1d374f 100644 --- a/database/service/count.go +++ b/database/service/count.go @@ -5,11 +5,13 @@ package service import ( + "context" + "github.com/go-vela/types/constants" ) // CountServices gets the count of all services from the database. -func (e *engine) CountServices() (int64, error) { +func (e *engine) CountServices(ctx context.Context) (int64, error) { e.logger.Tracef("getting count of all services from the database") // variable to store query results diff --git a/database/service/count_build.go b/database/service/count_build.go index 0cd773570..85d7e8b9e 100644 --- a/database/service/count_build.go +++ b/database/service/count_build.go @@ -5,13 +5,15 @@ package service import ( + "context" + "github.com/go-vela/types/constants" "github.com/go-vela/types/library" "github.com/sirupsen/logrus" ) // CountServicesForBuild gets the count of services by build ID from the database. -func (e *engine) CountServicesForBuild(b *library.Build, filters map[string]interface{}) (int64, error) { +func (e *engine) CountServicesForBuild(ctx context.Context, b *library.Build, filters map[string]interface{}) (int64, error) { e.logger.WithFields(logrus.Fields{ "build": b.GetNumber(), }).Tracef("getting count of services for build %d from the database", b.GetNumber()) diff --git a/database/service/count_build_test.go b/database/service/count_build_test.go index 160dfa5f8..3dec30151 100644 --- a/database/service/count_build_test.go +++ b/database/service/count_build_test.go @@ -5,6 +5,7 @@ package service import ( + "context" "reflect" "testing" @@ -46,12 +47,12 @@ func TestService_Engine_CountServicesForBuild(t *testing.T) { _sqlite := testSqlite(t) defer func() { _sql, _ := _sqlite.client.DB(); _sql.Close() }() - _, err := _sqlite.CreateService(_serviceOne) + _, err := _sqlite.CreateService(context.TODO(), _serviceOne) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } - _, err = _sqlite.CreateService(_serviceTwo) + _, err = _sqlite.CreateService(context.TODO(), _serviceTwo) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } @@ -82,7 +83,7 @@ func TestService_Engine_CountServicesForBuild(t *testing.T) { // run tests for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, err := test.database.CountServicesForBuild(_build, filters) + got, err := test.database.CountServicesForBuild(context.TODO(), _build, filters) if test.failure { if err == nil { diff --git a/database/service/count_test.go b/database/service/count_test.go index 4152c18e9..9de85b5e3 100644 --- a/database/service/count_test.go +++ b/database/service/count_test.go @@ -5,6 +5,7 @@ package service import ( + "context" "reflect" "testing" @@ -41,12 +42,12 @@ func TestService_Engine_CountServices(t *testing.T) { _sqlite := testSqlite(t) defer func() { _sql, _ := _sqlite.client.DB(); _sql.Close() }() - _, err := _sqlite.CreateService(_serviceOne) + _, err := _sqlite.CreateService(context.TODO(), _serviceOne) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } - _, err = _sqlite.CreateService(_serviceTwo) + _, err = _sqlite.CreateService(context.TODO(), _serviceTwo) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } @@ -75,7 +76,7 @@ func TestService_Engine_CountServices(t *testing.T) { // run tests for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, err := test.database.CountServices() + got, err := test.database.CountServices(context.TODO()) if test.failure { if err == nil { diff --git a/database/service/create.go b/database/service/create.go index f748be077..068d9b076 100644 --- a/database/service/create.go +++ b/database/service/create.go @@ -5,6 +5,8 @@ package service import ( + "context" + "github.com/go-vela/types/constants" "github.com/go-vela/types/database" "github.com/go-vela/types/library" @@ -12,7 +14,7 @@ import ( ) // CreateService creates a new service in the database. -func (e *engine) CreateService(s *library.Service) (*library.Service, error) { +func (e *engine) CreateService(ctx context.Context, s *library.Service) (*library.Service, error) { e.logger.WithFields(logrus.Fields{ "service": s.GetNumber(), }).Tracef("creating service %s in the database", s.GetName()) diff --git a/database/service/create_test.go b/database/service/create_test.go index 26771f31c..de5bd429c 100644 --- a/database/service/create_test.go +++ b/database/service/create_test.go @@ -5,6 +5,7 @@ package service import ( + "context" "reflect" "testing" @@ -58,7 +59,7 @@ VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15) RETURNING "id"`). // run tests for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, err := test.database.CreateService(_service) + got, err := test.database.CreateService(context.TODO(), _service) if test.failure { if err == nil { diff --git a/database/service/delete.go b/database/service/delete.go index 86c0c21b2..1fd80dfd9 100644 --- a/database/service/delete.go +++ b/database/service/delete.go @@ -5,6 +5,8 @@ package service import ( + "context" + "github.com/go-vela/types/constants" "github.com/go-vela/types/database" "github.com/go-vela/types/library" @@ -12,7 +14,7 @@ import ( ) // DeleteService deletes an existing service from the database. -func (e *engine) DeleteService(s *library.Service) error { +func (e *engine) DeleteService(ctx context.Context, s *library.Service) error { e.logger.WithFields(logrus.Fields{ "service": s.GetNumber(), }).Tracef("deleting service %s from the database", s.GetName()) diff --git a/database/service/delete_test.go b/database/service/delete_test.go index 04d08fdc8..adc1191e6 100644 --- a/database/service/delete_test.go +++ b/database/service/delete_test.go @@ -5,6 +5,7 @@ package service import ( + "context" "testing" "github.com/DATA-DOG/go-sqlmock" @@ -31,7 +32,7 @@ func TestService_Engine_DeleteService(t *testing.T) { _sqlite := testSqlite(t) defer func() { _sql, _ := _sqlite.client.DB(); _sql.Close() }() - _, err := _sqlite.CreateService(_service) + _, err := _sqlite.CreateService(context.TODO(), _service) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } @@ -57,7 +58,7 @@ func TestService_Engine_DeleteService(t *testing.T) { // run tests for _, test := range tests { t.Run(test.name, func(t *testing.T) { - err = test.database.DeleteService(_service) + err = test.database.DeleteService(context.TODO(), _service) if test.failure { if err == nil { diff --git a/database/service/get.go b/database/service/get.go index 7678168b2..14a6f5698 100644 --- a/database/service/get.go +++ b/database/service/get.go @@ -5,13 +5,15 @@ package service import ( + "context" + "github.com/go-vela/types/constants" "github.com/go-vela/types/database" "github.com/go-vela/types/library" ) // GetService gets a service by ID from the database. -func (e *engine) GetService(id int64) (*library.Service, error) { +func (e *engine) GetService(ctx context.Context, id int64) (*library.Service, error) { e.logger.Tracef("getting service %d from the database", id) // variable to store query results diff --git a/database/service/get_build.go b/database/service/get_build.go index 5321cc728..b0d65803a 100644 --- a/database/service/get_build.go +++ b/database/service/get_build.go @@ -5,6 +5,8 @@ package service import ( + "context" + "github.com/go-vela/types/constants" "github.com/go-vela/types/database" "github.com/go-vela/types/library" @@ -12,7 +14,7 @@ import ( ) // GetServiceForBuild gets a service by number and build ID from the database. -func (e *engine) GetServiceForBuild(b *library.Build, number int) (*library.Service, error) { +func (e *engine) GetServiceForBuild(ctx context.Context, b *library.Build, number int) (*library.Service, error) { e.logger.WithFields(logrus.Fields{ "build": b.GetNumber(), "service": number, diff --git a/database/service/get_build_test.go b/database/service/get_build_test.go index 4b6a629de..b639570b5 100644 --- a/database/service/get_build_test.go +++ b/database/service/get_build_test.go @@ -5,6 +5,7 @@ package service import ( + "context" "reflect" "testing" @@ -41,7 +42,7 @@ func TestService_Engine_GetServiceForBuild(t *testing.T) { _sqlite := testSqlite(t) defer func() { _sql, _ := _sqlite.client.DB(); _sql.Close() }() - _, err := _sqlite.CreateService(_service) + _, err := _sqlite.CreateService(context.TODO(), _service) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } @@ -70,7 +71,7 @@ func TestService_Engine_GetServiceForBuild(t *testing.T) { // run tests for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, err := test.database.GetServiceForBuild(_build, 1) + got, err := test.database.GetServiceForBuild(context.TODO(), _build, 1) if test.failure { if err == nil { diff --git a/database/service/get_test.go b/database/service/get_test.go index 1c2734b36..2d89d4433 100644 --- a/database/service/get_test.go +++ b/database/service/get_test.go @@ -5,6 +5,7 @@ package service import ( + "context" "reflect" "testing" @@ -36,7 +37,7 @@ func TestService_Engine_GetService(t *testing.T) { _sqlite := testSqlite(t) defer func() { _sql, _ := _sqlite.client.DB(); _sql.Close() }() - _, err := _sqlite.CreateService(_service) + _, err := _sqlite.CreateService(context.TODO(), _service) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } @@ -65,7 +66,7 @@ func TestService_Engine_GetService(t *testing.T) { // run tests for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, err := test.database.GetService(1) + got, err := test.database.GetService(context.TODO(), 1) if test.failure { if err == nil { diff --git a/database/service/interface.go b/database/service/interface.go index 0a05c626d..6a4ecdc64 100644 --- a/database/service/interface.go +++ b/database/service/interface.go @@ -5,6 +5,8 @@ package service import ( + "context" + "github.com/go-vela/types/library" ) @@ -18,34 +20,34 @@ type ServiceInterface interface { // https://en.wikipedia.org/wiki/Data_definition_language // CreateServiceTable defines a function that creates the services table. - CreateServiceTable(string) error + CreateServiceTable(context.Context, string) error // Service Data Manipulation Language Functions // // https://en.wikipedia.org/wiki/Data_manipulation_language // CleanServices defines a function that sets running or pending services to error status before a given created time. - CleanServices(string, int64) (int64, error) + CleanServices(context.Context, string, int64) (int64, error) // CountServices defines a function that gets the count of all services. - CountServices() (int64, error) + CountServices(context.Context) (int64, error) // CountServicesForBuild defines a function that gets the count of services by build ID. - CountServicesForBuild(*library.Build, map[string]interface{}) (int64, error) + CountServicesForBuild(context.Context, *library.Build, map[string]interface{}) (int64, error) // CreateService defines a function that creates a new service. - CreateService(*library.Service) (*library.Service, error) + CreateService(context.Context, *library.Service) (*library.Service, error) // DeleteService defines a function that deletes an existing service. - DeleteService(*library.Service) error + DeleteService(context.Context, *library.Service) error // GetService defines a function that gets a service by ID. - GetService(int64) (*library.Service, error) + GetService(context.Context, int64) (*library.Service, error) // GetServiceForBuild defines a function that gets a service by number and build ID. - GetServiceForBuild(*library.Build, int) (*library.Service, error) + GetServiceForBuild(context.Context, *library.Build, int) (*library.Service, error) // ListServices defines a function that gets a list of all services. - ListServices() ([]*library.Service, error) + ListServices(context.Context) ([]*library.Service, error) // ListServicesForBuild defines a function that gets a list of services by build ID. - ListServicesForBuild(*library.Build, map[string]interface{}, int, int) ([]*library.Service, int64, error) + ListServicesForBuild(context.Context, *library.Build, map[string]interface{}, int, int) ([]*library.Service, int64, error) // ListServiceImageCount defines a function that gets a list of all service images and the count of their occurrence. - ListServiceImageCount() (map[string]float64, error) + ListServiceImageCount(context.Context) (map[string]float64, error) // ListServiceStatusCount defines a function that gets a list of all service statuses and the count of their occurrence. - ListServiceStatusCount() (map[string]float64, error) + ListServiceStatusCount(context.Context) (map[string]float64, error) // UpdateService defines a function that updates an existing service. - UpdateService(*library.Service) (*library.Service, error) + UpdateService(context.Context, *library.Service) (*library.Service, error) } diff --git a/database/service/list.go b/database/service/list.go index c7b1b6b13..4ee397e5e 100644 --- a/database/service/list.go +++ b/database/service/list.go @@ -5,13 +5,15 @@ package service import ( + "context" + "github.com/go-vela/types/constants" "github.com/go-vela/types/database" "github.com/go-vela/types/library" ) // ListServices gets a list of all services from the database. -func (e *engine) ListServices() ([]*library.Service, error) { +func (e *engine) ListServices(ctx context.Context) ([]*library.Service, error) { e.logger.Trace("listing all services from the database") // variables to store query results and return value @@ -20,7 +22,7 @@ func (e *engine) ListServices() ([]*library.Service, error) { services := []*library.Service{} // count the results - count, err := e.CountServices() + count, err := e.CountServices(ctx) if err != nil { return nil, err } diff --git a/database/service/list_build.go b/database/service/list_build.go index caffb2d5c..8dec937ca 100644 --- a/database/service/list_build.go +++ b/database/service/list_build.go @@ -5,6 +5,8 @@ package service import ( + "context" + "github.com/go-vela/types/constants" "github.com/go-vela/types/database" "github.com/go-vela/types/library" @@ -12,7 +14,7 @@ import ( ) // ListServicesForBuild gets a list of all services from the database. -func (e *engine) ListServicesForBuild(b *library.Build, filters map[string]interface{}, page int, perPage int) ([]*library.Service, int64, error) { +func (e *engine) ListServicesForBuild(ctx context.Context, b *library.Build, filters map[string]interface{}, page int, perPage int) ([]*library.Service, int64, error) { e.logger.WithFields(logrus.Fields{ "build": b.GetNumber(), }).Tracef("listing services for build %d from the database", b.GetNumber()) @@ -23,7 +25,7 @@ func (e *engine) ListServicesForBuild(b *library.Build, filters map[string]inter services := []*library.Service{} // count the results - count, err := e.CountServicesForBuild(b, filters) + count, err := e.CountServicesForBuild(ctx, b, filters) if err != nil { return services, 0, err } diff --git a/database/service/list_build_test.go b/database/service/list_build_test.go index 1f0a860f4..061f4c6f3 100644 --- a/database/service/list_build_test.go +++ b/database/service/list_build_test.go @@ -5,6 +5,7 @@ package service import ( + "context" "reflect" "testing" @@ -56,12 +57,12 @@ func TestService_Engine_ListServicesForBuild(t *testing.T) { _sqlite := testSqlite(t) defer func() { _sql, _ := _sqlite.client.DB(); _sql.Close() }() - _, err := _sqlite.CreateService(_serviceOne) + _, err := _sqlite.CreateService(context.TODO(), _serviceOne) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } - _, err = _sqlite.CreateService(_serviceTwo) + _, err = _sqlite.CreateService(context.TODO(), _serviceTwo) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } @@ -92,7 +93,7 @@ func TestService_Engine_ListServicesForBuild(t *testing.T) { // run tests for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, _, err := test.database.ListServicesForBuild(_build, filters, 1, 10) + got, _, err := test.database.ListServicesForBuild(context.TODO(), _build, filters, 1, 10) if test.failure { if err == nil { diff --git a/database/service/list_image.go b/database/service/list_image.go index 6625420dc..758e8651a 100644 --- a/database/service/list_image.go +++ b/database/service/list_image.go @@ -5,13 +5,14 @@ package service import ( + "context" "database/sql" "github.com/go-vela/types/constants" ) // ListServiceImageCount gets a list of all service images and the count of their occurrence from the database. -func (e *engine) ListServiceImageCount() (map[string]float64, error) { +func (e *engine) ListServiceImageCount(ctx context.Context) (map[string]float64, error) { e.logger.Tracef("getting count of all images for services from the database") // variables to store query results and return value diff --git a/database/service/list_image_test.go b/database/service/list_image_test.go index 8f0d588d0..5272fb742 100644 --- a/database/service/list_image_test.go +++ b/database/service/list_image_test.go @@ -5,6 +5,7 @@ package service import ( + "context" "reflect" "testing" @@ -41,12 +42,12 @@ func TestService_Engine_ListServiceImageCount(t *testing.T) { _sqlite := testSqlite(t) defer func() { _sql, _ := _sqlite.client.DB(); _sql.Close() }() - _, err := _sqlite.CreateService(_serviceOne) + _, err := _sqlite.CreateService(context.TODO(), _serviceOne) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } - _, err = _sqlite.CreateService(_serviceTwo) + _, err = _sqlite.CreateService(context.TODO(), _serviceTwo) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } @@ -75,7 +76,7 @@ func TestService_Engine_ListServiceImageCount(t *testing.T) { // run tests for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, err := test.database.ListServiceImageCount() + got, err := test.database.ListServiceImageCount(context.TODO()) if test.failure { if err == nil { diff --git a/database/service/list_status.go b/database/service/list_status.go index 01aedeac1..c5df5afb5 100644 --- a/database/service/list_status.go +++ b/database/service/list_status.go @@ -5,13 +5,14 @@ package service import ( + "context" "database/sql" "github.com/go-vela/types/constants" ) // ListServiceStatusCount gets a list of all service statuses and the count of their occurrence from the database. -func (e *engine) ListServiceStatusCount() (map[string]float64, error) { +func (e *engine) ListServiceStatusCount(ctx context.Context) (map[string]float64, error) { e.logger.Tracef("getting count of all statuses for services from the database") // variables to store query results and return value diff --git a/database/service/list_status_test.go b/database/service/list_status_test.go index d1cb46649..54015f286 100644 --- a/database/service/list_status_test.go +++ b/database/service/list_status_test.go @@ -5,6 +5,7 @@ package service import ( + "context" "reflect" "testing" @@ -46,12 +47,12 @@ func TestService_Engine_ListServiceStatusCount(t *testing.T) { _sqlite := testSqlite(t) defer func() { _sql, _ := _sqlite.client.DB(); _sql.Close() }() - _, err := _sqlite.CreateService(_serviceOne) + _, err := _sqlite.CreateService(context.TODO(), _serviceOne) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } - _, err = _sqlite.CreateService(_serviceTwo) + _, err = _sqlite.CreateService(context.TODO(), _serviceTwo) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } @@ -92,7 +93,7 @@ func TestService_Engine_ListServiceStatusCount(t *testing.T) { // run tests for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, err := test.database.ListServiceStatusCount() + got, err := test.database.ListServiceStatusCount(context.TODO()) if test.failure { if err == nil { diff --git a/database/service/list_test.go b/database/service/list_test.go index a7351a8b6..95c9ab861 100644 --- a/database/service/list_test.go +++ b/database/service/list_test.go @@ -5,6 +5,7 @@ package service import ( + "context" "reflect" "testing" @@ -51,12 +52,12 @@ func TestService_Engine_ListServices(t *testing.T) { _sqlite := testSqlite(t) defer func() { _sql, _ := _sqlite.client.DB(); _sql.Close() }() - _, err := _sqlite.CreateService(_serviceOne) + _, err := _sqlite.CreateService(context.TODO(), _serviceOne) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } - _, err = _sqlite.CreateService(_serviceTwo) + _, err = _sqlite.CreateService(context.TODO(), _serviceTwo) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } @@ -85,7 +86,7 @@ func TestService_Engine_ListServices(t *testing.T) { // run tests for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, err := test.database.ListServices() + got, err := test.database.ListServices(context.TODO()) if test.failure { if err == nil { diff --git a/database/service/opts.go b/database/service/opts.go index 2201b1abd..398cdb6b0 100644 --- a/database/service/opts.go +++ b/database/service/opts.go @@ -5,6 +5,8 @@ package service import ( + "context" + "github.com/sirupsen/logrus" "gorm.io/gorm" @@ -42,3 +44,12 @@ func WithSkipCreation(skipCreation bool) EngineOpt { return nil } } + +// WithContext sets the context in the database engine for Services. +func WithContext(ctx context.Context) EngineOpt { + return func(e *engine) error { + e.ctx = ctx + + return nil + } +} diff --git a/database/service/opts_test.go b/database/service/opts_test.go index 62ce5adf8..b871ec924 100644 --- a/database/service/opts_test.go +++ b/database/service/opts_test.go @@ -5,6 +5,7 @@ package service import ( + "context" "reflect" "testing" @@ -159,3 +160,52 @@ func TestService_EngineOpt_WithSkipCreation(t *testing.T) { }) } } + +func TestService_EngineOpt_WithContext(t *testing.T) { + // setup types + e := &engine{config: new(config)} + + // setup tests + tests := []struct { + failure bool + name string + ctx context.Context + want context.Context + }{ + { + failure: false, + name: "context set to TODO", + ctx: context.TODO(), + want: context.TODO(), + }, + { + failure: false, + name: "context set to nil", + ctx: nil, + want: nil, + }, + } + + // run tests + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + err := WithContext(test.ctx)(e) + + if test.failure { + if err == nil { + t.Errorf("WithContext for %s should have returned err", test.name) + } + + return + } + + if err != nil { + t.Errorf("WithContext returned err: %v", err) + } + + if !reflect.DeepEqual(e.ctx, test.want) { + t.Errorf("WithContext is %v, want %v", e.ctx, test.want) + } + }) + } +} diff --git a/database/service/service.go b/database/service/service.go index 548164c0f..4fb016f8b 100644 --- a/database/service/service.go +++ b/database/service/service.go @@ -5,6 +5,7 @@ package service import ( + "context" "fmt" "github.com/go-vela/types/constants" @@ -25,6 +26,8 @@ type ( // engine configuration settings used in service functions config *config + ctx context.Context + // gorm.io/gorm database client used in service functions // // https://pkg.go.dev/gorm.io/gorm#DB @@ -65,7 +68,7 @@ func New(opts ...EngineOpt) (*engine, error) { } // create the services table - err := e.CreateServiceTable(e.client.Config.Dialector.Name()) + err := e.CreateServiceTable(e.ctx, e.client.Config.Dialector.Name()) if err != nil { return nil, fmt.Errorf("unable to create %s table: %w", constants.TableService, err) } diff --git a/database/service/table.go b/database/service/table.go index 48f8dc712..fad3aae2a 100644 --- a/database/service/table.go +++ b/database/service/table.go @@ -5,6 +5,8 @@ package service import ( + "context" + "github.com/go-vela/types/constants" ) @@ -59,7 +61,7 @@ services ( ) // CreateServiceTable creates the services table in the database. -func (e *engine) CreateServiceTable(driver string) error { +func (e *engine) CreateServiceTable(ctx context.Context, driver string) error { e.logger.Tracef("creating services table in the database") // handle the driver provided to create the table diff --git a/database/service/table_test.go b/database/service/table_test.go index 1b4d1b7de..9897ad4df 100644 --- a/database/service/table_test.go +++ b/database/service/table_test.go @@ -5,6 +5,7 @@ package service import ( + "context" "testing" "github.com/DATA-DOG/go-sqlmock" @@ -41,7 +42,7 @@ func TestService_Engine_CreateServiceTable(t *testing.T) { // run tests for _, test := range tests { t.Run(test.name, func(t *testing.T) { - err := test.database.CreateServiceTable(test.name) + err := test.database.CreateServiceTable(context.TODO(), test.name) if test.failure { if err == nil { diff --git a/database/service/update.go b/database/service/update.go index d9b0bd595..8c8d229fd 100644 --- a/database/service/update.go +++ b/database/service/update.go @@ -5,6 +5,8 @@ package service import ( + "context" + "github.com/go-vela/types/constants" "github.com/go-vela/types/database" "github.com/go-vela/types/library" @@ -12,7 +14,7 @@ import ( ) // UpdateService updates an existing service in the database. -func (e *engine) UpdateService(s *library.Service) (*library.Service, error) { +func (e *engine) UpdateService(ctx context.Context, s *library.Service) (*library.Service, error) { e.logger.WithFields(logrus.Fields{ "service": s.GetNumber(), }).Tracef("updating service %s in the database", s.GetName()) diff --git a/database/service/update_test.go b/database/service/update_test.go index 12979dce9..29f41c66f 100644 --- a/database/service/update_test.go +++ b/database/service/update_test.go @@ -5,6 +5,7 @@ package service import ( + "context" "reflect" "testing" @@ -32,7 +33,7 @@ func TestService_Engine_UpdateService(t *testing.T) { _sqlite := testSqlite(t) defer func() { _sql, _ := _sqlite.client.DB(); _sql.Close() }() - _, err := _sqlite.CreateService(_service) + _, err := _sqlite.CreateService(context.TODO(), _service) if err != nil { t.Errorf("unable to create test service for sqlite: %v", err) } @@ -58,7 +59,7 @@ func TestService_Engine_UpdateService(t *testing.T) { // run tests for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, err := test.database.UpdateService(_service) + got, err := test.database.UpdateService(context.TODO(), _service) if test.failure { if err == nil { diff --git a/router/middleware/service/service.go b/router/middleware/service/service.go index 30abf92d0..e6ef94c59 100644 --- a/router/middleware/service/service.go +++ b/router/middleware/service/service.go @@ -33,6 +33,7 @@ func Establish() gin.HandlerFunc { o := org.Retrieve(c) r := repo.Retrieve(c) u := user.Retrieve(c) + ctx := c.Request.Context() if r == nil { retErr := fmt.Errorf("repo %s/%s not found", o, util.PathParameter(c, "repo")) @@ -75,7 +76,7 @@ func Establish() gin.HandlerFunc { "user": u.GetName(), }).Debugf("reading service %s/%d/%d", r.GetFullName(), b.GetNumber(), number) - s, err := database.FromContext(c).GetServiceForBuild(b, number) + s, err := database.FromContext(c).GetServiceForBuild(ctx, b, number) if err != nil { retErr := fmt.Errorf("unable to read service %s/%d/%d: %w", r.GetFullName(), b.GetNumber(), number, err) util.HandleError(c, http.StatusNotFound, retErr) diff --git a/router/middleware/service/service_test.go b/router/middleware/service/service_test.go index 70a8024c3..4d21cb122 100644 --- a/router/middleware/service/service_test.go +++ b/router/middleware/service/service_test.go @@ -81,13 +81,13 @@ func TestService_Establish(t *testing.T) { defer func() { db.DeleteBuild(context.TODO(), b) db.DeleteRepo(context.TODO(), r) - db.DeleteService(want) + db.DeleteService(context.TODO(), want) db.Close() }() _, _ = db.CreateRepo(context.TODO(), r) _, _ = db.CreateBuild(context.TODO(), b) - _, _ = db.CreateService(want) + _, _ = db.CreateService(context.TODO(), want) // setup context gin.SetMode(gin.TestMode)