mirror of
https://github.com/onepanelio/onepanel.git
synced 2025-10-08 07:00:06 +08:00
Merge branch 'dev' into feat/provider-specific-config
This commit is contained in:
26
.github/workflows/run_unit_tests.yaml
vendored
Normal file
26
.github/workflows/run_unit_tests.yaml
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name: Run Unit Tests
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- test/docker.database
|
||||||
|
jobs:
|
||||||
|
test-code-job:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:12.3
|
||||||
|
env:
|
||||||
|
POSTGRES_DB: onepanel
|
||||||
|
POSTGRES_USER: admin
|
||||||
|
POSTGRES_PASSWORD: tester
|
||||||
|
options: >-
|
||||||
|
--health-cmd pg_isready
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@master
|
||||||
|
- name: Run testing code
|
||||||
|
uses: cedrickring/golang-action@1.5.2
|
||||||
|
with:
|
||||||
|
args: go test github.com/onepanelio/core/pkg -db=postgres
|
5
Makefile
5
Makefile
@@ -34,3 +34,8 @@ docker-push:
|
|||||||
docker push onepanel/core:$(COMMIT_HASH)
|
docker push onepanel/core:$(COMMIT_HASH)
|
||||||
|
|
||||||
docker: docker-build docker-push
|
docker: docker-build docker-push
|
||||||
|
|
||||||
|
run-tests:
|
||||||
|
docker run --rm --name test-onepanel-postgres -p 5432:5432 -e POSTGRES_USER=admin -e POSTGRES_PASSWORD=tester -e POSTGRES_DB=onepanel -d postgres:12.3
|
||||||
|
go test github.com/onepanelio/core/pkg -count=1 ||:
|
||||||
|
docker stop test-onepanel-postgres
|
@@ -1707,57 +1707,6 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/apis/v1beta1/{namespace}/workflow_templates/{workflowTemplate.uid}/versions/{workflowTemplate.version}": {
|
|
||||||
"put": {
|
|
||||||
"operationId": "UpdateWorkflowTemplateVersion",
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "A successful response.",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/WorkflowTemplate"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"default": {
|
|
||||||
"description": "An unexpected error response",
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/grpc.gateway.runtime.Error"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "namespace",
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "workflowTemplate.uid",
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "workflowTemplate.version",
|
|
||||||
"in": "path",
|
|
||||||
"required": true,
|
|
||||||
"type": "string",
|
|
||||||
"format": "int64"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "body",
|
|
||||||
"in": "body",
|
|
||||||
"required": true,
|
|
||||||
"schema": {
|
|
||||||
"$ref": "#/definitions/WorkflowTemplate"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"tags": [
|
|
||||||
"WorkflowTemplateService"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"/apis/v1beta1/{namespace}/workspace_templates": {
|
"/apis/v1beta1/{namespace}/workspace_templates": {
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "ListWorkspaceTemplates",
|
"operationId": "ListWorkspaceTemplates",
|
||||||
|
@@ -1093,7 +1093,7 @@ var file_workflow_template_proto_rawDesc = []byte{
|
|||||||
0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
|
0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
|
||||||
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76,
|
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76,
|
||||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65,
|
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65,
|
||||||
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x32, 0xa3, 0x0c, 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
|
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x32, 0xbb, 0x0a, 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
|
||||||
0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
|
0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||||
0x65, 0x12, 0x9b, 0x01, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b,
|
0x65, 0x12, 0x9b, 0x01, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b,
|
||||||
0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x22, 0x2e, 0x61,
|
0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x22, 0x2e, 0x61,
|
||||||
@@ -1105,94 +1105,79 @@ var file_workflow_template_proto_rawDesc = []byte{
|
|||||||
0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66,
|
0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66,
|
||||||
0x6c, 0x6f, 0x77, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x3a, 0x10, 0x77,
|
0x6c, 0x6f, 0x77, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x3a, 0x10, 0x77,
|
||||||
0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12,
|
0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12,
|
||||||
0xe5, 0x01, 0x0a, 0x1d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
|
0xc2, 0x01, 0x0a, 0x1d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
|
||||||
0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
|
0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
|
||||||
0x6e, 0x12, 0x29, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x6f,
|
0x6e, 0x12, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f,
|
||||||
0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65,
|
|
||||||
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x61,
|
|
||||||
0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c,
|
|
||||||
0x61, 0x74, 0x65, 0x22, 0x81, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x7b, 0x1a, 0x67, 0x2f, 0x61,
|
|
||||||
0x70, 0x69, 0x73, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d,
|
|
||||||
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
|
|
||||||
0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x77, 0x6f, 0x72, 0x6b,
|
|
||||||
0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e, 0x75, 0x69, 0x64,
|
|
||||||
0x7d, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x77, 0x6f, 0x72, 0x6b,
|
|
||||||
0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x65, 0x72,
|
|
||||||
0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x3a, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54,
|
|
||||||
0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0xc2, 0x01, 0x0a, 0x1d, 0x43, 0x72, 0x65, 0x61,
|
|
||||||
0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61,
|
|
||||||
0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x2e,
|
|
||||||
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65,
|
|
||||||
0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e,
|
|
||||||
0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70,
|
|
||||||
0x6c, 0x61, 0x74, 0x65, 0x22, 0x66, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x60, 0x22, 0x4c, 0x2f, 0x61,
|
|
||||||
0x70, 0x69, 0x73, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d,
|
|
||||||
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
|
|
||||||
0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x77, 0x6f, 0x72, 0x6b,
|
|
||||||
0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2e, 0x75, 0x69, 0x64,
|
|
||||||
0x7d, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x10, 0x77, 0x6f, 0x72, 0x6b,
|
|
||||||
0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0xd3, 0x01, 0x0a,
|
|
||||||
0x13, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70,
|
|
||||||
0x6c, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f,
|
|
||||||
0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65,
|
0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65,
|
||||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b,
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b,
|
||||||
0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x83, 0x01, 0x82,
|
0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x66, 0x82, 0xd3,
|
||||||
0xd3, 0xe4, 0x93, 0x02, 0x7d, 0x12, 0x32, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x76, 0x31, 0x62,
|
0xe4, 0x93, 0x02, 0x60, 0x22, 0x4c, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x76, 0x31, 0x62, 0x65,
|
||||||
0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d,
|
0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x2f,
|
||||||
0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61,
|
0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74,
|
||||||
0x74, 0x65, 0x73, 0x2f, 0x7b, 0x75, 0x69, 0x64, 0x7d, 0x5a, 0x47, 0x12, 0x45, 0x2f, 0x61, 0x70,
|
0x65, 0x73, 0x2f, 0x7b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70,
|
||||||
0x69, 0x73, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65,
|
0x6c, 0x61, 0x74, 0x65, 0x2e, 0x75, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
|
||||||
0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f,
|
0x6e, 0x73, 0x3a, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70,
|
||||||
0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x75, 0x69, 0x64, 0x7d, 0x2f,
|
0x6c, 0x61, 0x74, 0x65, 0x12, 0xd3, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b,
|
||||||
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
|
0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x61,
|
||||||
0x6e, 0x7d, 0x12, 0xb8, 0x01, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66,
|
0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65,
|
||||||
0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69,
|
0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e,
|
||||||
0x6f, 0x6e, 0x73, 0x12, 0x28, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f,
|
0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70,
|
||||||
0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65,
|
0x6c, 0x61, 0x74, 0x65, 0x22, 0x83, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x7d, 0x12, 0x32, 0x2f,
|
||||||
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e,
|
0x61, 0x70, 0x69, 0x73, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61,
|
||||||
0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
|
0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f,
|
||||||
0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73,
|
0x77, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x75, 0x69, 0x64,
|
||||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x43, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3d,
|
0x7d, 0x5a, 0x47, 0x12, 0x45, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74,
|
||||||
0x12, 0x3b, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f,
|
0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x2f, 0x77,
|
||||||
0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x2f, 0x77, 0x6f, 0x72, 0x6b,
|
0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65,
|
||||||
0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b,
|
0x73, 0x2f, 0x7b, 0x75, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73,
|
||||||
0x75, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x94, 0x01,
|
0x2f, 0x7b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x12, 0xb8, 0x01, 0x0a, 0x1c, 0x4c,
|
||||||
0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65,
|
0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c,
|
||||||
0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69,
|
0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x28, 0x2e, 0x61, 0x70,
|
||||||
0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61,
|
0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65,
|
||||||
0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61, 0x70, 0x69,
|
0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65,
|
||||||
0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d,
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74,
|
||||||
0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34,
|
0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65,
|
||||||
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x12, 0x2c, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x76, 0x31,
|
0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||||
0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
|
0x22, 0x43, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3d, 0x12, 0x3b, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f,
|
||||||
0x7d, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c,
|
0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
|
||||||
0x61, 0x74, 0x65, 0x73, 0x12, 0xe9, 0x01, 0x0a, 0x15, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x57, 0x6f,
|
0x63, 0x65, 0x7d, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x74, 0x65, 0x6d,
|
||||||
0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x21,
|
0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x75, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x65, 0x72,
|
||||||
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
|
0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x94, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f,
|
||||||
0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12,
|
||||||
0x74, 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77,
|
0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
|
||||||
0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x95, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02,
|
0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||||
0x8e, 0x01, 0x12, 0x3f, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61,
|
0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72,
|
||||||
0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x2f, 0x77, 0x6f,
|
0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65,
|
||||||
0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73,
|
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x12, 0x2c,
|
||||||
0x2f, 0x7b, 0x75, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x2f, 0x7b, 0x6e, 0x61,
|
0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e,
|
||||||
0x6d, 0x65, 0x7d, 0x5a, 0x4b, 0x12, 0x49, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x76, 0x31, 0x62,
|
0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
|
||||||
0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d,
|
0x6f, 0x77, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12, 0xe9, 0x01, 0x0a,
|
||||||
0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61,
|
0x15, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65,
|
||||||
0x74, 0x65, 0x73, 0x2f, 0x7b, 0x75, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x2f,
|
0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6c, 0x6f,
|
||||||
0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x2f, 0x7b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x7d,
|
0x6e, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61,
|
||||||
0x12, 0xa8, 0x01, 0x0a, 0x17, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b,
|
0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e,
|
||||||
0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x23, 0x2e, 0x61,
|
0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65,
|
||||||
0x70, 0x69, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c,
|
0x22, 0x95, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x8e, 0x01, 0x12, 0x3f, 0x2f, 0x61, 0x70, 0x69,
|
||||||
0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
0x73, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73,
|
||||||
0x74, 0x1a, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x57,
|
0x70, 0x61, 0x63, 0x65, 0x7d, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x74,
|
||||||
0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52,
|
0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x75, 0x69, 0x64, 0x7d, 0x2f, 0x63,
|
||||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x42, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3c, 0x1a,
|
0x6c, 0x6f, 0x6e, 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x5a, 0x4b, 0x12, 0x49, 0x2f,
|
||||||
0x3a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b,
|
0x61, 0x70, 0x69, 0x73, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61,
|
||||||
0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66,
|
0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x7d, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f,
|
||||||
0x6c, 0x6f, 0x77, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x75,
|
0x77, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x75, 0x69, 0x64,
|
||||||
0x69, 0x64, 0x7d, 0x2f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
0x7d, 0x2f, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x2f, 0x7b,
|
||||||
0x74, 0x6f, 0x33,
|
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x12, 0xa8, 0x01, 0x0a, 0x17, 0x41, 0x72, 0x63,
|
||||||
|
0x68, 0x69, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70,
|
||||||
|
0x6c, 0x61, 0x74, 0x65, 0x12, 0x23, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69,
|
||||||
|
0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61,
|
||||||
|
0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x2e,
|
||||||
|
0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54,
|
||||||
|
0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||||
|
0x42, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3c, 0x1a, 0x3a, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x76,
|
||||||
|
0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63,
|
||||||
|
0x65, 0x7d, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x74, 0x65, 0x6d, 0x70,
|
||||||
|
0x6c, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x75, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x72, 0x63, 0x68,
|
||||||
|
0x69, 0x76, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -1235,23 +1220,21 @@ var file_workflow_template_proto_depIdxs = []int32{
|
|||||||
10, // 6: api.WorkflowTemplate.stats:type_name -> api.WorkflowExecutionStatisticReport
|
10, // 6: api.WorkflowTemplate.stats:type_name -> api.WorkflowExecutionStatisticReport
|
||||||
11, // 7: api.WorkflowTemplate.cronStats:type_name -> api.CronWorkflowStatisticsReport
|
11, // 7: api.WorkflowTemplate.cronStats:type_name -> api.CronWorkflowStatisticsReport
|
||||||
0, // 8: api.WorkflowTemplateService.CreateWorkflowTemplate:input_type -> api.CreateWorkflowTemplateRequest
|
0, // 8: api.WorkflowTemplateService.CreateWorkflowTemplate:input_type -> api.CreateWorkflowTemplateRequest
|
||||||
1, // 9: api.WorkflowTemplateService.UpdateWorkflowTemplateVersion:input_type -> api.UpdateWorkflowTemplateVersionRequest
|
0, // 9: api.WorkflowTemplateService.CreateWorkflowTemplateVersion:input_type -> api.CreateWorkflowTemplateRequest
|
||||||
0, // 10: api.WorkflowTemplateService.CreateWorkflowTemplateVersion:input_type -> api.CreateWorkflowTemplateRequest
|
2, // 10: api.WorkflowTemplateService.GetWorkflowTemplate:input_type -> api.GetWorkflowTemplateRequest
|
||||||
2, // 11: api.WorkflowTemplateService.GetWorkflowTemplate:input_type -> api.GetWorkflowTemplateRequest
|
4, // 11: api.WorkflowTemplateService.ListWorkflowTemplateVersions:input_type -> api.ListWorkflowTemplateVersionsRequest
|
||||||
4, // 12: api.WorkflowTemplateService.ListWorkflowTemplateVersions:input_type -> api.ListWorkflowTemplateVersionsRequest
|
6, // 12: api.WorkflowTemplateService.ListWorkflowTemplates:input_type -> api.ListWorkflowTemplatesRequest
|
||||||
6, // 13: api.WorkflowTemplateService.ListWorkflowTemplates:input_type -> api.ListWorkflowTemplatesRequest
|
3, // 13: api.WorkflowTemplateService.CloneWorkflowTemplate:input_type -> api.CloneWorkflowTemplateRequest
|
||||||
3, // 14: api.WorkflowTemplateService.CloneWorkflowTemplate:input_type -> api.CloneWorkflowTemplateRequest
|
8, // 14: api.WorkflowTemplateService.ArchiveWorkflowTemplate:input_type -> api.ArchiveWorkflowTemplateRequest
|
||||||
8, // 15: api.WorkflowTemplateService.ArchiveWorkflowTemplate:input_type -> api.ArchiveWorkflowTemplateRequest
|
12, // 15: api.WorkflowTemplateService.CreateWorkflowTemplate:output_type -> api.WorkflowTemplate
|
||||||
12, // 16: api.WorkflowTemplateService.CreateWorkflowTemplate:output_type -> api.WorkflowTemplate
|
12, // 16: api.WorkflowTemplateService.CreateWorkflowTemplateVersion:output_type -> api.WorkflowTemplate
|
||||||
12, // 17: api.WorkflowTemplateService.UpdateWorkflowTemplateVersion:output_type -> api.WorkflowTemplate
|
12, // 17: api.WorkflowTemplateService.GetWorkflowTemplate:output_type -> api.WorkflowTemplate
|
||||||
12, // 18: api.WorkflowTemplateService.CreateWorkflowTemplateVersion:output_type -> api.WorkflowTemplate
|
5, // 18: api.WorkflowTemplateService.ListWorkflowTemplateVersions:output_type -> api.ListWorkflowTemplateVersionsResponse
|
||||||
12, // 19: api.WorkflowTemplateService.GetWorkflowTemplate:output_type -> api.WorkflowTemplate
|
7, // 19: api.WorkflowTemplateService.ListWorkflowTemplates:output_type -> api.ListWorkflowTemplatesResponse
|
||||||
5, // 20: api.WorkflowTemplateService.ListWorkflowTemplateVersions:output_type -> api.ListWorkflowTemplateVersionsResponse
|
12, // 20: api.WorkflowTemplateService.CloneWorkflowTemplate:output_type -> api.WorkflowTemplate
|
||||||
7, // 21: api.WorkflowTemplateService.ListWorkflowTemplates:output_type -> api.ListWorkflowTemplatesResponse
|
9, // 21: api.WorkflowTemplateService.ArchiveWorkflowTemplate:output_type -> api.ArchiveWorkflowTemplateResponse
|
||||||
12, // 22: api.WorkflowTemplateService.CloneWorkflowTemplate:output_type -> api.WorkflowTemplate
|
15, // [15:22] is the sub-list for method output_type
|
||||||
9, // 23: api.WorkflowTemplateService.ArchiveWorkflowTemplate:output_type -> api.ArchiveWorkflowTemplateResponse
|
8, // [8:15] is the sub-list for method input_type
|
||||||
16, // [16:24] is the sub-list for method output_type
|
|
||||||
8, // [8:16] is the sub-list for method input_type
|
|
||||||
8, // [8:8] is the sub-list for extension type_name
|
8, // [8:8] is the sub-list for extension type_name
|
||||||
8, // [8:8] is the sub-list for extension extendee
|
8, // [8:8] is the sub-list for extension extendee
|
||||||
0, // [0:8] is the sub-list for field type_name
|
0, // [0:8] is the sub-list for field type_name
|
||||||
@@ -1466,7 +1449,6 @@ const _ = grpc.SupportPackageIsVersion6
|
|||||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||||
type WorkflowTemplateServiceClient interface {
|
type WorkflowTemplateServiceClient interface {
|
||||||
CreateWorkflowTemplate(ctx context.Context, in *CreateWorkflowTemplateRequest, opts ...grpc.CallOption) (*WorkflowTemplate, error)
|
CreateWorkflowTemplate(ctx context.Context, in *CreateWorkflowTemplateRequest, opts ...grpc.CallOption) (*WorkflowTemplate, error)
|
||||||
UpdateWorkflowTemplateVersion(ctx context.Context, in *UpdateWorkflowTemplateVersionRequest, opts ...grpc.CallOption) (*WorkflowTemplate, error)
|
|
||||||
CreateWorkflowTemplateVersion(ctx context.Context, in *CreateWorkflowTemplateRequest, opts ...grpc.CallOption) (*WorkflowTemplate, error)
|
CreateWorkflowTemplateVersion(ctx context.Context, in *CreateWorkflowTemplateRequest, opts ...grpc.CallOption) (*WorkflowTemplate, error)
|
||||||
GetWorkflowTemplate(ctx context.Context, in *GetWorkflowTemplateRequest, opts ...grpc.CallOption) (*WorkflowTemplate, error)
|
GetWorkflowTemplate(ctx context.Context, in *GetWorkflowTemplateRequest, opts ...grpc.CallOption) (*WorkflowTemplate, error)
|
||||||
ListWorkflowTemplateVersions(ctx context.Context, in *ListWorkflowTemplateVersionsRequest, opts ...grpc.CallOption) (*ListWorkflowTemplateVersionsResponse, error)
|
ListWorkflowTemplateVersions(ctx context.Context, in *ListWorkflowTemplateVersionsRequest, opts ...grpc.CallOption) (*ListWorkflowTemplateVersionsResponse, error)
|
||||||
@@ -1492,15 +1474,6 @@ func (c *workflowTemplateServiceClient) CreateWorkflowTemplate(ctx context.Conte
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *workflowTemplateServiceClient) UpdateWorkflowTemplateVersion(ctx context.Context, in *UpdateWorkflowTemplateVersionRequest, opts ...grpc.CallOption) (*WorkflowTemplate, error) {
|
|
||||||
out := new(WorkflowTemplate)
|
|
||||||
err := c.cc.Invoke(ctx, "/api.WorkflowTemplateService/UpdateWorkflowTemplateVersion", in, out, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *workflowTemplateServiceClient) CreateWorkflowTemplateVersion(ctx context.Context, in *CreateWorkflowTemplateRequest, opts ...grpc.CallOption) (*WorkflowTemplate, error) {
|
func (c *workflowTemplateServiceClient) CreateWorkflowTemplateVersion(ctx context.Context, in *CreateWorkflowTemplateRequest, opts ...grpc.CallOption) (*WorkflowTemplate, error) {
|
||||||
out := new(WorkflowTemplate)
|
out := new(WorkflowTemplate)
|
||||||
err := c.cc.Invoke(ctx, "/api.WorkflowTemplateService/CreateWorkflowTemplateVersion", in, out, opts...)
|
err := c.cc.Invoke(ctx, "/api.WorkflowTemplateService/CreateWorkflowTemplateVersion", in, out, opts...)
|
||||||
@@ -1558,7 +1531,6 @@ func (c *workflowTemplateServiceClient) ArchiveWorkflowTemplate(ctx context.Cont
|
|||||||
// WorkflowTemplateServiceServer is the server API for WorkflowTemplateService service.
|
// WorkflowTemplateServiceServer is the server API for WorkflowTemplateService service.
|
||||||
type WorkflowTemplateServiceServer interface {
|
type WorkflowTemplateServiceServer interface {
|
||||||
CreateWorkflowTemplate(context.Context, *CreateWorkflowTemplateRequest) (*WorkflowTemplate, error)
|
CreateWorkflowTemplate(context.Context, *CreateWorkflowTemplateRequest) (*WorkflowTemplate, error)
|
||||||
UpdateWorkflowTemplateVersion(context.Context, *UpdateWorkflowTemplateVersionRequest) (*WorkflowTemplate, error)
|
|
||||||
CreateWorkflowTemplateVersion(context.Context, *CreateWorkflowTemplateRequest) (*WorkflowTemplate, error)
|
CreateWorkflowTemplateVersion(context.Context, *CreateWorkflowTemplateRequest) (*WorkflowTemplate, error)
|
||||||
GetWorkflowTemplate(context.Context, *GetWorkflowTemplateRequest) (*WorkflowTemplate, error)
|
GetWorkflowTemplate(context.Context, *GetWorkflowTemplateRequest) (*WorkflowTemplate, error)
|
||||||
ListWorkflowTemplateVersions(context.Context, *ListWorkflowTemplateVersionsRequest) (*ListWorkflowTemplateVersionsResponse, error)
|
ListWorkflowTemplateVersions(context.Context, *ListWorkflowTemplateVersionsRequest) (*ListWorkflowTemplateVersionsResponse, error)
|
||||||
@@ -1574,9 +1546,6 @@ type UnimplementedWorkflowTemplateServiceServer struct {
|
|||||||
func (*UnimplementedWorkflowTemplateServiceServer) CreateWorkflowTemplate(context.Context, *CreateWorkflowTemplateRequest) (*WorkflowTemplate, error) {
|
func (*UnimplementedWorkflowTemplateServiceServer) CreateWorkflowTemplate(context.Context, *CreateWorkflowTemplateRequest) (*WorkflowTemplate, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method CreateWorkflowTemplate not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method CreateWorkflowTemplate not implemented")
|
||||||
}
|
}
|
||||||
func (*UnimplementedWorkflowTemplateServiceServer) UpdateWorkflowTemplateVersion(context.Context, *UpdateWorkflowTemplateVersionRequest) (*WorkflowTemplate, error) {
|
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method UpdateWorkflowTemplateVersion not implemented")
|
|
||||||
}
|
|
||||||
func (*UnimplementedWorkflowTemplateServiceServer) CreateWorkflowTemplateVersion(context.Context, *CreateWorkflowTemplateRequest) (*WorkflowTemplate, error) {
|
func (*UnimplementedWorkflowTemplateServiceServer) CreateWorkflowTemplateVersion(context.Context, *CreateWorkflowTemplateRequest) (*WorkflowTemplate, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method CreateWorkflowTemplateVersion not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method CreateWorkflowTemplateVersion not implemented")
|
||||||
}
|
}
|
||||||
@@ -1618,24 +1587,6 @@ func _WorkflowTemplateService_CreateWorkflowTemplate_Handler(srv interface{}, ct
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func _WorkflowTemplateService_UpdateWorkflowTemplateVersion_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
|
||||||
in := new(UpdateWorkflowTemplateVersionRequest)
|
|
||||||
if err := dec(in); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if interceptor == nil {
|
|
||||||
return srv.(WorkflowTemplateServiceServer).UpdateWorkflowTemplateVersion(ctx, in)
|
|
||||||
}
|
|
||||||
info := &grpc.UnaryServerInfo{
|
|
||||||
Server: srv,
|
|
||||||
FullMethod: "/api.WorkflowTemplateService/UpdateWorkflowTemplateVersion",
|
|
||||||
}
|
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
||||||
return srv.(WorkflowTemplateServiceServer).UpdateWorkflowTemplateVersion(ctx, req.(*UpdateWorkflowTemplateVersionRequest))
|
|
||||||
}
|
|
||||||
return interceptor(ctx, in, info, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _WorkflowTemplateService_CreateWorkflowTemplateVersion_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _WorkflowTemplateService_CreateWorkflowTemplateVersion_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
in := new(CreateWorkflowTemplateRequest)
|
in := new(CreateWorkflowTemplateRequest)
|
||||||
if err := dec(in); err != nil {
|
if err := dec(in); err != nil {
|
||||||
@@ -1752,10 +1703,6 @@ var _WorkflowTemplateService_serviceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "CreateWorkflowTemplate",
|
MethodName: "CreateWorkflowTemplate",
|
||||||
Handler: _WorkflowTemplateService_CreateWorkflowTemplate_Handler,
|
Handler: _WorkflowTemplateService_CreateWorkflowTemplate_Handler,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
MethodName: "UpdateWorkflowTemplateVersion",
|
|
||||||
Handler: _WorkflowTemplateService_UpdateWorkflowTemplateVersion_Handler,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
MethodName: "CreateWorkflowTemplateVersion",
|
MethodName: "CreateWorkflowTemplateVersion",
|
||||||
Handler: _WorkflowTemplateService_CreateWorkflowTemplateVersion_Handler,
|
Handler: _WorkflowTemplateService_CreateWorkflowTemplateVersion_Handler,
|
||||||
|
@@ -101,120 +101,6 @@ func local_request_WorkflowTemplateService_CreateWorkflowTemplate_0(ctx context.
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func request_WorkflowTemplateService_UpdateWorkflowTemplateVersion_0(ctx context.Context, marshaler runtime.Marshaler, client WorkflowTemplateServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
|
||||||
var protoReq UpdateWorkflowTemplateVersionRequest
|
|
||||||
var metadata runtime.ServerMetadata
|
|
||||||
|
|
||||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
|
||||||
if berr != nil {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
|
||||||
}
|
|
||||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.WorkflowTemplate); err != nil && err != io.EOF {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
val string
|
|
||||||
ok bool
|
|
||||||
err error
|
|
||||||
_ = err
|
|
||||||
)
|
|
||||||
|
|
||||||
val, ok = pathParams["namespace"]
|
|
||||||
if !ok {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "namespace")
|
|
||||||
}
|
|
||||||
|
|
||||||
protoReq.Namespace, err = runtime.String(val)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "namespace", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
val, ok = pathParams["workflowTemplate.uid"]
|
|
||||||
if !ok {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "workflowTemplate.uid")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = runtime.PopulateFieldFromPath(&protoReq, "workflowTemplate.uid", val)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "workflowTemplate.uid", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
val, ok = pathParams["workflowTemplate.version"]
|
|
||||||
if !ok {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "workflowTemplate.version")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = runtime.PopulateFieldFromPath(&protoReq, "workflowTemplate.version", val)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "workflowTemplate.version", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
msg, err := client.UpdateWorkflowTemplateVersion(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
|
||||||
return msg, metadata, err
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func local_request_WorkflowTemplateService_UpdateWorkflowTemplateVersion_0(ctx context.Context, marshaler runtime.Marshaler, server WorkflowTemplateServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
|
||||||
var protoReq UpdateWorkflowTemplateVersionRequest
|
|
||||||
var metadata runtime.ServerMetadata
|
|
||||||
|
|
||||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
|
||||||
if berr != nil {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
|
||||||
}
|
|
||||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.WorkflowTemplate); err != nil && err != io.EOF {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
val string
|
|
||||||
ok bool
|
|
||||||
err error
|
|
||||||
_ = err
|
|
||||||
)
|
|
||||||
|
|
||||||
val, ok = pathParams["namespace"]
|
|
||||||
if !ok {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "namespace")
|
|
||||||
}
|
|
||||||
|
|
||||||
protoReq.Namespace, err = runtime.String(val)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "namespace", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
val, ok = pathParams["workflowTemplate.uid"]
|
|
||||||
if !ok {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "workflowTemplate.uid")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = runtime.PopulateFieldFromPath(&protoReq, "workflowTemplate.uid", val)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "workflowTemplate.uid", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
val, ok = pathParams["workflowTemplate.version"]
|
|
||||||
if !ok {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "workflowTemplate.version")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = runtime.PopulateFieldFromPath(&protoReq, "workflowTemplate.version", val)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "workflowTemplate.version", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
msg, err := server.UpdateWorkflowTemplateVersion(ctx, &protoReq)
|
|
||||||
return msg, metadata, err
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func request_WorkflowTemplateService_CreateWorkflowTemplateVersion_0(ctx context.Context, marshaler runtime.Marshaler, client WorkflowTemplateServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
func request_WorkflowTemplateService_CreateWorkflowTemplateVersion_0(ctx context.Context, marshaler runtime.Marshaler, client WorkflowTemplateServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
var protoReq CreateWorkflowTemplateRequest
|
var protoReq CreateWorkflowTemplateRequest
|
||||||
var metadata runtime.ServerMetadata
|
var metadata runtime.ServerMetadata
|
||||||
@@ -975,26 +861,6 @@ func RegisterWorkflowTemplateServiceHandlerServer(ctx context.Context, mux *runt
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
mux.Handle("PUT", pattern_WorkflowTemplateService_UpdateWorkflowTemplateVersion_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
|
||||||
ctx, cancel := context.WithCancel(req.Context())
|
|
||||||
defer cancel()
|
|
||||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
|
||||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
|
||||||
if err != nil {
|
|
||||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp, md, err := local_request_WorkflowTemplateService_UpdateWorkflowTemplateVersion_0(rctx, inboundMarshaler, server, req, pathParams)
|
|
||||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
|
||||||
if err != nil {
|
|
||||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
forward_WorkflowTemplateService_UpdateWorkflowTemplateVersion_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
mux.Handle("POST", pattern_WorkflowTemplateService_CreateWorkflowTemplateVersion_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
mux.Handle("POST", pattern_WorkflowTemplateService_CreateWorkflowTemplateVersion_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
ctx, cancel := context.WithCancel(req.Context())
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -1216,26 +1082,6 @@ func RegisterWorkflowTemplateServiceHandlerClient(ctx context.Context, mux *runt
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
mux.Handle("PUT", pattern_WorkflowTemplateService_UpdateWorkflowTemplateVersion_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
|
||||||
ctx, cancel := context.WithCancel(req.Context())
|
|
||||||
defer cancel()
|
|
||||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
|
||||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
|
||||||
if err != nil {
|
|
||||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp, md, err := request_WorkflowTemplateService_UpdateWorkflowTemplateVersion_0(rctx, inboundMarshaler, client, req, pathParams)
|
|
||||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
|
||||||
if err != nil {
|
|
||||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
forward_WorkflowTemplateService_UpdateWorkflowTemplateVersion_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
mux.Handle("POST", pattern_WorkflowTemplateService_CreateWorkflowTemplateVersion_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
mux.Handle("POST", pattern_WorkflowTemplateService_CreateWorkflowTemplateVersion_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
ctx, cancel := context.WithCancel(req.Context())
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -1402,8 +1248,6 @@ func RegisterWorkflowTemplateServiceHandlerClient(ctx context.Context, mux *runt
|
|||||||
var (
|
var (
|
||||||
pattern_WorkflowTemplateService_CreateWorkflowTemplate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3}, []string{"apis", "v1beta1", "namespace", "workflow_templates"}, "", runtime.AssumeColonVerbOpt(true)))
|
pattern_WorkflowTemplateService_CreateWorkflowTemplate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3}, []string{"apis", "v1beta1", "namespace", "workflow_templates"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||||
|
|
||||||
pattern_WorkflowTemplateService_UpdateWorkflowTemplateVersion_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5, 1, 0, 4, 1, 5, 6}, []string{"apis", "v1beta1", "namespace", "workflow_templates", "workflowTemplate.uid", "versions", "workflowTemplate.version"}, "", runtime.AssumeColonVerbOpt(true)))
|
|
||||||
|
|
||||||
pattern_WorkflowTemplateService_CreateWorkflowTemplateVersion_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"apis", "v1beta1", "namespace", "workflow_templates", "workflowTemplate.uid", "versions"}, "", runtime.AssumeColonVerbOpt(true)))
|
pattern_WorkflowTemplateService_CreateWorkflowTemplateVersion_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"apis", "v1beta1", "namespace", "workflow_templates", "workflowTemplate.uid", "versions"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||||
|
|
||||||
pattern_WorkflowTemplateService_GetWorkflowTemplate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"apis", "v1beta1", "namespace", "workflow_templates", "uid"}, "", runtime.AssumeColonVerbOpt(true)))
|
pattern_WorkflowTemplateService_GetWorkflowTemplate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"apis", "v1beta1", "namespace", "workflow_templates", "uid"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||||
@@ -1424,8 +1268,6 @@ var (
|
|||||||
var (
|
var (
|
||||||
forward_WorkflowTemplateService_CreateWorkflowTemplate_0 = runtime.ForwardResponseMessage
|
forward_WorkflowTemplateService_CreateWorkflowTemplate_0 = runtime.ForwardResponseMessage
|
||||||
|
|
||||||
forward_WorkflowTemplateService_UpdateWorkflowTemplateVersion_0 = runtime.ForwardResponseMessage
|
|
||||||
|
|
||||||
forward_WorkflowTemplateService_CreateWorkflowTemplateVersion_0 = runtime.ForwardResponseMessage
|
forward_WorkflowTemplateService_CreateWorkflowTemplateVersion_0 = runtime.ForwardResponseMessage
|
||||||
|
|
||||||
forward_WorkflowTemplateService_GetWorkflowTemplate_0 = runtime.ForwardResponseMessage
|
forward_WorkflowTemplateService_GetWorkflowTemplate_0 = runtime.ForwardResponseMessage
|
||||||
|
@@ -13,13 +13,6 @@ service WorkflowTemplateService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc UpdateWorkflowTemplateVersion (UpdateWorkflowTemplateVersionRequest) returns (WorkflowTemplate) {
|
|
||||||
option (google.api.http) = {
|
|
||||||
put: "/apis/v1beta1/{namespace}/workflow_templates/{workflowTemplate.uid}/versions/{workflowTemplate.version}"
|
|
||||||
body: "workflowTemplate"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
rpc CreateWorkflowTemplateVersion (CreateWorkflowTemplateRequest) returns (WorkflowTemplate) {
|
rpc CreateWorkflowTemplateVersion (CreateWorkflowTemplateRequest) returns (WorkflowTemplate) {
|
||||||
option (google.api.http) = {
|
option (google.api.http) = {
|
||||||
post: "/apis/v1beta1/{namespace}/workflow_templates/{workflowTemplate.uid}/versions"
|
post: "/apis/v1beta1/{namespace}/workflow_templates/{workflowTemplate.uid}/versions"
|
||||||
|
@@ -4,7 +4,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
_ "github.com/onepanelio/core/db"
|
_ "github.com/onepanelio/core/db"
|
||||||
v1 "github.com/onepanelio/core/pkg"
|
v1 "github.com/onepanelio/core/pkg"
|
||||||
@@ -38,10 +37,8 @@ func main() {
|
|||||||
log.Fatalf("Failed to get system config: %v", err)
|
log.Fatalf("Failed to get system config: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
databaseDataSourceName := fmt.Sprintf("host=%v user=%v password=%v dbname=%v sslmode=disable",
|
dbDriverName, dbDataSourceName := config.DatabaseConnection()
|
||||||
config["databaseHost"], config["databaseUsername"], config["databasePassword"], config["databaseName"])
|
db := sqlx.MustConnect(dbDriverName, dbDataSourceName)
|
||||||
|
|
||||||
db := sqlx.MustConnect(config["databaseDriverName"], databaseDataSourceName)
|
|
||||||
|
|
||||||
command := args[0]
|
command := args[0]
|
||||||
|
|
||||||
|
167
db/20200704151301_update_cvat_workspace_template.go
Normal file
167
db/20200704151301_update_cvat_workspace_template.go
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
package migration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
v1 "github.com/onepanelio/core/pkg"
|
||||||
|
uid2 "github.com/onepanelio/core/pkg/util/uid"
|
||||||
|
"github.com/pressly/goose"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const cvatWorkspaceTemplate3 = `# Docker containers that are part of the Workspace
|
||||||
|
containers:
|
||||||
|
- name: cvat-db
|
||||||
|
image: postgres:10-alpine
|
||||||
|
env:
|
||||||
|
- name: POSTGRES_USER
|
||||||
|
value: root
|
||||||
|
- name: POSTGRES_DB
|
||||||
|
value: cvat
|
||||||
|
- name: POSTGRES_HOST_AUTH_METHOD
|
||||||
|
value: trust
|
||||||
|
- name: PGDATA
|
||||||
|
value: /var/lib/psql/data
|
||||||
|
ports:
|
||||||
|
- containerPort: 5432
|
||||||
|
name: tcp
|
||||||
|
volumeMounts:
|
||||||
|
- name: db
|
||||||
|
mountPath: /var/lib/psql
|
||||||
|
- name: cvat-redis
|
||||||
|
image: redis:4.0-alpine
|
||||||
|
ports:
|
||||||
|
- containerPort: 6379
|
||||||
|
name: tcp
|
||||||
|
- name: cvat
|
||||||
|
image: onepanel/cvat:v0.7.10-stable
|
||||||
|
env:
|
||||||
|
- name: DJANGO_MODWSGI_EXTRA_ARGS
|
||||||
|
value: ""
|
||||||
|
- name: ALLOWED_HOSTS
|
||||||
|
value: '*'
|
||||||
|
- name: CVAT_REDIS_HOST
|
||||||
|
value: localhost
|
||||||
|
- name: CVAT_POSTGRES_HOST
|
||||||
|
value: localhost
|
||||||
|
- name: CVAT_SHARE_URL
|
||||||
|
value: /home/django/data
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
name: http
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: /home/django/data
|
||||||
|
- name: keys
|
||||||
|
mountPath: /home/django/keys
|
||||||
|
- name: logs
|
||||||
|
mountPath: /home/django/logs
|
||||||
|
- name: models
|
||||||
|
mountPath: /home/django/models
|
||||||
|
- name: share
|
||||||
|
mountPath: /home/django/share
|
||||||
|
- name: cvat-ui
|
||||||
|
image: onepanel/cvat-ui:v0.7.10-stable
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
name: http
|
||||||
|
# Uncomment following lines to enable S3 FileSyncer
|
||||||
|
# Refer to https://docs.onepanel.ai/docs/getting-started/use-cases/computervision/annotation/cvat/cvat_quick_guide#setting-up-environment-variables
|
||||||
|
#- name: filesyncer
|
||||||
|
# image: onepanel/filesyncer:v0.0.4
|
||||||
|
# command: ['python3', 'main.py']
|
||||||
|
# volumeMounts:
|
||||||
|
# - name: share
|
||||||
|
# mountPath: /mnt/share
|
||||||
|
ports:
|
||||||
|
- name: cvat-ui
|
||||||
|
port: 80
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 80
|
||||||
|
- name: cvat
|
||||||
|
port: 8080
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 8080
|
||||||
|
routes:
|
||||||
|
- match:
|
||||||
|
- uri:
|
||||||
|
regex: /api/.*|/git/.*|/tensorflow/.*|/auto_annotation/.*|/analytics/.*|/static/.*|/admin/.*|/documentation/.*|/dextr/.*|/reid/.*
|
||||||
|
- queryParams:
|
||||||
|
id:
|
||||||
|
regex: \d+.*
|
||||||
|
route:
|
||||||
|
- destination:
|
||||||
|
port:
|
||||||
|
number: 8080
|
||||||
|
timeout: 600s
|
||||||
|
- match:
|
||||||
|
- uri:
|
||||||
|
prefix: /
|
||||||
|
route:
|
||||||
|
- destination:
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
timeout: 600s
|
||||||
|
# DAG Workflow to be executed once a Workspace action completes (optional)
|
||||||
|
# Uncomment the lines below if you want to send Slack notifications
|
||||||
|
#postExecutionWorkflow:
|
||||||
|
# entrypoint: main
|
||||||
|
# templates:
|
||||||
|
# - name: main
|
||||||
|
# dag:
|
||||||
|
# tasks:
|
||||||
|
# - name: slack-notify
|
||||||
|
# template: slack-notify
|
||||||
|
# - name: slack-notify
|
||||||
|
# container:
|
||||||
|
# image: technosophos/slack-notify
|
||||||
|
# args:
|
||||||
|
# - SLACK_USERNAME=onepanel SLACK_TITLE="Your workspace is ready" SLACK_ICON=https://www.gravatar.com/avatar/5c4478592fe00878f62f0027be59c1bd SLACK_MESSAGE="Your workspace is now running" ./slack-notify
|
||||||
|
# command:
|
||||||
|
# - sh
|
||||||
|
# - -c
|
||||||
|
`
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
goose.AddMigration(Up20200704151301, Down20200704151301)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Up20200704151301 updates the CVAT template to a new version.
|
||||||
|
func Up20200704151301(tx *sql.Tx) error {
|
||||||
|
// This code is executed when the migration is applied.
|
||||||
|
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
|
||||||
|
client, err := getClient()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
namespaces, err := client.ListOnepanelEnabledNamespaces()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
uid, err := uid2.GenerateUID(cvatTemplateName, 30)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
workspaceTemplate := &v1.WorkspaceTemplate{
|
||||||
|
UID: uid,
|
||||||
|
Name: cvatTemplateName,
|
||||||
|
Manifest: cvatWorkspaceTemplate3,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, namespace := range namespaces {
|
||||||
|
if _, err := client.UpdateWorkspaceTemplate(namespace.Name, workspaceTemplate); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Down20200704151301 removes the CVAT template update
|
||||||
|
func Down20200704151301(tx *sql.Tx) error {
|
||||||
|
// This code is executed when the migration is rolled back.
|
||||||
|
return nil
|
||||||
|
}
|
25
db/db.go
25
db/db.go
@@ -1,25 +0,0 @@
|
|||||||
package migration
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/jmoiron/sqlx"
|
|
||||||
v1 "github.com/onepanelio/core/pkg"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getClient() (*v1.Client, error) {
|
|
||||||
kubeConfig := v1.NewConfig()
|
|
||||||
client, err := v1.NewClient(kubeConfig, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
config, err := client.GetSystemConfig()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
databaseDataSourceName := fmt.Sprintf("host=%v user=%v password=%v dbname=%v sslmode=disable",
|
|
||||||
config["databaseHost"], config["databaseUsername"], config["databasePassword"], config["databaseName"])
|
|
||||||
client.DB = v1.NewDB(sqlx.MustConnect(config["databaseDriverName"], databaseDataSourceName))
|
|
||||||
|
|
||||||
return client, nil
|
|
||||||
}
|
|
@@ -71,7 +71,7 @@ routes:
|
|||||||
|
|
||||||
const jupyterLabTemplateName = "JupyterLab"
|
const jupyterLabTemplateName = "JupyterLab"
|
||||||
|
|
||||||
func init() {
|
func initialize20200525160514() {
|
||||||
goose.AddMigration(Up20200525160514, Down20200525160514)
|
goose.AddMigration(Up20200525160514, Down20200525160514)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,6 +81,15 @@ func Up20200525160514(tx *sql.Tx) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
migrationsRan, err := getRanSQLMigrations(client)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := migrationsRan[20200525160514]; ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
namespaces, err := client.ListOnepanelEnabledNamespaces()
|
namespaces, err := client.ListOnepanelEnabledNamespaces()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
@@ -110,7 +110,7 @@ routes:
|
|||||||
|
|
||||||
const cvatTemplateName = "CVAT"
|
const cvatTemplateName = "CVAT"
|
||||||
|
|
||||||
func init() {
|
func initialize20200528140124() {
|
||||||
goose.AddMigration(Up20200528140124, Down20200528140124)
|
goose.AddMigration(Up20200528140124, Down20200528140124)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,6 +125,15 @@ func Up20200528140124(tx *sql.Tx) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
migrationsRan, err := getRanSQLMigrations(client)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := migrationsRan[20200528140124]; ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
namespaces, err := client.ListOnepanelEnabledNamespaces()
|
namespaces, err := client.ListOnepanelEnabledNamespaces()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
@@ -88,7 +88,7 @@ templates:
|
|||||||
|
|
||||||
const pytorchMnistWorkflowTemplateName = "PyTorch Training"
|
const pytorchMnistWorkflowTemplateName = "PyTorch Training"
|
||||||
|
|
||||||
func init() {
|
func initialize20200605090509() {
|
||||||
goose.AddMigration(Up20200605090509, Down20200605090509)
|
goose.AddMigration(Up20200605090509, Down20200605090509)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,6 +101,15 @@ func Up20200605090509(tx *sql.Tx) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
migrationsRan, err := getRanSQLMigrations(client)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := migrationsRan[20200605090509]; ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
namespaces, err := client.ListOnepanelEnabledNamespaces()
|
namespaces, err := client.ListOnepanelEnabledNamespaces()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
@@ -88,7 +88,7 @@ templates:
|
|||||||
|
|
||||||
const tensorflowWorkflowTemplateName = "TensorFlow Training"
|
const tensorflowWorkflowTemplateName = "TensorFlow Training"
|
||||||
|
|
||||||
func init() {
|
func initialize20200605090535() {
|
||||||
goose.AddMigration(Up20200605090535, Down20200605090535)
|
goose.AddMigration(Up20200605090535, Down20200605090535)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,6 +101,15 @@ func Up20200605090535(tx *sql.Tx) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
migrationsRan, err := getRanSQLMigrations(client)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := migrationsRan[20200605090535]; ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
namespaces, err := client.ListOnepanelEnabledNamespaces()
|
namespaces, err := client.ListOnepanelEnabledNamespaces()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
@@ -5,7 +5,6 @@ import (
|
|||||||
v1 "github.com/onepanelio/core/pkg"
|
v1 "github.com/onepanelio/core/pkg"
|
||||||
uid2 "github.com/onepanelio/core/pkg/util/uid"
|
uid2 "github.com/onepanelio/core/pkg/util/uid"
|
||||||
"github.com/pressly/goose"
|
"github.com/pressly/goose"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const cvatWorkspaceTemplate2 = `# Docker containers that are part of the Workspace
|
const cvatWorkspaceTemplate2 = `# Docker containers that are part of the Workspace
|
||||||
@@ -119,21 +118,27 @@ routes:
|
|||||||
# - -c
|
# - -c
|
||||||
`
|
`
|
||||||
|
|
||||||
func init() {
|
func initialize20200626113635() {
|
||||||
goose.AddMigration(Up20200626113635, Down20200626113635)
|
goose.AddMigration(Up20200626113635, Down20200626113635)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Up20200626113635 updates the CVAT template to a new version.
|
// Up20200626113635 updates the CVAT template to a new version.
|
||||||
func Up20200626113635(tx *sql.Tx) error {
|
func Up20200626113635(tx *sql.Tx) error {
|
||||||
// This code is executed when the migration is applied.
|
// This code is executed when the migration is applied.
|
||||||
|
|
||||||
time.Sleep(2 * time.Second)
|
|
||||||
|
|
||||||
client, err := getClient()
|
client, err := getClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
migrationsRan, err := getRanSQLMigrations(client)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := migrationsRan[20200626113635]; ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
namespaces, err := client.ListOnepanelEnabledNamespaces()
|
namespaces, err := client.ListOnepanelEnabledNamespaces()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
53
db/go/db.go
Normal file
53
db/go/db.go
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package migration
|
||||||
|
|
||||||
|
import (
|
||||||
|
sq "github.com/Masterminds/squirrel"
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
v1 "github.com/onepanelio/core/pkg"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Initialize sets up the go migrations.
|
||||||
|
func Initialize() {
|
||||||
|
initialize20200525160514()
|
||||||
|
initialize20200528140124()
|
||||||
|
initialize20200605090509()
|
||||||
|
initialize20200605090535()
|
||||||
|
initialize20200626113635()
|
||||||
|
}
|
||||||
|
|
||||||
|
func getClient() (*v1.Client, error) {
|
||||||
|
kubeConfig := v1.NewConfig()
|
||||||
|
client, err := v1.NewClient(kubeConfig, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
config, err := client.GetSystemConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
dbDriverName, dbDataSourceName := config.DatabaseConnection()
|
||||||
|
client.DB = v1.NewDB(sqlx.MustConnect(dbDriverName, dbDataSourceName))
|
||||||
|
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getRanSQLMigrations returns a map where each key is a sql migration version ran.
|
||||||
|
func getRanSQLMigrations(client *v1.Client) (map[uint64]bool, error) {
|
||||||
|
sb := sq.StatementBuilder.PlaceholderFormat(sq.Dollar)
|
||||||
|
|
||||||
|
query := sb.Select("version_id").
|
||||||
|
From("goose_db_version")
|
||||||
|
|
||||||
|
versions := make([]uint64, 0)
|
||||||
|
if err := client.Selectx(&versions, query); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make(map[uint64]bool)
|
||||||
|
for _, version := range versions {
|
||||||
|
result[version] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
@@ -2,5 +2,4 @@
|
|||||||
ALTER TABLE workflow_template_versions DROP COLUMN uid;
|
ALTER TABLE workflow_template_versions DROP COLUMN uid;
|
||||||
|
|
||||||
-- +goose Down
|
-- +goose Down
|
||||||
ALTER TABLE workflow_template_versions ADD COLUMN uid VARCHAR(30);
|
|
||||||
UPDATE workflow_template_versions SET uid = version::text;
|
UPDATE workflow_template_versions SET uid = version::text;
|
11
db/sql/20200630112657_update_version_types.sql
Normal file
11
db/sql/20200630112657_update_version_types.sql
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
-- +goose Up
|
||||||
|
-- SQL in this section is executed when the migration is applied.
|
||||||
|
ALTER TABLE workflow_template_versions ALTER COLUMN version TYPE BIGINT;
|
||||||
|
ALTER TABLE workspace_template_versions ALTER COLUMN version TYPE BIGINT;
|
||||||
|
ALTER TABLE workspaces ALTER COLUMN workspace_template_version TYPE BIGINT;
|
||||||
|
|
||||||
|
-- +goose Down
|
||||||
|
-- SQL in this section is executed when the migration is rolled back.
|
||||||
|
ALTER TABLE workflow_template_versions ALTER COLUMN version TYPE INT;
|
||||||
|
ALTER TABLE workspace_template_versions ALTER COLUMN version TYPE INT;
|
||||||
|
ALTER TABLE workspaces ALTER COLUMN workspace_template_version TYPE INT;
|
20
main.go
20
main.go
@@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
_ "github.com/onepanelio/core/db"
|
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
@@ -23,6 +22,7 @@ import (
|
|||||||
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/onepanelio/core/api"
|
"github.com/onepanelio/core/api"
|
||||||
|
migrations "github.com/onepanelio/core/db/go"
|
||||||
v1 "github.com/onepanelio/core/pkg"
|
v1 "github.com/onepanelio/core/pkg"
|
||||||
"github.com/onepanelio/core/pkg/util/env"
|
"github.com/onepanelio/core/pkg/util/env"
|
||||||
"github.com/onepanelio/core/server"
|
"github.com/onepanelio/core/server"
|
||||||
@@ -67,16 +67,20 @@ func main() {
|
|||||||
log.Fatalf("Failed to get system config: %v", err)
|
log.Fatalf("Failed to get system config: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
databaseDataSourceName := fmt.Sprintf("host=%v user=%v password=%v dbname=%v sslmode=disable",
|
dbDriverName, databaseDataSourceName := sysConfig.DatabaseConnection()
|
||||||
sysConfig["databaseHost"], sysConfig["databaseUsername"], sysConfig["databasePassword"], sysConfig["databaseName"])
|
|
||||||
|
|
||||||
// sqlx.MustConnect will panic when it can't connect to DB. In that case, this whole application will crash.
|
// sqlx.MustConnect will panic when it can't connect to DB. In that case, this whole application will crash.
|
||||||
// This is okay, as the pod will restart and try connecting to DB again.
|
// This is okay, as the pod will restart and try connecting to DB again.
|
||||||
// dbDriverName may be nil, but sqlx will then panic.
|
// dbDriverName may be nil, but sqlx will then panic.
|
||||||
dbDriverName := sysConfig.DatabaseDriverName()
|
db := sqlx.MustConnect(dbDriverName, databaseDataSourceName)
|
||||||
db := sqlx.MustConnect(*dbDriverName, databaseDataSourceName)
|
goose.SetTableName("goose_db_version")
|
||||||
if err := goose.Run("up", db.DB, "db"); err != nil {
|
if err := goose.Run("up", db.DB, "db/sql"); err != nil {
|
||||||
log.Fatalf("Failed to run database migrations: %v", err)
|
log.Fatalf("Failed to run database sql migrations: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
goose.SetTableName("goose_db_go_version")
|
||||||
|
migrations.Initialize()
|
||||||
|
if err := goose.Run("up", db.DB, "db/go"); err != nil {
|
||||||
|
log.Fatalf("Failed to run database go migrations: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s := startRPCServer(v1.NewDB(db), kubeConfig, sysConfig, stopCh)
|
s := startRPCServer(v1.NewDB(db), kubeConfig, sysConfig, stopCh)
|
||||||
|
@@ -1,10 +1,18 @@
|
|||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
argoFake "github.com/argoproj/argo/pkg/client/clientset/versioned/fake"
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
"github.com/pressly/goose"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -15,6 +23,20 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configArtifactRepository = `archiveLogs: true
|
||||||
|
s3:
|
||||||
|
keyFormat: artifacts/{{workflow.namespace}}/{{workflow.name}}/{{pod.name}}
|
||||||
|
bucket: test.onepanel.io
|
||||||
|
endpoint: s3.amazonaws.com
|
||||||
|
insecure: false
|
||||||
|
region: us-west-2
|
||||||
|
accessKeySecret:
|
||||||
|
name: onepanel
|
||||||
|
key: artifactRepositoryS3AccessKey
|
||||||
|
secretKeySecret:
|
||||||
|
name: onepanel
|
||||||
|
key: artifactRepositoryS3SecretKey`
|
||||||
|
|
||||||
mockSystemConfigMap = &v1.ConfigMap{
|
mockSystemConfigMap = &v1.ConfigMap{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "onepanel",
|
Name: "onepanel",
|
||||||
@@ -22,6 +44,8 @@ var (
|
|||||||
},
|
},
|
||||||
Data: map[string]string{
|
Data: map[string]string{
|
||||||
"ONEPANEL_HOST": "demo.onepanel.site",
|
"ONEPANEL_HOST": "demo.onepanel.site",
|
||||||
|
"ONEPANEL_DOMAIN": "demo.onepanel.site",
|
||||||
|
"artifactRepository": configArtifactRepository,
|
||||||
"applicationNodePoolLabel": "beta.kubernetes.io/instance-type",
|
"applicationNodePoolLabel": "beta.kubernetes.io/instance-type",
|
||||||
"applicationNodePoolOptions": `
|
"applicationNodePoolOptions": `
|
||||||
- name: 'CPU: 2, RAM: 8GB'
|
- name: 'CPU: 2, RAM: 8GB'
|
||||||
@@ -34,8 +58,60 @@ var (
|
|||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
database *sqlx.DB
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewTestClient(objects ...runtime.Object) (client *Client) {
|
var flagDatabaseService = flag.String("db", "localhost", "Name to connect to db, defaults to localhost")
|
||||||
return &Client{Interface: fake.NewSimpleClientset(objects...)}
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
// call flag.Parse() here if TestMain uses flags
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
databaseDataSourceName := fmt.Sprintf("host=%v user=%v password=%v dbname=%v sslmode=disable",
|
||||||
|
*flagDatabaseService, "admin", "tester", "onepanel")
|
||||||
|
|
||||||
|
dbDriverName := "postgres"
|
||||||
|
database = sqlx.MustConnect(dbDriverName, databaseDataSourceName)
|
||||||
|
|
||||||
|
// We don't run the go migrations as those setup data that we don't use in our testing
|
||||||
|
if err := goose.Run("up", database.DB, "../db/sql"); err != nil {
|
||||||
|
log.Fatalf("Failed to run database migrations: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Exit(m.Run())
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTestClient(db *sqlx.DB, objects ...runtime.Object) (client *Client) {
|
||||||
|
k8sFake := fake.NewSimpleClientset(objects...)
|
||||||
|
argoFakeClient := argoFake.NewSimpleClientset()
|
||||||
|
|
||||||
|
return &Client{
|
||||||
|
Interface: k8sFake,
|
||||||
|
DB: NewDB(db),
|
||||||
|
argoprojV1alpha1: argoFakeClient.ArgoprojV1alpha1(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DefaultTestClient() *Client {
|
||||||
|
return NewTestClient(database, mockSystemConfigMap, mockSystemSecret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func clearDatabase(t *testing.T) {
|
||||||
|
// We do not delete from goose_db_version as we need it to mark the migrations as ran.
|
||||||
|
query := `
|
||||||
|
DELETE FROM labels;
|
||||||
|
DELETE FROM workspaces;
|
||||||
|
DELETE FROM workflow_executions;
|
||||||
|
DELETE FROM cron_workflows;
|
||||||
|
DELETE FROM workspace_templates;
|
||||||
|
DELETE FROM workflow_templates;
|
||||||
|
DELETE FROM workspace_template_versions;
|
||||||
|
DELETE FROM workflow_template_versions;
|
||||||
|
`
|
||||||
|
|
||||||
|
_, err := database.Exec(query)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -36,20 +36,19 @@ func (c *Client) GetSystemConfig() (config SystemConfig, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace := "onepanel"
|
namespace := "onepanel"
|
||||||
configMap, err := c.getConfigMap(namespace, "onepanel")
|
name := "onepanel"
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
config = configMap.Data
|
|
||||||
|
|
||||||
secret, err := c.GetSecret(namespace, "onepanel")
|
configMap, err := c.getConfigMap(namespace, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
databaseUsername, _ := base64.StdEncoding.DecodeString(secret.Data["databaseUsername"])
|
|
||||||
config["databaseUsername"] = string(databaseUsername)
|
secret, err := c.GetSecret(namespace, name)
|
||||||
databasePassword, _ := base64.StdEncoding.DecodeString(secret.Data["databasePassword"])
|
if err != nil {
|
||||||
config["databasePassword"] = string(databasePassword)
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
config, err = NewSystemConfig(configMap, secret)
|
||||||
|
|
||||||
c.systemConfig = config
|
c.systemConfig = config
|
||||||
|
|
||||||
|
@@ -21,8 +21,9 @@ func testCreateNamespace(c *Client) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func TestListNamespace(t *testing.T) {
|
|
||||||
c := NewTestClient()
|
func TestClient_ListNamespace(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
|
||||||
testCreateNamespace(c)
|
testCreateNamespace(c)
|
||||||
|
|
||||||
|
@@ -6,8 +6,8 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCreateSecret(t *testing.T) {
|
func TestClient_CreateSecret(t *testing.T) {
|
||||||
c := NewTestClient()
|
c := DefaultTestClient()
|
||||||
|
|
||||||
err := c.CreateSecret("namespace", &Secret{
|
err := c.CreateSecret("namespace", &Secret{
|
||||||
Name: "name",
|
Name: "name",
|
||||||
@@ -15,8 +15,8 @@ func TestCreateSecret(t *testing.T) {
|
|||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetSecret(t *testing.T) {
|
func TestClient_GetSecret(t *testing.T) {
|
||||||
c := NewTestClient()
|
c := DefaultTestClient()
|
||||||
|
|
||||||
err := c.CreateSecret("namespace", &Secret{
|
err := c.CreateSecret("namespace", &Secret{
|
||||||
Name: "name",
|
Name: "name",
|
||||||
|
@@ -2,6 +2,7 @@ package v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -85,6 +86,18 @@ func UnmarshalWorkflows(wfBytes []byte, strict bool) (wfs []wfv1.Workflow, err e
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getWorkflowsFromWorkflowTemplate parses the WorkflowTemplate manifest and returns the argo workflows from it
|
||||||
|
func getWorkflowsFromWorkflowTemplate(wt *WorkflowTemplate) (wfs []wfv1.Workflow, err error) {
|
||||||
|
manifest, err := wt.GetWorkflowManifestBytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
wfs, err = UnmarshalWorkflows(manifest, true)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// appendArtifactRepositoryConfigIfMissing appends default artifact repository config to artifacts that have a key.
|
// appendArtifactRepositoryConfigIfMissing appends default artifact repository config to artifacts that have a key.
|
||||||
// Artifacts that contain anything other than key are skipped.
|
// Artifacts that contain anything other than key are skipped.
|
||||||
func injectArtifactRepositoryConfig(artifact *wfv1.Artifact, namespaceConfig *NamespaceConfig) {
|
func injectArtifactRepositoryConfig(artifact *wfv1.Artifact, namespaceConfig *NamespaceConfig) {
|
||||||
@@ -265,11 +278,19 @@ func (c *Client) injectAutomatedFields(namespace string, wf *wfv1.Workflow, opts
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArchiveWorkflowExecution marks a WorkflowExecution as archived in database
|
||||||
|
// and deletes the argo workflow.
|
||||||
|
//
|
||||||
|
// If the database record does not exist, we still try to delete the argo workflow record.
|
||||||
|
// No errors are returned if the records do not exist.
|
||||||
func (c *Client) ArchiveWorkflowExecution(namespace, uid string) error {
|
func (c *Client) ArchiveWorkflowExecution(namespace, uid string) error {
|
||||||
_, err := sb.Update("workflow_executions").Set("is_archived", true).Where(sq.Eq{
|
_, err := sb.Update("workflow_executions").
|
||||||
"uid": uid,
|
Set("is_archived", true).
|
||||||
"namespace": namespace,
|
Where(sq.Eq{
|
||||||
}).RunWith(c.DB).Exec()
|
"uid": uid,
|
||||||
|
"namespace": namespace,
|
||||||
|
}).RunWith(c.DB).
|
||||||
|
Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -285,11 +306,10 @@ func (c *Client) ArchiveWorkflowExecution(namespace, uid string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// createWorkflow creates the workflow in the database and argo.
|
||||||
Name is == to UID, no user friendly name.
|
// Name is == to UID, no user friendly name.
|
||||||
Workflow execution name == uid, example: name = my-friendly-wf-name-8skjz, uid = my-friendly-wf-name-8skjz
|
// Workflow execution name == uid, example: name = my-friendly-wf-name-8skjz, uid = my-friendly-wf-name-8skjz
|
||||||
*/
|
func (c *Client) createWorkflow(namespace string, workflowTemplateID uint64, workflowTemplateVersionID uint64, wf *wfv1.Workflow, opts *WorkflowExecutionOptions) (createdWorkflow *WorkflowExecution, err error) {
|
||||||
func (c *Client) createWorkflow(namespace string, workflowTemplateId uint64, workflowTemplateVersionId uint64, wf *wfv1.Workflow, opts *WorkflowExecutionOptions) (newDbId uint64, createdWorkflow *wfv1.Workflow, err error) {
|
|
||||||
if opts == nil {
|
if opts == nil {
|
||||||
opts = &WorkflowExecutionOptions{}
|
opts = &WorkflowExecutionOptions{}
|
||||||
}
|
}
|
||||||
@@ -330,34 +350,41 @@ func (c *Client) createWorkflow(namespace string, workflowTemplateId uint64, wor
|
|||||||
wf.ObjectMeta.Labels = opts.Labels
|
wf.ObjectMeta.Labels = opts.Labels
|
||||||
}
|
}
|
||||||
|
|
||||||
err = injectWorkflowExecutionStatusCaller(wf, wfv1.NodeRunning)
|
if err = injectWorkflowExecutionStatusCaller(wf, wfv1.NodeRunning); err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return 0, nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = injectExitHandlerWorkflowExecutionStatistic(wf, &workflowTemplateId)
|
if err = injectExitHandlerWorkflowExecutionStatistic(wf, &workflowTemplateID); err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return 0, nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = c.injectAutomatedFields(namespace, wf, opts); err != nil {
|
if err = c.injectAutomatedFields(namespace, wf, opts); err != nil {
|
||||||
return 0, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
createdWorkflow, err = c.ArgoprojV1alpha1().Workflows(namespace).Create(wf)
|
createdArgoWorkflow, err := c.ArgoprojV1alpha1().Workflows(namespace).Create(wf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
uid, err := uid2.GenerateUID(createdWorkflow.Name, 63)
|
createdWorkflow = &WorkflowExecution{
|
||||||
if err != nil {
|
Name: createdArgoWorkflow.Name,
|
||||||
return 0, nil, err
|
CreatedAt: createdArgoWorkflow.CreationTimestamp.UTC(),
|
||||||
|
ArgoWorkflow: createdArgoWorkflow,
|
||||||
|
WorkflowTemplate: &WorkflowTemplate{
|
||||||
|
WorkflowTemplateVersionID: workflowTemplateVersionID,
|
||||||
|
},
|
||||||
|
Parameters: opts.Parameters,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = createdWorkflow.GenerateUID(createdArgoWorkflow.Name); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
//Create an entry for workflow_executions statistic
|
//Create an entry for workflow_executions statistic
|
||||||
//CURL code will hit the API endpoint that will update the db row
|
//CURL code will hit the API endpoint that will update the db row
|
||||||
newDbId, err = c.insertPreWorkflowExecutionStatistic(namespace, createdWorkflow.Name, workflowTemplateVersionId, createdWorkflow.CreationTimestamp.UTC(), uid, opts.Parameters)
|
if err := c.createWorkflowExecutionDB(namespace, createdWorkflow); err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return 0, nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -376,7 +403,9 @@ func (c *Client) ValidateWorkflowExecution(namespace string, manifest []byte) (e
|
|||||||
|
|
||||||
wftmplGetter := templateresolution.WrapWorkflowTemplateInterface(c.ArgoprojV1alpha1().WorkflowTemplates(namespace))
|
wftmplGetter := templateresolution.WrapWorkflowTemplateInterface(c.ArgoprojV1alpha1().WorkflowTemplates(namespace))
|
||||||
for _, wf := range workflows {
|
for _, wf := range workflows {
|
||||||
c.injectAutomatedFields(namespace, &wf, &WorkflowExecutionOptions{})
|
if err = c.injectAutomatedFields(namespace, &wf, &WorkflowExecutionOptions{}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
_, err = validate.ValidateWorkflow(wftmplGetter, &wf, validate.ValidateOpts{})
|
_, err = validate.ValidateWorkflow(wftmplGetter, &wf, validate.ValidateOpts{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -398,16 +427,22 @@ func (c *Client) ValidateWorkflowExecution(namespace string, manifest []byte) (e
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateWorkflowExecution creates an argo workflow execution and related resources.
|
// CreateWorkflowExecution creates an argo workflow execution and related resources.
|
||||||
// Note that the workflow template is loaded from the database/k8s, so workflow.WorkflowTemplate.Manifest is not used.
|
// If workflow.Name is set, it is used instead of a generated name.
|
||||||
// Required:
|
// If there is a parameter named "workflow-execution-name" in workflow.Parameters, it is set as the name.
|
||||||
// * workflow.Parameters
|
|
||||||
// * workflow.Labels (optional)
|
|
||||||
func (c *Client) CreateWorkflowExecution(namespace string, workflow *WorkflowExecution, workflowTemplate *WorkflowTemplate) (*WorkflowExecution, error) {
|
func (c *Client) CreateWorkflowExecution(namespace string, workflow *WorkflowExecution, workflowTemplate *WorkflowTemplate) (*WorkflowExecution, error) {
|
||||||
opts := &WorkflowExecutionOptions{
|
opts := &WorkflowExecutionOptions{
|
||||||
Labels: make(map[string]string),
|
Labels: make(map[string]string),
|
||||||
Parameters: workflow.Parameters,
|
Parameters: workflow.Parameters,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if workflow.Name != "" {
|
||||||
|
opts.Name = workflow.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
if workflowExecutionName := workflow.GetParameterValue("workflow-execution-name"); workflowExecutionName != nil {
|
||||||
|
opts.Name = *workflowExecutionName
|
||||||
|
}
|
||||||
|
|
||||||
nameUID, err := uid2.GenerateUID(workflowTemplate.Name, 63)
|
nameUID, err := uid2.GenerateUID(workflowTemplate.Name, 63)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -418,19 +453,16 @@ func (c *Client) CreateWorkflowExecution(namespace string, workflow *WorkflowExe
|
|||||||
opts.Labels[workflowTemplateVersionLabelKey] = fmt.Sprint(workflowTemplate.Version)
|
opts.Labels[workflowTemplateVersionLabelKey] = fmt.Sprint(workflowTemplate.Version)
|
||||||
label.MergeLabelsPrefix(opts.Labels, workflow.Labels, label.TagPrefix)
|
label.MergeLabelsPrefix(opts.Labels, workflow.Labels, label.TagPrefix)
|
||||||
|
|
||||||
// @todo we need to enforce the below requirement in API.
|
workflows, err := getWorkflowsFromWorkflowTemplate(workflowTemplate)
|
||||||
//UX will prevent multiple workflows
|
|
||||||
manifest, err := workflowTemplate.GetWorkflowManifestBytes()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Namespace": namespace,
|
|
||||||
"WorkflowTemplate": workflowTemplate,
|
|
||||||
"Error": err.Error(),
|
|
||||||
}).Error("Error with getting WorkflowManifest from workflow template")
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
workflows, err := UnmarshalWorkflows(manifest, true)
|
if len(workflows) != 1 {
|
||||||
|
return nil, fmt.Errorf("workflow Template contained more than 1 workflow execution")
|
||||||
|
}
|
||||||
|
|
||||||
|
createdWorkflow, err := c.createWorkflow(namespace, workflowTemplate.ID, workflowTemplate.WorkflowTemplateVersionID, &workflows[0], opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"Namespace": namespace,
|
"Namespace": namespace,
|
||||||
@@ -440,35 +472,14 @@ func (c *Client) CreateWorkflowExecution(namespace string, workflow *WorkflowExe
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
id, createdWorkflow, err := c.createWorkflow(namespace, workflowTemplate.ID, workflowTemplate.WorkflowTemplateVersionID, &workflows[0], opts)
|
if _, err := c.InsertLabels(TypeWorkflowExecution, createdWorkflow.ID, workflow.Labels); err != nil {
|
||||||
if err != nil {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Namespace": namespace,
|
|
||||||
"Workflow": workflow,
|
|
||||||
"Error": err.Error(),
|
|
||||||
}).Error("Error parsing workflow.")
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := c.InsertLabels(TypeWorkflowExecution, id, workflow.Labels); err != nil {
|
workflow.ID = createdWorkflow.ID
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if createdWorkflow == nil {
|
|
||||||
err = errors.New("unable to create workflow")
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Namespace": namespace,
|
|
||||||
"WorkflowTemplate": workflowTemplate,
|
|
||||||
"Error": err.Error(),
|
|
||||||
}).Error("Error parsing workflow.")
|
|
||||||
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
workflow.ID = id
|
|
||||||
workflow.Name = createdWorkflow.Name
|
workflow.Name = createdWorkflow.Name
|
||||||
workflow.CreatedAt = createdWorkflow.CreationTimestamp.UTC()
|
workflow.CreatedAt = createdWorkflow.CreatedAt.UTC()
|
||||||
workflow.UID = createdWorkflow.Name
|
workflow.UID = createdWorkflow.UID
|
||||||
workflow.WorkflowTemplate = workflowTemplate
|
workflow.WorkflowTemplate = workflowTemplate
|
||||||
|
|
||||||
return workflow, nil
|
return workflow, nil
|
||||||
@@ -494,44 +505,41 @@ func (c *Client) CloneWorkflowExecution(namespace, uid string) (*WorkflowExecuti
|
|||||||
return c.CreateWorkflowExecution(namespace, workflowExecution, workflowTemplate)
|
return c.CreateWorkflowExecution(namespace, workflowExecution, workflowTemplate)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) insertPreWorkflowExecutionStatistic(namespace, name string, workflowTemplateVersionId uint64, createdAt time.Time, uid string, parameters []Parameter) (newId uint64, err error) {
|
// createWorkflowExecutionDB inserts a workflow execution into the database.
|
||||||
tx, err := c.DB.Begin()
|
// Required fields
|
||||||
|
// * name
|
||||||
|
// * createdAt // we sync the argo created at with the db
|
||||||
|
// * parameters, if any
|
||||||
|
// * WorkflowTemplate.WorkflowTemplateVersionID
|
||||||
|
//
|
||||||
|
// After success, the passed in WorkflowExecution will have it's ID set to the new db record.
|
||||||
|
func (c *Client) createWorkflowExecutionDB(namespace string, workflowExecution *WorkflowExecution) (err error) {
|
||||||
|
parametersJSON, err := json.Marshal(workflowExecution.Parameters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return err
|
||||||
}
|
|
||||||
defer tx.Rollback()
|
|
||||||
|
|
||||||
parametersJSON, err := json.Marshal(parameters)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
insertMap := sq.Eq{
|
if err := workflowExecution.GenerateUID(workflowExecution.Name); err != nil {
|
||||||
"uid": uid,
|
return err
|
||||||
"workflow_template_version_id": workflowTemplateVersionId,
|
|
||||||
"name": name,
|
|
||||||
"namespace": namespace,
|
|
||||||
"created_at": createdAt.UTC(),
|
|
||||||
"phase": wfv1.NodePending,
|
|
||||||
"parameters": string(parametersJSON),
|
|
||||||
"is_archived": false,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = sb.Insert("workflow_executions").
|
err = sb.Insert("workflow_executions").
|
||||||
SetMap(insertMap).
|
SetMap(sq.Eq{
|
||||||
|
"UID": workflowExecution.UID,
|
||||||
|
"workflow_template_version_id": workflowExecution.WorkflowTemplate.WorkflowTemplateVersionID,
|
||||||
|
"name": workflowExecution.Name,
|
||||||
|
"namespace": namespace,
|
||||||
|
"created_at": workflowExecution.CreatedAt.UTC(),
|
||||||
|
"phase": wfv1.NodePending,
|
||||||
|
"parameters": string(parametersJSON),
|
||||||
|
"is_archived": false,
|
||||||
|
}).
|
||||||
Suffix("RETURNING id").
|
Suffix("RETURNING id").
|
||||||
RunWith(tx).
|
RunWith(c.DB).
|
||||||
QueryRow().
|
QueryRow().
|
||||||
Scan(&newId)
|
Scan(&workflowExecution.ID)
|
||||||
|
|
||||||
if err != nil {
|
return
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
err = tx.Commit()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return newId, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) FinishWorkflowExecutionStatisticViaExitHandler(namespace, name string, workflowTemplateID int64, phase wfv1.NodePhase, startedAt time.Time) (err error) {
|
func (c *Client) FinishWorkflowExecutionStatisticViaExitHandler(namespace, name string, workflowTemplateID int64, phase wfv1.NodePhase, startedAt time.Time) (err error) {
|
||||||
@@ -562,32 +570,20 @@ func (c *Client) FinishWorkflowExecutionStatisticViaExitHandler(namespace, name
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) CronStartWorkflowExecutionStatisticInsert(namespace, uid string, workflowTemplateID int64) (err error) {
|
func (c *Client) CronStartWorkflowExecutionStatisticInsert(namespace, uid string, workflowTemplateID int64) (err error) {
|
||||||
query, args, err := c.workflowTemplatesSelectBuilder(namespace).
|
queryWt := c.workflowTemplatesSelectBuilder(namespace).
|
||||||
Where(sq.Eq{
|
Where(sq.Eq{
|
||||||
"wt.id": workflowTemplateID,
|
"wt.id": workflowTemplateID,
|
||||||
}).
|
})
|
||||||
ToSql()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
workflowTemplate := &WorkflowTemplate{}
|
workflowTemplate := &WorkflowTemplate{}
|
||||||
if err := c.DB.Get(workflowTemplate, query, args...); err != nil {
|
if err := c.DB.Getx(workflowTemplate, queryWt); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
query, args, err = c.cronWorkflowSelectBuilder(namespace, workflowTemplate.UID).ToSql()
|
queryCw := c.cronWorkflowSelectBuilder(namespace, workflowTemplate.UID)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
cronWorkflow := &CronWorkflow{}
|
cronWorkflow := &CronWorkflow{}
|
||||||
if err := c.DB.Get(cronWorkflow, query, args...); err != nil {
|
if err := c.DB.Getx(cronWorkflow, queryCw); err != nil {
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
cronLabels, err := c.GetDbLabels(TypeCronWorkflow, cronWorkflow.ID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -602,49 +598,43 @@ func (c *Client) CronStartWorkflowExecutionStatisticInsert(namespace, uid string
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
insertMap := sq.Eq{
|
workflowExecutionID := uint64(0)
|
||||||
"uid": uid,
|
|
||||||
"workflow_template_version_id": cronWorkflow.WorkflowTemplateVersionID,
|
|
||||||
"name": uid,
|
|
||||||
"namespace": namespace,
|
|
||||||
"phase": wfv1.NodeRunning,
|
|
||||||
"started_at": time.Now().UTC(),
|
|
||||||
"cron_workflow_id": cronWorkflow.ID,
|
|
||||||
"parameters": string(parametersJSON),
|
|
||||||
}
|
|
||||||
|
|
||||||
workflowExecutionId := uint64(0)
|
|
||||||
err = sb.Insert("workflow_executions").
|
err = sb.Insert("workflow_executions").
|
||||||
SetMap(insertMap).
|
SetMap(sq.Eq{
|
||||||
|
"uid": uid,
|
||||||
|
"workflow_template_version_id": cronWorkflow.WorkflowTemplateVersionID,
|
||||||
|
"name": uid,
|
||||||
|
"namespace": namespace,
|
||||||
|
"phase": wfv1.NodeRunning,
|
||||||
|
"started_at": time.Now().UTC(),
|
||||||
|
"cron_workflow_id": cronWorkflow.ID,
|
||||||
|
"parameters": string(parametersJSON),
|
||||||
|
}).
|
||||||
Suffix("RETURNING id").
|
Suffix("RETURNING id").
|
||||||
RunWith(tx).
|
RunWith(tx).
|
||||||
QueryRow().
|
QueryRow().
|
||||||
Scan(&workflowExecutionId)
|
Scan(&workflowExecutionID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(cronLabels) > 0 {
|
cronLabels, err := c.GetDBLabelsMapped(TypeCronWorkflow, cronWorkflow.ID)
|
||||||
labelsMapped := LabelsToMapping(cronLabels...)
|
if err != nil {
|
||||||
_, err = c.InsertLabelsBuilder(TypeWorkflowExecution, workflowExecutionId, labelsMapped).
|
return err
|
||||||
RunWith(tx).
|
}
|
||||||
Exec()
|
labelsMapped := cronLabels[cronWorkflow.ID]
|
||||||
if err != nil {
|
if _, err := c.InsertLabelsRunner(tx, TypeWorkflowExecution, workflowExecutionID, labelsMapped); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = tx.Commit()
|
err = tx.Commit()
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetWorkflowExecution(namespace, uid string) (workflow *WorkflowExecution, err error) {
|
func (c *Client) GetWorkflowExecution(namespace, uid string) (workflow *WorkflowExecution, err error) {
|
||||||
workflow = &WorkflowExecution{}
|
workflow = &WorkflowExecution{}
|
||||||
|
query := sb.Select(getWorkflowExecutionColumns("we")...).
|
||||||
query, args, err := sb.Select(getWorkflowExecutionColumns("we", "")...).
|
|
||||||
Columns(getWorkflowTemplateColumns("wt", "workflow_template")...).
|
Columns(getWorkflowTemplateColumns("wt", "workflow_template")...).
|
||||||
Columns(`wtv.manifest "workflow_template.manifest"`).
|
Columns(`wtv.manifest "workflow_template.manifest"`).
|
||||||
From("workflow_executions we").
|
From("workflow_executions we").
|
||||||
@@ -654,12 +644,13 @@ func (c *Client) GetWorkflowExecution(namespace, uid string) (workflow *Workflow
|
|||||||
"wt.namespace": namespace,
|
"wt.namespace": namespace,
|
||||||
"we.name": uid,
|
"we.name": uid,
|
||||||
"we.is_archived": false,
|
"we.is_archived": false,
|
||||||
}).
|
})
|
||||||
ToSql()
|
|
||||||
if err != nil {
|
if err := c.DB.Getx(workflow, query); err != nil {
|
||||||
return nil, err
|
if err == sql.ErrNoRows {
|
||||||
}
|
return nil, nil
|
||||||
if err := c.DB.Get(workflow, query, args...); err != nil {
|
}
|
||||||
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,7 +668,7 @@ func (c *Client) GetWorkflowExecution(namespace, uid string) (workflow *Workflow
|
|||||||
version, err := strconv.ParseInt(
|
version, err := strconv.ParseInt(
|
||||||
wf.ObjectMeta.Labels[workflowTemplateVersionLabelKey],
|
wf.ObjectMeta.Labels[workflowTemplateVersionLabelKey],
|
||||||
10,
|
10,
|
||||||
32,
|
64,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
@@ -713,6 +704,7 @@ func (c *Client) GetWorkflowExecution(namespace, uid string) (workflow *Workflow
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListWorkflowExecutions gets a list of WorkflowExecutions ordered by most recently created first.
|
||||||
func (c *Client) ListWorkflowExecutions(namespace, workflowTemplateUID, workflowTemplateVersion string, paginator *pagination.PaginationRequest) (workflows []*WorkflowExecution, err error) {
|
func (c *Client) ListWorkflowExecutions(namespace, workflowTemplateUID, workflowTemplateVersion string, paginator *pagination.PaginationRequest) (workflows []*WorkflowExecution, err error) {
|
||||||
sb := workflowExecutionsSelectBuilder(namespace, workflowTemplateUID, workflowTemplateVersion).
|
sb := workflowExecutionsSelectBuilder(namespace, workflowTemplateUID, workflowTemplateVersion).
|
||||||
OrderBy("we.created_at DESC")
|
OrderBy("we.created_at DESC")
|
||||||
@@ -725,10 +717,11 @@ func (c *Client) ListWorkflowExecutions(namespace, workflowTemplateUID, workflow
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CountWorkflowExecutions returns the number of workflow executions
|
||||||
func (c *Client) CountWorkflowExecutions(namespace, workflowTemplateUID, workflowTemplateVersion string) (count int, err error) {
|
func (c *Client) CountWorkflowExecutions(namespace, workflowTemplateUID, workflowTemplateVersion string) (count int, err error) {
|
||||||
err = workflowExecutionsSelectBuilderNoColumns(namespace, workflowTemplateUID, workflowTemplateVersion).
|
err = workflowExecutionsSelectBuilderNoColumns(namespace, workflowTemplateUID, workflowTemplateVersion).
|
||||||
Columns("COUNT(*)").
|
Columns("COUNT(*)").
|
||||||
RunWith(c.DB.DB).
|
RunWith(c.DB).
|
||||||
QueryRow().
|
QueryRow().
|
||||||
Scan(&count)
|
Scan(&count)
|
||||||
|
|
||||||
@@ -1069,8 +1062,9 @@ func (c *Client) SuspendWorkflowExecution(namespace, uid string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TerminateWorkflowExecution marks a workflows execution as terminated in DB and terminates the argo resource.
|
||||||
func (c *Client) TerminateWorkflowExecution(namespace, uid string) (err error) {
|
func (c *Client) TerminateWorkflowExecution(namespace, uid string) (err error) {
|
||||||
query, args, err := sb.Update("workflow_executions").
|
_, err = sb.Update("workflow_executions").
|
||||||
Set("phase", "Terminated").
|
Set("phase", "Terminated").
|
||||||
Set("started_at", time.Time.UTC(time.Now())).
|
Set("started_at", time.Time.UTC(time.Now())).
|
||||||
Set("finished_at", time.Time.UTC(time.Now())).
|
Set("finished_at", time.Time.UTC(time.Now())).
|
||||||
@@ -1078,16 +1072,12 @@ func (c *Client) TerminateWorkflowExecution(namespace, uid string) (err error) {
|
|||||||
"uid": uid,
|
"uid": uid,
|
||||||
"namespace": namespace,
|
"namespace": namespace,
|
||||||
}).
|
}).
|
||||||
ToSql()
|
RunWith(c.DB).
|
||||||
|
Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := c.DB.Exec(query, args...); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = argoutil.TerminateWorkflow(c.ArgoprojV1alpha1().Workflows(namespace), uid)
|
err = argoutil.TerminateWorkflow(c.ArgoprojV1alpha1().Workflows(namespace), uid)
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -1605,7 +1595,7 @@ func workflowExecutionsSelectBuilder(namespace, workflowTemplateUID, workflowTem
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) getWorkflowExecutionAndTemplate(namespace string, uid string) (workflow *WorkflowExecution, err error) {
|
func (c *Client) getWorkflowExecutionAndTemplate(namespace string, uid string) (workflow *WorkflowExecution, err error) {
|
||||||
query, args, err := sb.Select(getWorkflowExecutionColumns("we", "")...).
|
sb := sb.Select(getWorkflowExecutionColumns("we", "")...).
|
||||||
Columns(getWorkflowTemplateColumns("wt", "workflow_template")...).
|
Columns(getWorkflowTemplateColumns("wt", "workflow_template")...).
|
||||||
Columns(`wtv.manifest "workflow_template.manifest"`, `wtv.version "workflow_template.version"`).
|
Columns(`wtv.manifest "workflow_template.manifest"`, `wtv.version "workflow_template.version"`).
|
||||||
From("workflow_executions we").
|
From("workflow_executions we").
|
||||||
@@ -1615,16 +1605,10 @@ func (c *Client) getWorkflowExecutionAndTemplate(namespace string, uid string) (
|
|||||||
"wt.namespace": namespace,
|
"wt.namespace": namespace,
|
||||||
"we.name": uid,
|
"we.name": uid,
|
||||||
"we.is_archived": false,
|
"we.is_archived": false,
|
||||||
}).
|
})
|
||||||
ToSql()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO DB call
|
|
||||||
|
|
||||||
workflow = &WorkflowExecution{}
|
workflow = &WorkflowExecution{}
|
||||||
if err = c.DB.Get(workflow, query, args...); err != nil {
|
if err = c.DB.Getx(workflow, sb); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
99
pkg/workflow_execution_test.go
Normal file
99
pkg/workflow_execution_test.go
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestClient_CreateWorkflowExecution tests creating a workflow execution
|
||||||
|
func TestClient_CreateWorkflowExecution(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
|
||||||
|
wt := &WorkflowTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: defaultWorkflowTemplate,
|
||||||
|
}
|
||||||
|
wt, _ = c.CreateWorkflowTemplate(namespace, wt)
|
||||||
|
|
||||||
|
we := &WorkflowExecution{
|
||||||
|
Name: "test",
|
||||||
|
}
|
||||||
|
|
||||||
|
we, err := c.CreateWorkflowExecution(namespace, we, wt)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestClient_GetWorkflowExecution tests getting a workflow execution that exists
|
||||||
|
func TestClient_GetWorkflowExecution(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
|
||||||
|
wt := &WorkflowTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: defaultWorkflowTemplate,
|
||||||
|
}
|
||||||
|
wt, _ = c.CreateWorkflowTemplate(namespace, wt)
|
||||||
|
|
||||||
|
we := &WorkflowExecution{
|
||||||
|
Name: "test",
|
||||||
|
}
|
||||||
|
|
||||||
|
we, _ = c.CreateWorkflowExecution(namespace, we, wt)
|
||||||
|
|
||||||
|
getWe, err := c.GetWorkflowExecution(namespace, we.UID)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, we.Name, getWe.Name)
|
||||||
|
assert.Equal(t, we.UID, getWe.UID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestClient_GetWorkflowExecution tests getting a workflow execution that doesn't exist
|
||||||
|
func TestClient_GetWorkflowExecution_NotExists(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
|
||||||
|
getWe, err := c.GetWorkflowExecution(namespace, "not-exist")
|
||||||
|
assert.Nil(t, getWe)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestClient_ArchiveWorkflowExecution_NotExist makes sure there is no error if the workflow
|
||||||
|
// execution does not exist
|
||||||
|
func TestClient_ArchiveWorkflowExecution_NotExist(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
err := c.ArchiveWorkflowExecution("onepanel-no-exist", "test-no-exist")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestClient_ArchiveWorkflowExecution_Exist makes sure we archive an existing workflow execution correctly
|
||||||
|
func TestClient_ArchiveWorkflowExecution_Exist(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
weName := "test"
|
||||||
|
|
||||||
|
wt := &WorkflowTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: defaultWorkflowTemplate,
|
||||||
|
}
|
||||||
|
wt, _ = c.CreateWorkflowTemplate(namespace, wt)
|
||||||
|
|
||||||
|
we := &WorkflowExecution{
|
||||||
|
Name: weName,
|
||||||
|
}
|
||||||
|
|
||||||
|
we, err := c.CreateWorkflowExecution(namespace, we, wt)
|
||||||
|
|
||||||
|
err = c.ArchiveWorkflowExecution(namespace, weName)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
@@ -3,6 +3,7 @@ package v1
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1"
|
wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1"
|
||||||
|
uid2 "github.com/onepanelio/core/pkg/util/uid"
|
||||||
"github.com/onepanelio/core/util/sql"
|
"github.com/onepanelio/core/util/sql"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -22,6 +23,7 @@ type WorkflowExecution struct {
|
|||||||
FinishedAt *time.Time `db:"finished_at"`
|
FinishedAt *time.Time `db:"finished_at"`
|
||||||
WorkflowTemplate *WorkflowTemplate `db:"workflow_template"`
|
WorkflowTemplate *WorkflowTemplate `db:"workflow_template"`
|
||||||
Labels map[string]string
|
Labels map[string]string
|
||||||
|
ArgoWorkflow *wfv1.Workflow
|
||||||
}
|
}
|
||||||
|
|
||||||
// WorkflowExecutionOptions are options you have for an executing workflow
|
// WorkflowExecutionOptions are options you have for an executing workflow
|
||||||
@@ -55,6 +57,18 @@ type WorkflowExecutionStatus struct {
|
|||||||
FinishedAt *time.Time `db:"finished_at" json:"finishedAt"`
|
FinishedAt *time.Time `db:"finished_at" json:"finishedAt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateUID generates a uid from the input name and sets it on the workflow execution
|
||||||
|
func (we *WorkflowExecution) GenerateUID(name string) error {
|
||||||
|
result, err := uid2.GenerateUID(name, 63)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
we.UID = result
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// LoadParametersFromBytes loads Parameters from the WorkflowExecution's ParameterBytes field.
|
// LoadParametersFromBytes loads Parameters from the WorkflowExecution's ParameterBytes field.
|
||||||
func (we *WorkflowExecution) LoadParametersFromBytes() ([]Parameter, error) {
|
func (we *WorkflowExecution) LoadParametersFromBytes() ([]Parameter, error) {
|
||||||
loadedParameters := make([]Parameter, 0)
|
loadedParameters := make([]Parameter, 0)
|
||||||
@@ -75,6 +89,17 @@ func (we *WorkflowExecution) LoadParametersFromBytes() ([]Parameter, error) {
|
|||||||
return we.Parameters, err
|
return we.Parameters, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetParameterValue returns the value of the parameter with the given name, or nil if there is no such parameter
|
||||||
|
func (we *WorkflowExecution) GetParameterValue(name string) *string {
|
||||||
|
for _, p := range we.Parameters {
|
||||||
|
if p.Name == name {
|
||||||
|
return p.Value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// getWorkflowExecutionColumns returns all of the columns for workflowExecution modified by alias, destination.
|
// getWorkflowExecutionColumns returns all of the columns for workflowExecution modified by alias, destination.
|
||||||
// see formatColumnSelect
|
// see formatColumnSelect
|
||||||
func getWorkflowExecutionColumns(aliasAndDestination ...string) []string {
|
func getWorkflowExecutionColumns(aliasAndDestination ...string) []string {
|
||||||
|
@@ -5,7 +5,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/onepanelio/core/pkg/util/pagination"
|
"github.com/onepanelio/core/pkg/util/pagination"
|
||||||
uid2 "github.com/onepanelio/core/pkg/util/uid"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -21,23 +20,67 @@ import (
|
|||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Client) createWorkflowTemplate(namespace string, workflowTemplate *WorkflowTemplate) (*WorkflowTemplate, *WorkflowTemplateVersion, error) {
|
// createWorkflowTemplateVersionDB inserts a record into workflow_template_versions using the current time accurate to nanoseconds
|
||||||
uid, err := uid2.GenerateUID(workflowTemplate.Name, 30)
|
// the data is returned in the resulting WorkflowTemplateVersion struct.
|
||||||
|
func createWorkflowTemplateVersionDB(runner sq.BaseRunner, workflowTemplateID uint64, manifest string, latest bool) (workflowTemplateVersion *WorkflowTemplateVersion, err error) {
|
||||||
|
ts := time.Now().UnixNano()
|
||||||
|
|
||||||
|
workflowTemplateVersion = &WorkflowTemplateVersion{
|
||||||
|
WorkflowTemplate: &WorkflowTemplate{
|
||||||
|
ID: workflowTemplateID,
|
||||||
|
},
|
||||||
|
Manifest: manifest,
|
||||||
|
IsLatest: latest,
|
||||||
|
Version: ts,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sb.Insert("workflow_template_versions").
|
||||||
|
SetMap(sq.Eq{
|
||||||
|
"workflow_template_id": workflowTemplateID,
|
||||||
|
"version": ts,
|
||||||
|
"is_latest": true,
|
||||||
|
"manifest": manifest,
|
||||||
|
}).
|
||||||
|
Suffix("RETURNING id").
|
||||||
|
RunWith(runner).
|
||||||
|
QueryRow().
|
||||||
|
Scan(&workflowTemplateVersion.ID)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// createLatestWorkflowTemplateVersionDB creates a new workflow template version and marks all previous versions as not latest.
|
||||||
|
func createLatestWorkflowTemplateVersionDB(runner sq.BaseRunner, workflowTemplateID uint64, manifest string) (workflowTemplateVersion *WorkflowTemplateVersion, err error) {
|
||||||
|
_, err = sb.Update("workflow_template_versions").
|
||||||
|
Set("is_latest", false).
|
||||||
|
Where(sq.Eq{
|
||||||
|
"workflow_template_id": workflowTemplateID,
|
||||||
|
}).
|
||||||
|
RunWith(runner).
|
||||||
|
Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return createWorkflowTemplateVersionDB(runner, workflowTemplateID, manifest, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// createWorkflowTemplate creates a WorkflowTemplate and all of the DB/Argo/K8s related resources
|
||||||
|
// The returned WorkflowTemplate has the ArgoWorkflowTemplate set to the newly created one.
|
||||||
|
func (c *Client) createWorkflowTemplate(namespace string, workflowTemplate *WorkflowTemplate) (*WorkflowTemplate, *WorkflowTemplateVersion, error) {
|
||||||
|
if err := workflowTemplate.GenerateUID(workflowTemplate.Name); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
workflowTemplate.UID = uid
|
|
||||||
tx, err := c.DB.Begin()
|
tx, err := c.DB.Begin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
defer tx.Rollback()
|
defer tx.Rollback()
|
||||||
|
|
||||||
versionUnix := time.Now().Unix()
|
|
||||||
|
|
||||||
err = sb.Insert("workflow_templates").
|
err = sb.Insert("workflow_templates").
|
||||||
SetMap(sq.Eq{
|
SetMap(sq.Eq{
|
||||||
"uid": uid,
|
"uid": workflowTemplate.UID,
|
||||||
"name": workflowTemplate.Name,
|
"name": workflowTemplate.Name,
|
||||||
"namespace": namespace,
|
"namespace": namespace,
|
||||||
"is_system": workflowTemplate.IsSystem,
|
"is_system": workflowTemplate.IsSystem,
|
||||||
@@ -50,33 +93,22 @@ func (c *Client) createWorkflowTemplate(namespace string, workflowTemplate *Work
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
workflowTemplateVersion := &WorkflowTemplateVersion{}
|
workflowTemplateVersion, err := createWorkflowTemplateVersionDB(tx, workflowTemplate.ID, workflowTemplate.Manifest, true)
|
||||||
err = sb.Insert("workflow_template_versions").
|
|
||||||
SetMap(sq.Eq{
|
|
||||||
"workflow_template_id": workflowTemplate.ID,
|
|
||||||
"version": versionUnix,
|
|
||||||
"is_latest": true,
|
|
||||||
"manifest": workflowTemplate.Manifest,
|
|
||||||
}).
|
|
||||||
Suffix("RETURNING id").
|
|
||||||
RunWith(tx).
|
|
||||||
QueryRow().
|
|
||||||
Scan(&workflowTemplateVersion.ID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
workflowTemplate.WorkflowTemplateVersionID = workflowTemplateVersion.ID
|
||||||
|
|
||||||
_, err = c.InsertLabelsRunner(tx, TypeWorkflowTemplateVersion, workflowTemplateVersion.ID, workflowTemplate.Labels)
|
_, err = c.InsertLabelsRunner(tx, TypeWorkflowTemplateVersion, workflowTemplateVersion.ID, workflowTemplate.Labels)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
argoWft, err := createArgoWorkflowTemplate(workflowTemplate, versionUnix)
|
argoWft, err := createArgoWorkflowTemplate(workflowTemplate, workflowTemplateVersion.Version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
argoWft.Labels[label.WorkflowTemplateVersionUid] = strconv.FormatInt(workflowTemplateVersion.Version, 10)
|
||||||
argoWft.Labels[label.WorkflowTemplateVersionUid] = strconv.FormatInt(versionUnix, 10)
|
|
||||||
|
|
||||||
if workflowTemplate.Resource != nil && workflowTemplate.ResourceUID != nil {
|
if workflowTemplate.Resource != nil && workflowTemplate.ResourceUID != nil {
|
||||||
if *workflowTemplate.Resource == TypeWorkspaceTemplate {
|
if *workflowTemplate.Resource == TypeWorkspaceTemplate {
|
||||||
@@ -96,7 +128,8 @@ func (c *Client) createWorkflowTemplate(namespace string, workflowTemplate *Work
|
|||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
workflowTemplate.Version = versionUnix
|
workflowTemplate.ArgoWorkflowTemplate = argoWft
|
||||||
|
workflowTemplate.Version = workflowTemplateVersion.Version
|
||||||
|
|
||||||
return workflowTemplate, workflowTemplateVersion, nil
|
return workflowTemplate, workflowTemplateVersion, nil
|
||||||
}
|
}
|
||||||
@@ -131,6 +164,8 @@ func (c *Client) countWorkflowTemplateSelectBuilder(namespace string) sq.SelectB
|
|||||||
return sb
|
return sb
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// workflowTemplatesVersionSelectBuilder selects data from workflow template versions joined to a workflow template
|
||||||
|
// the versions/template are filtered by the workflow template's namespace.
|
||||||
func (c *Client) workflowTemplatesVersionSelectBuilder(namespace string) sq.SelectBuilder {
|
func (c *Client) workflowTemplatesVersionSelectBuilder(namespace string) sq.SelectBuilder {
|
||||||
sb := sb.Select(getWorkflowTemplateVersionColumns("wtv")...).
|
sb := sb.Select(getWorkflowTemplateVersionColumns("wtv")...).
|
||||||
From("workflow_template_versions wtv").
|
From("workflow_template_versions wtv").
|
||||||
@@ -142,11 +177,14 @@ func (c *Client) workflowTemplatesVersionSelectBuilder(namespace string) sq.Sele
|
|||||||
return sb
|
return sb
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWorkflowTemplateDB returns a WorkflowTemplate from the database
|
// GetWorkflowTemplateDB returns a WorkflowTemplate from the database that is not archived, should one exist.
|
||||||
func (c *Client) GetWorkflowTemplateDB(namespace, name string) (workflowTemplate *WorkflowTemplate, err error) {
|
func (c *Client) getWorkflowTemplateDB(namespace, name string) (workflowTemplate *WorkflowTemplate, err error) {
|
||||||
|
workflowTemplate = &WorkflowTemplate{}
|
||||||
|
|
||||||
sb := c.workflowTemplatesSelectBuilder(namespace).
|
sb := c.workflowTemplatesSelectBuilder(namespace).
|
||||||
Where(sq.Eq{
|
Where(sq.Eq{
|
||||||
"name": name,
|
"wt.name": name,
|
||||||
|
"wt.is_archived": false,
|
||||||
})
|
})
|
||||||
|
|
||||||
err = c.DB.Getx(workflowTemplate, sb)
|
err = c.DB.Getx(workflowTemplate, sb)
|
||||||
@@ -154,9 +192,11 @@ func (c *Client) GetWorkflowTemplateDB(namespace, name string) (workflowTemplate
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWorkflowTemplateVersionDB will return a WorkflowTemplateVersion given the arguments.
|
// getWorkflowTemplateVersionDB will return a WorkflowTemplateVersion given the arguments.
|
||||||
// version can be a number as a string, or the string "latest" to get the latest.
|
// version can be a number as a string, or the string "latest" to get the latest.
|
||||||
func (c *Client) GetWorkflowTemplateVersionDB(namespace, name, version string) (workflowTemplateVersion *WorkflowTemplateVersion, err error) {
|
func (c *Client) getWorkflowTemplateVersionDB(namespace, name, version string) (workflowTemplateVersion *WorkflowTemplateVersion, err error) {
|
||||||
|
workflowTemplateVersion = &WorkflowTemplateVersion{}
|
||||||
|
|
||||||
whereMap := sq.Eq{
|
whereMap := sq.Eq{
|
||||||
"wt.name": name,
|
"wt.name": name,
|
||||||
}
|
}
|
||||||
@@ -176,8 +216,8 @@ func (c *Client) GetWorkflowTemplateVersionDB(namespace, name, version string) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetLatestWorkflowTemplateVersionDB returns the latest WorkflowTemplateVersion
|
// GetLatestWorkflowTemplateVersionDB returns the latest WorkflowTemplateVersion
|
||||||
func (c *Client) GetLatestWorkflowTemplateVersionDB(namespace, name string) (workflowTemplateVersion *WorkflowTemplateVersion, err error) {
|
func (c *Client) getLatestWorkflowTemplateVersionDB(namespace, name string) (workflowTemplateVersion *WorkflowTemplateVersion, err error) {
|
||||||
return c.GetWorkflowTemplateVersionDB(namespace, name, "latest")
|
return c.getWorkflowTemplateVersionDB(namespace, name, "latest")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) getWorkflowTemplateById(id uint64) (workflowTemplate *WorkflowTemplate, err error) {
|
func (c *Client) getWorkflowTemplateById(id uint64) (workflowTemplate *WorkflowTemplate, err error) {
|
||||||
@@ -197,13 +237,16 @@ func (c *Client) getWorkflowTemplateById(id uint64) (workflowTemplate *WorkflowT
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// If version is 0, the latest workflow template is fetched.
|
// getWorkflowTemplate gets the workflowtemplate given the input data.
|
||||||
|
// it also loads the argo workflow and labels data.
|
||||||
|
// If version is <= 0, the latest workflow template is fetched.
|
||||||
|
// If not found, (nil, nil) is returned
|
||||||
func (c *Client) getWorkflowTemplate(namespace, uid string, version int64) (workflowTemplate *WorkflowTemplate, err error) {
|
func (c *Client) getWorkflowTemplate(namespace, uid string, version int64) (workflowTemplate *WorkflowTemplate, err error) {
|
||||||
workflowTemplate = &WorkflowTemplate{
|
workflowTemplate = &WorkflowTemplate{
|
||||||
WorkflowExecutionStatisticReport: &WorkflowExecutionStatisticReport{},
|
WorkflowExecutionStatisticReport: &WorkflowExecutionStatisticReport{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// A new workflow template version is created upon a change, so we use it's createdAt
|
// A new workflow template version is created upon a change, so we use it's created_at
|
||||||
// as a modified_at for the workflow template.
|
// as a modified_at for the workflow template.
|
||||||
sb := c.workflowTemplatesSelectBuilder(namespace).
|
sb := c.workflowTemplatesSelectBuilder(namespace).
|
||||||
Columns("wtv.manifest", "wtv.version", "wtv.id workflow_template_version_id", "wtv.created_at modified_at").
|
Columns("wtv.manifest", "wtv.version", "wtv.id workflow_template_version_id", "wtv.created_at modified_at").
|
||||||
@@ -213,7 +256,7 @@ func (c *Client) getWorkflowTemplate(namespace, uid string, version int64) (work
|
|||||||
"wt.is_archived": false,
|
"wt.is_archived": false,
|
||||||
})
|
})
|
||||||
|
|
||||||
if version == 0 {
|
if version <= 0 {
|
||||||
sb = sb.Where(sq.Eq{"wtv.is_latest": true})
|
sb = sb.Where(sq.Eq{"wtv.is_latest": true})
|
||||||
} else {
|
} else {
|
||||||
sb = sb.Where(sq.Eq{"wtv.version": version})
|
sb = sb.Where(sq.Eq{"wtv.version": version})
|
||||||
@@ -256,7 +299,7 @@ func (c *Client) getWorkflowTemplate(namespace, uid string, version int64) (work
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) listWorkflowTemplateVersions(namespace, uid string) (workflowTemplateVersions []*WorkflowTemplate, err error) {
|
func (c *Client) listWorkflowTemplateVersions(namespace, uid string) (workflowTemplateVersions []*WorkflowTemplate, err error) {
|
||||||
dbVersions, err := c.listDBWorkflowTemplateVersions(namespace, uid)
|
dbVersions, err := c.selectWorkflowTemplateVersionsDB(namespace, uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -291,8 +334,10 @@ func (c *Client) listWorkflowTemplateVersions(namespace, uid string) (workflowTe
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) listWorkflowTemplates(namespace string, paginator *pagination.PaginationRequest) (workflowTemplateVersions []*WorkflowTemplate, err error) {
|
// selectWorkflowTemplatesDB loads workflow templates from the database for the input namespace
|
||||||
workflowTemplateVersions = []*WorkflowTemplate{}
|
// it also selects the total number of versions and latest version id
|
||||||
|
func (c *Client) selectWorkflowTemplatesDB(namespace string, paginator *pagination.PaginationRequest) (workflowTemplates []*WorkflowTemplate, err error) {
|
||||||
|
workflowTemplates = make([]*WorkflowTemplate, 0)
|
||||||
|
|
||||||
sb := c.workflowTemplatesSelectBuilder(namespace).
|
sb := c.workflowTemplatesSelectBuilder(namespace).
|
||||||
Column("COUNT(wtv.*) versions, MAX(wtv.id) workflow_template_version_id").
|
Column("COUNT(wtv.*) versions, MAX(wtv.id) workflow_template_version_id").
|
||||||
@@ -303,28 +348,24 @@ func (c *Client) listWorkflowTemplates(namespace string, paginator *pagination.P
|
|||||||
"wt.is_system": false,
|
"wt.is_system": false,
|
||||||
}).
|
}).
|
||||||
OrderBy("wt.created_at DESC")
|
OrderBy("wt.created_at DESC")
|
||||||
|
|
||||||
sb = *paginator.ApplyToSelect(&sb)
|
sb = *paginator.ApplyToSelect(&sb)
|
||||||
query, args, err := sb.ToSql()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = c.DB.Select(&workflowTemplateVersions, query, args...)
|
err = c.DB.Selectx(&workflowTemplates, sb)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CountWorkflowTemplates counts the total number of workflow templates for the given namespace
|
||||||
|
// archived, and system templates are ignored.
|
||||||
func (c *Client) CountWorkflowTemplates(namespace string) (count int, err error) {
|
func (c *Client) CountWorkflowTemplates(namespace string) (count int, err error) {
|
||||||
err = sb.Select("COUNT( DISTINCT( wt.id ))").
|
err = sb.Select("COUNT(*)").
|
||||||
From("workflow_templates wt").
|
From("workflow_templates wt").
|
||||||
Join("workflow_template_versions wtv ON wtv.workflow_template_id = wt.id").
|
|
||||||
Where(sq.Eq{
|
Where(sq.Eq{
|
||||||
"wt.namespace": namespace,
|
"wt.namespace": namespace,
|
||||||
"wt.is_archived": false,
|
"wt.is_archived": false,
|
||||||
"wt.is_system": false,
|
"wt.is_system": false,
|
||||||
}).
|
}).
|
||||||
RunWith(c.DB.DB).
|
RunWith(c.DB).
|
||||||
QueryRow().
|
QueryRow().
|
||||||
Scan(&count)
|
Scan(&count)
|
||||||
|
|
||||||
@@ -368,6 +409,11 @@ func (c *Client) CreateWorkflowTemplate(namespace string, workflowTemplate *Work
|
|||||||
return newWorkflowTemplate, nil
|
return newWorkflowTemplate, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateWorkflowTemplateVersion creates a new workflow template version including argo resources.
|
||||||
|
// It marks any older workflow template versions as not latest
|
||||||
|
//
|
||||||
|
// Pre-condition: a Workflow Template version already exists
|
||||||
|
// Post-condition: the input workflow template will have it's fields updated so it matches the new version data.
|
||||||
func (c *Client) CreateWorkflowTemplateVersion(namespace string, workflowTemplate *WorkflowTemplate) (*WorkflowTemplate, error) {
|
func (c *Client) CreateWorkflowTemplateVersion(namespace string, workflowTemplate *WorkflowTemplate) (*WorkflowTemplate, error) {
|
||||||
if workflowTemplate.UID == "" {
|
if workflowTemplate.UID == "" {
|
||||||
return nil, fmt.Errorf("uid required for CreateWorkflowTemplateVersion")
|
return nil, fmt.Errorf("uid required for CreateWorkflowTemplateVersion")
|
||||||
@@ -378,8 +424,6 @@ func (c *Client) CreateWorkflowTemplateVersion(namespace string, workflowTemplat
|
|||||||
return nil, util.NewUserError(codes.InvalidArgument, err.Error())
|
return nil, util.NewUserError(codes.InvalidArgument, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
versionUnix := time.Now().Unix()
|
|
||||||
|
|
||||||
tx, err := c.DB.Begin()
|
tx, err := c.DB.Begin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -391,75 +435,26 @@ func (c *Client) CreateWorkflowTemplateVersion(namespace string, workflowTemplat
|
|||||||
"wt.uid": workflowTemplate.UID,
|
"wt.uid": workflowTemplate.UID,
|
||||||
"wt.is_archived": false,
|
"wt.is_archived": false,
|
||||||
})
|
})
|
||||||
query, args, err := wftSb.ToSql()
|
workflowTemplateDB := &WorkflowTemplate{}
|
||||||
if err != nil {
|
if err = c.DB.Getx(workflowTemplateDB, wftSb); err != nil {
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
workflowTemplateDb := &WorkflowTemplate{}
|
|
||||||
if err = c.DB.Get(workflowTemplateDb, query, args...); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = sb.Update("workflow_template_versions").
|
workflowTemplateVersion, err := createLatestWorkflowTemplateVersionDB(tx, workflowTemplateDB.ID, workflowTemplate.Manifest)
|
||||||
Set("is_latest", false).
|
|
||||||
Where(sq.Eq{
|
|
||||||
"workflow_template_id": workflowTemplateDb.ID,
|
|
||||||
}).
|
|
||||||
RunWith(tx).
|
|
||||||
Exec()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
workflowTemplate.WorkflowTemplateVersionID = workflowTemplateVersion.ID
|
||||||
|
|
||||||
workflowTemplateVersionID := uint64(0)
|
updatedTemplate, err := createArgoWorkflowTemplate(workflowTemplate, workflowTemplateVersion.Version)
|
||||||
err = sb.Insert("workflow_template_versions").
|
|
||||||
SetMap(sq.Eq{
|
|
||||||
"workflow_template_id": workflowTemplateDb.ID,
|
|
||||||
"version": versionUnix,
|
|
||||||
"is_latest": true,
|
|
||||||
"manifest": workflowTemplate.Manifest,
|
|
||||||
}).
|
|
||||||
Suffix("RETURNING id").
|
|
||||||
RunWith(tx).
|
|
||||||
QueryRow().
|
|
||||||
Scan(&workflowTemplateVersionID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
workflowTemplate.WorkflowTemplateVersionID = workflowTemplateVersionID
|
|
||||||
latest, err := c.getArgoWorkflowTemplate(namespace, workflowTemplate.UID, "latest")
|
|
||||||
if err != nil {
|
|
||||||
log.WithFields(log.Fields{
|
|
||||||
"Namespace": namespace,
|
|
||||||
"WorkflowTemplate": workflowTemplate,
|
|
||||||
"Error": err.Error(),
|
|
||||||
}).Error("Could not get latest argo workflow template")
|
|
||||||
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
delete(latest.Labels, label.VersionLatest)
|
|
||||||
|
|
||||||
latest, err = c.ArgoprojV1alpha1().WorkflowTemplates(namespace).Update(latest)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
updatedTemplate, err := createArgoWorkflowTemplate(workflowTemplate, versionUnix)
|
|
||||||
if err != nil {
|
|
||||||
latest.Labels[label.VersionLatest] = "true"
|
|
||||||
if _, err := c.ArgoprojV1alpha1().WorkflowTemplates(namespace).Update(latest); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
updatedTemplate.TypeMeta = v1.TypeMeta{}
|
updatedTemplate.TypeMeta = v1.TypeMeta{}
|
||||||
updatedTemplate.ObjectMeta.ResourceVersion = ""
|
updatedTemplate.ObjectMeta.ResourceVersion = ""
|
||||||
updatedTemplate.ObjectMeta.SetSelfLink("")
|
updatedTemplate.ObjectMeta.SetSelfLink("")
|
||||||
updatedTemplate.Labels[label.WorkflowTemplateVersionUid] = strconv.FormatInt(versionUnix, 10)
|
updatedTemplate.Labels[label.WorkflowTemplateVersionUid] = strconv.FormatInt(workflowTemplateVersion.Version, 10)
|
||||||
|
|
||||||
parametersMap, err := workflowTemplate.GetParametersKeyString()
|
parametersMap, err := workflowTemplate.GetParametersKeyString()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -473,15 +468,32 @@ func (c *Client) CreateWorkflowTemplateVersion(namespace string, workflowTemplat
|
|||||||
updatedTemplate.Annotations[key] = value
|
updatedTemplate.Annotations[key] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
latest, err := c.getArgoWorkflowTemplate(namespace, workflowTemplate.UID, "latest")
|
||||||
|
if err != nil {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"Namespace": namespace,
|
||||||
|
"WorkflowTemplate": workflowTemplate,
|
||||||
|
"Error": err.Error(),
|
||||||
|
}).Error("Could not get latest argo workflow template")
|
||||||
|
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
delete(latest.Labels, label.VersionLatest)
|
||||||
|
|
||||||
if _, err := c.ArgoprojV1alpha1().WorkflowTemplates(namespace).Create(updatedTemplate); err != nil {
|
if _, err := c.ArgoprojV1alpha1().WorkflowTemplates(namespace).Create(updatedTemplate); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
latest, err = c.ArgoprojV1alpha1().WorkflowTemplates(namespace).Update(latest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if err := tx.Commit(); err != nil {
|
if err := tx.Commit(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
workflowTemplate.Version = versionUnix
|
workflowTemplate.Version = workflowTemplateVersion.Version
|
||||||
|
|
||||||
return workflowTemplate, nil
|
return workflowTemplate, nil
|
||||||
}
|
}
|
||||||
@@ -564,7 +576,7 @@ func (c *Client) ListWorkflowTemplateVersions(namespace, uid string) (workflowTe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) ListWorkflowTemplates(namespace string, paginator *pagination.PaginationRequest) (workflowTemplateVersions []*WorkflowTemplate, err error) {
|
func (c *Client) ListWorkflowTemplates(namespace string, paginator *pagination.PaginationRequest) (workflowTemplateVersions []*WorkflowTemplate, err error) {
|
||||||
workflowTemplateVersions, err = c.listWorkflowTemplates(namespace, paginator)
|
workflowTemplateVersions, err = c.selectWorkflowTemplatesDB(namespace, paginator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"Namespace": namespace,
|
"Namespace": namespace,
|
||||||
@@ -722,6 +734,8 @@ func (c *Client) ArchiveWorkflowTemplate(namespace, uid string) (archived bool,
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// createArgoWorkflowTemplate creates an argo workflow template from the workflowTemplate struct
|
||||||
|
// the argo template stores the version information.
|
||||||
func createArgoWorkflowTemplate(workflowTemplate *WorkflowTemplate, version int64) (*v1alpha1.WorkflowTemplate, error) {
|
func createArgoWorkflowTemplate(workflowTemplate *WorkflowTemplate, version int64) (*v1alpha1.WorkflowTemplate, error) {
|
||||||
var argoWft *v1alpha1.WorkflowTemplate
|
var argoWft *v1alpha1.WorkflowTemplate
|
||||||
var jsonOpts []argojson.JSONOpt
|
var jsonOpts []argojson.JSONOpt
|
||||||
@@ -737,15 +751,14 @@ func createArgoWorkflowTemplate(workflowTemplate *WorkflowTemplate, version int6
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
worfklowTemplateName, err := uid2.GenerateUID(workflowTemplate.Name, 30)
|
if err := workflowTemplate.GenerateUID(workflowTemplate.Name); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
argoWft.Name = fmt.Sprintf("%v-v%v", worfklowTemplateName, version)
|
argoWft.Name = fmt.Sprintf("%v-v%v", workflowTemplate.UID, version)
|
||||||
|
|
||||||
labels := map[string]string{
|
labels := map[string]string{
|
||||||
label.WorkflowTemplate: worfklowTemplateName,
|
label.WorkflowTemplate: workflowTemplate.UID,
|
||||||
label.WorkflowTemplateUid: workflowTemplate.UID,
|
label.WorkflowTemplateUid: workflowTemplate.UID,
|
||||||
label.Version: fmt.Sprintf("%v", version),
|
label.Version: fmt.Sprintf("%v", version),
|
||||||
label.VersionLatest: "true",
|
label.VersionLatest: "true",
|
||||||
@@ -757,9 +770,10 @@ func createArgoWorkflowTemplate(workflowTemplate *WorkflowTemplate, version int6
|
|||||||
return argoWft, nil
|
return argoWft, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// version "latest" will get the latest version.
|
// getArgoWorkflowTemplate will load the argo workflow template.
|
||||||
func (c *Client) getArgoWorkflowTemplate(namespace, workflowTemplateUid, version string) (*v1alpha1.WorkflowTemplate, error) {
|
// version "latest" will get the latest version, otherwise a number (as a string) will be used.
|
||||||
labelSelect := fmt.Sprintf("%v=%v", label.WorkflowTemplateUid, workflowTemplateUid)
|
func (c *Client) getArgoWorkflowTemplate(namespace, workflowTemplateUID, version string) (*v1alpha1.WorkflowTemplate, error) {
|
||||||
|
labelSelect := fmt.Sprintf("%v=%v", label.WorkflowTemplateUid, workflowTemplateUID)
|
||||||
if version == "latest" {
|
if version == "latest" {
|
||||||
labelSelect += "," + label.VersionLatest + "=true"
|
labelSelect += "," + label.VersionLatest + "=true"
|
||||||
} else {
|
} else {
|
||||||
@@ -799,28 +813,22 @@ func (c *Client) listArgoWorkflowTemplates(namespace, workflowTemplateUid string
|
|||||||
return &templates, nil
|
return &templates, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) listDBWorkflowTemplateVersions(namespace, workflowTemplateUID string) ([]*WorkflowTemplateVersion, error) {
|
// listDBWorkflowTemplateVersions gets all of the workflow template versions for a specified workflow template uid
|
||||||
versions := make([]*WorkflowTemplateVersion, 0)
|
// archived ones are ignored. Returned in created_at desc order.
|
||||||
|
func (c *Client) selectWorkflowTemplateVersionsDB(namespace, workflowTemplateUID string) (versions []*WorkflowTemplateVersion, err error) {
|
||||||
|
versions = make([]*WorkflowTemplateVersion, 0)
|
||||||
|
|
||||||
sb := c.workflowTemplatesVersionSelectBuilder(namespace).
|
sb := c.workflowTemplatesVersionSelectBuilder(namespace).
|
||||||
Columns(`wt.id "workflow_template.id"`, `wt.created_at "workflow_template.created_at"`).
|
Columns(getWorkflowTemplateColumns("wt", "workflow_template")...).
|
||||||
Columns(`wt.name "workflow_template.name"`, `wt.is_archived "workflow_template.is_archived"`).
|
|
||||||
Where(sq.Eq{
|
Where(sq.Eq{
|
||||||
"wt.uid": workflowTemplateUID,
|
"wt.uid": workflowTemplateUID,
|
||||||
"wt.is_archived": false,
|
"wt.is_archived": false,
|
||||||
}).
|
}).
|
||||||
OrderBy("wtv.created_at DESC")
|
OrderBy("wtv.created_at DESC")
|
||||||
|
|
||||||
query, args, err := sb.ToSql()
|
err = c.DB.Selectx(&versions, sb)
|
||||||
if err != nil {
|
|
||||||
return versions, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.DB.Select(&versions, query, args...); err != nil {
|
return
|
||||||
return versions, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return versions, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// prefix is the label prefix.
|
// prefix is the label prefix.
|
||||||
|
345
pkg/workflow_template_test.go
Normal file
345
pkg/workflow_template_test.go
Normal file
@@ -0,0 +1,345 @@
|
|||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"github.com/onepanelio/core/pkg/util"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const defaultWorkflowTemplate = `entrypoint: main
|
||||||
|
arguments:
|
||||||
|
parameters:
|
||||||
|
- name: source
|
||||||
|
value: https://github.com/onepanelio/pytorch-examples.git
|
||||||
|
- name: command
|
||||||
|
value: "python mnist/main.py --epochs=1"
|
||||||
|
volumeClaimTemplates:
|
||||||
|
- metadata:
|
||||||
|
name: data
|
||||||
|
spec:
|
||||||
|
accessModes: [ "ReadWriteOnce" ]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 2Gi
|
||||||
|
- metadata:
|
||||||
|
name: output
|
||||||
|
spec:
|
||||||
|
accessModes: [ "ReadWriteOnce" ]
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 2Gi
|
||||||
|
templates:
|
||||||
|
- name: main
|
||||||
|
dag:
|
||||||
|
tasks:
|
||||||
|
- name: train-model
|
||||||
|
template: pytorch
|
||||||
|
# Uncomment section below to send metrics to Slack
|
||||||
|
# - name: notify-in-slack
|
||||||
|
# dependencies: [train-model]
|
||||||
|
# template: slack-notify-success
|
||||||
|
# arguments:
|
||||||
|
# parameters:
|
||||||
|
# - name: status
|
||||||
|
# value: "{{tasks.train-model.status}}"
|
||||||
|
# artifacts:
|
||||||
|
# - name: metrics
|
||||||
|
# from: "{{tasks.train-model.outputs.artifacts.sys-metrics}}"
|
||||||
|
- name: pytorch
|
||||||
|
inputs:
|
||||||
|
artifacts:
|
||||||
|
- name: src
|
||||||
|
path: /mnt/src
|
||||||
|
git:
|
||||||
|
repo: "{{workflow.parameters.source}}"
|
||||||
|
outputs:
|
||||||
|
artifacts:
|
||||||
|
- name: model
|
||||||
|
path: /mnt/output
|
||||||
|
optional: true
|
||||||
|
archive:
|
||||||
|
none: {}
|
||||||
|
container:
|
||||||
|
image: pytorch/pytorch:latest
|
||||||
|
command: [sh,-c]
|
||||||
|
args: ["{{workflow.parameters.command}}"]
|
||||||
|
workingDir: /mnt/src
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: /mnt/data
|
||||||
|
- name: output
|
||||||
|
mountPath: /mnt/output
|
||||||
|
- name: slack-notify-success
|
||||||
|
container:
|
||||||
|
image: technosophos/slack-notify
|
||||||
|
command: [sh,-c]
|
||||||
|
args: ['SLACK_USERNAME=Worker SLACK_TITLE="{{workflow.name}} {{inputs.parameters.status}}" SLACK_ICON=https://www.gravatar.com/avatar/5c4478592fe00878f62f0027be59c1bd SLACK_MESSAGE=$(cat /tmp/metrics.json)} ./slack-notify']
|
||||||
|
inputs:
|
||||||
|
parameters:
|
||||||
|
- name: status
|
||||||
|
artifacts:
|
||||||
|
- name: metrics
|
||||||
|
path: /tmp/metrics.json
|
||||||
|
optional: true
|
||||||
|
`
|
||||||
|
|
||||||
|
// testClientGetWorkflowTemplateDBEmpty attempts to get a WorkflowTemplate when there isn't one.
|
||||||
|
// this should fail.
|
||||||
|
func testClientGetWorkflowTemplateDBEmpty(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
_, err := c.getWorkflowTemplateDB("test", "test")
|
||||||
|
assert.Equal(t, sql.ErrNoRows, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testClientGetWorkflowTemplateDBExists gets a WorkflowTemplate when there is one
|
||||||
|
// this should succeed
|
||||||
|
func testClientGetWorkflowTemplateDBExists(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
workflowTemplate := &WorkflowTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: defaultWorkflowTemplate,
|
||||||
|
}
|
||||||
|
_, err := c.CreateWorkflowTemplate("onepanel", workflowTemplate)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = c.getWorkflowTemplateDB("onepanel", "test")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestClient_getWorkflowTemplateDB tests getting a workflow template from the database
|
||||||
|
func TestClient_getWorkflowTemplateDB(t *testing.T) {
|
||||||
|
testClientGetWorkflowTemplateDBEmpty(t)
|
||||||
|
testClientGetWorkflowTemplateDBExists(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testClientCreateWorkflowTemplateSuccess makes sure a correct workflow template is created correctly
|
||||||
|
func testClientCreateWorkflowTemplateSuccess(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
workflowTemplate := &WorkflowTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: defaultWorkflowTemplate,
|
||||||
|
}
|
||||||
|
|
||||||
|
wft, err := c.CreateWorkflowTemplate("onepanel", workflowTemplate)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, wft.ArgoWorkflowTemplate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testClientCreateWorkflowTemplateTimestamp makes sure we can create mulitple
|
||||||
|
// workflow templtate versions one after another with practically no time delay.
|
||||||
|
// This handles an edge case where versions were set using second time precision and could fail in migrations
|
||||||
|
// as they were created one after another.
|
||||||
|
func testClientCreateWorkflowTemplateTimestamp(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
|
||||||
|
workflowTemplate := &WorkflowTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: defaultWorkflowTemplate,
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method creates a workflow template version underneath
|
||||||
|
wft, err := c.CreateWorkflowTemplate("onepanel", workflowTemplate)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, wft.ArgoWorkflowTemplate)
|
||||||
|
|
||||||
|
// This method creates a brand new version
|
||||||
|
wft, err = c.CreateWorkflowTemplateVersion(namespace, workflowTemplate)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, wft.ArgoWorkflowTemplate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testClientCreateWorkflowTemplateInsertSameName attempts to insert a WorkflowTemplate with the same name
|
||||||
|
// this should fail
|
||||||
|
func testClientCreateWorkflowTemplateInsertSameName(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
workflowTemplate := &WorkflowTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: defaultWorkflowTemplate,
|
||||||
|
}
|
||||||
|
_, err := c.CreateWorkflowTemplate("onepanel", workflowTemplate)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = c.CreateWorkflowTemplate("onepanel", workflowTemplate)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
|
assert.IsType(t, &util.UserError{}, err)
|
||||||
|
userErr := err.(*util.UserError)
|
||||||
|
|
||||||
|
assert.Equal(t, userErr.Code, codes.AlreadyExists)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestClient_CreateWorkflowTemplate tests creating a workflow template
|
||||||
|
func TestClient_CreateWorkflowTemplate(t *testing.T) {
|
||||||
|
testClientCreateWorkflowTemplateInsertSameName(t)
|
||||||
|
testClientCreateWorkflowTemplateSuccess(t)
|
||||||
|
testClientCreateWorkflowTemplateTimestamp(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testClientPrivateGetWorkflowTemplateSuccess gets a workflow template with no error conditions encountered
|
||||||
|
func testClientPrivateGetWorkflowTemplateSuccess(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
workflowTemplate := &WorkflowTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: defaultWorkflowTemplate,
|
||||||
|
}
|
||||||
|
created, _ := c.CreateWorkflowTemplate(namespace, workflowTemplate)
|
||||||
|
|
||||||
|
wt, err := c.getWorkflowTemplate(namespace, created.UID, 0)
|
||||||
|
assert.NotNil(t, wt)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testClientGetWorkflowTemplateSuccessVersion gets a workflow template for a specific version with no error conditions encountered
|
||||||
|
func testClientPrivateGetWorkflowTemplateSuccessVersion(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
workflowTemplate := &WorkflowTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: defaultWorkflowTemplate,
|
||||||
|
}
|
||||||
|
created, _ := c.CreateWorkflowTemplate(namespace, workflowTemplate)
|
||||||
|
c.CreateWorkflowTemplateVersion(namespace, workflowTemplate)
|
||||||
|
|
||||||
|
wt, err := c.getWorkflowTemplate(namespace, created.UID, created.Version)
|
||||||
|
assert.NotNil(t, wt)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, created.Version, wt.Version)
|
||||||
|
assert.Equal(t, created.Manifest, wt.Manifest)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testClientGetWorkflowTemplateNotFound attempts to get a not-found workflow template
|
||||||
|
func testClientPrivateGetWorkflowTemplateNotFound(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
wt, err := c.getWorkflowTemplate("onepanel", "uid-not-found", 0)
|
||||||
|
assert.Nil(t, wt)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test_getWorkflowTemplate tests getting a workflow template
|
||||||
|
func Test_getWorkflowTemplate(t *testing.T) {
|
||||||
|
testClientPrivateGetWorkflowTemplateSuccess(t)
|
||||||
|
testClientPrivateGetWorkflowTemplateNotFound(t)
|
||||||
|
testClientPrivateGetWorkflowTemplateSuccessVersion(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_getWorkflowTemplateVersionDB(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
name := "test"
|
||||||
|
workflowTemplate := &WorkflowTemplate{
|
||||||
|
Name: name,
|
||||||
|
Manifest: defaultWorkflowTemplate,
|
||||||
|
}
|
||||||
|
|
||||||
|
original, _ := c.CreateWorkflowTemplate(namespace, workflowTemplate)
|
||||||
|
|
||||||
|
versionAsString := fmt.Sprintf("%v", original.Version)
|
||||||
|
originalRes, err := c.getWorkflowTemplateVersionDB(namespace, name, versionAsString)
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, original.Version, originalRes.Version)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testClientCreateWorkflowTemplateVersionNew makes sure you can successfully create a new workflow template version
|
||||||
|
func testClientCreateWorkflowTemplateVersionNew(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
workflowTemplate := &WorkflowTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: defaultWorkflowTemplate,
|
||||||
|
}
|
||||||
|
|
||||||
|
c.CreateWorkflowTemplate(namespace, workflowTemplate)
|
||||||
|
_, err := c.CreateWorkflowTemplateVersion(namespace, workflowTemplate)
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testClientCreateWorkflowTemplateVersionMarkOldNotLatest makes sure older versions are no longer marked as latest
|
||||||
|
func testClientCreateWorkflowTemplateVersionMarkOldNotLatest(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
name := "test"
|
||||||
|
workflowTemplate := &WorkflowTemplate{
|
||||||
|
Name: name,
|
||||||
|
Manifest: defaultWorkflowTemplate,
|
||||||
|
}
|
||||||
|
|
||||||
|
original, _ := c.CreateWorkflowTemplate(namespace, workflowTemplate)
|
||||||
|
originalVersionAsString := fmt.Sprintf("%v", original.Version)
|
||||||
|
c.CreateWorkflowTemplateVersion(namespace, workflowTemplate)
|
||||||
|
|
||||||
|
updated, _ := c.getWorkflowTemplateVersionDB(namespace, name, originalVersionAsString)
|
||||||
|
|
||||||
|
assert.False(t, updated.IsLatest)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test_getWorkflowTemplate_SuccessVersion tests cases for creating a workflow template version
|
||||||
|
func TestClient_CreateWorkflowTemplateVersion(t *testing.T) {
|
||||||
|
testClientCreateWorkflowTemplateVersionNew(t)
|
||||||
|
testClientCreateWorkflowTemplateVersionMarkOldNotLatest(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testGetWorkflowTemplateSuccess gets a workflow template with no error conditions encountered
|
||||||
|
func testClientGetWorkflowTemplateSuccess(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
workflowTemplate := &WorkflowTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: defaultWorkflowTemplate,
|
||||||
|
}
|
||||||
|
created, _ := c.CreateWorkflowTemplate(namespace, workflowTemplate)
|
||||||
|
|
||||||
|
wt, err := c.GetWorkflowTemplate(namespace, created.UID, 0)
|
||||||
|
assert.NotNil(t, wt)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testGetWorkflowTemplateNotFound attempts to get a not-found workflow template
|
||||||
|
func testClientGetWorkflowTemplateNotFound(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
wt, err := c.GetWorkflowTemplate("onepanel", "uid-not-found", 0)
|
||||||
|
assert.Nil(t, wt)
|
||||||
|
|
||||||
|
userErr, ok := err.(*util.UserError)
|
||||||
|
assert.True(t, ok)
|
||||||
|
|
||||||
|
assert.Equal(t, codes.NotFound, userErr.Code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_GetWorkflowTemplate(t *testing.T) {
|
||||||
|
testClientGetWorkflowTemplateSuccess(t)
|
||||||
|
testClientGetWorkflowTemplateNotFound(t)
|
||||||
|
}
|
@@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1"
|
wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1"
|
||||||
"github.com/onepanelio/core/pkg/util/mapping"
|
"github.com/onepanelio/core/pkg/util/mapping"
|
||||||
|
uid2 "github.com/onepanelio/core/pkg/util/uid"
|
||||||
"github.com/onepanelio/core/util/sql"
|
"github.com/onepanelio/core/util/sql"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
@@ -13,6 +14,9 @@ import (
|
|||||||
|
|
||||||
// WorkflowTemplate represents a Workflow Template backed by a database row
|
// WorkflowTemplate represents a Workflow Template backed by a database row
|
||||||
// it stores information required to run an execution
|
// it stores information required to run an execution
|
||||||
|
// A Workflow template is uniquely identified by
|
||||||
|
// (namespace, uid, is_archived)
|
||||||
|
// (namespace, name, is_archived) -- because we create a uid from the name.
|
||||||
type WorkflowTemplate struct {
|
type WorkflowTemplate struct {
|
||||||
ID uint64
|
ID uint64
|
||||||
CreatedAt time.Time `db:"created_at"`
|
CreatedAt time.Time `db:"created_at"`
|
||||||
@@ -35,6 +39,18 @@ type WorkflowTemplate struct {
|
|||||||
ResourceUID *string // see Resource field
|
ResourceUID *string // see Resource field
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateUID generates a uid from the input name and sets it on the workflow template
|
||||||
|
func (wt *WorkflowTemplate) GenerateUID(name string) error {
|
||||||
|
result, err := uid2.GenerateUID(name, 30)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
wt.UID = result
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetManifestBytes returns the manifest as []byte
|
// GetManifestBytes returns the manifest as []byte
|
||||||
func (wt *WorkflowTemplate) GetManifestBytes() []byte {
|
func (wt *WorkflowTemplate) GetManifestBytes() []byte {
|
||||||
return []byte(wt.Manifest)
|
return []byte(wt.Manifest)
|
||||||
|
157
pkg/workspace.go
157
pkg/workspace.go
@@ -10,9 +10,9 @@ import (
|
|||||||
"github.com/onepanelio/core/pkg/util"
|
"github.com/onepanelio/core/pkg/util"
|
||||||
"github.com/onepanelio/core/pkg/util/pagination"
|
"github.com/onepanelio/core/pkg/util/pagination"
|
||||||
"github.com/onepanelio/core/pkg/util/ptr"
|
"github.com/onepanelio/core/pkg/util/ptr"
|
||||||
uid2 "github.com/onepanelio/core/pkg/util/uid"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -33,16 +33,55 @@ func (c *Client) workspacesSelectBuilder(namespace string) sq.SelectBuilder {
|
|||||||
return sb
|
return sb
|
||||||
}
|
}
|
||||||
|
|
||||||
func getWorkspaceParameterValue(parameters []Parameter, name string) *string {
|
// workspaceStatusToFieldMap takes a status and creates a map of the fields that should be updated
|
||||||
for _, p := range parameters {
|
func workspaceStatusToFieldMap(status *WorkspaceStatus) sq.Eq {
|
||||||
if p.Name == name {
|
fieldMap := sq.Eq{
|
||||||
return p.Value
|
"phase": status.Phase,
|
||||||
}
|
"modified_at": time.Now().UTC(),
|
||||||
|
}
|
||||||
|
switch status.Phase {
|
||||||
|
case WorkspaceLaunching:
|
||||||
|
fieldMap["paused_at"] = pq.NullTime{}
|
||||||
|
fieldMap["started_at"] = time.Now().UTC()
|
||||||
|
break
|
||||||
|
case WorkspacePausing:
|
||||||
|
fieldMap["started_at"] = pq.NullTime{}
|
||||||
|
fieldMap["paused_at"] = time.Now().UTC()
|
||||||
|
break
|
||||||
|
case WorkspaceUpdating:
|
||||||
|
fieldMap["paused_at"] = pq.NullTime{}
|
||||||
|
fieldMap["updated_at"] = time.Now().UTC()
|
||||||
|
break
|
||||||
|
case WorkspaceTerminating:
|
||||||
|
fieldMap["started_at"] = pq.NullTime{}
|
||||||
|
fieldMap["paused_at"] = pq.NullTime{}
|
||||||
|
fieldMap["terminated_at"] = time.Now().UTC()
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return fieldMap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// updateWorkspaceStatusBuilder creates an update builder that updates a workspace's status and related fields to match that status.
|
||||||
|
func updateWorkspaceStatusBuilder(namespace, uid string, status *WorkspaceStatus) sq.UpdateBuilder {
|
||||||
|
fieldMap := workspaceStatusToFieldMap(status)
|
||||||
|
|
||||||
|
ub := sb.Update("workspaces").
|
||||||
|
SetMap(fieldMap).
|
||||||
|
Where(sq.And{
|
||||||
|
sq.Eq{
|
||||||
|
"namespace": namespace,
|
||||||
|
"uid": uid,
|
||||||
|
}, sq.NotEq{
|
||||||
|
"phase": WorkspaceTerminated,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return ub
|
||||||
|
}
|
||||||
|
|
||||||
|
// mergeWorkspaceParameters combines two parameter arrays. If a parameter in newParameters is not in
|
||||||
|
// the existing ones, it is added. If it is, it is ignored.
|
||||||
func mergeWorkspaceParameters(existingParameters, newParameters []Parameter) (parameters []Parameter) {
|
func mergeWorkspaceParameters(existingParameters, newParameters []Parameter) (parameters []Parameter) {
|
||||||
parameterMap := make(map[string]*string, 0)
|
parameterMap := make(map[string]*string, 0)
|
||||||
for _, p := range newParameters {
|
for _, p := range newParameters {
|
||||||
@@ -74,10 +113,6 @@ func mergeWorkspaceParameters(existingParameters, newParameters []Parameter) (pa
|
|||||||
// sys-resource-action
|
// sys-resource-action
|
||||||
// sys-host
|
// sys-host
|
||||||
func injectWorkspaceSystemParameters(namespace string, workspace *Workspace, workspaceAction, resourceAction string, config SystemConfig) (err error) {
|
func injectWorkspaceSystemParameters(namespace string, workspace *Workspace, workspaceAction, resourceAction string, config SystemConfig) (err error) {
|
||||||
workspace.UID, err = uid2.GenerateUID(workspace.Name, 30)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
host := fmt.Sprintf("%v--%v.%v", workspace.UID, namespace, *config.Domain())
|
host := fmt.Sprintf("%v--%v.%v", workspace.UID, namespace, *config.Domain())
|
||||||
systemParameters := []Parameter{
|
systemParameters := []Parameter{
|
||||||
{
|
{
|
||||||
@@ -98,6 +133,10 @@ func injectWorkspaceSystemParameters(namespace string, workspace *Workspace, wor
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// createWorkspace creates a workspace and related resources.
|
||||||
|
// The following are required on the workspace:
|
||||||
|
// WorkspaceTemplate.WorkflowTemplate.UID
|
||||||
|
// WorkspaceTemplate.WorkflowTemplate.Version
|
||||||
func (c *Client) createWorkspace(namespace string, parameters []byte, workspace *Workspace) (*Workspace, error) {
|
func (c *Client) createWorkspace(namespace string, parameters []byte, workspace *Workspace) (*Workspace, error) {
|
||||||
systemConfig, err := c.GetSystemConfig()
|
systemConfig, err := c.GetSystemConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -155,7 +194,11 @@ func (c *Client) createWorkspace(namespace string, parameters []byte, workspace
|
|||||||
QueryRow().
|
QueryRow().
|
||||||
Scan(&workspace.ID, &workspace.CreatedAt)
|
Scan(&workspace.ID, &workspace.CreatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, util.NewUserErrorWrap(err, "Workspace")
|
if strings.Contains(err.Error(), "invalid input syntax for type json") {
|
||||||
|
return nil, util.NewUserError(codes.InvalidArgument, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, util.NewUserError(codes.Unknown, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return workspace, nil
|
return workspace, nil
|
||||||
@@ -168,6 +211,10 @@ func (c *Client) CreateWorkspace(namespace string, workspace *Workspace) (*Works
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := workspace.GenerateUID(workspace.Name); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
parameters, err := json.Marshal(workspace.Parameters)
|
parameters, err := json.Marshal(workspace.Parameters)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -182,7 +229,7 @@ func (c *Client) CreateWorkspace(namespace string, workspace *Workspace) (*Works
|
|||||||
Value: ptr.String(workspace.UID),
|
Value: ptr.String(workspace.UID),
|
||||||
})
|
})
|
||||||
|
|
||||||
sysHost := getWorkspaceParameterValue(workspace.Parameters, "sys-host")
|
sysHost := workspace.GetParameterValue("sys-host")
|
||||||
if sysHost == nil {
|
if sysHost == nil {
|
||||||
return nil, fmt.Errorf("sys-host parameter not found")
|
return nil, fmt.Errorf("sys-host parameter not found")
|
||||||
}
|
}
|
||||||
@@ -267,51 +314,31 @@ func (c *Client) GetWorkspace(namespace, uid string) (workspace *Workspace, err
|
|||||||
|
|
||||||
// UpdateWorkspaceStatus updates workspace status and times based on phase
|
// UpdateWorkspaceStatus updates workspace status and times based on phase
|
||||||
func (c *Client) UpdateWorkspaceStatus(namespace, uid string, status *WorkspaceStatus) (err error) {
|
func (c *Client) UpdateWorkspaceStatus(namespace, uid string, status *WorkspaceStatus) (err error) {
|
||||||
fieldMap := sq.Eq{
|
result, err := updateWorkspaceStatusBuilder(namespace, uid, status).
|
||||||
"phase": status.Phase,
|
RunWith(c.DB).
|
||||||
"modified_at": time.Now().UTC(),
|
Exec()
|
||||||
}
|
|
||||||
switch status.Phase {
|
|
||||||
case WorkspaceLaunching:
|
|
||||||
fieldMap["paused_at"] = pq.NullTime{}
|
|
||||||
fieldMap["started_at"] = time.Now().UTC()
|
|
||||||
break
|
|
||||||
case WorkspacePausing:
|
|
||||||
fieldMap["started_at"] = pq.NullTime{}
|
|
||||||
fieldMap["paused_at"] = time.Now().UTC()
|
|
||||||
break
|
|
||||||
case WorkspaceUpdating:
|
|
||||||
fieldMap["paused_at"] = pq.NullTime{}
|
|
||||||
fieldMap["updated_at"] = time.Now().UTC()
|
|
||||||
break
|
|
||||||
case WorkspaceTerminating:
|
|
||||||
fieldMap["started_at"] = pq.NullTime{}
|
|
||||||
fieldMap["paused_at"] = pq.NullTime{}
|
|
||||||
fieldMap["terminated_at"] = time.Now().UTC()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
_, err = sb.Update("workspaces").
|
|
||||||
SetMap(fieldMap).
|
|
||||||
Where(sq.And{
|
|
||||||
sq.Eq{
|
|
||||||
"namespace": namespace,
|
|
||||||
"uid": uid,
|
|
||||||
}, sq.NotEq{
|
|
||||||
"phase": WorkspaceTerminated,
|
|
||||||
},
|
|
||||||
}).
|
|
||||||
RunWith(c.DB).Exec()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rowsAffected, err := result.RowsAffected()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if rowsAffected == 0 {
|
||||||
return util.NewUserError(codes.NotFound, "Workspace not found.")
|
return util.NewUserError(codes.NotFound, "Workspace not found.")
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListWorkspacesByTemplateID will return all the workspaces for a given workspace template id.
|
// ListWorkspacesByTemplateID will return all the workspaces for a given workspace template id that are not terminated.
|
||||||
// Sourced from database.
|
// Sourced from database.
|
||||||
|
// Includes labels.
|
||||||
func (c *Client) ListWorkspacesByTemplateID(namespace string, templateID uint64) (workspaces []*Workspace, err error) {
|
func (c *Client) ListWorkspacesByTemplateID(namespace string, templateID uint64) (workspaces []*Workspace, err error) {
|
||||||
sb := sb.Select(getWorkspaceColumns("w")...).
|
sb := sb.Select(getWorkspaceColumns("w")...).
|
||||||
|
Columns(getWorkspaceStatusColumns("w", "status")...).
|
||||||
From("workspaces w").
|
From("workspaces w").
|
||||||
Where(sq.And{
|
Where(sq.And{
|
||||||
sq.Eq{
|
sq.Eq{
|
||||||
@@ -391,6 +418,7 @@ func (c *Client) CountWorkspaces(namespace string) (count int, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// updateWorkspace updates the workspace to the indicated status
|
||||||
func (c *Client) updateWorkspace(namespace, uid, workspaceAction, resourceAction string, status *WorkspaceStatus, parameters ...Parameter) (err error) {
|
func (c *Client) updateWorkspace(namespace, uid, workspaceAction, resourceAction string, status *WorkspaceStatus, parameters ...Parameter) (err error) {
|
||||||
workspace, err := c.GetWorkspace(namespace, uid)
|
workspace, err := c.GetWorkspace(namespace, uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -444,32 +472,15 @@ func (c *Client) updateWorkspace(namespace, uid, workspaceAction, resourceAction
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = c.UpdateWorkspaceStatus(namespace, uid, status); err != nil {
|
sb := updateWorkspaceStatusBuilder(namespace, uid, status)
|
||||||
return
|
|
||||||
|
// Update parameters if they are passed in
|
||||||
|
if len(parameters) != 0 {
|
||||||
|
sb.Set("parameters", parametersJSON)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update parameters if they are passed
|
_, err = sb.RunWith(c.DB).
|
||||||
if len(parameters) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = sb.Update("workspaces").
|
|
||||||
SetMap(sq.Eq{
|
|
||||||
"parameters": parametersJSON,
|
|
||||||
}).
|
|
||||||
Where(sq.And{
|
|
||||||
sq.Eq{
|
|
||||||
"namespace": namespace,
|
|
||||||
"uid": uid,
|
|
||||||
}, sq.NotEq{
|
|
||||||
"phase": WorkspaceTerminated,
|
|
||||||
},
|
|
||||||
}).
|
|
||||||
RunWith(c.DB).
|
|
||||||
Exec()
|
Exec()
|
||||||
if err != nil {
|
|
||||||
return util.NewUserError(codes.NotFound, "Workspace not found.")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -492,6 +503,6 @@ func (c *Client) DeleteWorkspace(namespace, uid string) (err error) {
|
|||||||
|
|
||||||
// ArchiveWorkspace archives by setting the workspace to delete or terminate.
|
// ArchiveWorkspace archives by setting the workspace to delete or terminate.
|
||||||
// Kicks off DB archiving and k8s cleaning.
|
// Kicks off DB archiving and k8s cleaning.
|
||||||
func (c *Client) ArchiveWorkspace(namespace, uid string) (err error) {
|
func (c *Client) ArchiveWorkspace(namespace, uid string, parameters ...Parameter) (err error) {
|
||||||
return c.updateWorkspace(namespace, uid, "delete", "delete", &WorkspaceStatus{Phase: WorkspaceTerminating})
|
return c.updateWorkspace(namespace, uid, "delete", "delete", &WorkspaceStatus{Phase: WorkspaceTerminating}, parameters...)
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,6 @@ import (
|
|||||||
"github.com/onepanelio/core/pkg/util/env"
|
"github.com/onepanelio/core/pkg/util/env"
|
||||||
"github.com/onepanelio/core/pkg/util/pagination"
|
"github.com/onepanelio/core/pkg/util/pagination"
|
||||||
"github.com/onepanelio/core/pkg/util/ptr"
|
"github.com/onepanelio/core/pkg/util/ptr"
|
||||||
uid2 "github.com/onepanelio/core/pkg/util/uid"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
networking "istio.io/api/networking/v1alpha3"
|
networking "istio.io/api/networking/v1alpha3"
|
||||||
@@ -118,82 +117,6 @@ func generateRuntimeParameters(config SystemConfig) (parameters []Parameter, err
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateStaticParameters() (parameters []Parameter, err error) {
|
|
||||||
parameters = make([]Parameter, 0)
|
|
||||||
|
|
||||||
// Resource action parameter
|
|
||||||
parameters = append(parameters, Parameter{
|
|
||||||
Name: "sys-name",
|
|
||||||
Type: "input.text",
|
|
||||||
Value: ptr.String("name"),
|
|
||||||
DisplayName: ptr.String("Workspace name"),
|
|
||||||
Hint: ptr.String("Must be between 3-30 characters, contain only alphanumeric or `-` characters"),
|
|
||||||
Required: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
// TODO: These can be removed when lint validation of workflows work
|
|
||||||
// Resource action parameter
|
|
||||||
parameters = append(parameters, Parameter{
|
|
||||||
Name: "sys-resource-action",
|
|
||||||
Value: ptr.String("apply"),
|
|
||||||
Type: "input.hidden",
|
|
||||||
})
|
|
||||||
// Workspace action
|
|
||||||
parameters = append(parameters, Parameter{
|
|
||||||
Name: "sys-workspace-action",
|
|
||||||
Value: ptr.String("create"),
|
|
||||||
Type: "input.hidden",
|
|
||||||
})
|
|
||||||
|
|
||||||
// UID placeholder
|
|
||||||
parameters = append(parameters, Parameter{
|
|
||||||
Name: "sys-uid",
|
|
||||||
Value: ptr.String("uid"),
|
|
||||||
Type: "input.hidden",
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateVolumeParameters(spec *WorkspaceSpec) (parameters []Parameter, err error) {
|
|
||||||
if spec == nil {
|
|
||||||
return nil, fmt.Errorf("workspaceSpec is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
parameters = make([]Parameter, 0)
|
|
||||||
|
|
||||||
// Map all the volumeClaimTemplates that have storage set
|
|
||||||
volumeStorageQuantityIsSet := make(map[string]bool)
|
|
||||||
for _, v := range spec.VolumeClaimTemplates {
|
|
||||||
if v.Spec.Resources.Requests != nil {
|
|
||||||
volumeStorageQuantityIsSet[v.ObjectMeta.Name] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Volume size parameters
|
|
||||||
volumeClaimsMapped := make(map[string]bool)
|
|
||||||
for _, c := range spec.Containers {
|
|
||||||
for _, v := range c.VolumeMounts {
|
|
||||||
// Skip if already mapped or storage size is set
|
|
||||||
if volumeClaimsMapped[v.Name] || volumeStorageQuantityIsSet[v.Name] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
parameters = append(parameters, Parameter{
|
|
||||||
Name: fmt.Sprintf("sys-%v-volume-size", v.Name),
|
|
||||||
Type: "input.number",
|
|
||||||
Value: ptr.String("20480"),
|
|
||||||
DisplayName: ptr.String(fmt.Sprintf("Disk size for \"%v\"", v.Name)),
|
|
||||||
Hint: ptr.String(fmt.Sprintf("Disk size in MB for volume mounted at `%v`", v.MountPath)),
|
|
||||||
Required: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
volumeClaimsMapped[v.Name] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateArguments(spec *WorkspaceSpec, config SystemConfig) (err error) {
|
func generateArguments(spec *WorkspaceSpec, config SystemConfig) (err error) {
|
||||||
systemParameters := make([]Parameter, 0)
|
systemParameters := make([]Parameter, 0)
|
||||||
// Resource action parameter
|
// Resource action parameter
|
||||||
@@ -726,15 +649,14 @@ metadata:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) createWorkspaceTemplate(namespace string, workspaceTemplate *WorkspaceTemplate) (*WorkspaceTemplate, error) {
|
func (c *Client) createWorkspaceTemplate(namespace string, workspaceTemplate *WorkspaceTemplate) (*WorkspaceTemplate, error) {
|
||||||
uid, err := uid2.GenerateUID(workspaceTemplate.Name, 30)
|
err := workspaceTemplate.GenerateUID(workspaceTemplate.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
workspaceTemplate.UID = uid
|
|
||||||
|
|
||||||
workspaceTemplate.WorkflowTemplate.IsSystem = true
|
workspaceTemplate.WorkflowTemplate.IsSystem = true
|
||||||
workspaceTemplate.WorkflowTemplate.Resource = ptr.String(TypeWorkspaceTemplate)
|
workspaceTemplate.WorkflowTemplate.Resource = ptr.String(TypeWorkspaceTemplate)
|
||||||
workspaceTemplate.WorkflowTemplate.ResourceUID = ptr.String(uid)
|
workspaceTemplate.WorkflowTemplate.ResourceUID = &workspaceTemplate.UID
|
||||||
|
|
||||||
// validate workflow template
|
// validate workflow template
|
||||||
if err := c.validateWorkflowTemplate(namespace, workspaceTemplate.WorkflowTemplate); err != nil {
|
if err := c.validateWorkflowTemplate(namespace, workspaceTemplate.WorkflowTemplate); err != nil {
|
||||||
@@ -761,7 +683,7 @@ func (c *Client) createWorkspaceTemplate(namespace string, workspaceTemplate *Wo
|
|||||||
defer tx.Rollback()
|
defer tx.Rollback()
|
||||||
err = sb.Insert("workspace_templates").
|
err = sb.Insert("workspace_templates").
|
||||||
SetMap(sq.Eq{
|
SetMap(sq.Eq{
|
||||||
"uid": uid,
|
"uid": workspaceTemplate.UID,
|
||||||
"name": workspaceTemplate.Name,
|
"name": workspaceTemplate.Name,
|
||||||
"namespace": namespace,
|
"namespace": namespace,
|
||||||
"workflow_template_id": workspaceTemplate.WorkflowTemplate.ID,
|
"workflow_template_id": workspaceTemplate.WorkflowTemplate.ID,
|
||||||
@@ -1049,26 +971,23 @@ func (c *Client) UpdateWorkspaceTemplate(namespace string, workspaceTemplate *Wo
|
|||||||
return workspaceTemplate, nil
|
return workspaceTemplate, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListWorkspaceTemplates returns a list of workspace templates that are not archived, sorted by most recent created first
|
||||||
func (c *Client) ListWorkspaceTemplates(namespace string, paginator *pagination.PaginationRequest) (workspaceTemplates []*WorkspaceTemplate, err error) {
|
func (c *Client) ListWorkspaceTemplates(namespace string, paginator *pagination.PaginationRequest) (workspaceTemplates []*WorkspaceTemplate, err error) {
|
||||||
sb := c.workspaceTemplatesSelectBuilder(namespace).
|
sb := c.workspaceTemplatesSelectBuilder(namespace).
|
||||||
Where(sq.Eq{
|
Where(sq.Eq{
|
||||||
"wt.is_archived": false,
|
"wt.is_archived": false,
|
||||||
}).
|
}).
|
||||||
OrderBy("wt.created_at DESC")
|
OrderBy("wt.created_at DESC")
|
||||||
|
|
||||||
sb = *paginator.ApplyToSelect(&sb)
|
sb = *paginator.ApplyToSelect(&sb)
|
||||||
|
|
||||||
query, args, err := sb.ToSql()
|
err = c.DB.Selectx(&workspaceTemplates, sb)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.DB.Select(&workspaceTemplates, query, args...); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListWorkspaceTemplateVersions returns an array of WorkspaceTemplates with the version information loaded. Latest id is first.
|
||||||
|
// Labels are also loaded.
|
||||||
func (c *Client) ListWorkspaceTemplateVersions(namespace, uid string) (workspaceTemplates []*WorkspaceTemplate, err error) {
|
func (c *Client) ListWorkspaceTemplateVersions(namespace, uid string) (workspaceTemplates []*WorkspaceTemplate, err error) {
|
||||||
sb := c.workspaceTemplateVersionsSelectBuilder(namespace, uid).
|
sb := c.workspaceTemplateVersionsSelectBuilder(namespace, uid).
|
||||||
Options("DISTINCT ON (wtv.version) wtv.version,").
|
Options("DISTINCT ON (wtv.version) wtv.version,").
|
||||||
@@ -1077,11 +996,8 @@ func (c *Client) ListWorkspaceTemplateVersions(namespace, uid string) (workspace
|
|||||||
"wft.is_archived": false,
|
"wft.is_archived": false,
|
||||||
}).
|
}).
|
||||||
OrderBy("wtv.version DESC")
|
OrderBy("wtv.version DESC")
|
||||||
query, args, err := sb.ToSql()
|
|
||||||
if err != nil {
|
if err = c.DB.Selectx(&workspaceTemplates, sb); err != nil {
|
||||||
return
|
|
||||||
}
|
|
||||||
if err = c.DB.Select(&workspaceTemplates, query, args...); err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1099,6 +1015,7 @@ func (c *Client) ListWorkspaceTemplateVersions(namespace, uid string) (workspace
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CountWorkspaceTemplates returns the total number of non-archived workspace templates for the input namespace
|
||||||
func (c *Client) CountWorkspaceTemplates(namespace string) (count int, err error) {
|
func (c *Client) CountWorkspaceTemplates(namespace string) (count int, err error) {
|
||||||
err = sb.Select("count(*)").
|
err = sb.Select("count(*)").
|
||||||
From("workspace_templates wt").
|
From("workspace_templates wt").
|
||||||
@@ -1189,6 +1106,9 @@ func (c *Client) ArchiveWorkspaceTemplate(namespace string, uid string) (archive
|
|||||||
}).Error("Get Workspace Template failed.")
|
}).Error("Get Workspace Template failed.")
|
||||||
return false, util.NewUserError(codes.Unknown, "Unable to archive workspace template.")
|
return false, util.NewUserError(codes.Unknown, "Unable to archive workspace template.")
|
||||||
}
|
}
|
||||||
|
if wsTemp == nil {
|
||||||
|
return false, fmt.Errorf("not found")
|
||||||
|
}
|
||||||
|
|
||||||
wsList, err := c.ListWorkspacesByTemplateID(namespace, wsTemp.WorkspaceTemplateVersionID)
|
wsList, err := c.ListWorkspacesByTemplateID(namespace, wsTemp.WorkspaceTemplateVersionID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -52,9 +52,78 @@ routes:
|
|||||||
workspaceTemplate = WorkspaceTemplate{
|
workspaceTemplate = WorkspaceTemplate{
|
||||||
Manifest: workspaceSpecManifest,
|
Manifest: workspaceSpecManifest,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jupyterLabWorkspaceManifest = `# Docker containers that are part of the Workspace
|
||||||
|
containers:
|
||||||
|
- name: jupyterlab-tensorflow
|
||||||
|
image: jupyter/tensorflow-notebook
|
||||||
|
command: [start.sh, jupyter]
|
||||||
|
workingDir: /data
|
||||||
|
env:
|
||||||
|
- name: tornado
|
||||||
|
value: "{ 'headers': { 'Content-Security-Policy': \"frame-ancestors * 'self'\" } }"
|
||||||
|
- name: GRANT_SUDO
|
||||||
|
value: 1
|
||||||
|
- name: CHOWN_EXTRA
|
||||||
|
value: '/data'
|
||||||
|
- name: CHOWN_EXTRA_OPTS
|
||||||
|
value: '-R'
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 0
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
args:
|
||||||
|
- lab
|
||||||
|
- --LabApp.token=''
|
||||||
|
- --LabApp.allow_remote_access=True
|
||||||
|
- --LabApp.allow_origin="*"
|
||||||
|
- --LabApp.disable_check_xsrf=True
|
||||||
|
- --LabApp.trust_xheaders=True
|
||||||
|
- --LabApp.tornado_settings=$(tornado)
|
||||||
|
- --NotebookApp.notebook_dir='/data'
|
||||||
|
ports:
|
||||||
|
- containerPort: 8888
|
||||||
|
name: jupyterlab
|
||||||
|
# Volumes to be mounted in this container
|
||||||
|
# Onepanel will automatically create these volumes and mount them to the container
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: /data
|
||||||
|
# Ports that need to be exposed
|
||||||
|
ports:
|
||||||
|
- name: jupyterlab
|
||||||
|
port: 80
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 8888
|
||||||
|
# Routes that will map to ports
|
||||||
|
routes:
|
||||||
|
- match:
|
||||||
|
- uri:
|
||||||
|
prefix: /
|
||||||
|
route:
|
||||||
|
- destination:
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
# DAG Workflow to be executed once a Workspace action completes
|
||||||
|
# postExecutionWorkflow:
|
||||||
|
# entrypoint: main
|
||||||
|
# templates:
|
||||||
|
# - name: main
|
||||||
|
# dag:
|
||||||
|
# tasks:
|
||||||
|
# - name: slack-notify
|
||||||
|
# template: slack-notify
|
||||||
|
# - name: slack-notify
|
||||||
|
# container:
|
||||||
|
# image: technosophos/slack-notify
|
||||||
|
# args:
|
||||||
|
# - SLACK_USERNAME=onepanel SLACK_TITLE="Your workspace is ready" SLACK_ICON=https://www.gravatar.com/avatar/5c4478592fe00878f62f0027be59c1bd SLACK_MESSAGE="Your workspace is now running" ./slack-notify
|
||||||
|
# command:
|
||||||
|
# - sh
|
||||||
|
# - -c
|
||||||
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseWorkspaceSpec(t *testing.T) {
|
func Test_ParseWorkspaceSpec(t *testing.T) {
|
||||||
workspaceSpec, err := parseWorkspaceSpec(workspaceSpecManifest)
|
workspaceSpec, err := parseWorkspaceSpec(workspaceSpecManifest)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.NotEmpty(t, workspaceSpec)
|
assert.NotEmpty(t, workspaceSpec)
|
||||||
@@ -65,3 +134,151 @@ func TestParseWorkspaceSpec(t *testing.T) {
|
|||||||
assert.Equal(t, workspaceSpec.Containers[0].Ports[0].ContainerPort, int32(80))
|
assert.Equal(t, workspaceSpec.Containers[0].Ports[0].ContainerPort, int32(80))
|
||||||
assert.Equal(t, workspaceSpec.Containers[1].Ports[0].ContainerPort, int32(443))
|
assert.Equal(t, workspaceSpec.Containers[1].Ports[0].ContainerPort, int32(443))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// testClientCreateWorkspaceTemplateNew creates a new workspace template
|
||||||
|
func testClientCreateWorkspaceTemplateNew(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
|
||||||
|
wt := &WorkspaceTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: jupyterLabWorkspaceManifest,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := c.CreateWorkspaceTemplate(namespace, wt)
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testClientCreateWorkspaceTemplateDuplicateName attempts to create a workspace template for a name that already exists
|
||||||
|
// this should error
|
||||||
|
func testClientCreateWorkspaceTemplateDuplicateName(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
|
||||||
|
wt := &WorkspaceTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: jupyterLabWorkspaceManifest,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := c.CreateWorkspaceTemplate(namespace, wt)
|
||||||
|
_, err = c.CreateWorkspaceTemplate(namespace, wt)
|
||||||
|
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testClientCreateWorkspaceTemplateArchivedName attempts to create a workspace template for a name that has been archived
|
||||||
|
// this should work
|
||||||
|
func testClientCreateWorkspaceTemplateArchivedName(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
|
||||||
|
wt := &WorkspaceTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: jupyterLabWorkspaceManifest,
|
||||||
|
}
|
||||||
|
|
||||||
|
wtCreated, err := c.CreateWorkspaceTemplate(namespace, wt)
|
||||||
|
_, err = c.ArchiveWorkspaceTemplate(namespace, wtCreated.UID)
|
||||||
|
_, err = c.CreateWorkspaceTemplate(namespace, wt)
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestClient_CreateWorkspaceTemplate tests creating a workspace template
|
||||||
|
func TestClient_CreateWorkspaceTemplate(t *testing.T) {
|
||||||
|
testClientCreateWorkspaceTemplateNew(t)
|
||||||
|
testClientCreateWorkspaceTemplateDuplicateName(t)
|
||||||
|
testClientCreateWorkspaceTemplateArchivedName(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testClientArchiveWorkspaceTemplateSuccess(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
|
||||||
|
wt := &WorkspaceTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: jupyterLabWorkspaceManifest,
|
||||||
|
}
|
||||||
|
|
||||||
|
testTemplate, _ := c.CreateWorkspaceTemplate(namespace, wt)
|
||||||
|
archived, err := c.ArchiveWorkspaceTemplate(namespace, testTemplate.UID)
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.True(t, archived)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testClientArchiveWorkspaceTemplateNotFound tests the case where you try to archive a non-existing workspace template
|
||||||
|
func testClientArchiveWorkspaceTemplateNotFound(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
|
||||||
|
archived, err := c.ArchiveWorkspaceTemplate(namespace, "not-found")
|
||||||
|
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
assert.False(t, archived)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestClient_ArchiveWorkspaceTemplate tests archiving a workspace template
|
||||||
|
func TestClient_ArchiveWorkspaceTemplate(t *testing.T) {
|
||||||
|
testClientArchiveWorkspaceTemplateSuccess(t)
|
||||||
|
testClientArchiveWorkspaceTemplateNotFound(t)
|
||||||
|
|
||||||
|
// TODO we need more tests here to make sure the related resources are cleaned up, including workspaces and workflow templates
|
||||||
|
}
|
||||||
|
|
||||||
|
// testClientListWorkspaceTemplatesEmpty tests listing workspace templates when there are none
|
||||||
|
func testClientListWorkspaceTemplatesEmpty(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
templates, err := c.ListWorkspaceTemplates("onepanel", nil)
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Empty(t, templates)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testClientListWorkspaceTemplatesNotEmpty tests listing workspaces when there are records that are
|
||||||
|
// archived and not. It should only list the non-archived ones
|
||||||
|
func testClientListWorkspaceTemplatesNotEmpty(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
|
||||||
|
wt := &WorkspaceTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: jupyterLabWorkspaceManifest,
|
||||||
|
}
|
||||||
|
|
||||||
|
testTemplate, _ := c.CreateWorkspaceTemplate(namespace, wt)
|
||||||
|
c.ArchiveWorkspaceTemplate(namespace, testTemplate.UID)
|
||||||
|
|
||||||
|
wt2 := &WorkspaceTemplate{
|
||||||
|
Name: "test2",
|
||||||
|
Manifest: jupyterLabWorkspaceManifest,
|
||||||
|
}
|
||||||
|
|
||||||
|
wt2, _ = c.CreateWorkspaceTemplate(namespace, wt2)
|
||||||
|
|
||||||
|
templates, err := c.ListWorkspaceTemplates(namespace, nil)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, 1, len(templates))
|
||||||
|
assert.Equal(t, wt2.UID, templates[0].UID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestClient_ListWorkspaceTemplates tests listing workspace templates
|
||||||
|
func TestClient_ListWorkspaceTemplates(t *testing.T) {
|
||||||
|
testClientListWorkspaceTemplatesEmpty(t)
|
||||||
|
testClientListWorkspaceTemplatesNotEmpty(t)
|
||||||
|
}
|
||||||
|
@@ -3,6 +3,7 @@ package v1
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1"
|
wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1"
|
||||||
|
uid2 "github.com/onepanelio/core/pkg/util/uid"
|
||||||
"github.com/onepanelio/core/util/sql"
|
"github.com/onepanelio/core/util/sql"
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
"time"
|
"time"
|
||||||
@@ -25,6 +26,18 @@ type WorkspaceTemplate struct {
|
|||||||
WorkflowTemplateID uint64 `db:"workflow_template_id"`
|
WorkflowTemplateID uint64 `db:"workflow_template_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateUID generates a uid from the input name and sets it on the workflow template
|
||||||
|
func (wt *WorkspaceTemplate) GenerateUID(name string) error {
|
||||||
|
result, err := uid2.GenerateUID(name, 30)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
wt.UID = result
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// InjectRuntimeParameters will inject all runtime variables into the WorkflowTemplate's manifest.
|
// InjectRuntimeParameters will inject all runtime variables into the WorkflowTemplate's manifest.
|
||||||
func (wt *WorkspaceTemplate) InjectRuntimeParameters(config SystemConfig) error {
|
func (wt *WorkspaceTemplate) InjectRuntimeParameters(config SystemConfig) error {
|
||||||
if wt.WorkflowTemplate == nil {
|
if wt.WorkflowTemplate == nil {
|
||||||
|
314
pkg/workspace_test.go
Normal file
314
pkg/workspace_test.go
Normal file
@@ -0,0 +1,314 @@
|
|||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lib/pq"
|
||||||
|
"github.com/onepanelio/core/pkg/util"
|
||||||
|
"github.com/onepanelio/core/pkg/util/ptr"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func testWorkspaceStatusToFieldMapLaunching(t *testing.T) {
|
||||||
|
fm := workspaceStatusToFieldMap(&WorkspaceStatus{Phase: WorkspaceLaunching})
|
||||||
|
|
||||||
|
assert.Equal(t, fm["phase"], WorkspaceLaunching)
|
||||||
|
assert.Equal(t, fm["paused_at"], pq.NullTime{})
|
||||||
|
|
||||||
|
started := fm["started_at"].(time.Time)
|
||||||
|
|
||||||
|
assert.True(t, started.After(time.Time{}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testWorkspaceStatusToFieldMapPausing(t *testing.T) {
|
||||||
|
fm := workspaceStatusToFieldMap(&WorkspaceStatus{Phase: WorkspacePausing})
|
||||||
|
|
||||||
|
assert.Equal(t, fm["phase"], WorkspacePausing)
|
||||||
|
assert.Equal(t, fm["started_at"], pq.NullTime{})
|
||||||
|
|
||||||
|
paused := fm["paused_at"].(time.Time)
|
||||||
|
|
||||||
|
assert.True(t, paused.After(time.Time{}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testWorkspaceStatusToFieldMapUpdating(t *testing.T) {
|
||||||
|
fm := workspaceStatusToFieldMap(&WorkspaceStatus{Phase: WorkspaceUpdating})
|
||||||
|
|
||||||
|
assert.Equal(t, fm["phase"], WorkspaceUpdating)
|
||||||
|
assert.Equal(t, fm["paused_at"], pq.NullTime{})
|
||||||
|
|
||||||
|
updated := fm["updated_at"].(time.Time)
|
||||||
|
|
||||||
|
assert.True(t, updated.After(time.Time{}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testWorkspaceStatusToFieldMapTerminating(t *testing.T) {
|
||||||
|
fm := workspaceStatusToFieldMap(&WorkspaceStatus{Phase: WorkspaceTerminating})
|
||||||
|
|
||||||
|
assert.Equal(t, fm["phase"], WorkspaceTerminating)
|
||||||
|
assert.Equal(t, fm["paused_at"], pq.NullTime{})
|
||||||
|
assert.Equal(t, fm["started_at"], pq.NullTime{})
|
||||||
|
|
||||||
|
terminated := fm["terminated_at"].(time.Time)
|
||||||
|
|
||||||
|
assert.True(t, terminated.After(time.Time{}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_WorkspaceStatusToFieldMap(t *testing.T) {
|
||||||
|
testWorkspaceStatusToFieldMapLaunching(t)
|
||||||
|
testWorkspaceStatusToFieldMapPausing(t)
|
||||||
|
testWorkspaceStatusToFieldMapUpdating(t)
|
||||||
|
testWorkspaceStatusToFieldMapTerminating(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testClientPrivateCreateWorkspaceNoWorkflowTemplate makes sure we get an error when there is no workflow template for the workspace
|
||||||
|
func testClientPrivateCreateWorkspaceNoWorkflowTemplate(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
|
||||||
|
workspace := &Workspace{
|
||||||
|
Name: "test",
|
||||||
|
WorkspaceTemplate: &WorkspaceTemplate{
|
||||||
|
WorkflowTemplate: &WorkflowTemplate{
|
||||||
|
UID: "not-exist",
|
||||||
|
Version: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
workspace.GenerateUID("test")
|
||||||
|
|
||||||
|
_, err := c.createWorkspace(namespace, []byte(""), workspace)
|
||||||
|
|
||||||
|
userErr, ok := err.(*util.UserError)
|
||||||
|
assert.True(t, ok)
|
||||||
|
assert.Equal(t, userErr.Code, codes.NotFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
// testClientPrivateCreateWorkspaceSuccess tests creating a workspace successfully
|
||||||
|
func testClientPrivateCreateWorkspaceSuccess(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
|
||||||
|
workspaceTemplate := &WorkspaceTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: jupyterLabWorkspaceManifest,
|
||||||
|
}
|
||||||
|
|
||||||
|
workspaceTemplate, _ = c.CreateWorkspaceTemplate(namespace, workspaceTemplate)
|
||||||
|
|
||||||
|
workspace := &Workspace{
|
||||||
|
Name: "test2",
|
||||||
|
WorkspaceTemplate: workspaceTemplate,
|
||||||
|
Parameters: []Parameter{
|
||||||
|
{
|
||||||
|
Name: "workflow-execution-name",
|
||||||
|
Value: ptr.String("test2"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
workspace.GenerateUID("test")
|
||||||
|
|
||||||
|
_, err := c.createWorkspace(namespace, []byte("{}"), workspace)
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_createWorkspace(t *testing.T) {
|
||||||
|
testClientPrivateCreateWorkspaceNoWorkflowTemplate(t)
|
||||||
|
testClientPrivateCreateWorkspaceSuccess(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testClientCreateWorkspaceSuccess(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
|
||||||
|
wt := &WorkspaceTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: jupyterLabWorkspaceManifest,
|
||||||
|
}
|
||||||
|
|
||||||
|
testTemplate, _ := c.CreateWorkspaceTemplate(namespace, wt)
|
||||||
|
|
||||||
|
workspace := &Workspace{
|
||||||
|
Name: "test",
|
||||||
|
WorkspaceTemplate: &WorkspaceTemplate{
|
||||||
|
UID: testTemplate.UID,
|
||||||
|
Version: testTemplate.Version,
|
||||||
|
},
|
||||||
|
Parameters: []Parameter{
|
||||||
|
{
|
||||||
|
Name: "workflow-execution-name",
|
||||||
|
Value: ptr.String("test2"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
createdWorkspace, err := c.CreateWorkspace(namespace, workspace)
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, createdWorkspace)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_CreateWorkspace(t *testing.T) {
|
||||||
|
testClientCreateWorkspaceSuccess(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_ArchiveWorkspace(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
|
||||||
|
workspaceTemplate := &WorkspaceTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: jupyterLabWorkspaceManifest,
|
||||||
|
}
|
||||||
|
|
||||||
|
workspaceTemplate, _ = c.CreateWorkspaceTemplate(namespace, workspaceTemplate)
|
||||||
|
|
||||||
|
workspace := &Workspace{
|
||||||
|
Name: "test2",
|
||||||
|
WorkspaceTemplate: workspaceTemplate,
|
||||||
|
Parameters: []Parameter{
|
||||||
|
{
|
||||||
|
Name: "workflow-execution-name",
|
||||||
|
Value: ptr.String("test2"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
workspace.GenerateUID("test")
|
||||||
|
|
||||||
|
createdWorkspace, _ := c.createWorkspace(namespace, []byte("[]"), workspace)
|
||||||
|
|
||||||
|
params := []Parameter{
|
||||||
|
{
|
||||||
|
Name: "workflow-execution-name",
|
||||||
|
Value: ptr.String("test3"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
err := c.ArchiveWorkspace(namespace, createdWorkspace.UID, params...)
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestClient_ListWorkspacesByTemplateID tests listing workspaces by the template id
|
||||||
|
func TestClient_ListWorkspacesByTemplateID(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
|
||||||
|
wt := &WorkspaceTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: jupyterLabWorkspaceManifest,
|
||||||
|
}
|
||||||
|
|
||||||
|
testTemplate, _ := c.CreateWorkspaceTemplate(namespace, wt)
|
||||||
|
workspace := &Workspace{
|
||||||
|
Name: "test",
|
||||||
|
WorkspaceTemplate: testTemplate,
|
||||||
|
Parameters: []Parameter{
|
||||||
|
{
|
||||||
|
Name: "workflow-execution-name",
|
||||||
|
Value: ptr.String("test"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
workspace.GenerateUID("test")
|
||||||
|
|
||||||
|
c.createWorkspace(namespace, []byte("[]"), workspace)
|
||||||
|
|
||||||
|
wt2 := &WorkspaceTemplate{
|
||||||
|
Name: "test2",
|
||||||
|
Manifest: jupyterLabWorkspaceManifest,
|
||||||
|
}
|
||||||
|
|
||||||
|
testTemplate2, _ := c.CreateWorkspaceTemplate(namespace, wt2)
|
||||||
|
workspace2 := &Workspace{
|
||||||
|
Name: "test2",
|
||||||
|
WorkspaceTemplate: testTemplate2,
|
||||||
|
Parameters: []Parameter{
|
||||||
|
{
|
||||||
|
Name: "workflow-execution-name",
|
||||||
|
Value: ptr.String("test2"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
workspace2.GenerateUID("test2")
|
||||||
|
|
||||||
|
c.createWorkspace(namespace, []byte("[]"), workspace2)
|
||||||
|
|
||||||
|
workspaces, err := c.ListWorkspacesByTemplateID(namespace, testTemplate.ID)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, 1, len(workspaces))
|
||||||
|
|
||||||
|
params := []Parameter{
|
||||||
|
{
|
||||||
|
Name: "workflow-execution-name",
|
||||||
|
Value: ptr.String("test3"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
c.ArchiveWorkspace(namespace, testTemplate.UID, params...)
|
||||||
|
|
||||||
|
workspaces, err = c.ListWorkspacesByTemplateID(namespace, testTemplate.ID)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.True(t, workspaces[0].Status.Phase == WorkspaceTerminating)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUpdateWorkspaceStatusSuccess(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
namespace := "onepanel"
|
||||||
|
|
||||||
|
workspace := &Workspace{
|
||||||
|
Name: "test",
|
||||||
|
Parameters: []Parameter{
|
||||||
|
{
|
||||||
|
Name: "workflow-execution-name",
|
||||||
|
Value: ptr.String("test"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
WorkspaceTemplate: &WorkspaceTemplate{
|
||||||
|
Name: "test",
|
||||||
|
Manifest: jupyterLabWorkspaceManifest,
|
||||||
|
WorkflowTemplate: &WorkflowTemplate{
|
||||||
|
UID: "test",
|
||||||
|
Version: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
workspace.GenerateUID("test")
|
||||||
|
|
||||||
|
c.CreateWorkspaceTemplate(namespace, workspace.WorkspaceTemplate)
|
||||||
|
ws, _ := c.createWorkspace(namespace, []byte("[]"), workspace)
|
||||||
|
|
||||||
|
err := c.UpdateWorkspaceStatus(namespace, ws.UID, &WorkspaceStatus{Phase: WorkspacePausing})
|
||||||
|
|
||||||
|
assert.Nil(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUpdateWorkspaceStatusNotFound(t *testing.T) {
|
||||||
|
c := DefaultTestClient()
|
||||||
|
clearDatabase(t)
|
||||||
|
|
||||||
|
err := c.UpdateWorkspaceStatus("not-found", "random", &WorkspaceStatus{Phase: WorkspacePausing})
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
|
||||||
|
userErr, ok := err.(*util.UserError)
|
||||||
|
assert.True(t, ok)
|
||||||
|
|
||||||
|
assert.Equal(t, userErr.Code, codes.NotFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_UpdateWorkspaceStatus(t *testing.T) {
|
||||||
|
testUpdateWorkspaceStatusSuccess(t)
|
||||||
|
testUpdateWorkspaceStatusNotFound(t)
|
||||||
|
}
|
@@ -3,6 +3,7 @@ package v1
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1"
|
wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1"
|
||||||
|
uid2 "github.com/onepanelio/core/pkg/util/uid"
|
||||||
"github.com/onepanelio/core/util/sql"
|
"github.com/onepanelio/core/util/sql"
|
||||||
networking "istio.io/api/networking/v1alpha3"
|
networking "istio.io/api/networking/v1alpha3"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
@@ -63,6 +64,29 @@ func (w *Workspace) GetURL(protocol, domain string) string {
|
|||||||
return fmt.Sprintf("%v%v--%v.%v", protocol, w.UID, w.Namespace, domain)
|
return fmt.Sprintf("%v%v--%v.%v", protocol, w.UID, w.Namespace, domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetParameterValue returns the value of the parameter with the given name, or nil if there is no such parameter
|
||||||
|
func (w *Workspace) GetParameterValue(name string) *string {
|
||||||
|
for _, p := range w.Parameters {
|
||||||
|
if p.Name == name {
|
||||||
|
return p.Value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateUID generates a uid from the input name and sets it on the workspace
|
||||||
|
func (w *Workspace) GenerateUID(name string) error {
|
||||||
|
result, err := uid2.GenerateUID(name, 30)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
w.UID = result
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// getWorkspaceColumns returns all of the columns for workspace modified by alias, destination.
|
// getWorkspaceColumns returns all of the columns for workspace modified by alias, destination.
|
||||||
// see formatColumnSelect
|
// see formatColumnSelect
|
||||||
func getWorkspaceColumns(aliasAndDestination ...string) []string {
|
func getWorkspaceColumns(aliasAndDestination ...string) []string {
|
||||||
|
@@ -28,7 +28,7 @@ func assertWorkspaceNameValid(t *testing.T, name string) {
|
|||||||
assert.True(t, valid)
|
assert.True(t, valid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWorkspaceNameValidation_RegexValid(t *testing.T) {
|
func Test_WorkspaceNameValidation_RegexValid(t *testing.T) {
|
||||||
assertWorkspaceNameInvalid(t, "600s")
|
assertWorkspaceNameInvalid(t, "600s")
|
||||||
|
|
||||||
assertWorkspaceNameValid(t, "test-5")
|
assertWorkspaceNameValid(t, "test-5")
|
||||||
|
@@ -105,27 +105,6 @@ func (s *WorkflowTemplateServer) CreateWorkflowTemplateVersion(ctx context.Conte
|
|||||||
return req.WorkflowTemplate, nil
|
return req.WorkflowTemplate, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *WorkflowTemplateServer) UpdateWorkflowTemplateVersion(ctx context.Context, req *api.UpdateWorkflowTemplateVersionRequest) (*api.WorkflowTemplate, error) {
|
|
||||||
client := getClient(ctx)
|
|
||||||
allowed, err := auth.IsAuthorized(client, req.Namespace, "update", "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,
|
|
||||||
Version: req.WorkflowTemplate.Version,
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
func (s *WorkflowTemplateServer) GetWorkflowTemplate(ctx context.Context, req *api.GetWorkflowTemplateRequest) (*api.WorkflowTemplate, error) {
|
||||||
client := getClient(ctx)
|
client := getClient(ctx)
|
||||||
allowed, err := auth.IsAuthorized(client, req.Namespace, "get", "argoproj.io", "workflowtemplates", "")
|
allowed, err := auth.IsAuthorized(client, req.Namespace, "get", "argoproj.io", "workflowtemplates", "")
|
||||||
|
Reference in New Issue
Block a user