mirror of
https://github.com/onepanelio/onepanel.git
synced 2025-10-19 20:04:34 +08:00
385 lines
11 KiB
Go
385 lines
11 KiB
Go
package v1
|
|
|
|
import (
|
|
"database/sql"
|
|
"time"
|
|
|
|
sq "github.com/Masterminds/squirrel"
|
|
"github.com/onepanelio/core/pkg/util"
|
|
log "github.com/sirupsen/logrus"
|
|
"google.golang.org/grpc/codes"
|
|
)
|
|
|
|
var sb = sq.StatementBuilder.PlaceholderFormat(sq.Dollar)
|
|
|
|
func (c *Client) insertWorkflowTemplateVersion(workflowTemplate *WorkflowTemplate, runner sq.BaseRunner) (err error) {
|
|
err = sb.Insert("workflow_template_versions").
|
|
SetMap(sq.Eq{
|
|
"workflow_template_id": workflowTemplate.ID,
|
|
"manifest": workflowTemplate.Manifest,
|
|
"version": int32(time.Now().Unix()),
|
|
"is_latest": workflowTemplate.IsLatest,
|
|
}).
|
|
Suffix("RETURNING version").
|
|
RunWith(runner).
|
|
QueryRow().Scan(&workflowTemplate.Version)
|
|
|
|
return
|
|
}
|
|
|
|
func (c *Client) createWorkflowTemplate(namespace string, workflowTemplate *WorkflowTemplate) (*WorkflowTemplate, error) {
|
|
uid, err := workflowTemplate.GenerateUID()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
tx, err := c.DB.Begin()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer tx.Rollback()
|
|
|
|
err = sb.Insert("workflow_templates").
|
|
SetMap(sq.Eq{
|
|
"uid": uid,
|
|
"name": workflowTemplate.Name,
|
|
"namespace": namespace,
|
|
}).
|
|
Suffix("RETURNING id").
|
|
RunWith(tx).
|
|
QueryRow().Scan(&workflowTemplate.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err = c.insertWorkflowTemplateVersion(workflowTemplate, tx); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err = tx.Commit(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return workflowTemplate, nil
|
|
}
|
|
|
|
func (c *Client) removeIsLatestFromWorkflowTemplateVersions(workflowTemplate *WorkflowTemplate) error {
|
|
query, args, err := sb.Update("workflow_template_versions").
|
|
Set("is_latest", true).
|
|
Where(sq.Eq{
|
|
"workflow_template_id": workflowTemplate.ID,
|
|
"is_latest": false,
|
|
}).
|
|
ToSql()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := c.DB.Exec(query, args...); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *Client) createWorkflowTemplateVersion(namespace string, workflowTemplate *WorkflowTemplate) (*WorkflowTemplate, error) {
|
|
query, args, err := sb.Select("id, name").
|
|
From("workflow_templates").
|
|
Where(sq.Eq{
|
|
"namespace": namespace,
|
|
"uid": workflowTemplate.UID,
|
|
}).
|
|
Limit(1).ToSql()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err = c.DB.Get(workflowTemplate, query, args...); err == sql.ErrNoRows {
|
|
return nil, nil
|
|
}
|
|
|
|
if err = c.insertWorkflowTemplateVersion(workflowTemplate, c.DB); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return workflowTemplate, nil
|
|
}
|
|
|
|
func (c *Client) updateWorkflowTemplateVersion(workflowTemplate *WorkflowTemplate) (*WorkflowTemplate, error) {
|
|
query, args, err := sb.Update("workflow_template_versions").
|
|
Set("manifest", workflowTemplate.Manifest).
|
|
Where(sq.Eq{
|
|
"workflow_template_id": workflowTemplate.ID,
|
|
"version": workflowTemplate.Version,
|
|
}).
|
|
ToSql()
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if _, err := c.DB.Exec(query, args...); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return workflowTemplate, nil
|
|
}
|
|
|
|
func (c *Client) workflowTemplatesSelectBuilder(namespace string) sq.SelectBuilder {
|
|
sb := sb.Select("wt.id", "wt.created_at", "wt.uid", "wt.name", "wt.is_archived", "wtv.version", "wtv.is_latest").
|
|
From("workflow_template_versions wtv").
|
|
Join("workflow_templates wt ON wt.id = wtv.workflow_template_id").
|
|
Where(sq.Eq{
|
|
"wt.namespace": namespace,
|
|
})
|
|
|
|
return sb
|
|
}
|
|
|
|
func (c *Client) getWorkflowTemplate(namespace, uid string, version int32) (workflowTemplate *WorkflowTemplate, err error) {
|
|
workflowTemplate = &WorkflowTemplate{}
|
|
|
|
sb := c.workflowTemplatesSelectBuilder(namespace).Where(sq.Eq{"wt.uid": uid}).
|
|
Columns("wtv.manifest").
|
|
OrderBy("wtv.version desc").
|
|
Limit(1)
|
|
if version != 0 {
|
|
sb = sb.Where(sq.Eq{"wtv.version": version})
|
|
}
|
|
query, args, err := sb.ToSql()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
if err = c.DB.Get(workflowTemplate, query, args...); err == sql.ErrNoRows {
|
|
err = nil
|
|
workflowTemplate = nil
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (c *Client) listWorkflowTemplateVersions(namespace, uid string) (workflowTemplateVersions []*WorkflowTemplate, err error) {
|
|
workflowTemplateVersions = []*WorkflowTemplate{}
|
|
|
|
query, args, err := c.workflowTemplatesSelectBuilder(namespace).Where(sq.Eq{"wt.uid": uid}).
|
|
Columns("wtv.manifest").
|
|
OrderBy("wtv.version desc").ToSql()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
err = c.DB.Select(&workflowTemplateVersions, query, args...)
|
|
|
|
return
|
|
}
|
|
|
|
func (c *Client) listWorkflowTemplates(namespace string) (workflowTemplateVersions []*WorkflowTemplate, err error) {
|
|
workflowTemplateVersions = []*WorkflowTemplate{}
|
|
|
|
query, args, err := c.workflowTemplatesSelectBuilder(namespace).
|
|
Options("DISTINCT ON (wt.id) wt.id,").
|
|
Where(sq.Eq{
|
|
"wt.is_archived": false,
|
|
}).
|
|
OrderBy("wt.id desc").ToSql()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
err = c.DB.Select(&workflowTemplateVersions, query, args...)
|
|
|
|
return
|
|
}
|
|
|
|
func (c *Client) archiveWorkflowTemplate(namespace, uid string) (bool, error) {
|
|
query, args, err := sb.Update("workflow_templates").
|
|
Set("is_archived", true).
|
|
Where(sq.Eq{
|
|
"uid": uid,
|
|
"namespace": namespace,
|
|
}).
|
|
ToSql()
|
|
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if _, err := c.DB.Exec(query, args...); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
func (c *Client) CreateWorkflowTemplate(namespace string, workflowTemplate *WorkflowTemplate) (*WorkflowTemplate, error) {
|
|
// validate workflow template
|
|
if err := c.ValidateWorkflowExecution(namespace, workflowTemplate.GetManifestBytes()); err != nil {
|
|
log.WithFields(log.Fields{
|
|
"Namespace": namespace,
|
|
"WorkflowTemplate": workflowTemplate,
|
|
"Error": err.Error(),
|
|
}).Error("Workflow could not be validated.")
|
|
return nil, util.NewUserError(codes.InvalidArgument, err.Error())
|
|
}
|
|
|
|
workflowTemplate, err := c.createWorkflowTemplate(namespace, workflowTemplate)
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"Namespace": namespace,
|
|
"WorkflowTemplate": workflowTemplate,
|
|
"Error": err.Error(),
|
|
}).Error("Could not create workflow template.")
|
|
return nil, util.NewUserErrorWrap(err, "Workflow template")
|
|
}
|
|
|
|
return workflowTemplate, nil
|
|
}
|
|
|
|
func (c *Client) CreateWorkflowTemplateVersion(namespace string, workflowTemplate *WorkflowTemplate) (*WorkflowTemplate, error) {
|
|
// validate workflow template
|
|
if err := c.ValidateWorkflowExecution(namespace, workflowTemplate.GetManifestBytes()); err != nil {
|
|
log.WithFields(log.Fields{
|
|
"Namespace": namespace,
|
|
"WorkflowTemplate": workflowTemplate,
|
|
"Error": err.Error(),
|
|
}).Error("Workflow could not be validated.")
|
|
return nil, util.NewUserError(codes.InvalidArgument, err.Error())
|
|
}
|
|
|
|
if err := c.removeIsLatestFromWorkflowTemplateVersions(workflowTemplate); err != nil {
|
|
log.WithFields(log.Fields{
|
|
"Namespace": namespace,
|
|
"WorkflowTemplate": workflowTemplate,
|
|
"Error": err.Error(),
|
|
}).Error("Could not remove IsLatest from workflow template versions.")
|
|
return nil, util.NewUserError(codes.Unknown, "Unable to Create Workflow Template Version.")
|
|
}
|
|
|
|
workflowTemplate, err := c.createWorkflowTemplateVersion(namespace, workflowTemplate)
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"Namespace": namespace,
|
|
"WorkflowTemplate": workflowTemplate,
|
|
"Error": err.Error(),
|
|
}).Error("Could not create workflow template version.")
|
|
return nil, util.NewUserErrorWrap(err, "Workflow template")
|
|
}
|
|
if workflowTemplate == nil {
|
|
return nil, util.NewUserError(codes.NotFound, "Workflow template not found.")
|
|
}
|
|
|
|
return workflowTemplate, nil
|
|
}
|
|
|
|
func (c *Client) UpdateWorkflowTemplateVersion(namespace string, workflowTemplate *WorkflowTemplate) (*WorkflowTemplate, error) {
|
|
// validate workflow template
|
|
if err := c.ValidateWorkflowExecution(namespace, workflowTemplate.GetManifestBytes()); err != nil {
|
|
log.WithFields(log.Fields{
|
|
"Namespace": namespace,
|
|
"WorkflowTemplate": workflowTemplate,
|
|
"Error": err.Error(),
|
|
}).Error("Workflow could not be validated.")
|
|
return nil, util.NewUserError(codes.InvalidArgument, err.Error())
|
|
}
|
|
|
|
originalWorkflowTemplate, err := c.getWorkflowTemplate(namespace, workflowTemplate.UID, workflowTemplate.Version)
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"Namespace": namespace,
|
|
"WorkflowTemplate": workflowTemplate,
|
|
"Error": err.Error(),
|
|
}).Error("Could not get workflow template.")
|
|
return nil, util.NewUserError(codes.Unknown, "Could not update workflow template version.")
|
|
}
|
|
|
|
workflowTemplate.ID = originalWorkflowTemplate.ID
|
|
workflowTemplate, err = c.updateWorkflowTemplateVersion(workflowTemplate)
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"Namespace": namespace,
|
|
"WorkflowTemplate": workflowTemplate,
|
|
"Error": err.Error(),
|
|
}).Error("Could not update workflow template version.")
|
|
return nil, util.NewUserErrorWrap(err, "Workflow template")
|
|
}
|
|
if workflowTemplate == nil {
|
|
return nil, util.NewUserError(codes.NotFound, "Workflow template not found.")
|
|
}
|
|
|
|
return workflowTemplate, nil
|
|
}
|
|
|
|
func (c *Client) GetWorkflowTemplate(namespace, uid string, version int32) (workflowTemplate *WorkflowTemplate, err error) {
|
|
workflowTemplate, err = c.getWorkflowTemplate(namespace, uid, version)
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"Namespace": namespace,
|
|
"WorkflowTemplate": workflowTemplate,
|
|
"Error": err.Error(),
|
|
}).Error("Get Workflow Template failed.")
|
|
return nil, util.NewUserError(codes.Unknown, "Unknown error.")
|
|
}
|
|
if workflowTemplate == nil {
|
|
return nil, util.NewUserError(codes.NotFound, "Workflow template not found.")
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (c *Client) ListWorkflowTemplateVersions(namespace, uid string) (workflowTemplateVersions []*WorkflowTemplate, err error) {
|
|
workflowTemplateVersions, err = c.listWorkflowTemplateVersions(namespace, uid)
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"Namespace": namespace,
|
|
"UID": uid,
|
|
"Error": err.Error(),
|
|
}).Error("Workflow template versions not found.")
|
|
return nil, util.NewUserError(codes.NotFound, "Workflow template versions not found.")
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (c *Client) ListWorkflowTemplates(namespace string) (workflowTemplateVersions []*WorkflowTemplate, err error) {
|
|
workflowTemplateVersions, err = c.listWorkflowTemplates(namespace)
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"Namespace": namespace,
|
|
"Error": err.Error(),
|
|
}).Error("Workflow templates not found.")
|
|
return nil, util.NewUserError(codes.NotFound, "Workflow templates not found.")
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (c *Client) ArchiveWorkflowTemplate(namespace, uid string) (archived bool, err error) {
|
|
workflowTemplate, err := c.getWorkflowTemplate(namespace, uid, 0)
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"Namespace": namespace,
|
|
"UID": uid,
|
|
"Error": err.Error(),
|
|
}).Error("Get Workflow Template failed.")
|
|
return false, util.NewUserError(codes.Unknown, "Unable to archive workflow template.")
|
|
}
|
|
if workflowTemplate == nil {
|
|
return false, util.NewUserError(codes.NotFound, "Workflow template not found.")
|
|
}
|
|
|
|
archived, err = c.archiveWorkflowTemplate(namespace, uid)
|
|
if !archived || err != nil {
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"Namespace": namespace,
|
|
"UID": uid,
|
|
"Error": err.Error(),
|
|
}).Error("Archive Workflow Template failed.")
|
|
}
|
|
return false, util.NewUserError(codes.Unknown, "Unable to archive workflow template.")
|
|
}
|
|
|
|
return
|
|
}
|