Add support for access repos with credentials
This commit is contained in:
+27
-10
@@ -40,10 +40,15 @@ func LaunchDB(conf config.DBConfig) (Database, error) {
|
||||
db := Database{}
|
||||
|
||||
var err error
|
||||
log.Infof("Connecting to database with URL \"%v\"", dbURLNoPasswd)
|
||||
db.Conn, err = pgxpool.New(context.Background(), dbURL)
|
||||
if err != nil {
|
||||
return db, fmt.Errorf("could not create database pool: %w", err)
|
||||
}
|
||||
|
||||
// sleep until we can sucessfully acquire a connection
|
||||
for i := 0; i < 10; i++ {
|
||||
// TODO: retry logic is broken with pgxpool
|
||||
log.Infof("Connecting to database with URL \"%v\" (attempt %v)", dbURLNoPasswd, i)
|
||||
db.Conn, err = pgxpool.New(context.Background(), dbURL)
|
||||
_, err = db.Conn.Acquire(context.Background())
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
@@ -90,11 +95,24 @@ CREATE TABLE version (
|
||||
|
||||
);
|
||||
|
||||
CREATE TABLE credentials (
|
||||
id UUID PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
username TEXT NOT NULL,
|
||||
secret TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE pipelines (
|
||||
id UUID PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
url TEXT NOT NULL,
|
||||
poll_interval INTEGER
|
||||
poll_interval INTEGER,
|
||||
credential UUID DEFAULT NULL,
|
||||
|
||||
CONSTRAINT fk_credential
|
||||
FOREIGN KEY(credential)
|
||||
REFERENCES credentials(id)
|
||||
);
|
||||
|
||||
CREATE TABLE webhooks (
|
||||
@@ -108,12 +126,6 @@ CREATE TABLE webhooks (
|
||||
REFERENCES pipelines(id)
|
||||
);
|
||||
|
||||
CREATE TABLE runners (
|
||||
id UUID PRIMARY KEY,
|
||||
name TEXT,
|
||||
secret TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE runs (
|
||||
id UUID PRIMARY KEY,
|
||||
pipeline UUID,
|
||||
@@ -142,6 +154,11 @@ CREATE TABLE command_executions (
|
||||
REFERENCES runs(id)
|
||||
);
|
||||
|
||||
CREATE TABLE runners (
|
||||
id UUID PRIMARY KEY,
|
||||
name TEXT,
|
||||
secret TEXT
|
||||
);
|
||||
`
|
||||
|
||||
_, err := conn.Exec(context.Background(), createTablesQuery)
|
||||
|
||||
+132
-9
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
func (db *Database) GetPipelines() ([]Pipeline, error) {
|
||||
query := `
|
||||
SELECT id, name, url, poll_interval
|
||||
SELECT id, name, url, poll_interval, credential
|
||||
FROM pipelines;`
|
||||
|
||||
pipelines := make([]Pipeline, 0)
|
||||
@@ -23,7 +23,7 @@ FROM pipelines;`
|
||||
for rows.Next() {
|
||||
var pipeline Pipeline
|
||||
var idStr string
|
||||
if err := rows.Scan(&idStr, &pipeline.Name, &pipeline.Url, &pipeline.PollInterval); err != nil {
|
||||
if err := rows.Scan(&idStr, &pipeline.Name, &pipeline.Url, &pipeline.PollInterval, &pipeline.Credential); err != nil {
|
||||
return pipelines, err
|
||||
}
|
||||
|
||||
@@ -55,29 +55,71 @@ WHERE id=$1;`
|
||||
return pipeline, nil
|
||||
}
|
||||
|
||||
func (db *Database) CreatePipeline(name string, url string, pollInterval int) (Pipeline, error) {
|
||||
func (db *Database) CreatePipeline(name string, url string, pollInterval int, credential *uuid.UUID) (Pipeline, error) {
|
||||
query := `
|
||||
INSERT INTO pipelines (id, name, url, poll_interval)
|
||||
VALUES (uuid_generate_v4(), $1, $2, $3)
|
||||
INSERT INTO pipelines (id, name, url, poll_interval, credential)
|
||||
VALUES (uuid_generate_v4(), $1, $2, $3, $4)
|
||||
RETURNING id, name, url, poll_interval;`
|
||||
|
||||
pipeline := Pipeline{}
|
||||
var idStr string
|
||||
err := db.Conn.QueryRow(context.Background(), query, name, url, pollInterval).Scan(&idStr, &pipeline.Name, &pipeline.Url, &pipeline.PollInterval)
|
||||
err := db.Conn.QueryRow(context.Background(), query, name, url, pollInterval, credential).Scan(&idStr, &pipeline.Name, &pipeline.Url, &pipeline.PollInterval)
|
||||
if err != nil {
|
||||
return pipeline, fmt.Errorf("Could not create pipeline: %w", err)
|
||||
}
|
||||
|
||||
id, err := uuid.Parse(idStr)
|
||||
pipeline.Id, err = uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
return pipeline, fmt.Errorf("Could not parse UUID generated by DB: %w", err)
|
||||
}
|
||||
|
||||
pipeline.Id = id
|
||||
|
||||
return pipeline, nil
|
||||
}
|
||||
|
||||
func (db *Database) SetPipelineCredential(pipelineId uuid.UUID, credentialId *uuid.UUID) (Pipeline, error) {
|
||||
query := `
|
||||
UPDATE pipelines
|
||||
SET credential=$1
|
||||
WHERE id=$2
|
||||
RETURNING name, url, poll_interval, credential;`
|
||||
|
||||
pipeline := Pipeline{
|
||||
Id: pipelineId,
|
||||
}
|
||||
|
||||
err := db.Conn.QueryRow(context.Background(),
|
||||
query, credentialId, pipelineId).Scan(
|
||||
&pipeline.Name, &pipeline.Url, &pipeline.PollInterval, &pipeline.Credential,
|
||||
)
|
||||
if err != nil {
|
||||
return pipeline, fmt.Errorf("Could not add credential to pipeline: %w", err)
|
||||
}
|
||||
|
||||
return pipeline, err
|
||||
}
|
||||
|
||||
func (db *Database) RemovePipelineCredential(pipelineId uuid.UUID) (Pipeline, error) {
|
||||
query := `
|
||||
UPDATE pipelines
|
||||
SET credential=null
|
||||
WHERE id=$1
|
||||
RETURNING name, url, poll_interval, credential;`
|
||||
|
||||
pipeline := Pipeline{
|
||||
Id: pipelineId,
|
||||
}
|
||||
|
||||
err := db.Conn.QueryRow(context.Background(),
|
||||
query, pipelineId).Scan(
|
||||
&pipeline.Name, &pipeline.Url, &pipeline.PollInterval, &pipeline.Credential,
|
||||
)
|
||||
if err != nil {
|
||||
return pipeline, fmt.Errorf("Could not add credential to pipeline: %w", err)
|
||||
}
|
||||
|
||||
return pipeline, err
|
||||
}
|
||||
|
||||
func (db *Database) GetWebhooksForPipeline(id uuid.UUID) ([]Webhook, error) {
|
||||
query := `
|
||||
SELECT id, server_type, secret
|
||||
@@ -151,6 +193,86 @@ RETURNING id, server_type, secret, pipeline;`
|
||||
return webhook, nil
|
||||
}
|
||||
|
||||
func (db *Database) CreateCredential(name string, credentialtype CredentialType, username string, secret string) (Credential, error) {
|
||||
query := `
|
||||
INSERT INTO credentials (id, name, type, username, secret)
|
||||
VALUES(uuid_generate_v4(), $1, $2, $3, $4)
|
||||
RETURNING id, name, type, username, secret;`
|
||||
|
||||
credential := Credential{}
|
||||
var idStr string
|
||||
err := db.Conn.QueryRow(
|
||||
context.Background(),
|
||||
query,
|
||||
name,
|
||||
string(credentialtype),
|
||||
username,
|
||||
secret,
|
||||
).Scan(&idStr, &credential.Name, &credential.Type, &credential.Username, &credential.Secret)
|
||||
if err != nil {
|
||||
return credential, err
|
||||
}
|
||||
|
||||
id, err := uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
return credential, err
|
||||
}
|
||||
|
||||
credential.Id = id
|
||||
|
||||
return credential, nil
|
||||
}
|
||||
|
||||
func (db *Database) GetCredentialById(id uuid.UUID) (Credential, error) {
|
||||
query := `
|
||||
SELECT name, type, username, secret
|
||||
FROM credentials
|
||||
WHERE id=$1;`
|
||||
|
||||
log.Debugf("requested credential with id %v", id)
|
||||
|
||||
credential := Credential{
|
||||
Id: id,
|
||||
}
|
||||
|
||||
err := db.Conn.QueryRow(context.Background(), query, id).Scan(&credential.Name, &credential.Type, &credential.Username, &credential.Secret)
|
||||
if err != nil {
|
||||
return credential, fmt.Errorf("Could not query database for credential with id %v: %w", id.String(), err)
|
||||
}
|
||||
|
||||
return credential, nil
|
||||
}
|
||||
|
||||
func (db *Database) GetCredentials() ([]Credential, error) {
|
||||
query := `
|
||||
SELECT id, name, type, username, secret
|
||||
FROM credentials;`
|
||||
|
||||
credentials := make([]Credential, 0)
|
||||
|
||||
rows, err := db.Conn.Query(context.Background(), query)
|
||||
if err != nil {
|
||||
return credentials, fmt.Errorf("Could not query database for credentials: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var credential Credential
|
||||
var idStr string
|
||||
if err := rows.Scan(&idStr, &credential.Name, &credential.Type, &credential.Username, &credential.Secret); err != nil {
|
||||
return credentials, err
|
||||
}
|
||||
|
||||
credential.Id, err = uuid.Parse(idStr)
|
||||
if err != nil {
|
||||
return credentials, err
|
||||
}
|
||||
credentials = append(credentials, credential)
|
||||
}
|
||||
|
||||
return credentials, nil
|
||||
}
|
||||
|
||||
func (db *Database) CreateRun(pipelineId uuid.UUID) (Run, error) {
|
||||
query := `
|
||||
INSERT INTO runs (id, pipeline, in_progress)
|
||||
@@ -173,6 +295,7 @@ RETURNING id, pipeline, in_progress;`
|
||||
}
|
||||
|
||||
func (db *Database) UpdateRunResult(r Run) error {
|
||||
// TODO: the id fiend is the query is broken
|
||||
query := `
|
||||
UPDATE runs
|
||||
SET in_progress=$1, result=$2, stdout=$3, stderr=$4
|
||||
|
||||
+22
-6
@@ -6,11 +6,27 @@ import (
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type CredentialType string
|
||||
|
||||
const (
|
||||
USER_PASS CredentialType = "USER_PASS"
|
||||
SSH_KEY CredentialType = "SSH_KEY"
|
||||
)
|
||||
|
||||
type Credential struct {
|
||||
Id uuid.UUID
|
||||
Name string
|
||||
Type CredentialType
|
||||
Username string
|
||||
Secret string
|
||||
}
|
||||
|
||||
type Pipeline struct {
|
||||
Id uuid.UUID
|
||||
Name string
|
||||
Url string
|
||||
PollInterval int
|
||||
Credential *uuid.UUID
|
||||
}
|
||||
|
||||
type WebhookSender string
|
||||
@@ -26,12 +42,6 @@ type Webhook struct {
|
||||
Pipeline uuid.UUID
|
||||
}
|
||||
|
||||
type Runner struct {
|
||||
Id uuid.UUID
|
||||
Name string
|
||||
Secret string
|
||||
}
|
||||
|
||||
type Run struct {
|
||||
Id uuid.UUID
|
||||
Pipeline uuid.UUID
|
||||
@@ -51,3 +61,9 @@ type CommandExecution struct {
|
||||
StartTime time.Time
|
||||
EndTime time.Time
|
||||
}
|
||||
|
||||
type Runner struct {
|
||||
Id uuid.UUID
|
||||
Name string
|
||||
Secret string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user