Add basic graphql api
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
package admin_api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"git.ohea.xyz/cursorius/server/database"
|
||||
"github.com/google/uuid"
|
||||
"github.com/graphql-go/graphql"
|
||||
"github.com/graphql-go/handler"
|
||||
)
|
||||
|
||||
func createSchema(db database.Database) (graphql.Schema, error) {
|
||||
webhookType := graphql.NewObject(graphql.ObjectConfig{
|
||||
Name: "Webhook",
|
||||
Description: "A webhook for triggering pipelines",
|
||||
Fields: graphql.Fields{
|
||||
"id": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphql.String),
|
||||
Description: "The id of the webhook.",
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if webhook, ok := p.Source.(database.Webhook); ok {
|
||||
return webhook.Id, nil
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
},
|
||||
"serverType": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphql.String),
|
||||
Description: "The format of the webhook.",
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if webhook, ok := p.Source.(database.Webhook); ok {
|
||||
return webhook.ServerType, nil
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
},
|
||||
"secret": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphql.String),
|
||||
Description: "The secret used to validate the webhook.",
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if webhook, ok := p.Source.(database.Webhook); ok {
|
||||
return webhook.Secret, nil
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
pipelineType := graphql.NewObject(graphql.ObjectConfig{
|
||||
Name: "Pipeline",
|
||||
Description: "A pipeline for running ci jobs",
|
||||
Fields: graphql.Fields{
|
||||
"id": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphql.String),
|
||||
Description: "The id of the pipeline.",
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if pipeline, ok := p.Source.(database.Pipeline); ok {
|
||||
return pipeline.Id, nil
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
},
|
||||
"name": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphql.String),
|
||||
Description: "The name of the pipeline.",
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if pipeline, ok := p.Source.(database.Pipeline); ok {
|
||||
return pipeline.Name, nil
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
},
|
||||
"url": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphql.String),
|
||||
Description: "The url of the pipeline.",
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if pipeline, ok := p.Source.(database.Pipeline); ok {
|
||||
return pipeline.Url, nil
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
},
|
||||
"pollInterval": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphql.Int),
|
||||
Description: "The polling interval for the pipeline.",
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if pipeline, ok := p.Source.(database.Pipeline); ok {
|
||||
return pipeline.PollInterval, nil
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
},
|
||||
"createWebhook": &graphql.Field{
|
||||
Type: webhookType,
|
||||
Description: "Create a new webhook",
|
||||
Args: graphql.FieldConfigArgument{
|
||||
"type": &graphql.ArgumentConfig{
|
||||
Type: graphql.NewNonNull(graphql.String),
|
||||
},
|
||||
},
|
||||
Resolve: func(params graphql.ResolveParams) (interface{}, error) {
|
||||
webhook, err := db.CreateWebhook(
|
||||
database.WebhookSender(params.Args["type"].(string)),
|
||||
params.Source.(database.Pipeline).Id,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return webhook, nil
|
||||
},
|
||||
},
|
||||
"webhooks": &graphql.Field{
|
||||
Type: graphql.NewNonNull(graphql.NewList(graphql.NewNonNull(webhookType))),
|
||||
Description: "The list of webhooks for the pipeline.",
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
if pipeline, ok := p.Source.(database.Pipeline); ok {
|
||||
return db.GetWebhooksForPipeline(pipeline.Id)
|
||||
}
|
||||
return []database.Webhook{}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
queryType := graphql.NewObject(graphql.ObjectConfig{
|
||||
Name: "Query",
|
||||
Fields: graphql.Fields{
|
||||
"Pipeline": &graphql.Field{
|
||||
Type: pipelineType,
|
||||
Args: graphql.FieldConfigArgument{
|
||||
"id": &graphql.ArgumentConfig{
|
||||
Type: graphql.NewNonNull(graphql.String),
|
||||
Description: "The id of the requested pipeline.",
|
||||
},
|
||||
},
|
||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||
id, err := uuid.Parse(p.Args["id"].(string))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return db.GetPipelineById(id)
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
mutationType := graphql.NewObject(graphql.ObjectConfig{
|
||||
Name: "Mutation",
|
||||
Fields: graphql.Fields{
|
||||
"createPipeline": &graphql.Field{
|
||||
Type: pipelineType,
|
||||
Description: "Create a new pipeline",
|
||||
Args: graphql.FieldConfigArgument{
|
||||
"name": &graphql.ArgumentConfig{
|
||||
Type: graphql.NewNonNull(graphql.String),
|
||||
},
|
||||
"url": &graphql.ArgumentConfig{
|
||||
Type: graphql.NewNonNull(graphql.String),
|
||||
},
|
||||
"pollInterval": &graphql.ArgumentConfig{
|
||||
Type: graphql.Int,
|
||||
},
|
||||
},
|
||||
Resolve: func(params graphql.ResolveParams) (interface{}, error) {
|
||||
var interval int
|
||||
if intervalVal, ok := params.Args["pollInterval"]; ok {
|
||||
interval = intervalVal.(int)
|
||||
} else {
|
||||
interval = 0
|
||||
}
|
||||
pipeline, err := db.CreatePipeline(
|
||||
params.Args["name"].(string),
|
||||
params.Args["url"].(string),
|
||||
interval,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pipeline, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
schema, err := graphql.NewSchema(graphql.SchemaConfig{
|
||||
Query: queryType,
|
||||
Mutation: mutationType,
|
||||
})
|
||||
if err != nil {
|
||||
return schema, fmt.Errorf("Could not create schema: %w", err)
|
||||
}
|
||||
|
||||
return schema, nil
|
||||
}
|
||||
|
||||
func CreateHandler(db database.Database, mux *http.ServeMux) error {
|
||||
|
||||
schema, err := createSchema(db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
h := handler.New(&handler.Config{
|
||||
Schema: &schema,
|
||||
Pretty: true,
|
||||
GraphiQL: true,
|
||||
})
|
||||
|
||||
mux.Handle("/graphql", h)
|
||||
|
||||
return nil
|
||||
}
|
||||
+18
-16
@@ -18,7 +18,7 @@ type Database struct {
|
||||
Conn *pgx.Conn
|
||||
}
|
||||
|
||||
func LaunchDB(conf config.DBConfig) error {
|
||||
func LaunchDB(conf config.DBConfig) (Database, error) {
|
||||
|
||||
dbURL := fmt.Sprintf(
|
||||
"postgres://%v:%v@%v:%v/%v",
|
||||
@@ -50,7 +50,7 @@ func LaunchDB(conf config.DBConfig) error {
|
||||
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not open database: %w", err)
|
||||
return db, fmt.Errorf("Could not open database: %w", err)
|
||||
}
|
||||
|
||||
log.Infof("Database connected sucessfully!")
|
||||
@@ -64,7 +64,7 @@ SELECT EXISTS (
|
||||
var versionTableExists bool
|
||||
err = db.Conn.QueryRow(context.Background(), versionTableExistsQuery).Scan(&versionTableExists)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not check if database was initalized: %w", err)
|
||||
return db, fmt.Errorf("Could not check if database was initalized: %w", err)
|
||||
}
|
||||
|
||||
if versionTableExists {
|
||||
@@ -73,31 +73,33 @@ SELECT EXISTS (
|
||||
log.Info("New database found, initializing....")
|
||||
err = initDB(db.Conn)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not initalize database: %w", err)
|
||||
return db, fmt.Errorf("Could not initalize database: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return db, nil
|
||||
}
|
||||
|
||||
func initDB(conn *pgx.Conn) error {
|
||||
createTablesQuery := `
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
|
||||
CREATE TABLE version (
|
||||
version INT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE pipelines (
|
||||
id SERIAL PRIMARY KEY,
|
||||
id UUID PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
url TEXT NOT NULL,
|
||||
poll_interval INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE webhooks (
|
||||
id SERIAL PRIMARY KEY,
|
||||
type TEXT,
|
||||
secret TEXT,
|
||||
pipeline INTEGER,
|
||||
id UUID PRIMARY KEY,
|
||||
server_type TEXT,
|
||||
secret TEXT,
|
||||
pipeline UUID,
|
||||
|
||||
CONSTRAINT fk_pipeline
|
||||
FOREIGN KEY(pipeline)
|
||||
@@ -105,14 +107,14 @@ CREATE TABLE webhooks (
|
||||
);
|
||||
|
||||
CREATE TABLE runners (
|
||||
id SERIAL PRIMARY KEY,
|
||||
id UUID PRIMARY KEY,
|
||||
name TEXT,
|
||||
secret TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE runs (
|
||||
id SERIAL PRIMARY KEY,
|
||||
pipeline SERIAL,
|
||||
id UUID PRIMARY KEY,
|
||||
pipeline UUID,
|
||||
result BOOLEAN NOT NULL,
|
||||
|
||||
CONSTRAINT fk_pipeline
|
||||
@@ -121,10 +123,10 @@ CREATE TABLE runs (
|
||||
);
|
||||
|
||||
CREATE TABLE command_executions (
|
||||
id SERIAL PRIMARY KEY,
|
||||
run_id SERIAL,
|
||||
id UUID PRIMARY KEY,
|
||||
run_id UUID,
|
||||
command TEXT,
|
||||
return_code TEXT,
|
||||
return_code INT,
|
||||
stdout TEXT,
|
||||
stderr TEXT,
|
||||
start_time TIMESTAMP,
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func (d *Database) GetPipelineById(id uuid.UUID) (Pipeline, error) {
|
||||
query := `
|
||||
SELECT name, url, poll_interval
|
||||
FROM pipelines
|
||||
WHERE id=$1;`
|
||||
|
||||
pipeline := Pipeline{
|
||||
Id: id,
|
||||
}
|
||||
|
||||
err := d.Conn.QueryRow(context.Background(), query, id).Scan(&pipeline.Name, &pipeline.Url, &pipeline.PollInterval)
|
||||
if err != nil {
|
||||
return pipeline, fmt.Errorf("Could not query database for pipeline with id %v: %w", id.String(), err)
|
||||
}
|
||||
|
||||
return pipeline, nil
|
||||
}
|
||||
|
||||
func (d *Database) CreatePipeline(name string, url string, pollInterval int) (Pipeline, error) {
|
||||
query := `
|
||||
INSERT INTO pipelines (id, name, url, poll_interval)
|
||||
VALUES (uuid_generate_v4(), $1, $2, $3)
|
||||
RETURNING id, name, url, poll_interval;`
|
||||
|
||||
pipeline := Pipeline{}
|
||||
var idStr string
|
||||
err := d.Conn.QueryRow(context.Background(), query, name, url, pollInterval).Scan(&idStr, &pipeline.Name, &pipeline.Url, &pipeline.PollInterval)
|
||||
if err != nil {
|
||||
return pipeline, err
|
||||
}
|
||||
|
||||
id, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
return pipeline, err
|
||||
}
|
||||
|
||||
pipeline.Id = id
|
||||
|
||||
return pipeline, nil
|
||||
}
|
||||
|
||||
func (db *Database) GetWebhooksForPipeline(id uuid.UUID) ([]Webhook, error) {
|
||||
query := `
|
||||
SELECT id, server_type, secret
|
||||
FROM webhooks
|
||||
WHERE pipeline=$1;`
|
||||
|
||||
webhooks := make([]Webhook, 0)
|
||||
|
||||
rows, err := db.Conn.Query(context.Background(), query, id)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var webhook Webhook
|
||||
var idStr string
|
||||
if err := rows.Scan(&idStr, &webhook.ServerType, &webhook.Secret); err != nil {
|
||||
return webhooks, err
|
||||
}
|
||||
|
||||
webhook.Id, err = uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
return webhooks, err
|
||||
}
|
||||
webhooks = append(webhooks, webhook)
|
||||
}
|
||||
|
||||
return webhooks, nil
|
||||
}
|
||||
|
||||
func (d *Database) GetWebhookById(id uuid.UUID) (Webhook, error) {
|
||||
query := `
|
||||
SELECT server_type, secret, pipeline
|
||||
FROM webhooks
|
||||
WHERE id=$1;`
|
||||
|
||||
webhook := Webhook{
|
||||
Id: id,
|
||||
}
|
||||
|
||||
err := d.Conn.QueryRow(context.Background(), query, id).Scan(&webhook.ServerType, &webhook.Secret, &webhook.Pipeline)
|
||||
if err != nil {
|
||||
return webhook, fmt.Errorf("Could not query database for webhook with id %v: %w", id.String(), err)
|
||||
}
|
||||
|
||||
return webhook, nil
|
||||
}
|
||||
|
||||
func (d *Database) CreateWebhook(serverType WebhookSender, pipelineId uuid.UUID) (Webhook, error) {
|
||||
|
||||
//WITH secret_val as (select substr(md5(random()::text), 0, 50)),
|
||||
|
||||
query := `
|
||||
INSERT INTO webhooks (id, server_type, secret, pipeline)
|
||||
VALUES (uuid_generate_v4(), $1, (select substr(md5(random()::text), 0, 50)), $2)
|
||||
RETURNING id, server_type, secret, pipeline;`
|
||||
|
||||
webhook := Webhook{}
|
||||
var idStr string
|
||||
err := d.Conn.QueryRow(context.Background(), query, string(serverType), pipelineId).Scan(&idStr, &webhook.ServerType, &webhook.Secret, &webhook.Pipeline)
|
||||
if err != nil {
|
||||
return webhook, err
|
||||
}
|
||||
|
||||
id, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
return webhook, err
|
||||
}
|
||||
|
||||
webhook.Id = id
|
||||
|
||||
return webhook, nil
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Pipeline struct {
|
||||
Id uuid.UUID
|
||||
Name string
|
||||
Url string
|
||||
PollInterval int
|
||||
}
|
||||
|
||||
type WebhookSender string
|
||||
|
||||
const (
|
||||
Gitea WebhookSender = "gitea"
|
||||
)
|
||||
|
||||
type Webhook struct {
|
||||
Id uuid.UUID
|
||||
ServerType WebhookSender
|
||||
Secret string
|
||||
Pipeline uuid.UUID
|
||||
}
|
||||
|
||||
type Runner struct {
|
||||
Id uuid.UUID
|
||||
Name string
|
||||
Secret string
|
||||
}
|
||||
|
||||
type Run struct {
|
||||
Id uuid.UUID
|
||||
Pipeline uuid.UUID
|
||||
Result bool
|
||||
}
|
||||
|
||||
type CommandExecution struct {
|
||||
Id uuid.UUID
|
||||
RunId uuid.UUID
|
||||
Command string
|
||||
ReturnCode int
|
||||
Stdout string
|
||||
Stderr string
|
||||
StartTime time.Time
|
||||
EndTime time.Time
|
||||
}
|
||||
@@ -11,6 +11,8 @@ require (
|
||||
github.com/go-git/go-git/v5 v5.4.3-0.20220529141257-bc1f419cebcf
|
||||
github.com/go-playground/webhooks/v6 v6.0.1
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/graphql-go/graphql v0.8.0
|
||||
github.com/graphql-go/handler v0.2.3
|
||||
github.com/jackc/pgx/v5 v5.2.0
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
||||
golang.org/x/net v0.2.0
|
||||
|
||||
@@ -709,6 +709,10 @@ github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/graphql-go/graphql v0.8.0 h1:JHRQMeQjofwqVvGwYnr8JnPTY0AxgVy1HpHSGPLdH0I=
|
||||
github.com/graphql-go/graphql v0.8.0/go.mod h1:nKiHzRM0qopJEwCITUuIsxk9PlVlwIiiI8pnJEhordQ=
|
||||
github.com/graphql-go/handler v0.2.3 h1:CANh8WPnl5M9uA25c2GBhPqJhE53Fg0Iue/fRNla71E=
|
||||
github.com/graphql-go/handler v0.2.3/go.mod h1:leLF6RpV5uZMN1CdImAxuiayrYYhOk33bZciaUGaXeU=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI=
|
||||
|
||||
+19
-6
@@ -4,7 +4,9 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"git.ohea.xyz/cursorius/server/admin_api"
|
||||
"git.ohea.xyz/cursorius/server/config"
|
||||
"git.ohea.xyz/cursorius/server/database"
|
||||
"git.ohea.xyz/cursorius/server/pipeline_api"
|
||||
"git.ohea.xyz/cursorius/server/runnermanager"
|
||||
"git.ohea.xyz/cursorius/server/webhook"
|
||||
@@ -19,14 +21,20 @@ var log = logging.MustGetLogger("cursorius-server")
|
||||
func setupHTTPServer(
|
||||
mux *http.ServeMux,
|
||||
conf config.Config,
|
||||
db database.Database,
|
||||
registerCh chan runnermanager.RunnerRegistration,
|
||||
getRunnerCh chan runnermanager.GetRunnerRequest,
|
||||
) {
|
||||
) error {
|
||||
|
||||
webhook.CreateWebhookHandler(conf, mux)
|
||||
|
||||
pipeline_api.CreateHandler(getRunnerCh, mux)
|
||||
|
||||
err := admin_api.CreateHandler(db, mux)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not create admin api handler: %w", err)
|
||||
}
|
||||
|
||||
mux.HandleFunc("/runner", func(w http.ResponseWriter, r *http.Request) {
|
||||
conn, err := websocket.Accept(w, r, nil)
|
||||
if err != nil {
|
||||
@@ -35,6 +43,7 @@ func setupHTTPServer(
|
||||
}
|
||||
go runnermanager.RegisterRunner(conn, registerCh)
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func Listen(
|
||||
@@ -42,22 +51,26 @@ func Listen(
|
||||
address string,
|
||||
port int,
|
||||
conf config.Config,
|
||||
db database.Database,
|
||||
registerCh chan runnermanager.RunnerRegistration,
|
||||
getRunnerCh chan runnermanager.GetRunnerRequest,
|
||||
) {
|
||||
) error {
|
||||
|
||||
setupHTTPServer(
|
||||
err := setupHTTPServer(
|
||||
mux,
|
||||
conf,
|
||||
db,
|
||||
registerCh,
|
||||
getRunnerCh,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not setup http endpoints: %w", err)
|
||||
}
|
||||
|
||||
connect_string := fmt.Sprintf("%v:%v", address, port)
|
||||
log.Noticef("Launching HTTP server on %v\n", connect_string)
|
||||
log.Fatal(http.ListenAndServe(
|
||||
return http.ListenAndServe(
|
||||
connect_string,
|
||||
h2c.NewHandler(mux, &http2.Server{}),
|
||||
))
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
err = database.LaunchDB(configData.Config.DBConfig)
|
||||
db, err := database.LaunchDB(configData.Config.DBConfig)
|
||||
if err != nil {
|
||||
log.Errorf("Could not launch db: %v", err)
|
||||
return
|
||||
@@ -50,12 +50,13 @@ func main() {
|
||||
|
||||
mux := http.NewServeMux()
|
||||
|
||||
listen.Listen(
|
||||
log.Fatal(listen.Listen(
|
||||
mux,
|
||||
configData.Config.Address,
|
||||
configData.Config.Port,
|
||||
configData.Config,
|
||||
db,
|
||||
registerCh,
|
||||
getRunnerCh,
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user