Files
onepanel/server/workflow_template_server.go
2021-04-10 00:44:53 +08:00

297 lines
9.6 KiB
Go

package server
import (
"context"
"errors"
api "github.com/onepanelio/core/api/gen"
v1 "github.com/onepanelio/core/pkg"
"github.com/onepanelio/core/pkg/util/request"
"github.com/onepanelio/core/pkg/util/request/pagination"
"github.com/onepanelio/core/server/auth"
"github.com/onepanelio/core/server/converter"
)
// WorkflowTemplateServer is an implementation of the grpc WorkflowTemplateServer
type WorkflowTemplateServer struct {
api.UnimplementedWorkflowTemplateServiceServer
}
// NewWorkflowTemplateServer creates a new WorkflowTemplateServer
func NewWorkflowTemplateServer() *WorkflowTemplateServer {
return &WorkflowTemplateServer{}
}
// apiWorkflowTemplate converts a *v1.WorkflowTemplate to a *api.WorkflowTemplate
func apiWorkflowTemplate(wft *v1.WorkflowTemplate) *api.WorkflowTemplate {
res := &api.WorkflowTemplate{
Uid: wft.UID,
CreatedAt: converter.TimestampToAPIString(&wft.CreatedAt),
ModifiedAt: converter.TimestampToAPIString(wft.ModifiedAt),
Name: wft.Name,
Version: wft.Version,
Versions: wft.Versions,
Manifest: wft.Manifest,
IsLatest: wft.IsLatest,
IsArchived: wft.IsArchived,
Labels: converter.MappingToKeyValue(wft.Labels),
Parameters: converter.ParametersToAPI(wft.Parameters),
Stats: converter.WorkflowExecutionStatisticsReportToAPI(wft.WorkflowExecutionStatisticReport),
Description: wft.Description,
}
if wft.CronWorkflowsStatisticsReport != nil {
res.CronStats = &api.CronWorkflowStatisticsReport{
Total: wft.CronWorkflowsStatisticsReport.Total,
}
}
return res
}
// GenerateWorkflowTemplate generates a workflow template, applying any modifications based on the content of the manifest
func (s *WorkflowTemplateServer) GenerateWorkflowTemplate(ctx context.Context, req *api.GenerateWorkflowTemplateRequest) (*api.WorkflowTemplate, error) {
client := getClient(ctx)
allowed, err := auth.IsAuthorized(client, req.Namespace, "get", "argoproj.io", "workflowtemplates", "")
if err != nil || !allowed {
return nil, err
}
if req.WorkflowTemplate.Manifest == "" {
return &api.WorkflowTemplate{
Manifest: "",
}, nil
}
finalManifest, err := client.GenerateWorkflowTemplateManifest(req.WorkflowTemplate.Manifest)
if err != nil {
return &api.WorkflowTemplate{
Manifest: "",
}, err
}
workflowTemplate := &v1.WorkflowTemplate{
Manifest: finalManifest,
}
return apiWorkflowTemplate(workflowTemplate), nil
}
// CreateWorkflowTemplate creates a workflow template and the initial version
func (s *WorkflowTemplateServer) CreateWorkflowTemplate(ctx context.Context, req *api.CreateWorkflowTemplateRequest) (*api.WorkflowTemplate, error) {
client := getClient(ctx)
allowed, err := auth.IsAuthorized(client, req.Namespace, "create", "argoproj.io", "workflowtemplates", "")
if err != nil || !allowed {
return nil, err
}
workflowTemplate := &v1.WorkflowTemplate{
Name: req.WorkflowTemplate.Name,
Manifest: req.WorkflowTemplate.Manifest,
Labels: converter.APIKeyValueToLabel(req.WorkflowTemplate.Labels),
Description: req.WorkflowTemplate.Description,
}
workflowTemplate, err = client.CreateWorkflowTemplate(req.Namespace, workflowTemplate)
if err != nil {
return nil, err
}
req.WorkflowTemplate.Uid = workflowTemplate.UID
req.WorkflowTemplate.Version = workflowTemplate.Version
return req.WorkflowTemplate, nil
}
func (s *WorkflowTemplateServer) CreateWorkflowTemplateVersion(ctx context.Context, req *api.CreateWorkflowTemplateRequest) (*api.WorkflowTemplate, error) {
client := getClient(ctx)
allowed, err := auth.IsAuthorized(client, req.Namespace, "create", "argoproj.io", "workflowtemplates", req.WorkflowTemplate.Name)
if err != nil || !allowed {
return nil, err
}
workflowTemplate := &v1.WorkflowTemplate{
UID: req.WorkflowTemplate.Uid,
Name: req.WorkflowTemplate.Name,
Manifest: req.WorkflowTemplate.Manifest,
Labels: converter.APIKeyValueToLabel(req.WorkflowTemplate.Labels),
Description: req.WorkflowTemplate.Description,
}
workflowTemplate, err = client.CreateWorkflowTemplateVersion(req.Namespace, workflowTemplate)
if err != nil {
return nil, err
}
req.WorkflowTemplate.Uid = workflowTemplate.UID
req.WorkflowTemplate.Name = workflowTemplate.Name
req.WorkflowTemplate.Version = workflowTemplate.Version
return req.WorkflowTemplate, nil
}
func (s *WorkflowTemplateServer) GetWorkflowTemplate(ctx context.Context, req *api.GetWorkflowTemplateRequest) (*api.WorkflowTemplate, error) {
client := getClient(ctx)
allowed, err := auth.IsAuthorized(client, req.Namespace, "get", "argoproj.io", "workflowtemplates", "")
if err != nil || !allowed {
return nil, err
}
workflowTemplate, err := client.GetWorkflowTemplate(req.Namespace, req.Uid, req.Version)
if err != nil {
return nil, err
}
versionsCount, err := client.CountWorkflowTemplateVersions(req.Namespace, req.Uid)
if err != nil {
return nil, err
}
workflowTemplate.Versions = int64(versionsCount)
return apiWorkflowTemplate(workflowTemplate), nil
}
func (s *WorkflowTemplateServer) CloneWorkflowTemplate(ctx context.Context, req *api.CloneWorkflowTemplateRequest) (*api.WorkflowTemplate, error) {
client := getClient(ctx)
allowed, err := auth.IsAuthorized(client, req.Namespace, "create", "argoproj.io", "workflowtemplates", "")
if err != nil || !allowed {
return nil, err
}
//Verify the template exists
workflowTemplate, err := client.GetWorkflowTemplate(req.Namespace, req.Uid, req.Version)
if err != nil {
return nil, err
}
//Verify the cloned template name doesn't exist already
templatesCount, err := client.CountWorkflowTemplatesByName(req.Name, req.Name, nil)
if err != nil {
return nil, err
}
if templatesCount != 0 {
return nil, errors.New("Cannot clone, WorkflowTemplate name already taken.")
}
workflowTemplateClone := &v1.WorkflowTemplate{
Name: req.Name,
Manifest: workflowTemplate.Manifest,
IsLatest: true,
}
workflowTemplateCloned, err := client.CreateWorkflowTemplate(req.Namespace, workflowTemplateClone)
if err != nil {
return nil, err
}
return apiWorkflowTemplate(workflowTemplateCloned), nil
}
func (s *WorkflowTemplateServer) ListWorkflowTemplateVersions(ctx context.Context, req *api.ListWorkflowTemplateVersionsRequest) (*api.ListWorkflowTemplateVersionsResponse, error) {
client := getClient(ctx)
allowed, err := auth.IsAuthorized(client, req.Namespace, "list", "argoproj.io", "workflowtemplates", "")
if err != nil || !allowed {
return nil, err
}
workflowTemplateVersions, err := client.ListWorkflowTemplateVersions(req.Namespace, req.Uid)
if err != nil {
return nil, err
}
var workflowTemplates []*api.WorkflowTemplate
for _, wtv := range workflowTemplateVersions {
workflowTemplates = append(workflowTemplates, apiWorkflowTemplate(wtv))
}
return &api.ListWorkflowTemplateVersionsResponse{
Count: int32(len(workflowTemplateVersions)),
WorkflowTemplates: workflowTemplates,
}, nil
}
func (s *WorkflowTemplateServer) ListWorkflowTemplates(ctx context.Context, req *api.ListWorkflowTemplatesRequest) (*api.ListWorkflowTemplatesResponse, error) {
client := getClient(ctx)
allowed, err := auth.IsAuthorized(client, req.Namespace, "list", "argoproj.io", "workflowtemplates", "")
if err != nil || !allowed {
return nil, err
}
labelFilter, err := v1.LabelsFromString(req.Labels)
if err != nil {
return nil, err
}
resourceRequest := &request.Request{
Pagination: pagination.New(req.Page, req.PageSize),
Filter: v1.WorkflowTemplateFilter{
Labels: labelFilter,
},
}
workflowTemplates, err := client.ListWorkflowTemplates(req.Namespace, resourceRequest)
if err != nil {
return nil, err
}
apiWorkflowTemplates := []*api.WorkflowTemplate{}
for _, wtv := range workflowTemplates {
apiWorkflowTemplates = append(apiWorkflowTemplates, apiWorkflowTemplate(wtv))
}
count, err := client.CountWorkflowTemplates(req.Namespace, resourceRequest)
if err != nil {
return nil, err
}
totalCount, err := client.CountWorkflowTemplates(req.Namespace, nil)
if err != nil {
return nil, err
}
paginator := resourceRequest.Pagination
return &api.ListWorkflowTemplatesResponse{
Count: int32(len(apiWorkflowTemplates)),
WorkflowTemplates: apiWorkflowTemplates,
Page: int32(paginator.Page),
Pages: paginator.CalculatePages(count),
TotalCount: int32(count),
TotalAvailableCount: int32(totalCount),
}, nil
}
func (s *WorkflowTemplateServer) ArchiveWorkflowTemplate(ctx context.Context, req *api.ArchiveWorkflowTemplateRequest) (*api.ArchiveWorkflowTemplateResponse, error) {
client := getClient(ctx)
allowed, err := auth.IsAuthorized(client, req.Namespace, "delete", "argoproj.io", "workflowtemplates", "")
if err != nil || !allowed {
return nil, err
}
archived, err := client.ArchiveWorkflowTemplate(req.Namespace, req.Uid)
if err != nil {
return nil, err
}
return &api.ArchiveWorkflowTemplateResponse{
WorkflowTemplate: &api.WorkflowTemplate{
IsArchived: archived,
},
}, nil
}
// ListWorkflowTemplatesField returns a list of all the distinct values of a field from WorkflowTemplates
func (s *WorkflowTemplateServer) ListWorkflowTemplatesField(ctx context.Context, req *api.ListWorkflowTemplatesFieldRequest) (*api.ListWorkflowTemplatesFieldResponse, error) {
client := getClient(ctx)
allowed, err := auth.IsAuthorized(client, req.Namespace, "list", "onepanel.io", "workspaces", "")
if err != nil || !allowed {
return nil, err
}
values, err := client.ListWorkflowTemplatesField(req.Namespace, req.FieldName, req.IsSystem)
if err != nil {
return nil, err
}
return &api.ListWorkflowTemplatesFieldResponse{
Values: values,
}, nil
}