Skip to content
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

Service provider. Removes global services and passing services around. #61

Merged
merged 15 commits into from
Aug 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,6 @@ test/e2e/reports

# home folder generated by gaia during local test
tmp/

# Ignore the vault file.
.gaia_vault
26 changes: 8 additions & 18 deletions cmd/gaia/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ import (
"github.com/gaia-pipeline/gaia"
"github.com/gaia-pipeline/gaia/handlers"
"github.com/gaia-pipeline/gaia/pipeline"
"github.com/gaia-pipeline/gaia/plugin"
scheduler "github.com/gaia-pipeline/gaia/scheduler"
"github.com/gaia-pipeline/gaia/security"
"github.com/gaia-pipeline/gaia/store"
"github.com/gaia-pipeline/gaia/services"
hclog "github.com/hashicorp/go-hclog"
"github.com/labstack/echo"
)
Expand Down Expand Up @@ -133,8 +130,8 @@ func main() {
gaia.Cfg.CAPath = gaia.Cfg.DataPath
}

// Setup CA for cerificate signing
cert, err := security.InitCA()
// Initialize the certificate manager service
_, err = services.CertificateService()
if err != nil {
gaia.Cfg.Logger.Error("cannot create CA", "error", err.Error())
os.Exit(1)
Expand All @@ -144,26 +141,19 @@ func main() {
echoInstance = echo.New()

// Initialize store
store := store.NewStore()
err = store.Init()
_, err = services.StorageService()
if err != nil {
gaia.Cfg.Logger.Error("cannot initialize store", "error", err.Error())
os.Exit(1)
}

// Create new plugin system
pS := &plugin.Plugin{}

// Initialize scheduler
scheduler := scheduler.NewScheduler(store, pS, cert)
err = scheduler.Init()
_, err = services.SchedulerService()
if err != nil {
gaia.Cfg.Logger.Error("cannot initialize scheduler:", "error", err.Error())
os.Exit(1)
}

// Initialize handlers
err = handlers.InitHandlers(echoInstance, store, scheduler)
err = handlers.InitHandlers(echoInstance)
if err != nil {
gaia.Cfg.Logger.Error("cannot initialize handlers", "error", err.Error())
os.Exit(1)
Expand All @@ -175,14 +165,14 @@ func main() {
// Set default to data folder
gaia.Cfg.VaultPath = gaia.Cfg.DataPath
}
_, err = security.NewVault(cert, nil)
_, err = services.VaultService(nil)
if err != nil {
gaia.Cfg.Logger.Error("error initiating vault")
os.Exit(1)
}

// Start ticker. Periodic job to check for new plugins.
pipeline.InitTicker(store, scheduler)
pipeline.InitTicker()

// Start listen
echoInstance.Logger.Fatal(echoInstance.Start(":" + gaia.Cfg.ListenPort))
Expand Down
14 changes: 1 addition & 13 deletions handlers/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import (

jwt "github.com/dgrijalva/jwt-go"
"github.com/gaia-pipeline/gaia"
scheduler "github.com/gaia-pipeline/gaia/scheduler"
"github.com/gaia-pipeline/gaia/store"
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
)
Expand Down Expand Up @@ -49,18 +47,8 @@ var (
errPipelineRename = errors.New("pipeline could not be renamed")
)

// storeService is an instance of store.
// Use this to talk to the store.
var storeService *store.Store

var schedulerService *scheduler.Scheduler

// InitHandlers initializes(registers) all handlers
func InitHandlers(e *echo.Echo, store *store.Store, scheduler *scheduler.Scheduler) error {
// Set instances
storeService = store
schedulerService = scheduler

func InitHandlers(e *echo.Echo) error {
// Define prefix
p := "/api/" + apiVersion + "/"

Expand Down
7 changes: 7 additions & 0 deletions handlers/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/gaia-pipeline/gaia"
"github.com/gaia-pipeline/gaia/pipeline"
"github.com/gaia-pipeline/gaia/services"
"github.com/labstack/echo"
uuid "github.com/satori/go.uuid"
)
Expand Down Expand Up @@ -38,6 +39,7 @@ func PipelineGitLSRemote(c echo.Context) error {
// CreatePipeline accepts all data needed to create a pipeline.
// It then starts the create pipeline execution process async.
func CreatePipeline(c echo.Context) error {
storeService, _ := services.StorageService()
p := &gaia.CreatePipeline{}
if err := c.Bind(p); err != nil {
return c.String(http.StatusBadRequest, err.Error())
Expand Down Expand Up @@ -66,6 +68,7 @@ func CreatePipeline(c echo.Context) error {
// all pipelines which have been compiled.
func CreatePipelineGetAll(c echo.Context) error {
// Get all create pipelines
storeService, _ := services.StorageService()
pipelineList, err := storeService.CreatePipelineGet()
if err != nil {
gaia.Cfg.Logger.Debug("cannot get create pipelines from store", "error", err.Error())
Expand Down Expand Up @@ -138,6 +141,7 @@ func PipelineGet(c echo.Context) error {

// PipelineUpdate updates the given pipeline.
func PipelineUpdate(c echo.Context) error {
storeService, _ := services.StorageService()
p := gaia.Pipeline{}
if err := c.Bind(&p); err != nil {
return c.String(http.StatusBadRequest, err.Error())
Expand Down Expand Up @@ -188,6 +192,7 @@ func PipelineUpdate(c echo.Context) error {
// PipelineDelete accepts a pipeline id and deletes it from the
// store. It also removes the binary inside the pipeline folder.
func PipelineDelete(c echo.Context) error {
storeService, _ := services.StorageService()
pipelineIDStr := c.Param("pipelineid")

pipelineID, err := strconv.Atoi(pipelineIDStr)
Expand Down Expand Up @@ -232,6 +237,7 @@ func PipelineDelete(c echo.Context) error {
// PipelineStart starts a pipeline by the given id.
// Afterwards it returns the created/scheduled pipeline run.
func PipelineStart(c echo.Context) error {
schedulerService, _ := services.SchedulerService()
pipelineIDStr := c.Param("pipelineid")

// Convert string to int because id is int
Expand Down Expand Up @@ -270,6 +276,7 @@ type getAllWithLatestRun struct {
// included with the latest run.
func PipelineGetAllWithLatestRun(c echo.Context) error {
// Get all active pipelines
storeService, _ := services.StorageService()
var pipelines []gaia.Pipeline
for pipeline := range pipeline.GlobalActivePipelines.Iter() {
pipelines = append(pipelines, pipeline)
Expand Down
5 changes: 5 additions & 0 deletions handlers/pipeline_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strconv"

"github.com/gaia-pipeline/gaia"
"github.com/gaia-pipeline/gaia/services"
"github.com/labstack/echo"
)

Expand All @@ -26,6 +27,7 @@ type jobLogs struct {
// Required parameters are pipelineid and runid.
func PipelineRunGet(c echo.Context) error {
// Convert string to int because id is int
storeService, _ := services.StorageService()
pipelineID, err := strconv.Atoi(c.Param("pipelineid"))
if err != nil {
return c.String(http.StatusBadRequest, errInvalidPipelineID.Error())
Expand All @@ -52,6 +54,7 @@ func PipelineRunGet(c echo.Context) error {
// PipelineGetAllRuns returns all runs about the given pipeline.
func PipelineGetAllRuns(c echo.Context) error {
// Convert string to int because id is int
storeService, _ := services.StorageService()
pipelineID, err := strconv.Atoi(c.Param("pipelineid"))
if err != nil {
return c.String(http.StatusBadRequest, errInvalidPipelineID.Error())
Expand All @@ -69,6 +72,7 @@ func PipelineGetAllRuns(c echo.Context) error {
// PipelineGetLatestRun returns the latest run of a pipeline, given by id.
func PipelineGetLatestRun(c echo.Context) error {
// Convert string to int because id is int
storeService, _ := services.StorageService()
pipelineID, err := strconv.Atoi(c.Param("pipelineid"))
if err != nil {
return c.String(http.StatusBadRequest, errInvalidPipelineID.Error())
Expand All @@ -90,6 +94,7 @@ func PipelineGetLatestRun(c echo.Context) error {
// pipelinerunid - Related pipeline run id
func GetJobLogs(c echo.Context) error {
// Get parameters and validate
storeService, _ := services.StorageService()
pipelineID := c.Param("pipelineid")
pipelineRunID := c.Param("runid")

Expand Down
128 changes: 111 additions & 17 deletions handlers/pipeline_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,34 @@ package handlers
import (
"bytes"
"encoding/json"
"errors"
"io/ioutil"
"net/http"
"net/http/httptest"
"os"
"testing"
"time"

"github.com/gaia-pipeline/gaia/scheduler"

"github.com/gaia-pipeline/gaia/services"

"github.com/gaia-pipeline/gaia"
"github.com/gaia-pipeline/gaia/pipeline"
"github.com/gaia-pipeline/gaia/store"
hclog "github.com/hashicorp/go-hclog"
"github.com/labstack/echo"
)

type mockScheduleService struct {
scheduler.GaiaScheduler
pipelineRun *gaia.PipelineRun
err error
}

func (ms *mockScheduleService) SchedulePipeline(p *gaia.Pipeline) (*gaia.PipelineRun, error) {
return ms.pipelineRun, ms.err
}

func TestPipelineGitLSRemote(t *testing.T) {
dataDir, err := ioutil.TempDir("", "temp")
if err != nil {
Expand All @@ -33,14 +47,8 @@ func TestPipelineGitLSRemote(t *testing.T) {
DataPath: dataDir,
}

dataStore := store.NewStore()
err = dataStore.Init()
if err != nil {
t.Fatalf("cannot initialize store: %v", err.Error())
}

e := echo.New()
InitHandlers(e, dataStore, nil)
InitHandlers(e)

t.Run("fails with invalid data", func(t *testing.T) {
req := httptest.NewRequest(echo.POST, "/api/"+apiVersion+"/pipeline/gitlsremote", nil)
Expand Down Expand Up @@ -109,19 +117,14 @@ func TestPipelineUpdate(t *testing.T) {
}

// Initialize store
dataStore := store.NewStore()
err = dataStore.Init()
if err != nil {
t.Fatalf("cannot initialize store: %v", err.Error())
}

dataStore, _ := services.StorageService()
// Initialize global active pipelines
ap := pipeline.NewActivePipelines()
pipeline.GlobalActivePipelines = ap

// Initialize echo
e := echo.New()
InitHandlers(e, dataStore, nil)
InitHandlers(e)

pipeline1 := gaia.Pipeline{
ID: 1,
Expand Down Expand Up @@ -200,7 +203,7 @@ func TestPipelineDelete(t *testing.T) {
}

// Initialize store
dataStore := store.NewStore()
dataStore, _ := services.StorageService()
err = dataStore.Init()
if err != nil {
t.Fatalf("cannot initialize store: %v", err.Error())
Expand All @@ -212,7 +215,7 @@ func TestPipelineDelete(t *testing.T) {

// Initialize echo
e := echo.New()
InitHandlers(e, dataStore, nil)
InitHandlers(e)

p := gaia.Pipeline{
ID: 1,
Expand Down Expand Up @@ -269,3 +272,94 @@ func TestPipelineDelete(t *testing.T) {
})

}

func TestPipelineStart(t *testing.T) {
gaia.Cfg = &gaia.Config{
Logger: hclog.NewNullLogger(),
}

// Initialize global active pipelines
ap := pipeline.NewActivePipelines()
pipeline.GlobalActivePipelines = ap

// Initialize echo
e := echo.New()
InitHandlers(e)

p := gaia.Pipeline{
ID: 1,
Name: "Pipeline A",
Type: gaia.PTypeGolang,
Created: time.Now(),
}

// Add to active pipelines
ap.Append(p)

t.Run("can start a pipeline", func(t *testing.T) {
req := httptest.NewRequest(echo.POST, "/api/"+apiVersion+"/pipeline/:pipelineid/start", nil)
req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
c.SetParamNames("pipelineid")
c.SetParamValues("1")

ms := new(mockScheduleService)
pRun := new(gaia.PipelineRun)
pRun.ID = 999
ms.pipelineRun = pRun
services.MockSchedulerService(ms)

PipelineStart(c)

if rec.Code != http.StatusCreated {
t.Fatalf("expected response code %v got %v", http.StatusCreated, rec.Code)
}

expectedBody := `{"uniqueid":"","id":999,"pipelineid":0,"startdate":"0001-01-01T00:00:00Z","finishdate":"0001-01-01T00:00:00Z","scheduledate":"0001-01-01T00:00:00Z"}`
body, _ := ioutil.ReadAll(rec.Body)
if string(body) != expectedBody {
t.Fatalf("body did not equal expected content. expected: %s, got: %s", expectedBody, string(body))
}
})

t.Run("fails when scheduler throws error", func(t *testing.T) {
req := httptest.NewRequest(echo.POST, "/api/"+apiVersion+"/pipeline/:pipelineid/start", nil)
req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
c.SetParamNames("pipelineid")
c.SetParamValues("1")

ms := new(mockScheduleService)
pRun := new(gaia.PipelineRun)
pRun.ID = 999
ms.pipelineRun = pRun
ms.err = errors.New("failed to run pipeline")
services.MockSchedulerService(ms)

PipelineStart(c)

if rec.Code != http.StatusBadRequest {
t.Fatalf("expected response code %v got %v", http.StatusBadRequest, rec.Code)
}
})

t.Run("fails when scheduler doesn't find the pipeline but does not return error", func(t *testing.T) {
req := httptest.NewRequest(echo.POST, "/api/"+apiVersion+"/pipeline/:pipelineid/start", nil)
req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
c.SetParamNames("pipelineid")
c.SetParamValues("1")

ms := new(mockScheduleService)
services.MockSchedulerService(ms)

PipelineStart(c)

if rec.Code != http.StatusNotFound {
t.Fatalf("expected response code %v got %v", http.StatusNotFound, rec.Code)
}
})
}
Loading