mirror of
				https://github.com/onepanelio/onepanel.git
				synced 2025-10-31 16:56:19 +08:00 
			
		
		
		
	Compare commits
	
		
			18 Commits
		
	
	
		
			v0.12.0-rc
			...
			v0.12.0-rc
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 0ffa3aee32 | ||
|   | 35982bf85a | ||
|   | ecadd189a2 | ||
|   | b68de30418 | ||
|   | dedc295441 | ||
|   | 2108691f68 | ||
|   | 0262a9ec90 | ||
|   | c6c8e80516 | ||
|   | 9381dd0a85 | ||
|   | b6f7118a43 | ||
|   | f7b941f8a0 | ||
|   | e00a54c24e | ||
|   | 8d29cd0c5c | ||
|   | dafaadd80a | ||
|   | 4f036468b0 | ||
|   | 8df966fcee | ||
|   | cfd9bc6f43 | ||
|   | 3ee8497cac | 
							
								
								
									
										16
									
								
								.github/PULL_REQUEST_TEMPLATE.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								.github/PULL_REQUEST_TEMPLATE.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| <!--  Thanks for sending a pull request! Here are some tips for you: | ||||
| 1. Please read our contributor guidelines: https://docs.onepanel.ai/docs/getting-started/contributing | ||||
| 2. Prefix the title of this PR with `feat:`, `fix:`, `docs:` or `chore:`, example: `feat: added great feature` | ||||
| 3. If this PR is a feature or enhancement, then create an issue (https://github.com/onepanelio/core/issues) first.  | ||||
| --> | ||||
|  | ||||
| **What this PR does**: | ||||
|  | ||||
| **Which issue(s) this PR fixes**: | ||||
| <!-- | ||||
| *Automatically closes linked issue when PR is merged. | ||||
| Usage: `Fixes onepanelio/core#<issue-number>` | ||||
| --> | ||||
| Fixes onepanelio/core# | ||||
|  | ||||
| **Special notes for your reviewer**: | ||||
							
								
								
									
										4
									
								
								.github/issue_label_bot.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.github/issue_label_bot.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| label-alias: | ||||
|   bug: 'kind/bug' | ||||
|   feature_request: 'kind/enhancement' | ||||
|   question: 'kind/question' | ||||
							
								
								
									
										1
									
								
								.github/semantic.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.github/semantic.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| titleOnly: true | ||||
							
								
								
									
										26
									
								
								.github/workflows/run_unit_tests.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								.github/workflows/run_unit_tests.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -1,26 +0,0 @@ | ||||
| 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 | ||||
							
								
								
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							| @@ -1,3 +1,5 @@ | ||||
|                 Copyright 2020 Onepanel, Inc.  All rights reserved. | ||||
|                  | ||||
|                                  Apache License | ||||
|                            Version 2.0, January 2004 | ||||
|                         http://www.apache.org/licenses/ | ||||
|   | ||||
							
								
								
									
										5
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								Makefile
									
									
									
									
									
								
							| @@ -34,8 +34,3 @@ docker-push: | ||||
| 	docker push onepanel/core:$(COMMIT_HASH) | ||||
|  | ||||
| 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 | ||||
| @@ -1,3 +1,5 @@ | ||||
|  | ||||
|  | ||||
| # Onepanel | ||||
|  | ||||
| Welcome to Onepanel! This is the main repository for the API. It is also where you can submit bugs and enhancement requests. | ||||
| @@ -10,4 +12,4 @@ See our [Quick start guide](https://docs.onepanel.ai/docs/getting-started/quicks | ||||
| See our [Contribution guide](https://docs.onepanel.ai/docs/getting-started/contributing) to get started. | ||||
|  | ||||
| ## Acknowledgments | ||||
| Onepanel uses the excellent [Argo](https://github.com/argoproj/argo) project under the hood to orchestrate workflows. | ||||
| Onepanel uses the excellent [Argo](https://github.com/argoproj/argo) project under the hood to orchestrate workflows. | ||||
|   | ||||
| @@ -31,8 +31,8 @@ var file_api_proto_rawDesc = []byte{ | ||||
| 	0x0a, 0x09, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x61, 0x70, 0x69, | ||||
| 	0x1a, 0x2c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x73, 0x77, 0x61, | ||||
| 	0x67, 0x67, 0x65, 0x72, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x61, 0x6e, 0x6e, | ||||
| 	0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x89, | ||||
| 	0x02, 0x92, 0x41, 0x85, 0x02, 0x12, 0x58, 0x0a, 0x08, 0x4f, 0x6e, 0x65, 0x70, 0x61, 0x6e, 0x65, | ||||
| 	0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0xef, | ||||
| 	0x01, 0x92, 0x41, 0xeb, 0x01, 0x12, 0x58, 0x0a, 0x08, 0x4f, 0x6e, 0x65, 0x70, 0x61, 0x6e, 0x65, | ||||
| 	0x6c, 0x12, 0x0c, 0x4f, 0x6e, 0x65, 0x70, 0x61, 0x6e, 0x65, 0x6c, 0x20, 0x41, 0x50, 0x49, 0x22, | ||||
| 	0x36, 0x0a, 0x10, 0x4f, 0x6e, 0x65, 0x70, 0x61, 0x6e, 0x65, 0x6c, 0x20, 0x70, 0x72, 0x6f, 0x6a, | ||||
| 	0x65, 0x63, 0x74, 0x12, 0x22, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, | ||||
| @@ -41,15 +41,13 @@ var file_api_proto_rawDesc = []byte{ | ||||
| 	0x0e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x3a, 0x38, 0x38, 0x38, 0x38, 0x2a, | ||||
| 	0x02, 0x01, 0x02, 0x32, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, | ||||
| 	0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, | ||||
| 	0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x18, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, | ||||
| 	0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, | ||||
| 	0x6d, 0x5a, 0x49, 0x0a, 0x47, 0x0a, 0x06, 0x42, 0x65, 0x61, 0x72, 0x65, 0x72, 0x12, 0x3d, 0x08, | ||||
| 	0x02, 0x12, 0x28, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, | ||||
| 	0x6e, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2c, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x65, | ||||
| 	0x64, 0x20, 0x62, 0x79, 0x20, 0x42, 0x65, 0x61, 0x72, 0x65, 0x72, 0x1a, 0x0d, 0x61, 0x75, 0x74, | ||||
| 	0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x02, 0x62, 0x0c, 0x0a, 0x0a, | ||||
| 	0x0a, 0x06, 0x42, 0x65, 0x61, 0x72, 0x65, 0x72, 0x12, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, | ||||
| 	0x6f, 0x33, | ||||
| 	0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x5a, 0x49, 0x0a, 0x47, 0x0a, 0x06, 0x42, 0x65, 0x61, | ||||
| 	0x72, 0x65, 0x72, 0x12, 0x3d, 0x08, 0x02, 0x12, 0x28, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, | ||||
| 	0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2c, 0x20, 0x70, | ||||
| 	0x72, 0x65, 0x66, 0x69, 0x78, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x42, 0x65, 0x61, 0x72, 0x65, | ||||
| 	0x72, 0x1a, 0x0d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, | ||||
| 	0x20, 0x02, 0x62, 0x0c, 0x0a, 0x0a, 0x0a, 0x06, 0x42, 0x65, 0x61, 0x72, 0x65, 0x72, 0x12, 0x00, | ||||
| 	0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, | ||||
| } | ||||
|  | ||||
| var file_api_proto_goTypes = []interface{}{} | ||||
|   | ||||
| @@ -19,7 +19,6 @@ option (grpc.gateway.protoc_gen_swagger.options.openapiv2_swagger) = { | ||||
| 	schemes: HTTPS; | ||||
| 	consumes: "application/json"; | ||||
| 	produces: "application/json"; | ||||
| 	produces: "application/octet-stream"; | ||||
| 	security_definitions: { | ||||
| 		security: { | ||||
| 			key: "Bearer"; | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
|   "info": { | ||||
|     "title": "Onepanel", | ||||
|     "description": "Onepanel API", | ||||
|     "version": "0.12.0-rc.0", | ||||
|     "version": "0.11.0", | ||||
|     "contact": { | ||||
|       "name": "Onepanel project", | ||||
|       "url": "https://github.com/onepanelio/core" | ||||
| @@ -18,8 +18,7 @@ | ||||
|     "application/json" | ||||
|   ], | ||||
|   "produces": [ | ||||
|     "application/json", | ||||
|     "application/octet-stream" | ||||
|     "application/json" | ||||
|   ], | ||||
|   "paths": { | ||||
|     "/apis/v1beta1/auth": { | ||||
| @@ -734,86 +733,6 @@ | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|     "/apis/v1beta1/{namespace}/service": { | ||||
|       "get": { | ||||
|         "operationId": "ListServices", | ||||
|         "responses": { | ||||
|           "200": { | ||||
|             "description": "A successful response.", | ||||
|             "schema": { | ||||
|               "$ref": "#/definitions/ListServicesResponse" | ||||
|             } | ||||
|           }, | ||||
|           "default": { | ||||
|             "description": "An unexpected error response", | ||||
|             "schema": { | ||||
|               "$ref": "#/definitions/grpc.gateway.runtime.Error" | ||||
|             } | ||||
|           } | ||||
|         }, | ||||
|         "parameters": [ | ||||
|           { | ||||
|             "name": "namespace", | ||||
|             "in": "path", | ||||
|             "required": true, | ||||
|             "type": "string" | ||||
|           }, | ||||
|           { | ||||
|             "name": "pageSize", | ||||
|             "in": "query", | ||||
|             "required": false, | ||||
|             "type": "integer", | ||||
|             "format": "int32" | ||||
|           }, | ||||
|           { | ||||
|             "name": "page", | ||||
|             "in": "query", | ||||
|             "required": false, | ||||
|             "type": "integer", | ||||
|             "format": "int32" | ||||
|           } | ||||
|         ], | ||||
|         "tags": [ | ||||
|           "ServiceService" | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|     "/apis/v1beta1/{namespace}/service/{name}": { | ||||
|       "get": { | ||||
|         "operationId": "GetService", | ||||
|         "responses": { | ||||
|           "200": { | ||||
|             "description": "A successful response.", | ||||
|             "schema": { | ||||
|               "$ref": "#/definitions/Service" | ||||
|             } | ||||
|           }, | ||||
|           "default": { | ||||
|             "description": "An unexpected error response", | ||||
|             "schema": { | ||||
|               "$ref": "#/definitions/grpc.gateway.runtime.Error" | ||||
|             } | ||||
|           } | ||||
|         }, | ||||
|         "parameters": [ | ||||
|           { | ||||
|             "name": "namespace", | ||||
|             "in": "path", | ||||
|             "required": true, | ||||
|             "type": "string" | ||||
|           }, | ||||
|           { | ||||
|             "name": "name", | ||||
|             "in": "path", | ||||
|             "required": true, | ||||
|             "type": "string" | ||||
|           } | ||||
|         ], | ||||
|         "tags": [ | ||||
|           "ServiceService" | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|     "/apis/v1beta1/{namespace}/workflow_executions": { | ||||
|       "get": { | ||||
|         "operationId": "ListWorkflowExecutions", | ||||
| @@ -1445,12 +1364,6 @@ | ||||
|             "required": false, | ||||
|             "type": "integer", | ||||
|             "format": "int32" | ||||
|           }, | ||||
|           { | ||||
|             "name": "labels", | ||||
|             "in": "query", | ||||
|             "required": false, | ||||
|             "type": "string" | ||||
|           } | ||||
|         ], | ||||
|         "tags": [ | ||||
| @@ -1794,6 +1707,57 @@ | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|     "/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": { | ||||
|       "get": { | ||||
|         "operationId": "ListWorkspaceTemplates", | ||||
| @@ -2907,33 +2871,6 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "ListServicesResponse": { | ||||
|       "type": "object", | ||||
|       "properties": { | ||||
|         "count": { | ||||
|           "type": "integer", | ||||
|           "format": "int32" | ||||
|         }, | ||||
|         "services": { | ||||
|           "type": "array", | ||||
|           "items": { | ||||
|             "$ref": "#/definitions/Service" | ||||
|           } | ||||
|         }, | ||||
|         "page": { | ||||
|           "type": "integer", | ||||
|           "format": "int32" | ||||
|         }, | ||||
|         "pages": { | ||||
|           "type": "integer", | ||||
|           "format": "int32" | ||||
|         }, | ||||
|         "totalCount": { | ||||
|           "type": "integer", | ||||
|           "format": "int32" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "ListWorkflowExecutionsResponse": { | ||||
|       "type": "object", | ||||
|       "properties": { | ||||
| @@ -3153,9 +3090,6 @@ | ||||
|           "type": "boolean", | ||||
|           "format": "boolean" | ||||
|         }, | ||||
|         "visibility": { | ||||
|           "type": "string" | ||||
|         }, | ||||
|         "options": { | ||||
|           "type": "array", | ||||
|           "items": { | ||||
| @@ -3198,17 +3132,6 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "Service": { | ||||
|       "type": "object", | ||||
|       "properties": { | ||||
|         "name": { | ||||
|           "type": "string" | ||||
|         }, | ||||
|         "url": { | ||||
|           "type": "string" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "Statistics": { | ||||
|       "type": "object", | ||||
|       "properties": { | ||||
| @@ -3293,17 +3216,6 @@ | ||||
|           "items": { | ||||
|             "$ref": "#/definitions/KeyValue" | ||||
|           } | ||||
|         }, | ||||
|         "metadata": { | ||||
|           "$ref": "#/definitions/WorkflowExecutionMetadata" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "WorkflowExecutionMetadata": { | ||||
|       "type": "object", | ||||
|       "properties": { | ||||
|         "url": { | ||||
|           "type": "string" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
| @@ -3388,12 +3300,6 @@ | ||||
|         }, | ||||
|         "cronStats": { | ||||
|           "$ref": "#/definitions/CronWorkflowStatisticsReport" | ||||
|         }, | ||||
|         "parameters": { | ||||
|           "type": "array", | ||||
|           "items": { | ||||
|             "$ref": "#/definitions/Parameter" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
| @@ -3494,9 +3400,6 @@ | ||||
|         "isArchived": { | ||||
|           "type": "boolean", | ||||
|           "format": "boolean" | ||||
|         }, | ||||
|         "description": { | ||||
|           "type": "string" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|   | ||||
| @@ -36,8 +36,7 @@ type Parameter struct { | ||||
| 	DisplayName string             `protobuf:"bytes,4,opt,name=displayName,proto3" json:"displayName,omitempty"` | ||||
| 	Hint        string             `protobuf:"bytes,5,opt,name=hint,proto3" json:"hint,omitempty"` | ||||
| 	Required    bool               `protobuf:"varint,6,opt,name=required,proto3" json:"required,omitempty"` | ||||
| 	Visibility  string             `protobuf:"bytes,7,opt,name=visibility,proto3" json:"visibility,omitempty"` | ||||
| 	Options     []*ParameterOption `protobuf:"bytes,8,rep,name=options,proto3" json:"options,omitempty"` | ||||
| 	Options     []*ParameterOption `protobuf:"bytes,7,rep,name=options,proto3" json:"options,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *Parameter) Reset() { | ||||
| @@ -114,13 +113,6 @@ func (x *Parameter) GetRequired() bool { | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func (x *Parameter) GetVisibility() string { | ||||
| 	if x != nil { | ||||
| 		return x.Visibility | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (x *Parameter) GetOptions() []*ParameterOption { | ||||
| 	if x != nil { | ||||
| 		return x.Options | ||||
| @@ -187,7 +179,7 @@ var File_common_proto protoreflect.FileDescriptor | ||||
|  | ||||
| var file_common_proto_rawDesc = []byte{ | ||||
| 	0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, | ||||
| 	0x61, 0x70, 0x69, 0x22, 0xeb, 0x01, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, | ||||
| 	0x61, 0x70, 0x69, 0x22, 0xcb, 0x01, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, | ||||
| 	0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, | ||||
| 	0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, | ||||
| 	0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, | ||||
| @@ -197,9 +189,7 @@ var file_common_proto_rawDesc = []byte{ | ||||
| 	0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x69, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, | ||||
| 	0x04, 0x68, 0x69, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, | ||||
| 	0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, | ||||
| 	0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, | ||||
| 	0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, | ||||
| 	0x79, 0x12, 0x2e, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x03, | ||||
| 	0x64, 0x12, 0x2e, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x03, | ||||
| 	0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, | ||||
| 	0x65, 0x72, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, | ||||
| 	0x73, 0x22, 0x3b, 0x0a, 0x0f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x4f, 0x70, | ||||
|   | ||||
| @@ -9,9 +9,8 @@ message Parameter { | ||||
|     string displayName = 4; | ||||
|     string hint = 5; | ||||
|     bool required = 6; | ||||
|     string visibility = 7; | ||||
|  | ||||
|     repeated ParameterOption options = 8; | ||||
|     repeated ParameterOption options = 7; | ||||
| } | ||||
|  | ||||
| message ParameterOption { | ||||
|   | ||||
| @@ -1,557 +0,0 @@ | ||||
| // Code generated by protoc-gen-go. DO NOT EDIT. | ||||
| // versions: | ||||
| // 	protoc-gen-go v1.22.0 | ||||
| // 	protoc        v3.11.4 | ||||
| // source: services.proto | ||||
|  | ||||
| package api | ||||
|  | ||||
| import ( | ||||
| 	context "context" | ||||
| 	proto "github.com/golang/protobuf/proto" | ||||
| 	_ "github.com/golang/protobuf/ptypes/empty" | ||||
| 	_ "google.golang.org/genproto/googleapis/api/annotations" | ||||
| 	grpc "google.golang.org/grpc" | ||||
| 	codes "google.golang.org/grpc/codes" | ||||
| 	status "google.golang.org/grpc/status" | ||||
| 	protoreflect "google.golang.org/protobuf/reflect/protoreflect" | ||||
| 	protoimpl "google.golang.org/protobuf/runtime/protoimpl" | ||||
| 	reflect "reflect" | ||||
| 	sync "sync" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	// Verify that this generated code is sufficiently up-to-date. | ||||
| 	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) | ||||
| 	// Verify that runtime/protoimpl is sufficiently up-to-date. | ||||
| 	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) | ||||
| ) | ||||
|  | ||||
| // This is a compile-time assertion that a sufficiently up-to-date version | ||||
| // of the legacy proto package is being used. | ||||
| const _ = proto.ProtoPackageIsVersion4 | ||||
|  | ||||
| type Service struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| 	unknownFields protoimpl.UnknownFields | ||||
|  | ||||
| 	Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` | ||||
| 	Url  string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *Service) Reset() { | ||||
| 	*x = Service{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_services_proto_msgTypes[0] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (x *Service) String() string { | ||||
| 	return protoimpl.X.MessageStringOf(x) | ||||
| } | ||||
|  | ||||
| func (*Service) ProtoMessage() {} | ||||
|  | ||||
| func (x *Service) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_services_proto_msgTypes[0] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| 			ms.StoreMessageInfo(mi) | ||||
| 		} | ||||
| 		return ms | ||||
| 	} | ||||
| 	return mi.MessageOf(x) | ||||
| } | ||||
|  | ||||
| // Deprecated: Use Service.ProtoReflect.Descriptor instead. | ||||
| func (*Service) Descriptor() ([]byte, []int) { | ||||
| 	return file_services_proto_rawDescGZIP(), []int{0} | ||||
| } | ||||
|  | ||||
| func (x *Service) GetName() string { | ||||
| 	if x != nil { | ||||
| 		return x.Name | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (x *Service) GetUrl() string { | ||||
| 	if x != nil { | ||||
| 		return x.Url | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| type GetServiceRequest struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| 	unknownFields protoimpl.UnknownFields | ||||
|  | ||||
| 	Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` | ||||
| 	Name      string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *GetServiceRequest) Reset() { | ||||
| 	*x = GetServiceRequest{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_services_proto_msgTypes[1] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (x *GetServiceRequest) String() string { | ||||
| 	return protoimpl.X.MessageStringOf(x) | ||||
| } | ||||
|  | ||||
| func (*GetServiceRequest) ProtoMessage() {} | ||||
|  | ||||
| func (x *GetServiceRequest) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_services_proto_msgTypes[1] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| 			ms.StoreMessageInfo(mi) | ||||
| 		} | ||||
| 		return ms | ||||
| 	} | ||||
| 	return mi.MessageOf(x) | ||||
| } | ||||
|  | ||||
| // Deprecated: Use GetServiceRequest.ProtoReflect.Descriptor instead. | ||||
| func (*GetServiceRequest) Descriptor() ([]byte, []int) { | ||||
| 	return file_services_proto_rawDescGZIP(), []int{1} | ||||
| } | ||||
|  | ||||
| func (x *GetServiceRequest) GetNamespace() string { | ||||
| 	if x != nil { | ||||
| 		return x.Namespace | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (x *GetServiceRequest) GetName() string { | ||||
| 	if x != nil { | ||||
| 		return x.Name | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| type ListServicesRequest struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| 	unknownFields protoimpl.UnknownFields | ||||
|  | ||||
| 	Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` | ||||
| 	PageSize  int32  `protobuf:"varint,2,opt,name=pageSize,proto3" json:"pageSize,omitempty"` | ||||
| 	Page      int32  `protobuf:"varint,3,opt,name=page,proto3" json:"page,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *ListServicesRequest) Reset() { | ||||
| 	*x = ListServicesRequest{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_services_proto_msgTypes[2] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (x *ListServicesRequest) String() string { | ||||
| 	return protoimpl.X.MessageStringOf(x) | ||||
| } | ||||
|  | ||||
| func (*ListServicesRequest) ProtoMessage() {} | ||||
|  | ||||
| func (x *ListServicesRequest) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_services_proto_msgTypes[2] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| 			ms.StoreMessageInfo(mi) | ||||
| 		} | ||||
| 		return ms | ||||
| 	} | ||||
| 	return mi.MessageOf(x) | ||||
| } | ||||
|  | ||||
| // Deprecated: Use ListServicesRequest.ProtoReflect.Descriptor instead. | ||||
| func (*ListServicesRequest) Descriptor() ([]byte, []int) { | ||||
| 	return file_services_proto_rawDescGZIP(), []int{2} | ||||
| } | ||||
|  | ||||
| func (x *ListServicesRequest) GetNamespace() string { | ||||
| 	if x != nil { | ||||
| 		return x.Namespace | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (x *ListServicesRequest) GetPageSize() int32 { | ||||
| 	if x != nil { | ||||
| 		return x.PageSize | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (x *ListServicesRequest) GetPage() int32 { | ||||
| 	if x != nil { | ||||
| 		return x.Page | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| type ListServicesResponse struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| 	unknownFields protoimpl.UnknownFields | ||||
|  | ||||
| 	Count      int32      `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` | ||||
| 	Services   []*Service `protobuf:"bytes,2,rep,name=services,proto3" json:"services,omitempty"` | ||||
| 	Page       int32      `protobuf:"varint,3,opt,name=page,proto3" json:"page,omitempty"` | ||||
| 	Pages      int32      `protobuf:"varint,4,opt,name=pages,proto3" json:"pages,omitempty"` | ||||
| 	TotalCount int32      `protobuf:"varint,5,opt,name=totalCount,proto3" json:"totalCount,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *ListServicesResponse) Reset() { | ||||
| 	*x = ListServicesResponse{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_services_proto_msgTypes[3] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (x *ListServicesResponse) String() string { | ||||
| 	return protoimpl.X.MessageStringOf(x) | ||||
| } | ||||
|  | ||||
| func (*ListServicesResponse) ProtoMessage() {} | ||||
|  | ||||
| func (x *ListServicesResponse) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_services_proto_msgTypes[3] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| 			ms.StoreMessageInfo(mi) | ||||
| 		} | ||||
| 		return ms | ||||
| 	} | ||||
| 	return mi.MessageOf(x) | ||||
| } | ||||
|  | ||||
| // Deprecated: Use ListServicesResponse.ProtoReflect.Descriptor instead. | ||||
| func (*ListServicesResponse) Descriptor() ([]byte, []int) { | ||||
| 	return file_services_proto_rawDescGZIP(), []int{3} | ||||
| } | ||||
|  | ||||
| func (x *ListServicesResponse) GetCount() int32 { | ||||
| 	if x != nil { | ||||
| 		return x.Count | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (x *ListServicesResponse) GetServices() []*Service { | ||||
| 	if x != nil { | ||||
| 		return x.Services | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (x *ListServicesResponse) GetPage() int32 { | ||||
| 	if x != nil { | ||||
| 		return x.Page | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (x *ListServicesResponse) GetPages() int32 { | ||||
| 	if x != nil { | ||||
| 		return x.Pages | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (x *ListServicesResponse) GetTotalCount() int32 { | ||||
| 	if x != nil { | ||||
| 		return x.TotalCount | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| var File_services_proto protoreflect.FileDescriptor | ||||
|  | ||||
| var file_services_proto_rawDesc = []byte{ | ||||
| 	0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, | ||||
| 	0x12, 0x03, 0x61, 0x70, 0x69, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, | ||||
| 	0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, | ||||
| 	0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, | ||||
| 	0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, | ||||
| 	0x22, 0x2f, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, | ||||
| 	0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, | ||||
| 	0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, | ||||
| 	0x6c, 0x22, 0x45, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, | ||||
| 	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, | ||||
| 	0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 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, 0x22, 0x63, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, | ||||
| 	0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, | ||||
| 	0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, | ||||
| 	0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1a, 0x0a, | ||||
| 	0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, | ||||
| 	0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, | ||||
| 	0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x22, 0xa0, 0x01, | ||||
| 	0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, | ||||
| 	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, | ||||
| 	0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x08, | ||||
| 	0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, | ||||
| 	0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x73, 0x65, | ||||
| 	0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x03, | ||||
| 	0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, | ||||
| 	0x67, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x70, 0x61, 0x67, 0x65, 0x73, | ||||
| 	0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, | ||||
| 	0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, | ||||
| 	0x32, 0xe6, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, | ||||
| 	0x69, 0x63, 0x65, 0x12, 0x64, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, | ||||
| 	0x65, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, | ||||
| 	0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x61, 0x70, 0x69, 0x2e, | ||||
| 	0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x12, | ||||
| 	0x28, 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, 0x73, 0x65, 0x72, 0x76, 0x69, | ||||
| 	0x63, 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x12, 0x6e, 0x0a, 0x0c, 0x4c, 0x69, 0x73, | ||||
| 	0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, | ||||
| 	0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, | ||||
| 	0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, | ||||
| 	0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, | ||||
| 	0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x12, 0x21, 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, | ||||
| 	0x33, | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	file_services_proto_rawDescOnce sync.Once | ||||
| 	file_services_proto_rawDescData = file_services_proto_rawDesc | ||||
| ) | ||||
|  | ||||
| func file_services_proto_rawDescGZIP() []byte { | ||||
| 	file_services_proto_rawDescOnce.Do(func() { | ||||
| 		file_services_proto_rawDescData = protoimpl.X.CompressGZIP(file_services_proto_rawDescData) | ||||
| 	}) | ||||
| 	return file_services_proto_rawDescData | ||||
| } | ||||
|  | ||||
| var file_services_proto_msgTypes = make([]protoimpl.MessageInfo, 4) | ||||
| var file_services_proto_goTypes = []interface{}{ | ||||
| 	(*Service)(nil),              // 0: api.Service | ||||
| 	(*GetServiceRequest)(nil),    // 1: api.GetServiceRequest | ||||
| 	(*ListServicesRequest)(nil),  // 2: api.ListServicesRequest | ||||
| 	(*ListServicesResponse)(nil), // 3: api.ListServicesResponse | ||||
| } | ||||
| var file_services_proto_depIdxs = []int32{ | ||||
| 	0, // 0: api.ListServicesResponse.services:type_name -> api.Service | ||||
| 	1, // 1: api.ServiceService.GetService:input_type -> api.GetServiceRequest | ||||
| 	2, // 2: api.ServiceService.ListServices:input_type -> api.ListServicesRequest | ||||
| 	0, // 3: api.ServiceService.GetService:output_type -> api.Service | ||||
| 	3, // 4: api.ServiceService.ListServices:output_type -> api.ListServicesResponse | ||||
| 	3, // [3:5] is the sub-list for method output_type | ||||
| 	1, // [1:3] is the sub-list for method input_type | ||||
| 	1, // [1:1] is the sub-list for extension type_name | ||||
| 	1, // [1:1] is the sub-list for extension extendee | ||||
| 	0, // [0:1] is the sub-list for field type_name | ||||
| } | ||||
|  | ||||
| func init() { file_services_proto_init() } | ||||
| func file_services_proto_init() { | ||||
| 	if File_services_proto != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	if !protoimpl.UnsafeEnabled { | ||||
| 		file_services_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*Service); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| 				return &v.sizeCache | ||||
| 			case 2: | ||||
| 				return &v.unknownFields | ||||
| 			default: | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 		file_services_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*GetServiceRequest); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| 				return &v.sizeCache | ||||
| 			case 2: | ||||
| 				return &v.unknownFields | ||||
| 			default: | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 		file_services_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*ListServicesRequest); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| 				return &v.sizeCache | ||||
| 			case 2: | ||||
| 				return &v.unknownFields | ||||
| 			default: | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 		file_services_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*ListServicesResponse); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| 				return &v.sizeCache | ||||
| 			case 2: | ||||
| 				return &v.unknownFields | ||||
| 			default: | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	type x struct{} | ||||
| 	out := protoimpl.TypeBuilder{ | ||||
| 		File: protoimpl.DescBuilder{ | ||||
| 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(), | ||||
| 			RawDescriptor: file_services_proto_rawDesc, | ||||
| 			NumEnums:      0, | ||||
| 			NumMessages:   4, | ||||
| 			NumExtensions: 0, | ||||
| 			NumServices:   1, | ||||
| 		}, | ||||
| 		GoTypes:           file_services_proto_goTypes, | ||||
| 		DependencyIndexes: file_services_proto_depIdxs, | ||||
| 		MessageInfos:      file_services_proto_msgTypes, | ||||
| 	}.Build() | ||||
| 	File_services_proto = out.File | ||||
| 	file_services_proto_rawDesc = nil | ||||
| 	file_services_proto_goTypes = nil | ||||
| 	file_services_proto_depIdxs = nil | ||||
| } | ||||
|  | ||||
| // Reference imports to suppress errors if they are not otherwise used. | ||||
| var _ context.Context | ||||
| var _ grpc.ClientConnInterface | ||||
|  | ||||
| // This is a compile-time assertion to ensure that this generated file | ||||
| // is compatible with the grpc package it is being compiled against. | ||||
| const _ = grpc.SupportPackageIsVersion6 | ||||
|  | ||||
| // ServiceServiceClient is the client API for ServiceService service. | ||||
| // | ||||
| // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. | ||||
| type ServiceServiceClient interface { | ||||
| 	GetService(ctx context.Context, in *GetServiceRequest, opts ...grpc.CallOption) (*Service, error) | ||||
| 	ListServices(ctx context.Context, in *ListServicesRequest, opts ...grpc.CallOption) (*ListServicesResponse, error) | ||||
| } | ||||
|  | ||||
| type serviceServiceClient struct { | ||||
| 	cc grpc.ClientConnInterface | ||||
| } | ||||
|  | ||||
| func NewServiceServiceClient(cc grpc.ClientConnInterface) ServiceServiceClient { | ||||
| 	return &serviceServiceClient{cc} | ||||
| } | ||||
|  | ||||
| func (c *serviceServiceClient) GetService(ctx context.Context, in *GetServiceRequest, opts ...grpc.CallOption) (*Service, error) { | ||||
| 	out := new(Service) | ||||
| 	err := c.cc.Invoke(ctx, "/api.ServiceService/GetService", in, out, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| func (c *serviceServiceClient) ListServices(ctx context.Context, in *ListServicesRequest, opts ...grpc.CallOption) (*ListServicesResponse, error) { | ||||
| 	out := new(ListServicesResponse) | ||||
| 	err := c.cc.Invoke(ctx, "/api.ServiceService/ListServices", in, out, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| // ServiceServiceServer is the server API for ServiceService service. | ||||
| type ServiceServiceServer interface { | ||||
| 	GetService(context.Context, *GetServiceRequest) (*Service, error) | ||||
| 	ListServices(context.Context, *ListServicesRequest) (*ListServicesResponse, error) | ||||
| } | ||||
|  | ||||
| // UnimplementedServiceServiceServer can be embedded to have forward compatible implementations. | ||||
| type UnimplementedServiceServiceServer struct { | ||||
| } | ||||
|  | ||||
| func (*UnimplementedServiceServiceServer) GetService(context.Context, *GetServiceRequest) (*Service, error) { | ||||
| 	return nil, status.Errorf(codes.Unimplemented, "method GetService not implemented") | ||||
| } | ||||
| func (*UnimplementedServiceServiceServer) ListServices(context.Context, *ListServicesRequest) (*ListServicesResponse, error) { | ||||
| 	return nil, status.Errorf(codes.Unimplemented, "method ListServices not implemented") | ||||
| } | ||||
|  | ||||
| func RegisterServiceServiceServer(s *grpc.Server, srv ServiceServiceServer) { | ||||
| 	s.RegisterService(&_ServiceService_serviceDesc, srv) | ||||
| } | ||||
|  | ||||
| func _ServiceService_GetService_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { | ||||
| 	in := new(GetServiceRequest) | ||||
| 	if err := dec(in); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if interceptor == nil { | ||||
| 		return srv.(ServiceServiceServer).GetService(ctx, in) | ||||
| 	} | ||||
| 	info := &grpc.UnaryServerInfo{ | ||||
| 		Server:     srv, | ||||
| 		FullMethod: "/api.ServiceService/GetService", | ||||
| 	} | ||||
| 	handler := func(ctx context.Context, req interface{}) (interface{}, error) { | ||||
| 		return srv.(ServiceServiceServer).GetService(ctx, req.(*GetServiceRequest)) | ||||
| 	} | ||||
| 	return interceptor(ctx, in, info, handler) | ||||
| } | ||||
|  | ||||
| func _ServiceService_ListServices_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { | ||||
| 	in := new(ListServicesRequest) | ||||
| 	if err := dec(in); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if interceptor == nil { | ||||
| 		return srv.(ServiceServiceServer).ListServices(ctx, in) | ||||
| 	} | ||||
| 	info := &grpc.UnaryServerInfo{ | ||||
| 		Server:     srv, | ||||
| 		FullMethod: "/api.ServiceService/ListServices", | ||||
| 	} | ||||
| 	handler := func(ctx context.Context, req interface{}) (interface{}, error) { | ||||
| 		return srv.(ServiceServiceServer).ListServices(ctx, req.(*ListServicesRequest)) | ||||
| 	} | ||||
| 	return interceptor(ctx, in, info, handler) | ||||
| } | ||||
|  | ||||
| var _ServiceService_serviceDesc = grpc.ServiceDesc{ | ||||
| 	ServiceName: "api.ServiceService", | ||||
| 	HandlerType: (*ServiceServiceServer)(nil), | ||||
| 	Methods: []grpc.MethodDesc{ | ||||
| 		{ | ||||
| 			MethodName: "GetService", | ||||
| 			Handler:    _ServiceService_GetService_Handler, | ||||
| 		}, | ||||
| 		{ | ||||
| 			MethodName: "ListServices", | ||||
| 			Handler:    _ServiceService_ListServices_Handler, | ||||
| 		}, | ||||
| 	}, | ||||
| 	Streams:  []grpc.StreamDesc{}, | ||||
| 	Metadata: "services.proto", | ||||
| } | ||||
| @@ -1,318 +0,0 @@ | ||||
| // Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. | ||||
| // source: services.proto | ||||
|  | ||||
| /* | ||||
| Package api is a reverse proxy. | ||||
|  | ||||
| It translates gRPC into RESTful JSON APIs. | ||||
| */ | ||||
| package api | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
|  | ||||
| 	"github.com/golang/protobuf/descriptor" | ||||
| 	"github.com/golang/protobuf/proto" | ||||
| 	"github.com/grpc-ecosystem/grpc-gateway/runtime" | ||||
| 	"github.com/grpc-ecosystem/grpc-gateway/utilities" | ||||
| 	"google.golang.org/grpc" | ||||
| 	"google.golang.org/grpc/codes" | ||||
| 	"google.golang.org/grpc/grpclog" | ||||
| 	"google.golang.org/grpc/status" | ||||
| ) | ||||
|  | ||||
| // Suppress "imported and not used" errors | ||||
| var _ codes.Code | ||||
| var _ io.Reader | ||||
| var _ status.Status | ||||
| var _ = runtime.String | ||||
| var _ = utilities.NewDoubleArray | ||||
| var _ = descriptor.ForMessage | ||||
|  | ||||
| func request_ServiceService_GetService_0(ctx context.Context, marshaler runtime.Marshaler, client ServiceServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { | ||||
| 	var protoReq GetServiceRequest | ||||
| 	var metadata runtime.ServerMetadata | ||||
|  | ||||
| 	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["name"] | ||||
| 	if !ok { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name") | ||||
| 	} | ||||
|  | ||||
| 	protoReq.Name, err = runtime.String(val) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err) | ||||
| 	} | ||||
|  | ||||
| 	msg, err := client.GetService(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) | ||||
| 	return msg, metadata, err | ||||
|  | ||||
| } | ||||
|  | ||||
| func local_request_ServiceService_GetService_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { | ||||
| 	var protoReq GetServiceRequest | ||||
| 	var metadata runtime.ServerMetadata | ||||
|  | ||||
| 	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["name"] | ||||
| 	if !ok { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name") | ||||
| 	} | ||||
|  | ||||
| 	protoReq.Name, err = runtime.String(val) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err) | ||||
| 	} | ||||
|  | ||||
| 	msg, err := server.GetService(ctx, &protoReq) | ||||
| 	return msg, metadata, err | ||||
|  | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	filter_ServiceService_ListServices_0 = &utilities.DoubleArray{Encoding: map[string]int{"namespace": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} | ||||
| ) | ||||
|  | ||||
| func request_ServiceService_ListServices_0(ctx context.Context, marshaler runtime.Marshaler, client ServiceServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { | ||||
| 	var protoReq ListServicesRequest | ||||
| 	var metadata runtime.ServerMetadata | ||||
|  | ||||
| 	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) | ||||
| 	} | ||||
|  | ||||
| 	if err := req.ParseForm(); err != nil { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) | ||||
| 	} | ||||
| 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ServiceService_ListServices_0); err != nil { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) | ||||
| 	} | ||||
|  | ||||
| 	msg, err := client.ListServices(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) | ||||
| 	return msg, metadata, err | ||||
|  | ||||
| } | ||||
|  | ||||
| func local_request_ServiceService_ListServices_0(ctx context.Context, marshaler runtime.Marshaler, server ServiceServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { | ||||
| 	var protoReq ListServicesRequest | ||||
| 	var metadata runtime.ServerMetadata | ||||
|  | ||||
| 	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) | ||||
| 	} | ||||
|  | ||||
| 	if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_ServiceService_ListServices_0); err != nil { | ||||
| 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) | ||||
| 	} | ||||
|  | ||||
| 	msg, err := server.ListServices(ctx, &protoReq) | ||||
| 	return msg, metadata, err | ||||
|  | ||||
| } | ||||
|  | ||||
| // RegisterServiceServiceHandlerServer registers the http handlers for service ServiceService to "mux". | ||||
| // UnaryRPC     :call ServiceServiceServer directly. | ||||
| // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. | ||||
| func RegisterServiceServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server ServiceServiceServer) error { | ||||
|  | ||||
| 	mux.Handle("GET", pattern_ServiceService_GetService_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_ServiceService_GetService_0(rctx, inboundMarshaler, server, req, pathParams) | ||||
| 		ctx = runtime.NewServerMetadataContext(ctx, md) | ||||
| 		if err != nil { | ||||
| 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		forward_ServiceService_GetService_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) | ||||
|  | ||||
| 	}) | ||||
|  | ||||
| 	mux.Handle("GET", pattern_ServiceService_ListServices_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_ServiceService_ListServices_0(rctx, inboundMarshaler, server, req, pathParams) | ||||
| 		ctx = runtime.NewServerMetadataContext(ctx, md) | ||||
| 		if err != nil { | ||||
| 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		forward_ServiceService_ListServices_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) | ||||
|  | ||||
| 	}) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // RegisterServiceServiceHandlerFromEndpoint is same as RegisterServiceServiceHandler but | ||||
| // automatically dials to "endpoint" and closes the connection when "ctx" gets done. | ||||
| func RegisterServiceServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { | ||||
| 	conn, err := grpc.Dial(endpoint, opts...) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer func() { | ||||
| 		if err != nil { | ||||
| 			if cerr := conn.Close(); cerr != nil { | ||||
| 				grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) | ||||
| 			} | ||||
| 			return | ||||
| 		} | ||||
| 		go func() { | ||||
| 			<-ctx.Done() | ||||
| 			if cerr := conn.Close(); cerr != nil { | ||||
| 				grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) | ||||
| 			} | ||||
| 		}() | ||||
| 	}() | ||||
|  | ||||
| 	return RegisterServiceServiceHandler(ctx, mux, conn) | ||||
| } | ||||
|  | ||||
| // RegisterServiceServiceHandler registers the http handlers for service ServiceService to "mux". | ||||
| // The handlers forward requests to the grpc endpoint over "conn". | ||||
| func RegisterServiceServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { | ||||
| 	return RegisterServiceServiceHandlerClient(ctx, mux, NewServiceServiceClient(conn)) | ||||
| } | ||||
|  | ||||
| // RegisterServiceServiceHandlerClient registers the http handlers for service ServiceService | ||||
| // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "ServiceServiceClient". | ||||
| // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "ServiceServiceClient" | ||||
| // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in | ||||
| // "ServiceServiceClient" to call the correct interceptors. | ||||
| func RegisterServiceServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client ServiceServiceClient) error { | ||||
|  | ||||
| 	mux.Handle("GET", pattern_ServiceService_GetService_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_ServiceService_GetService_0(rctx, inboundMarshaler, client, req, pathParams) | ||||
| 		ctx = runtime.NewServerMetadataContext(ctx, md) | ||||
| 		if err != nil { | ||||
| 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		forward_ServiceService_GetService_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) | ||||
|  | ||||
| 	}) | ||||
|  | ||||
| 	mux.Handle("GET", pattern_ServiceService_ListServices_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_ServiceService_ListServices_0(rctx, inboundMarshaler, client, req, pathParams) | ||||
| 		ctx = runtime.NewServerMetadataContext(ctx, md) | ||||
| 		if err != nil { | ||||
| 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		forward_ServiceService_ListServices_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) | ||||
|  | ||||
| 	}) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	pattern_ServiceService_GetService_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", "service", "name"}, "", runtime.AssumeColonVerbOpt(true))) | ||||
|  | ||||
| 	pattern_ServiceService_ListServices_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3}, []string{"apis", "v1beta1", "namespace", "service"}, "", runtime.AssumeColonVerbOpt(true))) | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	forward_ServiceService_GetService_0 = runtime.ForwardResponseMessage | ||||
|  | ||||
| 	forward_ServiceService_ListServices_0 = runtime.ForwardResponseMessage | ||||
| ) | ||||
| @@ -1,44 +0,0 @@ | ||||
| syntax = "proto3"; | ||||
|  | ||||
| package api; | ||||
|  | ||||
| import "google/api/annotations.proto"; | ||||
| import "google/protobuf/empty.proto"; | ||||
|  | ||||
| service ServiceService { | ||||
|     rpc GetService(GetServiceRequest) returns (Service) { | ||||
|         option (google.api.http) = { | ||||
|             get: "/apis/v1beta1/{namespace}/service/{name}" | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     rpc ListServices(ListServicesRequest) returns (ListServicesResponse) { | ||||
|         option (google.api.http) = { | ||||
|             get: "/apis/v1beta1/{namespace}/service" | ||||
|         }; | ||||
|     } | ||||
| } | ||||
|  | ||||
| message Service { | ||||
|     string name = 1; | ||||
|     string url = 2; | ||||
| } | ||||
|  | ||||
| message GetServiceRequest { | ||||
|     string namespace = 1; | ||||
|     string name = 2; | ||||
| } | ||||
|  | ||||
| message ListServicesRequest { | ||||
|     string namespace = 1; | ||||
|     int32 pageSize = 2; | ||||
|     int32 page = 3; | ||||
| } | ||||
|  | ||||
| message ListServicesResponse { | ||||
|     int32 count = 1; | ||||
|     repeated Service services = 2; | ||||
|     int32 page = 3; | ||||
|     int32 pages = 4; | ||||
|     int32 totalCount = 5; | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -184,10 +184,6 @@ message LogEntry { | ||||
|     string content = 2; | ||||
| } | ||||
|  | ||||
| message WorkflowExecutionMetadata { | ||||
|     string url = 1; | ||||
| } | ||||
|  | ||||
| message WorkflowExecution { | ||||
|     string createdAt = 1; | ||||
|     string uid = 2; | ||||
| @@ -202,8 +198,6 @@ message WorkflowExecution { | ||||
|     WorkflowTemplate workflowTemplate = 9; | ||||
|  | ||||
|     repeated KeyValue labels = 10; | ||||
|  | ||||
|     WorkflowExecutionMetadata metadata = 11; | ||||
| } | ||||
|  | ||||
| message ArtifactResponse { | ||||
|   | ||||
| @@ -392,7 +392,6 @@ type ListWorkflowTemplatesRequest struct { | ||||
| 	Namespace string `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` | ||||
| 	PageSize  int32  `protobuf:"varint,2,opt,name=pageSize,proto3" json:"pageSize,omitempty"` | ||||
| 	Page      int32  `protobuf:"varint,3,opt,name=page,proto3" json:"page,omitempty"` | ||||
| 	Labels    string `protobuf:"bytes,4,opt,name=labels,proto3" json:"labels,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *ListWorkflowTemplatesRequest) Reset() { | ||||
| @@ -448,13 +447,6 @@ func (x *ListWorkflowTemplatesRequest) GetPage() int32 { | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (x *ListWorkflowTemplatesRequest) GetLabels() string { | ||||
| 	if x != nil { | ||||
| 		return x.Labels | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| type ListWorkflowTemplatesResponse struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| @@ -787,7 +779,6 @@ type WorkflowTemplate struct { | ||||
| 	Labels     []*KeyValue                       `protobuf:"bytes,10,rep,name=labels,proto3" json:"labels,omitempty"` | ||||
| 	Stats      *WorkflowExecutionStatisticReport `protobuf:"bytes,11,opt,name=stats,proto3" json:"stats,omitempty"` | ||||
| 	CronStats  *CronWorkflowStatisticsReport     `protobuf:"bytes,12,opt,name=cronStats,proto3" json:"cronStats,omitempty"` | ||||
| 	Parameters []*Parameter                      `protobuf:"bytes,13,rep,name=parameters,proto3" json:"parameters,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *WorkflowTemplate) Reset() { | ||||
| @@ -906,13 +897,6 @@ func (x *WorkflowTemplate) GetCronStats() *CronWorkflowStatisticsReport { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (x *WorkflowTemplate) GetParameters() []*Parameter { | ||||
| 	if x != nil { | ||||
| 		return x.Parameters | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type GetWorkflowTemplateLabelsRequest struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| @@ -983,223 +967,232 @@ var file_workflow_template_proto_rawDesc = []byte{ | ||||
| 	0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x61, 0x70, 0x69, 0x1a, 0x1c, | ||||
| 	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, | ||||
| 	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0b, 0x6c, 0x61, | ||||
| 	0x62, 0x65, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, | ||||
| 	0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x80, 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, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, | ||||
| 	0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, | ||||
| 	0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x41, 0x0a, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, | ||||
| 	0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, | ||||
| 	0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, | ||||
| 	0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, | ||||
| 	0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x87, 0x01, 0x0a, 0x24, 0x55, | ||||
| 	0x70, 0x64, 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, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, | ||||
| 	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, | ||||
| 	0x65, 0x12, 0x41, 0x0a, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, | ||||
| 	0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, | ||||
| 	0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, | ||||
| 	0x74, 0x65, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, | ||||
| 	0x6c, 0x61, 0x74, 0x65, 0x22, 0x66, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, | ||||
| 	0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, | ||||
| 	0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, | ||||
| 	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, | ||||
| 	0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, | ||||
| 	0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, | ||||
| 	0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x7c, 0x0a, 0x1c, | ||||
| 	0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, | ||||
| 	0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, | ||||
| 	0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, | ||||
| 	0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, | ||||
| 	0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, | ||||
| 	0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, | ||||
| 	0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, | ||||
| 	0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x55, 0x0a, 0x23, 0x4c, 0x69, | ||||
| 	0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, | ||||
| 	0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, | ||||
| 	0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, | ||||
| 	0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, | ||||
| 	0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, | ||||
| 	0x64, 0x22, 0x81, 0x01, 0x0a, 0x24, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, | ||||
| 	0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, | ||||
| 	0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, | ||||
| 	0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, | ||||
| 	0x12, 0x43, 0x0a, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, | ||||
| 	0x6c, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, | ||||
| 	0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, | ||||
| 	0x74, 0x65, 0x52, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, | ||||
| 	0x6c, 0x61, 0x74, 0x65, 0x73, 0x22, 0x84, 0x01, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, | ||||
| 	0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, | ||||
| 	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, | ||||
| 	0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, | ||||
| 	0x70, 0x61, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, | ||||
| 	0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, | ||||
| 	0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, | ||||
| 	0x70, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x04, | ||||
| 	0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x22, 0xc4, 0x01, 0x0a, | ||||
| 	0x1d, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, | ||||
| 	0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, | ||||
| 	0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, | ||||
| 	0x6f, 0x75, 0x6e, 0x74, 0x12, 0x43, 0x0a, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, | ||||
| 	0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, | ||||
| 	0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, | ||||
| 	0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, | ||||
| 	0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, | ||||
| 	0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, | ||||
| 	0x05, 0x70, 0x61, 0x67, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x70, 0x61, | ||||
| 	0x67, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, | ||||
| 	0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, | ||||
| 	0x75, 0x6e, 0x74, 0x22, 0x50, 0x0a, 0x1e, 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, | ||||
| 	0x62, 0x65, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x80, 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, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, | ||||
| 	0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, | ||||
| 	0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x41, 0x0a, 0x10, 0x77, 0x6f, 0x72, | ||||
| 	0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, | ||||
| 	0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, | ||||
| 	0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, | ||||
| 	0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x87, 0x01, 0x0a, | ||||
| 	0x24, 0x55, 0x70, 0x64, 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, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, | ||||
| 	0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, | ||||
| 	0x61, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, | ||||
| 	0x52, 0x03, 0x75, 0x69, 0x64, 0x22, 0x64, 0x0a, 0x1f, 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, 0x12, 0x41, 0x0a, 0x10, 0x77, 0x6f, 0x72, 0x6b, | ||||
| 	0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, | ||||
| 	0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, | ||||
| 	0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, | ||||
| 	0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0xcc, 0x01, 0x0a, 0x20, | ||||
| 	0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, | ||||
| 	0x6e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, | ||||
| 	0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, | ||||
| 	0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x22, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x45, 0x78, | ||||
| 	0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x61, | ||||
| 	0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x75, | ||||
| 	0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x72, 0x75, 0x6e, | ||||
| 	0x6e, 0x69, 0x6e, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, | ||||
| 	0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, | ||||
| 	0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, | ||||
| 	0x28, 0x05, 0x52, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x65, | ||||
| 	0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, | ||||
| 	0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x22, 0x34, 0x0a, 0x1c, 0x43, 0x72, | ||||
| 	0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, | ||||
| 	0x74, 0x69, 0x63, 0x73, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, | ||||
| 	0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, | ||||
| 	0x22, 0xd9, 0x03, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, | ||||
| 	0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, | ||||
| 	0x41, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, | ||||
| 	0x64, 0x41, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x41, | ||||
| 	0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, | ||||
| 	0x64, 0x41, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, | ||||
| 	0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, | ||||
| 	0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, | ||||
| 	0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, | ||||
| 	0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, | ||||
| 	0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, | ||||
| 	0x1a, 0x0a, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, | ||||
| 	0x09, 0x52, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x69, | ||||
| 	0x73, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, | ||||
| 	0x73, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x41, 0x72, 0x63, | ||||
| 	0x68, 0x69, 0x76, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x41, | ||||
| 	0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, | ||||
| 	0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4b, 0x65, | ||||
| 	0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x3b, | ||||
| 	0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, | ||||
| 	0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x45, 0x78, 0x65, 0x63, | ||||
| 	0x75, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x52, 0x65, | ||||
| 	0x70, 0x6f, 0x72, 0x74, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x12, 0x3f, 0x0a, 0x09, 0x63, | ||||
| 	0x72, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, | ||||
| 	0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, | ||||
| 	0x77, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x52, 0x65, 0x70, 0x6f, 0x72, | ||||
| 	0x74, 0x52, 0x09, 0x63, 0x72, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x2e, 0x0a, 0x0a, | ||||
| 	0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, | ||||
| 	0x32, 0x0e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, | ||||
| 	0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x22, 0x6e, 0x0a, 0x20, | ||||
| 	0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, | ||||
| 	0x61, 0x74, 0x65, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, | ||||
| 	0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, | ||||
| 	0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 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, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, | ||||
| 	0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 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, 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, 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, 0x46, | ||||
| 	0x82, 0xd3, 0xe4, 0x93, 0x02, 0x40, 0x22, 0x2c, 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, 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, | ||||
| 	0x61, 0x63, 0x65, 0x12, 0x41, 0x0a, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, | ||||
| 	0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, | ||||
| 	0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, | ||||
| 	0x6c, 0x61, 0x74, 0x65, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, | ||||
| 	0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x66, 0x0a, 0x1a, 0x47, 0x65, 0x74, 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, 0x83, 0x01, 0x82, 0xd3, | ||||
| 	0xe4, 0x93, 0x02, 0x7d, 0x12, 0x32, 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, 0x5a, 0x47, 0x12, 0x45, 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, 0x76, | ||||
| 	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, | ||||
| 	0x7d, 0x12, 0xb8, 0x01, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, | ||||
| 	0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, | ||||
| 	0x6e, 0x73, 0x12, 0x28, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, | ||||
| 	0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, | ||||
| 	0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x61, | ||||
| 	0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, | ||||
| 	0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, | ||||
| 	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x43, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3d, 0x12, | ||||
| 	0x3b, 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, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x94, 0x01, 0x0a, | ||||
| 	0x15, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, | ||||
| 	0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, | ||||
| 	0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, | ||||
| 	0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x2e, | ||||
| 	0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, | ||||
| 	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, | ||||
| 	0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, | ||||
| 	0x03, 0x75, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, | ||||
| 	0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x7c, | ||||
| 	0x0a, 0x1c, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, | ||||
| 	0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, | ||||
| 	0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, | ||||
| 	0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, | ||||
| 	0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x12, | ||||
| 	0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, | ||||
| 	0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, | ||||
| 	0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x55, 0x0a, 0x23, | ||||
| 	0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, | ||||
| 	0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x82, | ||||
| 	0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x12, 0x2c, 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, 0x12, 0xe9, 0x01, 0x0a, 0x15, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x57, 0x6f, 0x72, | ||||
| 	0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x21, 0x2e, | ||||
| 	0x61, 0x70, 0x69, 0x2e, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, | ||||
| 	0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, | ||||
| 	0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, | ||||
| 	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, | ||||
| 	0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, | ||||
| 	0x75, 0x69, 0x64, 0x22, 0x81, 0x01, 0x0a, 0x24, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, | ||||
| 	0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, | ||||
| 	0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, | ||||
| 	0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, | ||||
| 	0x6e, 0x74, 0x12, 0x43, 0x0a, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, | ||||
| 	0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, | ||||
| 	0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, | ||||
| 	0x6c, 0x61, 0x74, 0x65, 0x52, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, | ||||
| 	0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x22, 0x6c, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x57, | ||||
| 	0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, | ||||
| 	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, | ||||
| 	0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, | ||||
| 	0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, | ||||
| 	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, | ||||
| 	0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, | ||||
| 	0x04, 0x70, 0x61, 0x67, 0x65, 0x22, 0xc4, 0x01, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, | ||||
| 	0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, | ||||
| 	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, | ||||
| 	0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x43, 0x0a, | ||||
| 	0x11, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, | ||||
| 	0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, | ||||
| 	0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, | ||||
| 	0x11, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, | ||||
| 	0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, | ||||
| 	0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, 0x67, 0x65, 0x73, 0x18, | ||||
| 	0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x70, 0x61, 0x67, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, | ||||
| 	0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, | ||||
| 	0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x50, 0x0a, 0x1e, | ||||
| 	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, 0x12, 0x1c, | ||||
| 	0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, | ||||
| 	0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, | ||||
| 	0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x22, 0x64, | ||||
| 	0x0a, 0x1f, 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, 0x12, 0x41, 0x0a, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, | ||||
| 	0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x70, | ||||
| 	0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, | ||||
| 	0x74, 0x65, 0x52, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, | ||||
| 	0x6c, 0x61, 0x74, 0x65, 0x22, 0xcc, 0x01, 0x0a, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, | ||||
| 	0x77, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, | ||||
| 	0x74, 0x69, 0x63, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, | ||||
| 	0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, | ||||
| 	0x22, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64, 0x18, | ||||
| 	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, | ||||
| 	0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x03, | ||||
| 	0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x1c, 0x0a, | ||||
| 	0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, | ||||
| 	0x52, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x66, | ||||
| 	0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x66, 0x61, 0x69, | ||||
| 	0x6c, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, | ||||
| 	0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, | ||||
| 	0x74, 0x65, 0x64, 0x22, 0x34, 0x0a, 0x1c, 0x43, 0x72, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, | ||||
| 	0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x52, 0x65, 0x70, | ||||
| 	0x6f, 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, | ||||
| 	0x28, 0x05, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0xa9, 0x03, 0x0a, 0x10, 0x57, 0x6f, | ||||
| 	0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x1c, | ||||
| 	0x0a, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, | ||||
| 	0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1e, 0x0a, 0x0a, | ||||
| 	0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x41, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, | ||||
| 	0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x41, 0x74, 0x12, 0x10, 0x0a, 0x03, | ||||
| 	0x75, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x12, | ||||
| 	0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, | ||||
| 	0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, | ||||
| 	0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, | ||||
| 	0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, | ||||
| 	0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x61, 0x6e, 0x69, | ||||
| 	0x66, 0x65, 0x73, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x61, 0x6e, 0x69, | ||||
| 	0x66, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x73, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, | ||||
| 	0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, | ||||
| 	0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x18, 0x09, | ||||
| 	0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, | ||||
| 	0x12, 0x25, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, | ||||
| 	0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, | ||||
| 	0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x3b, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, | ||||
| 	0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, | ||||
| 	0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, | ||||
| 	0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x05, 0x73, | ||||
| 	0x74, 0x61, 0x74, 0x73, 0x12, 0x3f, 0x0a, 0x09, 0x63, 0x72, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, | ||||
| 	0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, | ||||
| 	0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, | ||||
| 	0x74, 0x69, 0x63, 0x73, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x09, 0x63, 0x72, 0x6f, 0x6e, | ||||
| 	0x53, 0x74, 0x61, 0x74, 0x73, 0x22, 0x6e, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, | ||||
| 	0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x4c, 0x61, 0x62, 0x65, | ||||
| 	0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, | ||||
| 	0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, | ||||
| 	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, | ||||
| 	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, | ||||
| 	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, | ||||
| 	0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 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, 0x95, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x8e, | ||||
| 	0x01, 0x12, 0x3f, 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, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, | ||||
| 	0x65, 0x7d, 0x5a, 0x4b, 0x12, 0x49, 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, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x2f, 0x7b, | ||||
| 	0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x2f, 0x7b, 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, | ||||
| 	0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x46, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x40, 0x22, | ||||
| 	0x2c, 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, 0x3a, 0x10, 0x77, | ||||
| 	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, | ||||
| 	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, | ||||
| 	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, | ||||
| 	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, | ||||
| 	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, | ||||
| 	0xd3, 0xe4, 0x93, 0x02, 0x7d, 0x12, 0x32, 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, 0x5a, 0x47, 0x12, 0x45, 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, | ||||
| 	0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, | ||||
| 	0x6e, 0x7d, 0x12, 0xb8, 0x01, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, | ||||
| 	0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, | ||||
| 	0x6f, 0x6e, 0x73, 0x12, 0x28, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, | ||||
| 	0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, | ||||
| 	0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, | ||||
| 	0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, | ||||
| 	0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, | ||||
| 	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x43, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3d, | ||||
| 	0x12, 0x3b, 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, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x94, 0x01, | ||||
| 	0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, | ||||
| 	0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, | ||||
| 	0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, | ||||
| 	0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61, 0x70, 0x69, | ||||
| 	0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, | ||||
| 	0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, | ||||
| 	0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x12, 0x2c, 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, 0x12, 0xe9, 0x01, 0x0a, 0x15, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x57, 0x6f, | ||||
| 	0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x21, | ||||
| 	0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6c, 0x6f, 0x6e, 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, 0x95, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, | ||||
| 	0x8e, 0x01, 0x12, 0x3f, 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, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x2f, 0x7b, 0x6e, 0x61, | ||||
| 	0x6d, 0x65, 0x7d, 0x5a, 0x4b, 0x12, 0x49, 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, 0x63, 0x6c, 0x6f, 0x6e, 0x65, 0x2f, | ||||
| 	0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x2f, 0x7b, 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 ( | ||||
| @@ -1231,7 +1224,6 @@ var file_workflow_template_proto_goTypes = []interface{}{ | ||||
| 	(*WorkflowTemplate)(nil),                     // 12: api.WorkflowTemplate | ||||
| 	(*GetWorkflowTemplateLabelsRequest)(nil),     // 13: api.GetWorkflowTemplateLabelsRequest | ||||
| 	(*KeyValue)(nil),                             // 14: api.KeyValue | ||||
| 	(*Parameter)(nil),                            // 15: api.Parameter | ||||
| } | ||||
| var file_workflow_template_proto_depIdxs = []int32{ | ||||
| 	12, // 0: api.CreateWorkflowTemplateRequest.workflowTemplate:type_name -> api.WorkflowTemplate | ||||
| @@ -1242,8 +1234,8 @@ var file_workflow_template_proto_depIdxs = []int32{ | ||||
| 	14, // 5: api.WorkflowTemplate.labels:type_name -> api.KeyValue | ||||
| 	10, // 6: api.WorkflowTemplate.stats:type_name -> api.WorkflowExecutionStatisticReport | ||||
| 	11, // 7: api.WorkflowTemplate.cronStats:type_name -> api.CronWorkflowStatisticsReport | ||||
| 	15, // 8: api.WorkflowTemplate.parameters:type_name -> api.Parameter | ||||
| 	0,  // 9: 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,  // 10: api.WorkflowTemplateService.CreateWorkflowTemplateVersion:input_type -> api.CreateWorkflowTemplateRequest | ||||
| 	2,  // 11: api.WorkflowTemplateService.GetWorkflowTemplate:input_type -> api.GetWorkflowTemplateRequest | ||||
| 	4,  // 12: api.WorkflowTemplateService.ListWorkflowTemplateVersions:input_type -> api.ListWorkflowTemplateVersionsRequest | ||||
| @@ -1251,17 +1243,18 @@ var file_workflow_template_proto_depIdxs = []int32{ | ||||
| 	3,  // 14: api.WorkflowTemplateService.CloneWorkflowTemplate:input_type -> api.CloneWorkflowTemplateRequest | ||||
| 	8,  // 15: api.WorkflowTemplateService.ArchiveWorkflowTemplate:input_type -> api.ArchiveWorkflowTemplateRequest | ||||
| 	12, // 16: api.WorkflowTemplateService.CreateWorkflowTemplate:output_type -> api.WorkflowTemplate | ||||
| 	12, // 17: api.WorkflowTemplateService.CreateWorkflowTemplateVersion:output_type -> api.WorkflowTemplate | ||||
| 	12, // 18: api.WorkflowTemplateService.GetWorkflowTemplate:output_type -> api.WorkflowTemplate | ||||
| 	5,  // 19: api.WorkflowTemplateService.ListWorkflowTemplateVersions:output_type -> api.ListWorkflowTemplateVersionsResponse | ||||
| 	7,  // 20: api.WorkflowTemplateService.ListWorkflowTemplates:output_type -> api.ListWorkflowTemplatesResponse | ||||
| 	12, // 21: api.WorkflowTemplateService.CloneWorkflowTemplate:output_type -> api.WorkflowTemplate | ||||
| 	9,  // 22: api.WorkflowTemplateService.ArchiveWorkflowTemplate:output_type -> api.ArchiveWorkflowTemplateResponse | ||||
| 	16, // [16:23] is the sub-list for method output_type | ||||
| 	9,  // [9:16] is the sub-list for method input_type | ||||
| 	9,  // [9:9] is the sub-list for extension type_name | ||||
| 	9,  // [9:9] is the sub-list for extension extendee | ||||
| 	0,  // [0:9] is the sub-list for field type_name | ||||
| 	12, // 17: api.WorkflowTemplateService.UpdateWorkflowTemplateVersion:output_type -> api.WorkflowTemplate | ||||
| 	12, // 18: api.WorkflowTemplateService.CreateWorkflowTemplateVersion:output_type -> api.WorkflowTemplate | ||||
| 	12, // 19: api.WorkflowTemplateService.GetWorkflowTemplate:output_type -> api.WorkflowTemplate | ||||
| 	5,  // 20: api.WorkflowTemplateService.ListWorkflowTemplateVersions:output_type -> api.ListWorkflowTemplateVersionsResponse | ||||
| 	7,  // 21: api.WorkflowTemplateService.ListWorkflowTemplates:output_type -> api.ListWorkflowTemplatesResponse | ||||
| 	12, // 22: api.WorkflowTemplateService.CloneWorkflowTemplate:output_type -> api.WorkflowTemplate | ||||
| 	9,  // 23: api.WorkflowTemplateService.ArchiveWorkflowTemplate:output_type -> api.ArchiveWorkflowTemplateResponse | ||||
| 	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 extendee | ||||
| 	0,  // [0:8] is the sub-list for field type_name | ||||
| } | ||||
|  | ||||
| func init() { file_workflow_template_proto_init() } | ||||
| @@ -1270,7 +1263,6 @@ func file_workflow_template_proto_init() { | ||||
| 		return | ||||
| 	} | ||||
| 	file_label_proto_init() | ||||
| 	file_common_proto_init() | ||||
| 	if !protoimpl.UnsafeEnabled { | ||||
| 		file_workflow_template_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*CreateWorkflowTemplateRequest); i { | ||||
| @@ -1474,6 +1466,7 @@ 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. | ||||
| type WorkflowTemplateServiceClient interface { | ||||
| 	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) | ||||
| 	GetWorkflowTemplate(ctx context.Context, in *GetWorkflowTemplateRequest, opts ...grpc.CallOption) (*WorkflowTemplate, error) | ||||
| 	ListWorkflowTemplateVersions(ctx context.Context, in *ListWorkflowTemplateVersionsRequest, opts ...grpc.CallOption) (*ListWorkflowTemplateVersionsResponse, error) | ||||
| @@ -1499,6 +1492,15 @@ func (c *workflowTemplateServiceClient) CreateWorkflowTemplate(ctx context.Conte | ||||
| 	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) { | ||||
| 	out := new(WorkflowTemplate) | ||||
| 	err := c.cc.Invoke(ctx, "/api.WorkflowTemplateService/CreateWorkflowTemplateVersion", in, out, opts...) | ||||
| @@ -1556,6 +1558,7 @@ func (c *workflowTemplateServiceClient) ArchiveWorkflowTemplate(ctx context.Cont | ||||
| // WorkflowTemplateServiceServer is the server API for WorkflowTemplateService service. | ||||
| type WorkflowTemplateServiceServer interface { | ||||
| 	CreateWorkflowTemplate(context.Context, *CreateWorkflowTemplateRequest) (*WorkflowTemplate, error) | ||||
| 	UpdateWorkflowTemplateVersion(context.Context, *UpdateWorkflowTemplateVersionRequest) (*WorkflowTemplate, error) | ||||
| 	CreateWorkflowTemplateVersion(context.Context, *CreateWorkflowTemplateRequest) (*WorkflowTemplate, error) | ||||
| 	GetWorkflowTemplate(context.Context, *GetWorkflowTemplateRequest) (*WorkflowTemplate, error) | ||||
| 	ListWorkflowTemplateVersions(context.Context, *ListWorkflowTemplateVersionsRequest) (*ListWorkflowTemplateVersionsResponse, error) | ||||
| @@ -1571,6 +1574,9 @@ type UnimplementedWorkflowTemplateServiceServer struct { | ||||
| func (*UnimplementedWorkflowTemplateServiceServer) CreateWorkflowTemplate(context.Context, *CreateWorkflowTemplateRequest) (*WorkflowTemplate, error) { | ||||
| 	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) { | ||||
| 	return nil, status.Errorf(codes.Unimplemented, "method CreateWorkflowTemplateVersion not implemented") | ||||
| } | ||||
| @@ -1612,6 +1618,24 @@ func _WorkflowTemplateService_CreateWorkflowTemplate_Handler(srv interface{}, ct | ||||
| 	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) { | ||||
| 	in := new(CreateWorkflowTemplateRequest) | ||||
| 	if err := dec(in); err != nil { | ||||
| @@ -1728,6 +1752,10 @@ var _WorkflowTemplateService_serviceDesc = grpc.ServiceDesc{ | ||||
| 			MethodName: "CreateWorkflowTemplate", | ||||
| 			Handler:    _WorkflowTemplateService_CreateWorkflowTemplate_Handler, | ||||
| 		}, | ||||
| 		{ | ||||
| 			MethodName: "UpdateWorkflowTemplateVersion", | ||||
| 			Handler:    _WorkflowTemplateService_UpdateWorkflowTemplateVersion_Handler, | ||||
| 		}, | ||||
| 		{ | ||||
| 			MethodName: "CreateWorkflowTemplateVersion", | ||||
| 			Handler:    _WorkflowTemplateService_CreateWorkflowTemplateVersion_Handler, | ||||
|   | ||||
| @@ -101,6 +101,120 @@ 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) { | ||||
| 	var protoReq CreateWorkflowTemplateRequest | ||||
| 	var metadata runtime.ServerMetadata | ||||
| @@ -861,6 +975,26 @@ 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) { | ||||
| 		ctx, cancel := context.WithCancel(req.Context()) | ||||
| 		defer cancel() | ||||
| @@ -1082,6 +1216,26 @@ 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) { | ||||
| 		ctx, cancel := context.WithCancel(req.Context()) | ||||
| 		defer cancel() | ||||
| @@ -1248,6 +1402,8 @@ func RegisterWorkflowTemplateServiceHandlerClient(ctx context.Context, mux *runt | ||||
| 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_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_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))) | ||||
| @@ -1268,6 +1424,8 @@ var ( | ||||
| var ( | ||||
| 	forward_WorkflowTemplateService_CreateWorkflowTemplate_0 = runtime.ForwardResponseMessage | ||||
|  | ||||
| 	forward_WorkflowTemplateService_UpdateWorkflowTemplateVersion_0 = runtime.ForwardResponseMessage | ||||
|  | ||||
| 	forward_WorkflowTemplateService_CreateWorkflowTemplateVersion_0 = runtime.ForwardResponseMessage | ||||
|  | ||||
| 	forward_WorkflowTemplateService_GetWorkflowTemplate_0 = runtime.ForwardResponseMessage | ||||
|   | ||||
| @@ -4,7 +4,6 @@ package api; | ||||
|  | ||||
| import "google/api/annotations.proto"; | ||||
| import "label.proto"; | ||||
| import "common.proto"; | ||||
|  | ||||
| service WorkflowTemplateService { | ||||
|     rpc CreateWorkflowTemplate (CreateWorkflowTemplateRequest) returns (WorkflowTemplate) { | ||||
| @@ -14,6 +13,13 @@ 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) { | ||||
|         option (google.api.http) = { | ||||
|             post: "/apis/v1beta1/{namespace}/workflow_templates/{workflowTemplate.uid}/versions" | ||||
| @@ -95,8 +101,6 @@ message ListWorkflowTemplatesRequest { | ||||
|     string namespace = 1; | ||||
|     int32 pageSize = 2; | ||||
|     int32 page = 3; | ||||
|  | ||||
|     string labels = 4; | ||||
| } | ||||
|  | ||||
| message ListWorkflowTemplatesResponse { | ||||
| @@ -143,7 +147,6 @@ message WorkflowTemplate { | ||||
|  | ||||
|     WorkflowExecutionStatisticReport stats = 11; | ||||
|     CronWorkflowStatisticsReport cronStats = 12; | ||||
|     repeated Parameter parameters = 13; | ||||
| } | ||||
|  | ||||
| message GetWorkflowTemplateLabelsRequest { | ||||
|   | ||||
| @@ -45,7 +45,6 @@ type WorkspaceTemplate struct { | ||||
| 	WorkflowTemplate *WorkflowTemplate `protobuf:"bytes,7,opt,name=workflowTemplate,proto3" json:"workflowTemplate,omitempty"` | ||||
| 	Labels           []*KeyValue       `protobuf:"bytes,8,rep,name=labels,proto3" json:"labels,omitempty"` | ||||
| 	IsArchived       bool              `protobuf:"varint,9,opt,name=isArchived,proto3" json:"isArchived,omitempty"` | ||||
| 	Description      string            `protobuf:"bytes,10,opt,name=description,proto3" json:"description,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *WorkspaceTemplate) Reset() { | ||||
| @@ -143,13 +142,6 @@ func (x *WorkspaceTemplate) GetIsArchived() bool { | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func (x *WorkspaceTemplate) GetDescription() string { | ||||
| 	if x != nil { | ||||
| 		return x.Description | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| type GenerateWorkspaceTemplateWorkflowTemplateRequest struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| @@ -712,7 +704,7 @@ var file_workspace_template_proto_rawDesc = []byte{ | ||||
| 	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, | ||||
| 	0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, | ||||
| 	0x6f, 0x74, 0x6f, 0x1a, 0x0b, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, | ||||
| 	0x22, 0xd5, 0x02, 0x0a, 0x11, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, | ||||
| 	0x22, 0xb3, 0x02, 0x0a, 0x11, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, | ||||
| 	0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, | ||||
| 	0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, | ||||
| 	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, | ||||
| @@ -731,161 +723,158 @@ var file_workspace_template_proto_rawDesc = []byte{ | ||||
| 	0x0d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, | ||||
| 	0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x41, 0x72, 0x63, 0x68, | ||||
| 	0x69, 0x76, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x41, 0x72, | ||||
| 	0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, | ||||
| 	0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, | ||||
| 	0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa8, 0x01, 0x0a, 0x30, 0x47, 0x65, 0x6e, | ||||
| 	0x65, 0x72, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, | ||||
| 	0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, | ||||
| 	0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x22, 0xa8, 0x01, 0x0a, 0x30, 0x47, 0x65, 0x6e, 0x65, 0x72, | ||||
| 	0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, | ||||
| 	0x6c, 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, 0x12, 0x1c, 0x0a, 0x09, 0x6e, | ||||
| 	0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, | ||||
| 	0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, | ||||
| 	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x44, 0x0a, 0x11, 0x77, | ||||
| 	0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, | ||||
| 	0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, | ||||
| 	0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x11, | ||||
| 	0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, | ||||
| 	0x65, 0x22, 0x84, 0x01, 0x0a, 0x1e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, | ||||
| 	0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, | ||||
| 	0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, | ||||
| 	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, | ||||
| 	0x63, 0x65, 0x12, 0x44, 0x0a, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, | ||||
| 	0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, | ||||
| 	0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, | ||||
| 	0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, | ||||
| 	0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x96, 0x01, 0x0a, 0x1e, 0x55, 0x70, 0x64, | ||||
| 	0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, | ||||
| 	0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, | ||||
| 	0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, | ||||
| 	0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, | ||||
| 	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x44, 0x0a, 0x11, 0x77, | ||||
| 	0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, | ||||
| 	0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, | ||||
| 	0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x11, | ||||
| 	0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, | ||||
| 	0x65, 0x22, 0x67, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, | ||||
| 	0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, | ||||
| 	0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, | ||||
| 	0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x10, | ||||
| 	0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, | ||||
| 	0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, | ||||
| 	0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x51, 0x0a, 0x1f, 0x41, 0x72, | ||||
| 	0x63, 0x68, 0x69, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, | ||||
| 	0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, | ||||
| 	0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, | ||||
| 	0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, | ||||
| 	0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x44, 0x0a, | ||||
| 	0x11, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, | ||||
| 	0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, | ||||
| 	0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x22, 0x6d, 0x0a, | ||||
| 	0x1d, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, | ||||
| 	0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, | ||||
| 	0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, | ||||
| 	0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, | ||||
| 	0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, | ||||
| 	0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, | ||||
| 	0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x22, 0xc8, 0x01, 0x0a, | ||||
| 	0x1e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, | ||||
| 	0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, | ||||
| 	0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, | ||||
| 	0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x46, 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, | ||||
| 	0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, | ||||
| 	0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, | ||||
| 	0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, | ||||
| 	0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12, 0x12, 0x0a, | ||||
| 	0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, | ||||
| 	0x65, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, 0x67, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, | ||||
| 	0x52, 0x05, 0x70, 0x61, 0x67, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, | ||||
| 	0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x74, 0x6f, 0x74, | ||||
| 	0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x56, 0x0a, 0x24, 0x4c, 0x69, 0x73, 0x74, 0x57, | ||||
| 	0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, | ||||
| 	0x52, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, | ||||
| 	0x61, 0x74, 0x65, 0x22, 0x84, 0x01, 0x0a, 0x1e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, | ||||
| 	0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, | ||||
| 	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, | ||||
| 	0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, | ||||
| 	0x70, 0x61, 0x63, 0x65, 0x12, 0x44, 0x0a, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, | ||||
| 	0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, | ||||
| 	0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, | ||||
| 	0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, | ||||
| 	0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x96, 0x01, 0x0a, 0x1e, 0x55, | ||||
| 	0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, | ||||
| 	0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, | ||||
| 	0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, | ||||
| 	0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, | ||||
| 	0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x44, 0x0a, | ||||
| 	0x11, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, | ||||
| 	0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, | ||||
| 	0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, | ||||
| 	0x52, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, | ||||
| 	0x61, 0x74, 0x65, 0x22, 0x67, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, | ||||
| 	0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, | ||||
| 	0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, | ||||
| 	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, | ||||
| 	0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, | ||||
| 	0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, | ||||
| 	0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x51, 0x0a, 0x1f, | ||||
| 	0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, | ||||
| 	0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, | ||||
| 	0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, | ||||
| 	0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, | ||||
| 	0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x10, 0x0a, | ||||
| 	0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x22, | ||||
| 	0x6d, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, | ||||
| 	0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, | ||||
| 	0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, | ||||
| 	0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1a, | ||||
| 	0x0a, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, | ||||
| 	0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, | ||||
| 	0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x22, 0xc8, | ||||
| 	0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, | ||||
| 	0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, | ||||
| 	0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, | ||||
| 	0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x46, 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, | ||||
| 	0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, | ||||
| 	0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, | ||||
| 	0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x12, 0x77, 0x6f, 0x72, | ||||
| 	0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12, | ||||
| 	0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, | ||||
| 	0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, 0x67, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, | ||||
| 	0x28, 0x05, 0x52, 0x05, 0x70, 0x61, 0x67, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x6f, 0x74, | ||||
| 	0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x74, | ||||
| 	0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x56, 0x0a, 0x24, 0x4c, 0x69, 0x73, | ||||
| 	0x85, 0x01, 0x0a, 0x25, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, | ||||
| 	0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, | ||||
| 	0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, | ||||
| 	0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, | ||||
| 	0x46, 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, | ||||
| 	0x6c, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, | ||||
| 	0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, | ||||
| 	0x61, 0x74, 0x65, 0x52, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, | ||||
| 	0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x32, 0xce, 0x09, 0x0a, 0x18, 0x57, 0x6f, 0x72, 0x6b, | ||||
| 	0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, | ||||
| 	0x76, 0x69, 0x63, 0x65, 0x12, 0xdb, 0x01, 0x0a, 0x29, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, | ||||
| 	0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, | ||||
| 	0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, | ||||
| 	0x74, 0x65, 0x12, 0x35, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, | ||||
| 	0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 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, 0x60, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x5a, 0x22, 0x45, 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, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x65, | ||||
| 	0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x75, 0x69, 0x64, 0x7d, 0x2f, 0x77, 0x6f, | ||||
| 	0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3a, | ||||
| 	0x11, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, | ||||
| 	0x74, 0x65, 0x12, 0xa0, 0x01, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, | ||||
| 	0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x23, | ||||
| 	0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, | ||||
| 	0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, | ||||
| 	0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, | ||||
| 	0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x48, 0x82, 0xd3, 0xe4, | ||||
| 	0x93, 0x02, 0x42, 0x22, 0x2d, 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, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, | ||||
| 	0x65, 0x73, 0x3a, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, | ||||
| 	0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0xa6, 0x01, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, | ||||
| 	0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, | ||||
| 	0x65, 0x12, 0x23, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x6f, | ||||
| 	0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, | ||||
| 	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, | ||||
| 	0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x4e, | ||||
| 	0x82, 0xd3, 0xe4, 0x93, 0x02, 0x48, 0x1a, 0x33, 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, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x65, 0x6d, 0x70, | ||||
| 	0x6c, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x75, 0x69, 0x64, 0x7d, 0x3a, 0x11, 0x77, 0x6f, 0x72, | ||||
| 	0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x9d, | ||||
| 	0x01, 0x0a, 0x18, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, | ||||
| 	0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x24, 0x2e, 0x61, 0x70, | ||||
| 	0x69, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, | ||||
| 	0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, | ||||
| 	0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, | ||||
| 	0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x43, 0x82, 0xd3, 0xe4, 0x93, 0x02, | ||||
| 	0x3d, 0x1a, 0x3b, 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, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, | ||||
| 	0x2f, 0x7b, 0x75, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x12, 0x8d, | ||||
| 	0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, | ||||
| 	0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, | ||||
| 	0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, | ||||
| 	0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, | ||||
| 	0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, | ||||
| 	0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, | ||||
| 	0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, | ||||
| 	0x64, 0x22, 0x85, 0x01, 0x0a, 0x25, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, | ||||
| 	0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, | ||||
| 	0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, | ||||
| 	0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, | ||||
| 	0x74, 0x12, 0x46, 0x0a, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, | ||||
| 	0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, | ||||
| 	0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, | ||||
| 	0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, | ||||
| 	0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x32, 0xce, 0x09, 0x0a, 0x18, 0x57, 0x6f, | ||||
| 	0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x53, | ||||
| 	0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xdb, 0x01, 0x0a, 0x29, 0x47, 0x65, 0x6e, 0x65, 0x72, | ||||
| 	0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, | ||||
| 	0x6c, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x54, 0x65, 0x6d, 0x70, | ||||
| 	0x6c, 0x61, 0x74, 0x65, 0x12, 0x35, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, | ||||
| 	0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, | ||||
| 	0x6c, 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, 0x60, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x5a, 0x22, 0x45, 0x2f, 0x61, 0x70, 0x69, | ||||
| 	0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, | ||||
| 	0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, | ||||
| 	0x65, 0x22, 0x3b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x12, 0x33, 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, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, | ||||
| 	0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x75, 0x69, 0x64, 0x7d, 0x12, 0x98, | ||||
| 	0x01, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, | ||||
| 	0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x2e, | ||||
| 	0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, | ||||
| 	0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, | ||||
| 	0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, | ||||
| 	0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, | ||||
| 	0x73, 0x65, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x12, 0x2d, 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, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, | ||||
| 	0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12, 0xbc, 0x01, 0x0a, 0x1d, 0x4c, 0x69, | ||||
| 	0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, | ||||
| 	0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x2e, 0x61, 0x70, | ||||
| 	0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, | ||||
| 	0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, | ||||
| 	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, | ||||
| 	0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, | ||||
| 	0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, | ||||
| 	0x73, 0x65, 0x22, 0x44, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3e, 0x12, 0x3c, 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, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, | ||||
| 	0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x75, 0x69, 0x64, 0x7d, 0x2f, | ||||
| 	0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, | ||||
| 	0x65, 0x3a, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, | ||||
| 	0x6c, 0x61, 0x74, 0x65, 0x12, 0xa0, 0x01, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, | ||||
| 	0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, | ||||
| 	0x12, 0x23, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, | ||||
| 	0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, | ||||
| 	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, | ||||
| 	0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x48, 0x82, | ||||
| 	0xd3, 0xe4, 0x93, 0x02, 0x42, 0x22, 0x2d, 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, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, | ||||
| 	0x61, 0x74, 0x65, 0x73, 0x3a, 0x11, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, | ||||
| 	0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0xa6, 0x01, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, | ||||
| 	0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, | ||||
| 	0x61, 0x74, 0x65, 0x12, 0x23, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, | ||||
| 	0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, | ||||
| 	0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, | ||||
| 	0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, | ||||
| 	0x22, 0x4e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x48, 0x1a, 0x33, 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, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x65, | ||||
| 	0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x75, 0x69, 0x64, 0x7d, 0x3a, 0x11, 0x77, | ||||
| 	0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, | ||||
| 	0x12, 0x9d, 0x01, 0x0a, 0x18, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, | ||||
| 	0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x24, 0x2e, | ||||
| 	0x61, 0x70, 0x69, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, | ||||
| 	0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, | ||||
| 	0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, | ||||
| 	0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x43, 0x82, 0xd3, 0xe4, | ||||
| 	0x93, 0x02, 0x3d, 0x1a, 0x3b, 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, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, | ||||
| 	0x65, 0x73, 0x2f, 0x7b, 0x75, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, | ||||
| 	0x12, 0x8d, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, | ||||
| 	0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, | ||||
| 	0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, | ||||
| 	0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, | ||||
| 	0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, | ||||
| 	0x61, 0x74, 0x65, 0x22, 0x3b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x35, 0x12, 0x33, 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, 0x73, 0x70, 0x61, 0x63, 0x65, | ||||
| 	0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x75, 0x69, 0x64, 0x7d, | ||||
| 	0x12, 0x98, 0x01, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, | ||||
| 	0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x61, 0x70, | ||||
| 	0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, | ||||
| 	0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, | ||||
| 	0x23, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, | ||||
| 	0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, | ||||
| 	0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x12, 0x2d, 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, 0x73, 0x70, 0x61, 0x63, | ||||
| 	0x65, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x12, 0xbc, 0x01, 0x0a, 0x1d, | ||||
| 	0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, | ||||
| 	0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x2e, | ||||
| 	0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, | ||||
| 	0x65, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, | ||||
| 	0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, | ||||
| 	0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x65, 0x6d, 0x70, | ||||
| 	0x6c, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, | ||||
| 	0x6f, 0x6e, 0x73, 0x65, 0x22, 0x44, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3e, 0x12, 0x3c, 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, 0x73, 0x70, 0x61, 0x63, | ||||
| 	0x65, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x7b, 0x75, 0x69, 0x64, | ||||
| 	0x7d, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, | ||||
| 	0x6f, 0x33, | ||||
| 	0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, | ||||
| } | ||||
|  | ||||
| var ( | ||||
|   | ||||
| @@ -69,7 +69,6 @@ message WorkspaceTemplate { | ||||
|     WorkflowTemplate workflowTemplate = 7; | ||||
|     repeated KeyValue labels = 8; | ||||
|     bool isArchived = 9; | ||||
|     string description = 10; | ||||
| } | ||||
|  | ||||
| message GenerateWorkspaceTemplateWorkflowTemplateRequest { | ||||
|   | ||||
| @@ -4,12 +4,12 @@ package main | ||||
|  | ||||
| import ( | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
| 	"github.com/jmoiron/sqlx" | ||||
| 	migrations "github.com/onepanelio/core/db/go" | ||||
| 	_ "github.com/onepanelio/core/db" | ||||
| 	v1 "github.com/onepanelio/core/pkg" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
|  | ||||
| 	"github.com/pressly/goose" | ||||
| ) | ||||
| @@ -38,9 +38,10 @@ func main() { | ||||
| 		log.Fatalf("Failed to get system config: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	dbDriverName, dbDataSourceName := config.DatabaseConnection() | ||||
| 	db := sqlx.MustConnect(dbDriverName, dbDataSourceName) | ||||
| 	defer db.Close() | ||||
| 	databaseDataSourceName := fmt.Sprintf("host=%v user=%v password=%v dbname=%v sslmode=disable", | ||||
| 		config["databaseHost"], config["databaseUsername"], config["databasePassword"], config["databaseName"]) | ||||
|  | ||||
| 	db := sqlx.MustConnect(config["databaseDriverName"], databaseDataSourceName) | ||||
|  | ||||
| 	command := args[0] | ||||
|  | ||||
| @@ -49,14 +50,7 @@ func main() { | ||||
| 		arguments = append(arguments, args[2:]...) | ||||
| 	} | ||||
|  | ||||
| 	goose.SetTableName("goose_db_version") | ||||
| 	if err := goose.Run(command, db.DB, filepath.Join(*dir, "sql"), arguments...); err != nil { | ||||
| 		log.Fatalf("Failed to run database sql migrations: %v %v", command, err) | ||||
| 	} | ||||
|  | ||||
| 	goose.SetTableName("goose_db_go_version") | ||||
| 	migrations.Initialize() | ||||
| 	if err := goose.Run(command, db.DB, filepath.Join(*dir, "go"), arguments...); err != nil { | ||||
| 		log.Fatalf("Failed to run database go migrations: %v %v", command, err) | ||||
| 	if err := goose.Run(command, db.DB, *dir, arguments...); err != nil { | ||||
| 		log.Fatalf("goose %v: %v", command, err) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -71,11 +71,8 @@ routes: | ||||
| 
 | ||||
| const jupyterLabTemplateName = "JupyterLab" | ||||
| 
 | ||||
| func initialize20200525160514() { | ||||
| 	if _, ok := initializedMigrations[20200525160514]; !ok { | ||||
| 		goose.AddMigration(Up20200525160514, Down20200525160514) | ||||
| 		initializedMigrations[20200525160514] = true | ||||
| 	} | ||||
| func init() { | ||||
| 	goose.AddMigration(Up20200525160514, Down20200525160514) | ||||
| } | ||||
| 
 | ||||
| func Up20200525160514(tx *sql.Tx) error { | ||||
| @@ -83,16 +80,6 @@ func Up20200525160514(tx *sql.Tx) error { | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer client.DB.Close() | ||||
| 
 | ||||
| 	migrationsRan, err := getRanSQLMigrations(client) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if _, ok := migrationsRan[20200525160514]; ok { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	namespaces, err := client.ListOnepanelEnabledNamespaces() | ||||
| 	if err != nil { | ||||
| @@ -110,11 +110,8 @@ routes: | ||||
| 
 | ||||
| const cvatTemplateName = "CVAT" | ||||
| 
 | ||||
| func initialize20200528140124() { | ||||
| 	if _, ok := initializedMigrations[20200528140124]; !ok { | ||||
| 		goose.AddMigration(Up20200528140124, Down20200528140124) | ||||
| 		initializedMigrations[20200528140124] = true | ||||
| 	} | ||||
| func init() { | ||||
| 	goose.AddMigration(Up20200528140124, Down20200528140124) | ||||
| } | ||||
| 
 | ||||
| // Up20200528140124 will insert the cvatTemplate to each user. | ||||
| @@ -127,16 +124,6 @@ func Up20200528140124(tx *sql.Tx) error { | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer client.DB.Close() | ||||
| 
 | ||||
| 	migrationsRan, err := getRanSQLMigrations(client) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if _, ok := migrationsRan[20200528140124]; ok { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	namespaces, err := client.ListOnepanelEnabledNamespaces() | ||||
| 	if err != nil { | ||||
| @@ -88,11 +88,8 @@ templates: | ||||
| 
 | ||||
| const pytorchMnistWorkflowTemplateName = "PyTorch Training" | ||||
| 
 | ||||
| func initialize20200605090509() { | ||||
| 	if _, ok := initializedMigrations[20200605090509]; !ok { | ||||
| 		goose.AddMigration(Up20200605090509, Down20200605090509) | ||||
| 		initializedMigrations[20200605090509] = true | ||||
| 	} | ||||
| func init() { | ||||
| 	goose.AddMigration(Up20200605090509, Down20200605090509) | ||||
| } | ||||
| 
 | ||||
| // Up20200605090509 will insert a Pytorch workflow template to each user. | ||||
| @@ -103,16 +100,6 @@ func Up20200605090509(tx *sql.Tx) error { | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer client.DB.Close() | ||||
| 
 | ||||
| 	migrationsRan, err := getRanSQLMigrations(client) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if _, ok := migrationsRan[20200605090509]; ok { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	namespaces, err := client.ListOnepanelEnabledNamespaces() | ||||
| 	if err != nil { | ||||
| @@ -88,11 +88,8 @@ templates: | ||||
| 
 | ||||
| const tensorflowWorkflowTemplateName = "TensorFlow Training" | ||||
| 
 | ||||
| func initialize20200605090535() { | ||||
| 	if _, ok := initializedMigrations[20200605090535]; !ok { | ||||
| 		goose.AddMigration(Up20200605090535, Down20200605090535) | ||||
| 		initializedMigrations[20200605090535] = true | ||||
| 	} | ||||
| func init() { | ||||
| 	goose.AddMigration(Up20200605090535, Down20200605090535) | ||||
| } | ||||
| 
 | ||||
| // Up20200605090535 will insert a tensorflow workflow template to each user. | ||||
| @@ -103,16 +100,6 @@ func Up20200605090535(tx *sql.Tx) error { | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer client.DB.Close() | ||||
| 
 | ||||
| 	migrationsRan, err := getRanSQLMigrations(client) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if _, ok := migrationsRan[20200605090535]; ok { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	namespaces, err := client.ListOnepanelEnabledNamespaces() | ||||
| 	if err != nil { | ||||
| @@ -2,4 +2,5 @@ | ||||
| ALTER TABLE workflow_template_versions DROP COLUMN uid; | ||||
| 
 | ||||
| -- +goose Down | ||||
| ALTER TABLE workflow_template_versions ADD COLUMN uid VARCHAR(30); | ||||
| UPDATE workflow_template_versions SET uid = version::text; | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
| 	v1 "github.com/onepanelio/core/pkg" | ||||
| 	uid2 "github.com/onepanelio/core/pkg/util/uid" | ||||
| 	"github.com/pressly/goose" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| const cvatWorkspaceTemplate2 = `# Docker containers that are part of the Workspace | ||||
| @@ -118,30 +119,20 @@ routes: | ||||
| #       - -c | ||||
| ` | ||||
| 
 | ||||
| func initialize20200626113635() { | ||||
| 	if _, ok := initializedMigrations[20200626113635]; !ok { | ||||
| 		goose.AddMigration(Up20200626113635, Down20200626113635) | ||||
| 		initializedMigrations[20200626113635] = true | ||||
| 	} | ||||
| func init() { | ||||
| 	goose.AddMigration(Up20200626113635, Down20200626113635) | ||||
| } | ||||
| 
 | ||||
| // Up20200626113635 updates the CVAT template to a new version. | ||||
| func Up20200626113635(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 | ||||
| 	} | ||||
| 	defer client.DB.Close() | ||||
| 
 | ||||
| 	migrationsRan, err := getRanSQLMigrations(client) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if _, ok := migrationsRan[20200626113635]; ok { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	namespaces, err := client.ListOnepanelEnabledNamespaces() | ||||
| 	if err != nil { | ||||
							
								
								
									
										25
									
								
								db/db.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								db/db.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| 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 | ||||
| } | ||||
| @@ -1,176 +0,0 @@ | ||||
| package migration | ||||
|  | ||||
| import ( | ||||
| 	"database/sql" | ||||
| 	v1 "github.com/onepanelio/core/pkg" | ||||
| 	uid2 "github.com/onepanelio/core/pkg/util/uid" | ||||
| 	"github.com/pressly/goose" | ||||
| ) | ||||
|  | ||||
| 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 initialize20200704151301() { | ||||
| 	if _, ok := initializedMigrations[20200704151301]; !ok { | ||||
| 		goose.AddMigration(Up20200704151301, Down20200704151301) | ||||
| 		initializedMigrations[20200704151301] = true | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Up20200704151301 updates the CVAT template to a new version. | ||||
| func Up20200704151301(tx *sql.Tx) error { | ||||
| 	// This code is executed when the migration is applied. | ||||
| 	client, err := getClient() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer client.DB.Close() | ||||
|  | ||||
| 	migrationsRan, err := getRanSQLMigrations(client) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if _, ok := migrationsRan[20200704151301]; ok { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	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 | ||||
| } | ||||
| @@ -1,204 +0,0 @@ | ||||
| package migration | ||||
|  | ||||
| import ( | ||||
| 	"database/sql" | ||||
| 	v1 "github.com/onepanelio/core/pkg" | ||||
| 	uid2 "github.com/onepanelio/core/pkg/util/uid" | ||||
| 	"github.com/pressly/goose" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| const cvatWorkspaceTemplate4 = `# Workspace arguments | ||||
| arguments: | ||||
|   parameters: | ||||
|   - name: storage-prefix | ||||
|     displayName: Directory in default object storage | ||||
|     value: data | ||||
|     hint: Location of data and models in default object storage, will continuously sync to '/mnt/share' | ||||
| 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: sys-namespace-config | ||||
|     mountPath: /etc/onepanel | ||||
|     readOnly: true | ||||
| - name: cvat-ui | ||||
|   image: onepanel/cvat-ui:v0.7.10-stable | ||||
|   ports: | ||||
|   - containerPort: 80 | ||||
|     name: http | ||||
| # You can add multiple FileSyncer sidecar containers if needed | ||||
| - name: filesyncer | ||||
|   image: onepanel/filesyncer:{{.ArtifactRepositoryType}} | ||||
|   args: | ||||
|   - download | ||||
|   env: | ||||
|   - name: FS_PATH | ||||
|     value: /mnt/share | ||||
|   - name: FS_PREFIX | ||||
|     value: '{{workspace.parameters.storage-prefix}}' | ||||
|   volumeMounts: | ||||
|   - name: share | ||||
|     mountPath: /mnt/share | ||||
|   - name: sys-namespace-config | ||||
|     mountPath: /etc/onepanel | ||||
|     readOnly: true | ||||
| 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 initialize20200724220450() { | ||||
| 	if _, ok := initializedMigrations[20200724220450]; !ok { | ||||
| 		goose.AddMigration(Up20200724220450, Down20200724220450) | ||||
| 		initializedMigrations[20200724220450] = true | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Up20200724220450 updates the CVAT template to a new version. | ||||
| func Up20200724220450(tx *sql.Tx) error { | ||||
| 	// This code is executed when the migration is applied. | ||||
| 	client, err := getClient() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer client.DB.Close() | ||||
|  | ||||
| 	migrationsRan, err := getRanSQLMigrations(client) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if _, ok := migrationsRan[20200724220450]; ok { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	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: cvatWorkspaceTemplate4, | ||||
| 	} | ||||
|  | ||||
| 	for _, namespace := range namespaces { | ||||
| 		artifactRepositoryType := "s3" | ||||
| 		nsConfig, err := client.GetNamespaceConfig(namespace.Name) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if nsConfig.ArtifactRepository.GCS != nil { | ||||
| 			artifactRepositoryType = "gcs" | ||||
| 		} | ||||
| 		workspaceTemplate.Manifest = strings.NewReplacer( | ||||
| 			"{{.ArtifactRepositoryType}}", artifactRepositoryType).Replace(workspaceTemplate.Manifest) | ||||
| 		if _, err := client.UpdateWorkspaceTemplate(namespace.Name, workspaceTemplate); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Down20200724220450 rolls back the CVAT template version | ||||
| func Down20200724220450(tx *sql.Tx) error { | ||||
| 	// This code is executed when the migration is rolled back. | ||||
| 	return nil | ||||
| } | ||||
| @@ -1,74 +0,0 @@ | ||||
| package migration | ||||
|  | ||||
| import ( | ||||
| 	"database/sql" | ||||
| 	v1 "github.com/onepanelio/core/pkg" | ||||
| 	"github.com/onepanelio/core/pkg/util/pagination" | ||||
| 	"github.com/pressly/goose" | ||||
| ) | ||||
|  | ||||
| func initialize20200727144157() { | ||||
| 	if _, ok := initializedMigrations[20200727144157]; !ok { | ||||
| 		goose.AddMigration(Up20200727144157, Down20200727144157) | ||||
| 		initializedMigrations[20200727144157] = true | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Up20200727144157 will go through all WorkflowTemplateVersion database entries | ||||
| // and attempt to generate the "parameters" column from the "manifests" column. | ||||
| func Up20200727144157(tx *sql.Tx) error { | ||||
| 	// This code is executed when the migration is applied. | ||||
|  | ||||
| 	client, err := getClient() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer client.DB.Close() | ||||
|  | ||||
| 	migrationsRan, err := getRanSQLMigrations(client) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if _, ok := migrationsRan[20200727144157]; ok { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	pageSize := int32(100) | ||||
| 	page := int32(0) | ||||
| 	paginator := pagination.NewRequest(page, pageSize) | ||||
| 	wtvsResults := -1 | ||||
| 	for wtvsResults != 0 { | ||||
| 		wtvs, err := client.ListWorkflowTemplateVersionsAll(&paginator) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		//Exit condition; Check for more results | ||||
| 		wtvsResults = len(wtvs) | ||||
| 		if wtvsResults > 0 { | ||||
| 			page++ | ||||
| 			paginator = pagination.NewRequest(page, pageSize) | ||||
| 		} | ||||
|  | ||||
| 		for _, wtv := range wtvs { | ||||
| 			params, err := v1.ParseParametersFromManifest([]byte(wtv.Manifest)) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			wtv.Parameters = params | ||||
| 			err = client.UpdateWorkflowTemplateVersion(wtv) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Down20200727144157 can be run before 20200727155027_add_parameters_col_to_workflow_template_version.sql | ||||
| // Nothing happens because the referenced SQL file will drop the "parameters" column. | ||||
| func Down20200727144157(tx *sql.Tx) error { | ||||
| 	// This code is executed when the migration is rolled back. | ||||
| 	return nil | ||||
| } | ||||
| @@ -1,42 +0,0 @@ | ||||
| package migration | ||||
|  | ||||
| import ( | ||||
| 	"database/sql" | ||||
| 	v1 "github.com/onepanelio/core/pkg" | ||||
| 	"github.com/pressly/goose" | ||||
| ) | ||||
|  | ||||
| func initialize20200728190804() { | ||||
| 	if _, ok := initializedMigrations[20200728190804]; !ok { | ||||
| 		goose.AddMigration(Up20200728190804, Down20200728190804) | ||||
| 		initializedMigrations[20200728190804] = true | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Up20200728190804 is a legacy migration. Due to code changes, it no longer does anything. | ||||
| // It used to update labels so that we keep track of WorkflowTemplate labels. | ||||
| // Before, only workflow template versions had labels, but to speed up some queries, we now cache the latest version's labels | ||||
| // for workflow templates themselves. | ||||
| func Up20200728190804(tx *sql.Tx) error { | ||||
| 	// This code is executed when the migration is applied. | ||||
| 	if migrationHasAlreadyBeenRun(20200728190804) { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	// Do nothing, be preserve for legacy. | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Down20200728190804 rolls down the migration by deleting all workflow template labels, since they did not exist before this | ||||
| func Down20200728190804(tx *sql.Tx) error { | ||||
| 	// This code is executed when the migration is rolled back. | ||||
|  | ||||
| 	client, err := getClient() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer client.DB.Close() | ||||
|  | ||||
| 	return client.DeleteResourceLabels(tx, v1.TypeWorkflowTemplate) | ||||
| } | ||||
| @@ -1,503 +0,0 @@ | ||||
| package migration | ||||
|  | ||||
| import ( | ||||
| 	"database/sql" | ||||
| 	v1 "github.com/onepanelio/core/pkg" | ||||
| 	"github.com/pressly/goose" | ||||
| 	"log" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| const maskRCNNWorkflowTemplate = `arguments: | ||||
|   parameters: | ||||
|   - name: source | ||||
|     value: https://github.com/onepanelio/Mask_RCNN.git | ||||
|     displayName: Model source code | ||||
|     type: hidden | ||||
|     visibility: private | ||||
|  | ||||
|   - name: sys-annotation-path | ||||
|     value: annotation-dump/sample_dataset | ||||
|     hint: Path to annotated data in default object storage (i.e S3). In CVAT, this parameter will be pre-populated. | ||||
|     displayName: Dataset path | ||||
|     visibility: private | ||||
|      | ||||
|   - name: sys-output-path | ||||
|     value: workflow-data/output/sample_output | ||||
|     hint: Path to store output artifacts in default object storage (i.e s3). In CVAT, this parameter will be pre-populated. | ||||
|     displayName: Workflow output path | ||||
|     visibility: private | ||||
|  | ||||
|   - name: sys-finetune-checkpoint | ||||
|     value: '' | ||||
|     hint: Select the last fine-tune checkpoint for this model. It may take up to 5 minutes for a recent checkpoint show here. Leave empty if this is the first time you're training this model. | ||||
|     displayName: Checkpoint path | ||||
|     visibility: public | ||||
|    | ||||
|   - name: sys-num-classes | ||||
|     displayName: Number of classes | ||||
|     hint: Number of classes (i.e in CVAT taks) + 1 for background | ||||
|     value: 81 | ||||
|     visibility: private | ||||
|      | ||||
|   - name: extras | ||||
|     displayName: Hyperparameters | ||||
|     visibility: public | ||||
|     type: textarea.textarea | ||||
|     value: |- | ||||
|       stage-1-epochs=1    #  Epochs for network heads | ||||
|       stage-2-epochs=2    #  Epochs for finetune layers | ||||
|       stage-3-epochs=3    #  Epochs for all layers | ||||
|     hint: "Please refer to our <a href='https://docs.onepanel.ai/docs/getting-started/use-cases/computervision/annotation/cvat/cvat_annotation_model#arguments-optional' target='_blank'>documentation</a> for more information on parameters." | ||||
|      | ||||
|   - name: dump-format | ||||
|     type: select.select | ||||
|     value: cvat_coco | ||||
|     displayName: CVAT dump format | ||||
|     visibility: public | ||||
|     options: | ||||
|     - name: 'MS COCO' | ||||
|       value: 'cvat_coco' | ||||
|     - name: 'TF Detection API' | ||||
|       value: 'cvat_tfrecord' | ||||
|        | ||||
|   - name: tf-image | ||||
|     visibility: public | ||||
|     value: tensorflow/tensorflow:1.13.1-py3 | ||||
|     type: select.select | ||||
|     displayName: Select TensorFlow image | ||||
|     hint: Select the GPU image if you are running on a GPU node pool | ||||
|     options: | ||||
|     - name: 'TensorFlow 1.13.1 CPU Image' | ||||
|       value: 'tensorflow/tensorflow:1.13.1-py3' | ||||
|     - name: 'TensorFlow 1.13.1 GPU Image' | ||||
|       value: 'tensorflow/tensorflow:1.13.1-gpu-py3' | ||||
|    | ||||
|   - displayName: Node pool | ||||
|     hint: Name of node pool or group to run this workflow task | ||||
|     type: select.select | ||||
|     visibility: public | ||||
|     name: sys-node-pool | ||||
|     value: Standard_D4s_v3 | ||||
|     required: true | ||||
|     options: | ||||
|     - name: 'CPU: 2, RAM: 8GB' | ||||
|       value: Standard_D2s_v3 | ||||
|     - name: 'CPU: 4, RAM: 16GB' | ||||
|       value: Standard_D4s_v3 | ||||
|     - name: 'GPU: 1xK80, CPU: 6, RAM: 56GB' | ||||
|       value: Standard_NC6 | ||||
|  | ||||
| entrypoint: main | ||||
| templates: | ||||
| - dag: | ||||
|     tasks: | ||||
|     - name: train-model | ||||
|       template: tensorflow | ||||
| # Uncomment the lines below if you want to send Slack notifications | ||||
| #    - arguments: | ||||
| #        artifacts: | ||||
| #        - from: '{{tasks.train-model.outputs.artifacts.sys-metrics}}' | ||||
| #          name: metrics | ||||
| #        parameters: | ||||
| #        - name: status | ||||
| #          value: '{{tasks.train-model.status}}' | ||||
| #      dependencies: | ||||
| #      - train-model | ||||
| #      name: notify-in-slack | ||||
| #      template: slack-notify-success | ||||
|   name: main | ||||
| - container: | ||||
|     args: | ||||
|     - | | ||||
|       apt-get update \ | ||||
|       && apt-get install -y git wget libglib2.0-0 libsm6 libxext6 libxrender-dev \ | ||||
|       && pip install -r requirements.txt \ | ||||
|       && pip install boto3 pyyaml google-cloud-storage \ | ||||
|       && git clone https://github.com/waleedka/coco \ | ||||
|       && cd coco/PythonAPI \ | ||||
|       && python setup.py build_ext install \ | ||||
|       && rm -rf build \ | ||||
|       && cd ../../ \ | ||||
|       && wget https://github.com/matterport/Mask_RCNN/releases/download/v2.0/mask_rcnn_coco.h5 \ | ||||
|       && python setup.py install && ls \ | ||||
|       && python samples/coco/cvat.py train --dataset=/mnt/data/datasets \ | ||||
|         --model=workflow_maskrcnn \ | ||||
|         --extras="{{workflow.parameters.extras}}"  \ | ||||
|         --ref_model_path="{{workflow.parameters.sys-finetune-checkpoint}}"  \ | ||||
|         --num_classes="{{workflow.parameters.sys-num-classes}}" \ | ||||
|       && cd /mnt/src/ \ | ||||
|       && python prepare_dataset.py /mnt/data/datasets/annotations/instances_default.json | ||||
|     command: | ||||
|     - sh | ||||
|     - -c | ||||
|     image: '{{workflow.parameters.tf-image}}' | ||||
|     volumeMounts: | ||||
|     - mountPath: /mnt/data | ||||
|       name: data | ||||
|     - mountPath: /mnt/output | ||||
|       name: output | ||||
|     workingDir: /mnt/src | ||||
|   nodeSelector: | ||||
|     beta.kubernetes.io/instance-type: '{{workflow.parameters.sys-node-pool}}' | ||||
|   inputs: | ||||
|     artifacts: | ||||
|     - name: data | ||||
|       path: /mnt/data/datasets/ | ||||
|       s3: | ||||
|         key: '{{workflow.namespace}}/{{workflow.parameters.sys-annotation-path}}' | ||||
|     - git: | ||||
|         repo: '{{workflow.parameters.source}}' | ||||
|         revision: "no-boto" | ||||
|       name: src | ||||
|       path: /mnt/src | ||||
|   name: tensorflow | ||||
|   outputs: | ||||
|     artifacts: | ||||
|     - name: model | ||||
|       optional: true | ||||
|       path: /mnt/output | ||||
|       s3: | ||||
|         key: '{{workflow.namespace}}/{{workflow.parameters.sys-output-path}}' | ||||
| # Uncomment the lines below if you want to send Slack notifications | ||||
| #- container: | ||||
| #    args: | ||||
| #    - SLACK_USERNAME=Onepanel SLACK_TITLE="{{workflow.name}} {{inputs.parameters.status}}" | ||||
| #      SLACK_ICON=https://www.gravatar.com/avatar/5c4478592fe00878f62f0027be59c1bd | ||||
| #      SLACK_MESSAGE=$(cat /tmp/metrics.json)} ./slack-notify | ||||
| #    command: | ||||
| #    - sh | ||||
| #    - -c | ||||
| #    image: technosophos/slack-notify | ||||
| #  inputs: | ||||
| #    artifacts: | ||||
| #    - name: metrics | ||||
| #      optional: true | ||||
| #      path: /tmp/metrics.json | ||||
| #    parameters: | ||||
| #    - name: status | ||||
| #  name: slack-notify-success | ||||
| volumeClaimTemplates: | ||||
| - metadata: | ||||
|     creationTimestamp: null | ||||
|     name: data | ||||
|   spec: | ||||
|     accessModes: | ||||
|     - ReadWriteOnce | ||||
|     resources: | ||||
|       requests: | ||||
|         storage: 200Gi | ||||
| - metadata: | ||||
|     creationTimestamp: null | ||||
|     name: output | ||||
|   spec: | ||||
|     accessModes: | ||||
|     - ReadWriteOnce | ||||
|     resources: | ||||
|       requests: | ||||
|         storage: 200Gi` | ||||
|  | ||||
| const maskRCNNWorkflowTemplateName = "MaskRCNN Training" | ||||
|  | ||||
| const tensorflowObjectDetectionWorkflowTemplate = `arguments: | ||||
|   parameters: | ||||
|   - name: source | ||||
|     value: https://github.com/tensorflow/models.git | ||||
|     displayName: Model source code | ||||
|     type: hidden | ||||
|     visibility: private | ||||
|  | ||||
|   - name: trainingsource | ||||
|     value: https://github.com/onepanelio/cvat-training.git | ||||
|     type: hidden | ||||
|     visibility: private | ||||
|  | ||||
|   - name: revision | ||||
|     value: v1.13.0 | ||||
|     type: hidden  | ||||
|     visibility: private | ||||
|  | ||||
|   - name: sys-annotation-path | ||||
|     value: annotation-dump/sample_dataset | ||||
|     displayName: Dataset path | ||||
|     hint: Path to annotated data in default object storage (i.e S3). In CVAT, this parameter will be pre-populated. | ||||
|  | ||||
|   - name: sys-output-path | ||||
|     value: workflow-data/output/sample_output | ||||
|     hint: Path to store output artifacts in default object storage (i.e s3). In CVAT, this parameter will be pre-populated. | ||||
|     displayName: Workflow output path | ||||
|     visibility: private | ||||
|  | ||||
|   - name: ref-model | ||||
|     value: frcnn-res50-coco | ||||
|     displayName: Model | ||||
|     hint: TF Detection API's model to use for training. | ||||
|     type: select.select | ||||
|     visibility: public | ||||
|     options: | ||||
|     - name: 'Faster RCNN-ResNet 101-COCO' | ||||
|       value: frcnn-res101-coco | ||||
|     - name: 'Faster RCNN-ResNet 101-Low Proposal-COCO' | ||||
|       value: frcnn-res101-low | ||||
|     - name: 'Faster RCNN-ResNet 50-COCO' | ||||
|       value: frcnn-res50-coco | ||||
|     - name: 'Faster RCNN-NAS-COCO' | ||||
|       value: frcnn-nas-coco | ||||
|     - name: 'SSD MobileNet V1-COCO' | ||||
|       value: ssd-mobilenet-v1-coco2 | ||||
|     - name: 'SSD MobileNet V2-COCO' | ||||
|       value: ssd-mobilenet-v2-coco | ||||
|     - name: 'SSDLite MobileNet-COCO' | ||||
|       value: ssdlite-mobilenet-coco | ||||
|    | ||||
|   - name: extras | ||||
|     value: |- | ||||
|       epochs=1000 | ||||
|     displayName: Hyperparameters | ||||
|     visibility: public | ||||
|     type: textarea.textarea | ||||
|     hint: "Please refer to our <a href='https://docs.onepanel.ai/docs/getting-started/use-cases/computervision/annotation/cvat/cvat_annotation_model#arguments-optional' target='_blank'>documentation</a> for more information on parameters. Number of classes will be automatically populated if you had 'sys-num-classes' parameter in a workflow." | ||||
|    | ||||
|   - name: sys-finetune-checkpoint | ||||
|     value: '' | ||||
|     hint: Select the last fine-tune checkpoint for this model. It may take up to 5 minutes for a recent checkpoint show here. Leave empty if this is the first time you're training this model. | ||||
|     displayName: Checkpoint path | ||||
|     visibility: public | ||||
|      | ||||
|   - name: sys-num-classes | ||||
|     value: 81 | ||||
|     hint: Number of classes | ||||
|     displayName: Number of classes | ||||
|     visibility: private | ||||
|  | ||||
|   - name: tf-image | ||||
|     value: tensorflow/tensorflow:1.13.1-py3 | ||||
|     type: select.select | ||||
|     displayName: Select TensorFlow image | ||||
|     visibility: public | ||||
|     hint: Select the GPU image if you are running on a GPU node pool | ||||
|     options: | ||||
|     - name: 'TensorFlow 1.13.1 CPU Image' | ||||
|       value: 'tensorflow/tensorflow:1.13.1-py3' | ||||
|     - name: 'TensorFlow 1.13.1 GPU Image' | ||||
|       value: 'tensorflow/tensorflow:1.13.1-gpu-py3' | ||||
|  | ||||
|   - displayName: Node pool | ||||
|     hint: Name of node pool or group to run this workflow task | ||||
|     type: select.select | ||||
|     name: sys-node-pool | ||||
|     value: Standard_D4s_v3 | ||||
|     visibility: public | ||||
|     required: true | ||||
|     options: | ||||
|     - name: 'CPU: 2, RAM: 8GB' | ||||
|       value: Standard_D2s_v3 | ||||
|     - name: 'CPU: 4, RAM: 16GB' | ||||
|       value: Standard_D4s_v3 | ||||
|     - name: 'GPU: 1xK80, CPU: 6, RAM: 56GB' | ||||
|       value: Standard_NC6 | ||||
|   - name: dump-format | ||||
|     value: cvat_tfrecord | ||||
|     visibility: public | ||||
| entrypoint: main | ||||
| templates: | ||||
| - dag: | ||||
|     tasks: | ||||
|     - name: train-model | ||||
|       template: tensorflow | ||||
| # Uncomment the lines below if you want to send Slack notifications | ||||
| #    - arguments: | ||||
| #        artifacts: | ||||
| #        - from: '{{tasks.train-model.outputs.artifacts.sys-metrics}}' | ||||
| #          name: metrics | ||||
| #        parameters: | ||||
| #        - name: status | ||||
| #          value: '{{tasks.train-model.status}}' | ||||
| #      dependencies: | ||||
| #      - train-model | ||||
| #      name: notify-in-slack | ||||
| #      template: slack-notify-success | ||||
|   name: main | ||||
| - container: | ||||
|     args: | ||||
|     - | | ||||
|       apt-get update && \ | ||||
|       apt-get install -y python3-pip git wget unzip libglib2.0-0 libsm6 libxext6 libxrender-dev && \ | ||||
|       pip install pillow lxml Cython contextlib2 jupyter matplotlib numpy scipy boto3 pycocotools pyyaml google-cloud-storage && \ | ||||
|       cd /mnt/src/tf/research && \ | ||||
|       export PYTHONPATH=$PYTHONPATH:` + "`pwd`:`pwd`/slim" + ` && \ | ||||
|       cd /mnt/src/train && \ | ||||
|       python convert_workflow.py \ | ||||
|         --extras="{{workflow.parameters.extras}}" \ | ||||
|         --model="{{workflow.parameters.ref-model}}" \ | ||||
|         --num_classes="{{workflow.parameters.sys-num-classes}}" \ | ||||
|         --sys_finetune_checkpoint={{workflow.parameters.sys-finetune-checkpoint}} | ||||
|     command: | ||||
|     - sh | ||||
|     - -c | ||||
|     image: '{{workflow.parameters.tf-image}}' | ||||
|     volumeMounts: | ||||
|     - mountPath: /mnt/data | ||||
|       name: data | ||||
|     - mountPath: /mnt/output | ||||
|       name: output | ||||
|     workingDir: /mnt/src | ||||
|   nodeSelector: | ||||
|     beta.kubernetes.io/instance-type: '{{workflow.parameters.sys-node-pool}}' | ||||
|   inputs: | ||||
|     artifacts: | ||||
|     - name: data | ||||
|       path: /mnt/data/datasets/ | ||||
|       s3: | ||||
|         key: '{{workflow.namespace}}/{{workflow.parameters.sys-annotation-path}}' | ||||
|     - name: models | ||||
|       path: /mnt/data/models/ | ||||
|       optional: true | ||||
|       s3: | ||||
|         key: '{{workflow.namespace}}/{{workflow.parameters.sys-finetune-checkpoint}}' | ||||
|     - git: | ||||
|         repo: '{{workflow.parameters.source}}' | ||||
|         revision: '{{workflow.parameters.revision}}' | ||||
|       name: src | ||||
|       path: /mnt/src/tf | ||||
|     - git: | ||||
|         repo: '{{workflow.parameters.trainingsource}}' | ||||
|         revision: 'optional-artifacts' | ||||
|       name: tsrc | ||||
|       path: /mnt/src/train | ||||
|   name: tensorflow | ||||
|   outputs: | ||||
|     artifacts: | ||||
|     - name: model | ||||
|       optional: true | ||||
|       path: /mnt/output | ||||
|       s3: | ||||
|         key: '{{workflow.namespace}}/{{workflow.parameters.sys-output-path}}' | ||||
| # Uncomment the lines below if you want to send Slack notifications | ||||
| #- container: | ||||
| #    args: | ||||
| #    - SLACK_USERNAME=Onepanel SLACK_TITLE="{{workflow.name}} {{inputs.parameters.status}}" | ||||
| #      SLACK_ICON=https://www.gravatar.com/avatar/5c4478592fe00878f62f0027be59c1bd | ||||
| #      SLACK_MESSAGE=$(cat /tmp/metrics.json)} ./slack-notify | ||||
| #    command: | ||||
| #    - sh | ||||
| #    - -c | ||||
| #    image: technosophos/slack-notify | ||||
| #  inputs: | ||||
| #    artifacts: | ||||
| #    - name: metrics | ||||
| #      optional: true | ||||
| #      path: /tmp/metrics.json | ||||
| #    parameters: | ||||
| #    - name: status | ||||
| #  name: slack-notify-success | ||||
| volumeClaimTemplates: | ||||
| - metadata: | ||||
|     creationTimestamp: null | ||||
|     name: data | ||||
|   spec: | ||||
|     accessModes: | ||||
|     - ReadWriteOnce | ||||
|     resources: | ||||
|       requests: | ||||
|         storage: 200Gi | ||||
| - metadata: | ||||
|     creationTimestamp: null | ||||
|     name: output | ||||
|   spec: | ||||
|     accessModes: | ||||
|     - ReadWriteOnce | ||||
|     resources: | ||||
|       requests: | ||||
|         storage: 200Gi` | ||||
|  | ||||
| const tensorflowObjectDetectionWorkflowTemplateName = "TF Object Detection Training" | ||||
|  | ||||
| func initialize20200812104328() { | ||||
| 	if _, ok := initializedMigrations[20200812104328]; !ok { | ||||
| 		goose.AddMigration(Up20200812104328, Down20200812104328) | ||||
| 		initializedMigrations[20200812104328] = true | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Up20200812104328 runs the migration to update MaskRCNN and TF_OD templates | ||||
| func Up20200812104328(tx *sql.Tx) error { | ||||
| 	// This code is executed when the migration is applied. | ||||
| 	client, err := getClient() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer client.DB.Close() | ||||
|  | ||||
| 	migrationsRan, err := getRanSQLMigrations(client) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if _, ok := migrationsRan[20200812104328]; ok { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	namespaces, err := client.ListOnepanelEnabledNamespaces() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Create maskrcnn | ||||
| 	workflowTemplate := &v1.WorkflowTemplate{ | ||||
| 		Name:     maskRCNNWorkflowTemplateName, | ||||
| 		Manifest: maskRCNNWorkflowTemplate, | ||||
| 		Labels: map[string]string{ | ||||
| 			"used-by": "cvat", | ||||
| 		}, | ||||
| 	} | ||||
| 	if err := workflowTemplate.GenerateUID(workflowTemplate.Name); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	for _, namespace := range namespaces { | ||||
| 		existingWorkflowTemplate, err := client.GetLatestWorkflowTemplate(namespace.Name, workflowTemplate.UID) | ||||
| 		if err != nil { | ||||
| 			if strings.Contains(err.Error(), "Workflow template not found") { | ||||
| 				err = nil | ||||
| 				existingWorkflowTemplate = nil | ||||
| 			} else { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 		if existingWorkflowTemplate != nil { | ||||
| 			log.Printf("Skipping creating template '%v'. It already exists in namespace '%v'", workflowTemplate.Name, namespace.Name) | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if _, err := client.CreateWorkflowTemplate(namespace.Name, workflowTemplate); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Update tf-od | ||||
| 	workflowTemplate = &v1.WorkflowTemplate{ | ||||
| 		Name:     tensorflowObjectDetectionWorkflowTemplateName, | ||||
| 		Manifest: tensorflowObjectDetectionWorkflowTemplate, | ||||
| 		Labels: map[string]string{ | ||||
| 			"used-by": "cvat", | ||||
| 		}, | ||||
| 	} | ||||
| 	if err := workflowTemplate.GenerateUID(workflowTemplate.Name); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	for _, namespace := range namespaces { | ||||
| 		if _, err := client.CreateWorkflowTemplateVersion(namespace.Name, workflowTemplate); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Down20200812104328 does nothing | ||||
| func Down20200812104328(tx *sql.Tx) error { | ||||
| 	// This code is executed when the migration is rolled back. | ||||
| 	return nil | ||||
| } | ||||
| @@ -1,213 +0,0 @@ | ||||
| package migration | ||||
|  | ||||
| import ( | ||||
| 	"database/sql" | ||||
| 	v1 "github.com/onepanelio/core/pkg" | ||||
| 	uid2 "github.com/onepanelio/core/pkg/util/uid" | ||||
| 	"github.com/pressly/goose" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| const cvatWorkspaceTemplate5 = `# Workspace arguments | ||||
| arguments: | ||||
|   parameters: | ||||
|   - name: sync-directory | ||||
|     displayName: Directory to sync raw input and training output | ||||
|     value: workflow-data | ||||
|     hint: Location to sync raw input, models and checkpoints from default object storage. Note that this will be relative to the current namespace. | ||||
| 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:0.12.0_cvat.1.0.0-beta.2-cuda | ||||
|   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 | ||||
|   - name: ONEPANEL_SYNC_DIRECTORY | ||||
|     value: '{{workspace.parameters.sync-directory}}' | ||||
|   - name: NVIDIA_VISIBLE_DEVICES | ||||
|     value: all | ||||
|   - name: NVIDIA_DRIVER_CAPABILITIES | ||||
|     value: compute,utility | ||||
|   - name: NVIDIA_REQUIRE_CUDA | ||||
|     value: "cuda>=10.0 brand=tesla,driver>=384,driver<385 brand=tesla,driver>=410,driver<411" | ||||
|   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: sys-namespace-config | ||||
|     mountPath: /etc/onepanel | ||||
|     readOnly: true | ||||
| - name: cvat-ui | ||||
|   image: onepanel/cvat-ui:0.12.0_cvat.1.0.0-beta.2 | ||||
|   ports: | ||||
|   - containerPort: 80 | ||||
|     name: http | ||||
| # You can add multiple FileSyncer sidecar containers if needed | ||||
| - name: filesyncer | ||||
|   image: onepanel/filesyncer:{{.ArtifactRepositoryType}} | ||||
|   imagePullPolicy: Always | ||||
|   args: | ||||
|   - download | ||||
|   env: | ||||
|   - name: FS_PATH | ||||
|     value: /mnt/share | ||||
|   - name: FS_PREFIX | ||||
|     value: '{{workflow.namespace}}/{{workspace.parameters.sync-directory}}' | ||||
|   volumeMounts: | ||||
|   - name: share | ||||
|     mountPath: /mnt/share | ||||
|   - name: sys-namespace-config | ||||
|     mountPath: /etc/onepanel | ||||
|     readOnly: true | ||||
| 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/.*|/onepanelio/.*|/tracking/.*|/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 initialize20200812113316() { | ||||
| 	if _, ok := initializedMigrations[20200812113316]; !ok { | ||||
| 		goose.AddMigration(Up20200812113316, Down20200812113316) | ||||
| 		initializedMigrations[20200812113316] = true | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Up20200812113316 runs the go migration to update cvat template | ||||
| func Up20200812113316(tx *sql.Tx) error { | ||||
| 	// This code is executed when the migration is applied. | ||||
| 	client, err := getClient() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer client.DB.Close() | ||||
|  | ||||
| 	migrationsRan, err := getRanSQLMigrations(client) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if _, ok := migrationsRan[20200812113316]; ok { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	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:    cvatWorkspaceTemplate5, | ||||
| 		Description: "Powerful and efficient Computer Vision Annotation Tool (CVAT)", | ||||
| 	} | ||||
|  | ||||
| 	for _, namespace := range namespaces { | ||||
| 		artifactRepositoryType := "s3" | ||||
| 		nsConfig, err := client.GetNamespaceConfig(namespace.Name) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		if nsConfig.ArtifactRepository.GCS != nil { | ||||
| 			artifactRepositoryType = "gcs" | ||||
| 		} | ||||
| 		workspaceTemplate.Manifest = strings.NewReplacer( | ||||
| 			"{{.ArtifactRepositoryType}}", artifactRepositoryType).Replace(workspaceTemplate.Manifest) | ||||
| 		if _, err := client.UpdateWorkspaceTemplate(namespace.Name, workspaceTemplate); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Down20200812113316 does nothing | ||||
| func Down20200812113316(tx *sql.Tx) error { | ||||
| 	// This code is executed when the migration is rolled back. | ||||
| 	return nil | ||||
| } | ||||
| @@ -1,58 +0,0 @@ | ||||
| package migration | ||||
|  | ||||
| import ( | ||||
| 	"database/sql" | ||||
| 	"github.com/pressly/goose" | ||||
| ) | ||||
|  | ||||
| func initialize20200814160856() { | ||||
| 	if _, ok := initializedMigrations[20200814160856]; !ok { | ||||
| 		goose.AddMigration(Up20200814160856, Down20200814160856) | ||||
| 		initializedMigrations[20200814160856] = true | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Up20200814160856 runs a migration to add description to jupyterlab template | ||||
| func Up20200814160856(tx *sql.Tx) error { | ||||
| 	// This code is executed when the migration is applied. | ||||
| 	// This code is executed when the migration is applied. | ||||
| 	client, err := getClient() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer client.DB.Close() | ||||
|  | ||||
| 	migrationsRan, err := getRanSQLMigrations(client) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if _, ok := migrationsRan[20200814160856]; ok { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	namespaces, err := client.ListOnepanelEnabledNamespaces() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	for _, namespace := range namespaces { | ||||
| 		workspaceTemplate, err := client.GetWorkspaceTemplate(namespace.Name, "jupyterlab", 0) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		workspaceTemplate.Description = "Interactive development environment for notebooks" | ||||
| 		if _, err := client.UpdateWorkspaceTemplate(namespace.Name, workspaceTemplate); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Down20200814160856 does nothing | ||||
| func Down20200814160856(tx *sql.Tx) error { | ||||
| 	// This code is executed when the migration is rolled back. | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										92
									
								
								db/go/db.go
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								db/go/db.go
									
									
									
									
									
								
							| @@ -1,92 +0,0 @@ | ||||
| package migration | ||||
|  | ||||
| import ( | ||||
| 	sq "github.com/Masterminds/squirrel" | ||||
| 	"github.com/jmoiron/sqlx" | ||||
| 	v1 "github.com/onepanelio/core/pkg" | ||||
| 	"log" | ||||
| ) | ||||
|  | ||||
| // initializedMigrations is used to keep track of which migrations have been initialized. | ||||
| // if they are initialized more than once, goose panics. | ||||
| var initializedMigrations = make(map[int]bool) | ||||
|  | ||||
| // sqlRanMigrations keeps track of all the sql migrations that have been run. | ||||
| // we need to know this because in an older version some go migrations ran alongside sql. | ||||
| // So if they have already been run, we can't run them again. | ||||
| var sqlRanMigrations = make(map[uint64]bool) | ||||
|  | ||||
| // migrationHasAlreadyBeenRun returns true if the migration has already been run in sql | ||||
| // see sqlRanMigrations var | ||||
| func migrationHasAlreadyBeenRun(version int) bool { | ||||
| 	_, ok := sqlRanMigrations[uint64(version)] | ||||
| 	return ok | ||||
| } | ||||
|  | ||||
| // Initialize sets up the go migrations. | ||||
| func Initialize() { | ||||
| 	client, err := getClient() | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("unable to get client for go migrations: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	migrationsRan, err := getRanSQLMigrations(client) | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Unable to get already run sql migrations: %v", err) | ||||
| 	} | ||||
| 	sqlRanMigrations = migrationsRan | ||||
|  | ||||
| 	initialize20200525160514() | ||||
| 	initialize20200528140124() | ||||
| 	initialize20200605090509() | ||||
| 	initialize20200605090535() | ||||
| 	initialize20200626113635() | ||||
| 	initialize20200704151301() | ||||
| 	initialize20200724220450() | ||||
| 	initialize20200727144157() | ||||
| 	initialize20200728190804() | ||||
| 	initialize20200812104328() | ||||
| 	initialize20200812113316() | ||||
| 	initialize20200814160856() | ||||
|  | ||||
| 	if err := client.DB.Close(); err != nil { | ||||
| 		log.Printf("[error] closing db %v", err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| 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 | ||||
| } | ||||
| @@ -1,11 +0,0 @@ | ||||
| -- +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; | ||||
| @@ -1,7 +0,0 @@ | ||||
| -- +goose Up | ||||
| ALTER TABLE workflow_template_versions ADD COLUMN parameters JSONB; | ||||
| UPDATE workflow_template_versions SET parameters = '[]'::JSONB; | ||||
| ALTER TABLE workflow_template_versions ALTER COLUMN parameters SET NOT NULL; | ||||
|  | ||||
| -- +goose Down | ||||
| ALTER TABLE workflow_template_versions DROP COLUMN parameters; | ||||
| @@ -1,195 +0,0 @@ | ||||
| -- +goose Up | ||||
| -- SQL in this section is executed when the migration is applied. | ||||
| ALTER TABLE workflow_templates ADD COLUMN labels JSONB DEFAULT '{}'::JSONB; | ||||
| ALTER TABLE workflow_template_versions ADD COLUMN labels JSONB DEFAULT '{}'::JSONB; | ||||
| ALTER TABLE workflow_executions ADD COLUMN labels JSONB DEFAULT '{}'::JSONB; | ||||
| ALTER TABLE workspaces ADD COLUMN labels JSONB DEFAULT '{}'::JSONB; | ||||
| ALTER TABLE workspace_templates ADD COLUMN labels JSONB DEFAULT '{}'::JSONB; | ||||
| ALTER TABLE workspace_template_versions ADD COLUMN labels JSONB DEFAULT '{}'::JSONB; | ||||
| ALTER TABLE cron_workflows ADD COLUMN labels JSONB DEFAULT '{}'::JSONB; | ||||
|  | ||||
| -- We take the old labels and put them into the new jsonb columns | ||||
| UPDATE workflow_templates wt | ||||
| SET labels = | ||||
|         ( | ||||
|             SELECT jsonb_object_agg(key, value) | ||||
|             FROM labels l | ||||
|             WHERE resource = 'workflow_template' | ||||
|               AND wt.id = l.resource_id | ||||
|         ) | ||||
| ; | ||||
| UPDATE workflow_templates SET labels = '{}'::jsonb WHERE labels IS NULL; | ||||
|  | ||||
| UPDATE workflow_template_versions wtv | ||||
| SET labels = | ||||
|         ( | ||||
|             SELECT jsonb_object_agg(key, value) | ||||
|             FROM labels l | ||||
|             WHERE resource = 'workflow_template_version' | ||||
|               AND wtv.id = l.resource_id | ||||
|         ) | ||||
| ; | ||||
| UPDATE workflow_template_versions SET labels = '{}'::jsonb WHERE labels IS NULL; | ||||
|  | ||||
| UPDATE workflow_executions we | ||||
| SET labels = | ||||
|     ( | ||||
|         SELECT jsonb_object_agg(key, value) | ||||
|         FROM labels l | ||||
|         WHERE resource = 'workflow_execution' | ||||
|           AND we.id = l.resource_id | ||||
|     ) | ||||
| ; | ||||
| UPDATE workflow_executions SET labels = '{}'::jsonb WHERE labels IS NULL; | ||||
|  | ||||
| UPDATE workspaces w | ||||
| SET labels = | ||||
|         ( | ||||
|             SELECT jsonb_object_agg(key, value) | ||||
|             FROM labels l | ||||
|             WHERE resource = 'workspace' | ||||
|               AND w.id = l.resource_id | ||||
|         ) | ||||
| ; | ||||
| UPDATE workspaces SET labels = '{}'::jsonb WHERE labels IS NULL; | ||||
|  | ||||
| UPDATE workspace_templates wt | ||||
| SET labels = | ||||
|         ( | ||||
|             SELECT jsonb_object_agg(key, value) | ||||
|             FROM labels l | ||||
|             WHERE resource = 'workspace_template' | ||||
|               AND wt.id = l.resource_id | ||||
|         ) | ||||
| ; | ||||
| UPDATE workspace_templates SET labels = '{}'::jsonb WHERE labels IS NULL; | ||||
|  | ||||
| UPDATE workspace_template_versions wtv | ||||
| SET labels = | ||||
|         ( | ||||
|             SELECT jsonb_object_agg(key, value) | ||||
|             FROM labels l | ||||
|             WHERE resource = 'workspace_template_version' | ||||
|               AND wtv.id = l.resource_id | ||||
|         ) | ||||
| ; | ||||
| UPDATE workspace_template_versions SET labels = '{}'::jsonb WHERE labels IS NULL; | ||||
|  | ||||
| UPDATE cron_workflows cw | ||||
| SET labels = | ||||
|         ( | ||||
|             SELECT jsonb_object_agg(key, value) | ||||
|             FROM labels l | ||||
|             WHERE resource = 'cron_workflow' | ||||
|               AND cw.id = l.resource_id | ||||
|         ) | ||||
| ; | ||||
| UPDATE cron_workflows SET labels = '{}'::jsonb WHERE labels IS NULL; | ||||
|  | ||||
| DROP table labels; | ||||
|  | ||||
| -- +goose Down | ||||
| -- SQL in this section is executed when the migration is rolled back. | ||||
|  | ||||
| -- We take the jsonb column labels and put them back into a separate labels table | ||||
| CREATE TABLE labels | ||||
| ( | ||||
|     id serial PRIMARY KEY, | ||||
|     key character varying(255), | ||||
|     value character varying(255), | ||||
|     resource character varying(255), | ||||
|     resource_id integer, | ||||
|     created_at timestamp without time zone NOT NULL DEFAULT timezone('utc'::text, now()) | ||||
| ); | ||||
|  | ||||
| INSERT INTO labels(key, value, resource, resource_id, created_at) | ||||
| SELECT key, value, 'cron_workflow', id, now() | ||||
| FROM ( | ||||
|          SELECT wt1.id as id, wt1.key as key, wt2.labels->>wt1.key as value | ||||
|          FROM cron_workflows wt2 | ||||
|                   JOIN ( | ||||
|              SELECT wt.id, jsonb_object_keys(wt.labels) as key | ||||
|              FROM cron_workflows wt | ||||
|          ) wt1 on wt2.id = wt1.id | ||||
|      ) subquery | ||||
| ; | ||||
|  | ||||
| INSERT INTO labels(key, value, resource, resource_id, created_at) | ||||
| SELECT key, value, 'workflow_template_version', id, now() | ||||
| FROM ( | ||||
|          SELECT wt1.id as id, wt1.key as key, wt2.labels->>wt1.key as value | ||||
|          FROM workflow_template_versions wt2 | ||||
|                   JOIN ( | ||||
|              SELECT wt.id, jsonb_object_keys(wt.labels) as key | ||||
|              FROM workflow_template_versions wt | ||||
|          ) wt1 on wt2.id = wt1.id | ||||
|      ) subquery | ||||
| ; | ||||
|  | ||||
| INSERT INTO labels(key, value, resource, resource_id, created_at) | ||||
| SELECT key, value, 'workspace_template', id, now() | ||||
| FROM ( | ||||
|          SELECT wt1.id as id, wt1.key as key, wt2.labels->>wt1.key as value | ||||
|          FROM workspace_templates wt2 | ||||
|                   JOIN ( | ||||
|              SELECT wt.id, jsonb_object_keys(wt.labels) as key | ||||
|              FROM workspace_templates wt | ||||
|          ) wt1 on wt2.id = wt1.id | ||||
|      ) subquery | ||||
| ; | ||||
|  | ||||
| INSERT INTO labels(key, value, resource, resource_id, created_at) | ||||
| SELECT key, value, 'workspace', id, now() | ||||
| FROM ( | ||||
|          SELECT wt1.id as id, wt1.key as key, wt2.labels->>wt1.key as value | ||||
|          FROM workspaces wt2 | ||||
|                   JOIN ( | ||||
|              SELECT wt.id, jsonb_object_keys(wt.labels) as key | ||||
|              FROM workspaces wt | ||||
|          ) wt1 on wt2.id = wt1.id | ||||
|      ) subquery | ||||
| ; | ||||
|  | ||||
| INSERT INTO labels(key, value, resource, resource_id, created_at) | ||||
| SELECT key, value, 'workflow_execution', id, now() | ||||
| FROM ( | ||||
|          SELECT wt1.id as id, wt1.key as key, wt2.labels->>wt1.key as value | ||||
|          FROM workflow_executions wt2 | ||||
|                   JOIN ( | ||||
|              SELECT wt.id, jsonb_object_keys(wt.labels) as key | ||||
|              FROM workflow_executions wt | ||||
|          ) wt1 on wt2.id = wt1.id | ||||
|      ) subquery | ||||
| ; | ||||
|  | ||||
| INSERT INTO labels(key, value, resource, resource_id, created_at) | ||||
| SELECT key, value, 'workflow_template_version', id, now() | ||||
| FROM ( | ||||
|          SELECT wt1.id as id, wt1.key as key, wt2.labels->>wt1.key as value | ||||
|          FROM workflow_template_versions wt2 | ||||
|                   JOIN ( | ||||
|              SELECT wt.id, jsonb_object_keys(wt.labels) as key | ||||
|              FROM workflow_template_versions wt | ||||
|          ) wt1 on wt2.id = wt1.id | ||||
|      ) subquery | ||||
| ; | ||||
|  | ||||
| INSERT INTO labels(key, value, resource, resource_id, created_at) | ||||
| SELECT key, value, 'workflow_template', id, now() | ||||
| FROM ( | ||||
|          SELECT wt1.id as id, wt1.key as key, wt2.labels->>wt1.key as value | ||||
|          FROM workflow_templates wt2 | ||||
|                   JOIN ( | ||||
|              SELECT wt.id, jsonb_object_keys(wt.labels) as key | ||||
|              FROM workflow_templates wt | ||||
|          ) wt1 on wt2.id = wt1.id | ||||
|      ) subquery | ||||
| ; | ||||
|  | ||||
| ALTER TABLE cron_workflows DROP COLUMN labels; | ||||
| ALTER TABLE workspace_template_versions DROP COLUMN labels; | ||||
| ALTER TABLE workspace_templates DROP COLUMN labels; | ||||
| ALTER TABLE workspaces DROP COLUMN labels; | ||||
| ALTER TABLE workflow_executions DROP COLUMN labels; | ||||
| ALTER TABLE workflow_template_versions DROP COLUMN labels; | ||||
| ALTER TABLE workflow_templates DROP COLUMN labels; | ||||
| @@ -1,7 +0,0 @@ | ||||
| -- +goose Up | ||||
| -- SQL in this section is executed when the migration is applied. | ||||
| ALTER TABLE workspace_templates ADD COLUMN description TEXT DEFAULT ''; | ||||
|  | ||||
| -- +goose Down | ||||
| -- SQL in this section is executed when the migration is rolled back. | ||||
| ALTER TABLE workspace_templates DROP COLUMN description; | ||||
							
								
								
									
										8
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								go.mod
									
									
									
									
									
								
							| @@ -4,7 +4,6 @@ go 1.14 | ||||
|  | ||||
| require ( | ||||
| 	github.com/Azure/go-autorest v14.0.0+incompatible // indirect | ||||
| 	cloud.google.com/go/storage v1.6.0 | ||||
| 	github.com/Azure/go-autorest/autorest/adal v0.8.2 // indirect | ||||
| 	github.com/Masterminds/squirrel v1.1.0 | ||||
| 	github.com/argoproj/argo v0.0.0-20200331233432-4d1175eb68f6 | ||||
| @@ -15,10 +14,11 @@ require ( | ||||
| 	github.com/ghodss/yaml v1.0.0 | ||||
| 	github.com/go-sql-driver/mysql v1.5.0 // indirect | ||||
| 	github.com/golang/protobuf v1.4.1 | ||||
| 	github.com/google/uuid v1.1.1 | ||||
| 	github.com/gorilla/handlers v1.4.2 | ||||
| 	github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 | ||||
| 	github.com/grpc-ecosystem/grpc-gateway v1.14.4 | ||||
| 	github.com/hashicorp/go-uuid v1.0.2 // indirect | ||||
| 	github.com/hashicorp/go-uuid v1.0.2 | ||||
| 	github.com/hashicorp/golang-lru v0.5.4 // indirect | ||||
| 	github.com/jmoiron/sqlx v1.2.0 | ||||
| 	github.com/lib/pq v1.3.0 | ||||
| @@ -30,14 +30,10 @@ require ( | ||||
| 	github.com/spf13/cobra v0.0.5 // indirect | ||||
| 	github.com/stretchr/testify v1.4.0 | ||||
| 	github.com/tmc/grpc-websocket-proxy v0.0.0-20200122045848-3419fae592fc | ||||
| 	golang.org/x/net v0.0.0-20200301022130-244492dfa37a | ||||
| 	golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d | ||||
| 	google.golang.org/api v0.20.0 | ||||
| 	google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84 | ||||
| 	google.golang.org/grpc v1.28.0 | ||||
| 	google.golang.org/protobuf v1.22.0 | ||||
| 	gopkg.in/yaml.v2 v2.2.8 | ||||
| 	gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 | ||||
| 	istio.io/api v0.0.0-20200107183329-ed4b507c54e1 | ||||
| 	k8s.io/api v0.16.4 | ||||
| 	k8s.io/apimachinery v0.16.7-beta.0 | ||||
|   | ||||
							
								
								
									
										24
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								go.sum
									
									
									
									
									
								
							| @@ -12,18 +12,14 @@ cloud.google.com/go v0.55.0 h1:eoz/lYxKSL4CNAiaUJ0ZfD1J3bfMYbU5B3rwM1C1EIU= | ||||
| cloud.google.com/go v0.55.0/go.mod h1:ZHmoY+/lIMNkN2+fBmuTiqZ4inFhvQad8ft7MT8IV5Y= | ||||
| cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= | ||||
| cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= | ||||
| cloud.google.com/go/bigquery v1.4.0 h1:xE3CPsOgttP4ACBePh79zTKALtXwn/Edhcr16R5hMWU= | ||||
| cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= | ||||
| cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= | ||||
| cloud.google.com/go/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ= | ||||
| cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= | ||||
| cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= | ||||
| cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= | ||||
| cloud.google.com/go/pubsub v1.2.0 h1:Lpy6hKgdcl7a3WGSfJIFmxmcdjSpP6OmBEfcOv1Y680= | ||||
| cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= | ||||
| cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= | ||||
| cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= | ||||
| cloud.google.com/go/storage v1.6.0 h1:UDpwYIwla4jHGzZJaEJYx1tOejbgSoNqsAfHAUYe2r8= | ||||
| cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= | ||||
| dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= | ||||
| github.com/Azure/go-autorest v11.1.2+incompatible h1:viZ3tV5l4gE2Sw0xrasFHytCGtzYCrT+um/rrSQ1BfA= | ||||
| @@ -35,6 +31,8 @@ github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+B | ||||
| github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.8.2 h1:O1X4oexUxnZCaEUGsvMnr8ZGj8HI37tNezwY4npRqA0= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.8.3 h1:O1AGG9Xig71FxdX9HO5pGNyZ7TbSyHaVg+5eJO/jSGw= | ||||
| github.com/Azure/go-autorest/autorest/adal v0.8.3/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= | ||||
| github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= | ||||
| github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM= | ||||
| github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= | ||||
| @@ -46,7 +44,6 @@ github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1Gn | ||||
| github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= | ||||
| github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k= | ||||
| github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= | ||||
| github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= | ||||
| github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= | ||||
| github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= | ||||
| github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= | ||||
| @@ -210,7 +207,6 @@ github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSN | ||||
| github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= | ||||
| github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= | ||||
| github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= | ||||
| github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= | ||||
| github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= | ||||
| github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= | ||||
| github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= | ||||
| @@ -222,7 +218,6 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ | ||||
| github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= | ||||
| github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||||
| github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= | ||||
| github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= | ||||
| github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= | ||||
| github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= | ||||
| github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk= | ||||
| @@ -242,6 +237,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xC | ||||
| github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 h1:0IKlLyQ3Hs9nDaiK5cSHAGmcQEIC8l2Ts1u6x5Dfrqg= | ||||
| github.com/grpc-ecosystem/go-grpc-middleware v1.2.0/go.mod h1:mJzapYve32yjrKlk9GbyCZHuPgZsrbyIbyKhSzOpg6s= | ||||
| github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= | ||||
| github.com/grpc-ecosystem/grpc-gateway v1.14.3 h1:OCJlWkOUoTnl0neNGlf4fUm3TmbEtguw7vR+nGtnDjY= | ||||
| github.com/grpc-ecosystem/grpc-gateway v1.14.3/go.mod h1:6CwZWGDSPRJidgKAtJVvND6soZe6fT7iteq8wDPdhb0= | ||||
| github.com/grpc-ecosystem/grpc-gateway v1.14.4 h1:IOPK2xMPP3aV6/NPt4jt//ELFo3Vv8sDVD8j3+tleDU= | ||||
| github.com/grpc-ecosystem/grpc-gateway v1.14.4/go.mod h1:6CwZWGDSPRJidgKAtJVvND6soZe6fT7iteq8wDPdhb0= | ||||
| github.com/hashicorp/go-uuid v0.0.0-20180228145832-27454136f036/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= | ||||
| @@ -278,7 +275,6 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u | ||||
| github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= | ||||
| github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= | ||||
| github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= | ||||
| github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= | ||||
| github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= | ||||
| github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= | ||||
| github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= | ||||
| @@ -441,7 +437,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de | ||||
| go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= | ||||
| go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= | ||||
| go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | ||||
| go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= | ||||
| go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | ||||
| go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= | ||||
| go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= | ||||
| @@ -484,7 +479,6 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl | ||||
| golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= | ||||
| golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= | ||||
| golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= | ||||
| golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= | ||||
| golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= | ||||
| golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= | ||||
| golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= | ||||
| @@ -492,7 +486,6 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG | ||||
| golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= | ||||
| golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= | ||||
| golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= | ||||
| golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= | ||||
| golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||
| golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||
| golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||
| @@ -534,7 +527,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ | ||||
| golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o= | ||||
| golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| @@ -616,7 +608,6 @@ golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapK | ||||
| golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= | ||||
| golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= | ||||
| golang.org/x/tools v0.0.0-20200317043434-63da46f3035e/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= | ||||
| golang.org/x/tools v0.0.0-20200331202046-9d5940d49312 h1:2PHG+Ia3gK1K2kjxZnSylizb//eyaMG8gDFbOG7wLV8= | ||||
| golang.org/x/tools v0.0.0-20200331202046-9d5940d49312/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= | ||||
| golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| @@ -631,7 +622,6 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb | ||||
| google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= | ||||
| google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= | ||||
| google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= | ||||
| google.golang.org/api v0.20.0 h1:jz2KixHX7EcCPiQrySzPdnYT7DbINAypCqKZ1Z7GM40= | ||||
| google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= | ||||
| google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= | ||||
| google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= | ||||
| @@ -658,6 +648,8 @@ google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4 | ||||
| google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= | ||||
| google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= | ||||
| google.golang.org/genproto v0.0.0-20200317114155-1f3552e48f24/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= | ||||
| google.golang.org/genproto v0.0.0-20200413115906-b5235f65be36 h1:j7CmVRD4Kec0+f8VuBAc2Ak2MFfXm5Q2/RxuJLL+76E= | ||||
| google.golang.org/genproto v0.0.0-20200413115906-b5235f65be36/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= | ||||
| google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84 h1:pSLkPbrjnPyLDYUO2VM9mDLqo2V6CFBY84lFSZAfoi4= | ||||
| google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= | ||||
| google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= | ||||
| @@ -719,14 +711,11 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= | ||||
| gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= | ||||
| gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||
| honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= | ||||
| honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= | ||||
| honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= | ||||
| honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= | ||||
| honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= | ||||
| honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U= | ||||
| honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= | ||||
| istio.io/api v0.0.0-20200107183329-ed4b507c54e1 h1:q4xggEkhMn4RMRo8AJVNmMtNzy514DGiAUxRDDKPhZU= | ||||
| istio.io/api v0.0.0-20200107183329-ed4b507c54e1/go.mod h1:+cyHH83OwC0rFpwk8eXctzPNpiCAbB+r6kmMiAxxBHw= | ||||
| @@ -741,6 +730,7 @@ k8s.io/apimachinery v0.0.0-20191219145857-f69eda767ee8/go.mod h1:mhhO3hoLkWO+2eC | ||||
| k8s.io/apimachinery v0.16.4/go.mod h1:llRdnznGEAqC3DcNm6yEj472xaFVfLM7hnYofMb12tQ= | ||||
| k8s.io/apimachinery v0.16.7-beta.0 h1:1cNiN7ZXJzlWq7dnWojG5UcrX1AIfQqpbyuzhu7Bhsc= | ||||
| k8s.io/apimachinery v0.16.7-beta.0/go.mod h1:mhhO3hoLkWO+2eCvqjPtH2Ly92l9nJDwsswzWKpkN2w= | ||||
| k8s.io/apimachinery v0.18.3 h1:pOGcbVAhxADgUYnjS08EFXs9QMl8qaH5U4fr5LGUrSk= | ||||
| k8s.io/client-go v0.0.0-20191225075139-73fd2ddc9180/go.mod h1:ksVkYlACXo9hR9AV+cYyCkuWL1xnWcGtAFxsfqMcozg= | ||||
| k8s.io/client-go v0.16.4 h1:sf+FEZXYhJNjpTZapQDLvvN+0kBeUTxCYxlXcVdhv2E= | ||||
| k8s.io/client-go v0.16.4/go.mod h1:ZgxhFDxSnoKY0J0U2/Y1C8obKDdlhGPZwA7oHH863Ok= | ||||
|   | ||||
							
								
								
									
										50
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								main.go
									
									
									
									
									
								
							| @@ -4,6 +4,7 @@ import ( | ||||
| 	"context" | ||||
| 	"flag" | ||||
| 	"fmt" | ||||
| 	_ "github.com/onepanelio/core/db" | ||||
| 	"google.golang.org/grpc/codes" | ||||
| 	"google.golang.org/grpc/status" | ||||
| 	corev1 "k8s.io/api/core/v1" | ||||
| @@ -12,11 +13,8 @@ import ( | ||||
| 	k8runtime "k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/watch" | ||||
| 	"k8s.io/client-go/tools/cache" | ||||
| 	"math" | ||||
| 	"net" | ||||
| 	"net/http" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/gorilla/handlers" | ||||
| 	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" | ||||
| @@ -25,7 +23,6 @@ import ( | ||||
| 	"github.com/grpc-ecosystem/grpc-gateway/runtime" | ||||
| 	"github.com/jmoiron/sqlx" | ||||
| 	"github.com/onepanelio/core/api" | ||||
| 	migrations "github.com/onepanelio/core/db/go" | ||||
| 	v1 "github.com/onepanelio/core/pkg" | ||||
| 	"github.com/onepanelio/core/pkg/util/env" | ||||
| 	"github.com/onepanelio/core/server" | ||||
| @@ -70,22 +67,16 @@ func main() { | ||||
| 				log.Fatalf("Failed to get system config: %v", err) | ||||
| 			} | ||||
|  | ||||
| 			dbDriverName, databaseDataSourceName := sysConfig.DatabaseConnection() | ||||
| 			databaseDataSourceName := fmt.Sprintf("host=%v user=%v password=%v dbname=%v sslmode=disable", | ||||
| 				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. | ||||
| 			// This is okay, as the pod will restart and try connecting to DB again. | ||||
| 			// dbDriverName may be nil, but sqlx will then panic. | ||||
| 			db := sqlx.MustConnect(dbDriverName, databaseDataSourceName) | ||||
| 			goose.SetTableName("goose_db_version") | ||||
| 			if err := goose.Run("up", db.DB, filepath.Join("db", "sql")); err != nil { | ||||
| 				log.Fatalf("Failed to run database sql migrations: %v", err) | ||||
| 				db.Close() | ||||
| 			} | ||||
|  | ||||
| 			goose.SetTableName("goose_db_go_version") | ||||
| 			migrations.Initialize() | ||||
| 			if err := goose.Run("up", db.DB, filepath.Join("db", "go")); err != nil { | ||||
| 				log.Fatalf("Failed to run database go migrations: %v", err) | ||||
| 				db.Close() | ||||
| 			dbDriverName := sysConfig.DatabaseDriverName() | ||||
| 			db := sqlx.MustConnect(*dbDriverName, databaseDataSourceName) | ||||
| 			if err := goose.Run("up", db.DB, "db"); err != nil { | ||||
| 				log.Fatalf("Failed to run database migrations: %v", err) | ||||
| 			} | ||||
|  | ||||
| 			s := startRPCServer(v1.NewDB(db), kubeConfig, sysConfig, stopCh) | ||||
| @@ -93,9 +84,6 @@ func main() { | ||||
| 			<-stopCh | ||||
|  | ||||
| 			s.Stop() | ||||
| 			if err := db.Close(); err != nil { | ||||
| 				log.Printf("[error] closing db connection") | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| @@ -135,7 +123,7 @@ func startRPCServer(db *v1.DB, kubeConfig *v1.Config, sysConfig v1.SystemConfig, | ||||
| 			grpc_logrus.StreamServerInterceptor(logEntry), | ||||
| 			grpc_recovery.StreamServerInterceptor(recoveryOpts...), | ||||
| 			auth.StreamingInterceptor(kubeConfig, db, sysConfig)), | ||||
| 	), grpc.MaxRecvMsgSize(math.MaxInt64), grpc.MaxSendMsgSize(math.MaxInt64)) | ||||
| 	)) | ||||
| 	api.RegisterWorkflowTemplateServiceServer(s, server.NewWorkflowTemplateServer()) | ||||
| 	api.RegisterCronWorkflowServiceServer(s, server.NewCronWorkflowServer()) | ||||
| 	api.RegisterWorkflowServiceServer(s, server.NewWorkflowServer()) | ||||
| @@ -146,7 +134,6 @@ func startRPCServer(db *v1.DB, kubeConfig *v1.Config, sysConfig v1.SystemConfig, | ||||
| 	api.RegisterWorkspaceTemplateServiceServer(s, server.NewWorkspaceTemplateServer()) | ||||
| 	api.RegisterWorkspaceServiceServer(s, server.NewWorkspaceServer()) | ||||
| 	api.RegisterConfigServiceServer(s, server.NewConfigServer()) | ||||
| 	api.RegisterServiceServiceServer(s, server.NewServiceServer()) | ||||
|  | ||||
| 	go func() { | ||||
| 		if err := s.Serve(lis); err != nil { | ||||
| @@ -167,9 +154,8 @@ func startHTTPProxy() { | ||||
|  | ||||
| 	// Register gRPC server endpoint | ||||
| 	// Note: Make sure the gRPC server is running properly and accessible | ||||
| 	mux := runtime.NewServeMux(runtime.WithIncomingHeaderMatcher(customHeaderMatcher)) | ||||
| 	opts := []grpc.DialOption{grpc.WithInsecure(), grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(math.MaxInt64), | ||||
| 		grpc.MaxCallRecvMsgSize(math.MaxInt64))} | ||||
| 	mux := runtime.NewServeMux() | ||||
| 	opts := []grpc.DialOption{grpc.WithInsecure()} | ||||
|  | ||||
| 	registerHandler(api.RegisterWorkflowTemplateServiceHandlerFromEndpoint, ctx, mux, endpoint, opts) | ||||
| 	registerHandler(api.RegisterWorkflowServiceHandlerFromEndpoint, ctx, mux, endpoint, opts) | ||||
| @@ -181,7 +167,6 @@ func startHTTPProxy() { | ||||
| 	registerHandler(api.RegisterWorkspaceTemplateServiceHandlerFromEndpoint, ctx, mux, endpoint, opts) | ||||
| 	registerHandler(api.RegisterWorkspaceServiceHandlerFromEndpoint, ctx, mux, endpoint, opts) | ||||
| 	registerHandler(api.RegisterConfigServiceHandlerFromEndpoint, ctx, mux, endpoint, opts) | ||||
| 	registerHandler(api.RegisterServiceServiceHandlerFromEndpoint, ctx, mux, endpoint, opts) | ||||
|  | ||||
| 	log.Printf("Starting HTTP proxy on port %v", *httpPort) | ||||
|  | ||||
| @@ -261,16 +246,3 @@ func watchConfigmapChanges(client *v1.Client, namespace string, stopCh <-chan st | ||||
| 	neverStopCh := make(chan struct{}) | ||||
| 	controller.Run(neverStopCh) | ||||
| } | ||||
|  | ||||
| // customHeaderMatcher is used to allow certain headers so we don't require a grpc-gateway prefix | ||||
| func customHeaderMatcher(key string) (string, bool) { | ||||
| 	lowerCaseKey := strings.ToLower(key) | ||||
| 	switch lowerCaseKey { | ||||
| 	case "onepanel-auth-token": | ||||
| 		return lowerCaseKey, true | ||||
| 	case "cookie": | ||||
| 		return lowerCaseKey, true | ||||
| 	default: | ||||
| 		return runtime.DefaultHeaderMatcher(key) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,11 +1,8 @@ | ||||
| package v1 | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	sq "github.com/Masterminds/squirrel" | ||||
| 	argoprojv1alpha1 "github.com/argoproj/argo/pkg/client/clientset/versioned/typed/workflow/v1alpha1" | ||||
| 	"github.com/onepanelio/core/pkg/util/gcs" | ||||
| 	"github.com/onepanelio/core/pkg/util/router" | ||||
| 	"github.com/onepanelio/core/pkg/util/s3" | ||||
| 	log "github.com/sirupsen/logrus" | ||||
| 	"k8s.io/client-go/kubernetes" | ||||
| @@ -67,8 +64,7 @@ func NewClient(config *Config, db *DB, systemConfig SystemConfig) (client *Clien | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| // GetS3Client initializes a client to Amazon Cloud Storage. | ||||
| func (c *Client) GetS3Client(namespace string, config *ArtifactRepositoryS3Provider) (s3Client *s3.Client, err error) { | ||||
| func (c *Client) GetS3Client(namespace string, config *ArtifactRepositoryS3Config) (s3Client *s3.Client, err error) { | ||||
| 	s3Client, err = s3.NewClient(s3.Config{ | ||||
| 		Endpoint:  config.Endpoint, | ||||
| 		Region:    config.Region, | ||||
| @@ -84,32 +80,6 @@ func (c *Client) GetS3Client(namespace string, config *ArtifactRepositoryS3Provi | ||||
| 		}).Error("getS3Client failed when initializing a new S3 client.") | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GetGCSClient initializes a client to Google Cloud Storage. | ||||
| func (c *Client) GetGCSClient(namespace string, config *ArtifactRepositoryGCSProvider) (gcsClient *gcs.Client, err error) { | ||||
| 	return gcs.NewClient(namespace, config.ServiceAccountJSON) | ||||
| } | ||||
|  | ||||
| // GetWebRouter creates a new web router using the system configuration | ||||
| func (c *Client) GetWebRouter() (router.Web, error) { | ||||
| 	sysConfig, err := c.GetSystemConfig() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	fqdn := sysConfig.FQDN() | ||||
| 	if fqdn == nil { | ||||
| 		return nil, fmt.Errorf("unable to get fqdn") | ||||
| 	} | ||||
|  | ||||
| 	protocol := sysConfig.APIProtocol() | ||||
| 	if protocol == nil { | ||||
| 		return nil, fmt.Errorf("unable to get protcol") | ||||
| 	} | ||||
|  | ||||
| 	webRouter, err := router.NewWebRouter(*protocol, *fqdn) | ||||
|  | ||||
| 	return webRouter, err | ||||
| } | ||||
|   | ||||
| @@ -1,18 +1,10 @@ | ||||
| package v1 | ||||
|  | ||||
| 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" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/client-go/kubernetes/fake" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| @@ -23,20 +15,6 @@ 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{ | ||||
| 		ObjectMeta: metav1.ObjectMeta{ | ||||
| 			Name:      "onepanel", | ||||
| @@ -44,8 +22,6 @@ s3: | ||||
| 		}, | ||||
| 		Data: map[string]string{ | ||||
| 			"ONEPANEL_HOST":            "demo.onepanel.site", | ||||
| 			"ONEPANEL_DOMAIN":          "demo.onepanel.site", | ||||
| 			"artifactRepository":       configArtifactRepository, | ||||
| 			"applicationNodePoolLabel": "beta.kubernetes.io/instance-type", | ||||
| 			"applicationNodePoolOptions": ` | ||||
| - name: 'CPU: 2, RAM: 8GB' | ||||
| @@ -58,60 +34,8 @@ s3: | ||||
| `, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	database *sqlx.DB | ||||
| ) | ||||
|  | ||||
| var flagDatabaseService = flag.String("db", "localhost", "Name to connect to db, defaults to localhost") | ||||
|  | ||||
| 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) | ||||
| 	} | ||||
| func NewTestClient(objects ...runtime.Object) (client *Client) { | ||||
| 	return &Client{Interface: fake.NewSimpleClientset(objects...)} | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| package v1 | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"github.com/onepanelio/core/pkg/util/ptr" | ||||
| 	"gopkg.in/yaml.v2" | ||||
| ) | ||||
| @@ -17,90 +16,114 @@ type ParameterOption struct { | ||||
| type Parameter struct { | ||||
| 	Name        string             `json:"name" protobuf:"bytes,1,opt,name=name"` | ||||
| 	Value       *string            `json:"value,omitempty" protobuf:"bytes,2,opt,name=value"` | ||||
| 	Visibility  *string            `json:"visibility,omitempty"` | ||||
| 	Type        string             `json:"type,omitempty" protobuf:"bytes,3,opt,name=type"` | ||||
| 	DisplayName *string            `json:"displayName,omitempty" yaml:"displayName"` | ||||
| 	DisplayName *string            `json:"displayName,omitempty" protobuf:"bytes,4,opt,name=displayName"` | ||||
| 	Hint        *string            `json:"hint,omitempty" protobuf:"bytes,5,opt,name=hint"` | ||||
| 	Options     []*ParameterOption `json:"options,omitempty" protobuf:"bytes,6,opt,name=options"` | ||||
| 	Required    bool               `json:"required,omitempty" protobuf:"bytes,7,opt,name=required"` | ||||
| } | ||||
|  | ||||
| // IsValidParameter returns nil if the parameter is valid or an error otherwise | ||||
| func IsValidParameter(parameter Parameter) error { | ||||
| 	if parameter.Visibility == nil { | ||||
| 		return nil | ||||
| func ParameterFromMap(paramMap map[interface{}]interface{}) *Parameter { | ||||
| 	workflowParameter := Parameter{ | ||||
| 		Options: []*ParameterOption{}, | ||||
| 	} | ||||
|  | ||||
| 	visibility := *parameter.Visibility | ||||
| 	if visibility != "public" && visibility != "protected" && visibility != "internal" && visibility != "private" { | ||||
| 		return fmt.Errorf("invalid visibility '%v' for parameter '%v'", visibility, parameter.Name) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // IsValidParameters returns nil if all parameters are valid or an error otherwise | ||||
| func IsValidParameters(parameters []Parameter) error { | ||||
| 	for _, param := range parameters { | ||||
| 		if err := IsValidParameter(param); err != nil { | ||||
| 			return err | ||||
| 	// TODO choose a consistent way and use that. | ||||
| 	if value, ok := paramMap["displayname"]; ok { | ||||
| 		if displayName, ok := value.(string); ok { | ||||
| 			workflowParameter.DisplayName = &displayName | ||||
| 		} | ||||
| 	} else if value, ok := paramMap["displayName"]; ok { | ||||
| 		if displayName, ok := value.(string); ok { | ||||
| 			workflowParameter.DisplayName = &displayName | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| 	if value, ok := paramMap["hint"]; ok { | ||||
| 		if hint, ok := value.(string); ok { | ||||
| 			workflowParameter.Hint = ptr.String(hint) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if value, ok := paramMap["required"]; ok { | ||||
| 		if required, ok := value.(bool); ok { | ||||
| 			workflowParameter.Required = required | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if value, ok := paramMap["type"]; ok { | ||||
| 		if typeValue, ok := value.(string); ok { | ||||
| 			workflowParameter.Type = typeValue | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if value, ok := paramMap["name"]; ok { | ||||
| 		if nameValue, ok := value.(string); ok { | ||||
| 			workflowParameter.Name = nameValue | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if value, ok := paramMap["value"]; ok { | ||||
| 		if valueValue, ok := value.(string); ok { | ||||
| 			workflowParameter.Value = &valueValue | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	options := paramMap["options"] | ||||
| 	optionsArray, ok := options.([]interface{}) | ||||
| 	if !ok { | ||||
| 		return &workflowParameter | ||||
| 	} | ||||
|  | ||||
| 	for _, option := range optionsArray { | ||||
| 		optionMap := option.(map[interface{}]interface{}) | ||||
|  | ||||
| 		newOption := ParameterOption{ | ||||
| 			Name:  optionMap["name"].(string), | ||||
| 			Value: optionMap["value"].(string), | ||||
| 		} | ||||
|  | ||||
| 		workflowParameter.Options = append(workflowParameter.Options, &newOption) | ||||
| 	} | ||||
|  | ||||
| 	return &workflowParameter | ||||
| } | ||||
|  | ||||
| // Arguments are the arguments in a manifest file. | ||||
| type Arguments struct { | ||||
| 	Parameters []Parameter `json:"parameters"` | ||||
| 	Parameters []Parameter `json:"parameters" protobuf:"bytes,1,opt,name=parameters"` | ||||
| } | ||||
|  | ||||
| // WorkflowTemplateManifest is a client representation of a WorkflowTemplate | ||||
| // It is usually provided as YAML by a client and this struct helps to marshal/unmarshal it | ||||
| type WorkflowTemplateManifest struct { | ||||
| 	Arguments Arguments | ||||
| } | ||||
|  | ||||
| // WorkflowExecutionSpec is a client representation of a WorkflowExecution. | ||||
| // It is usually provided as YAML by a client and this struct helps to marshal/unmarshal it | ||||
| // This may be redundant with WorkflowTemplateManifest and should be looked at. # TODO | ||||
| type WorkflowExecutionSpec struct { | ||||
| 	Arguments Arguments | ||||
| } | ||||
|  | ||||
| // ParseParametersFromManifest takes a manifest and picks out the parameters and returns them as structs | ||||
| func ParseParametersFromManifest(manifest []byte) ([]Parameter, error) { | ||||
| 	manifestResult := &WorkflowTemplateManifest{ | ||||
| 		Arguments: Arguments{}, | ||||
| 	} | ||||
| 	var parameters []Parameter | ||||
|  | ||||
| 	err := yaml.Unmarshal(manifest, manifestResult) | ||||
| 	if err != nil { | ||||
| 	mappedData := make(map[string]interface{}) | ||||
|  | ||||
| 	if err := yaml.Unmarshal(manifest, mappedData); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// Default parameter value | ||||
| 	for i := range manifestResult.Arguments.Parameters { | ||||
| 		parameter := &manifestResult.Arguments.Parameters[i] | ||||
| 		if parameter.Visibility == nil { | ||||
| 			parameter.Visibility = ptr.String("public") | ||||
| 	arguments, ok := mappedData["arguments"] | ||||
| 	if !ok { | ||||
| 		return parameters, nil | ||||
| 	} | ||||
|  | ||||
| 	argumentsMap := arguments.(map[interface{}]interface{}) | ||||
| 	parametersRaw, ok := argumentsMap["parameters"] | ||||
| 	if !ok { | ||||
| 		return parameters, nil | ||||
| 	} | ||||
|  | ||||
| 	parametersArray, ok := parametersRaw.([]interface{}) | ||||
| 	for _, parameter := range parametersArray { | ||||
| 		paramMap, ok := parameter.(map[interface{}]interface{}) | ||||
| 		if !ok { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		workflowParameter := ParameterFromMap(paramMap) | ||||
|  | ||||
| 		parameters = append(parameters, *workflowParameter) | ||||
| 	} | ||||
|  | ||||
| 	if err := IsValidParameters(manifestResult.Arguments.Parameters); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return manifestResult.Arguments.Parameters, nil | ||||
| } | ||||
|  | ||||
| // MapParametersByName returns a map where the parameter name is the key and the parameter is the value | ||||
| func MapParametersByName(parameters []Parameter) map[string]Parameter { | ||||
| 	result := make(map[string]Parameter) | ||||
|  | ||||
| 	for _, param := range parameters { | ||||
| 		result[param.Name] = param | ||||
| 	} | ||||
|  | ||||
| 	return result | ||||
| 	return parameters, nil | ||||
| } | ||||
|   | ||||
| @@ -1,68 +0,0 @@ | ||||
| package v1 | ||||
|  | ||||
| import ( | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| // TestParseParametersFromManifest makes sure that we have correct parsing of parameters from a manifest | ||||
| func TestParseParametersFromManifest(t *testing.T) { | ||||
| 	manifest := `arguments: | ||||
|   parameters: | ||||
|   - name: source | ||||
|     value: https://github.com/onepanelio/Mask_RCNN.git | ||||
|   - name: dataset-path | ||||
|     value: datasets/test_05142020170720 | ||||
|     visibility: public | ||||
|   - name: model-path | ||||
|     value: models/rush/cvat6-20 | ||||
|   - name: extras | ||||
|     value: none | ||||
|   - name: task-name | ||||
|     value: test | ||||
|   - name: num-classes | ||||
|     value: 2 | ||||
|   - name: tf-image | ||||
|     value: tensorflow/tensorflow:1.13.1-py3 | ||||
|   - displayName: Node pool | ||||
|     hint: Name of node pool or group | ||||
|     type: select.select | ||||
|     name: sys-node-pool | ||||
|     required: true | ||||
|     options: | ||||
|     - name: 'CPU: 2, RAM: 8GB' | ||||
|       value: Standard_D2s_v3 | ||||
|     - name: 'CPU: 4, RAM: 16GB' | ||||
|       value: Standard_D4s_v3 | ||||
|     - name: 'GPU: 1xK80, CPU: 6, RAM: 56GB' | ||||
|       value: Standard_NC6 | ||||
| ` | ||||
|  | ||||
| 	parameters, err := ParseParametersFromManifest([]byte(manifest)) | ||||
| 	assert.Nil(t, err) | ||||
| 	assert.NotNil(t, parameters) | ||||
| 	assert.Len(t, parameters, 8) | ||||
|  | ||||
| 	keyedParameters := MapParametersByName(parameters) | ||||
|  | ||||
| 	// Make sure visibility is set | ||||
| 	assert.Equal(t, *keyedParameters["dataset-path"].Visibility, "public") | ||||
|  | ||||
| 	// Make sure visibility is not set if omitted | ||||
| 	assert.Nil(t, keyedParameters["tf-image"].Visibility) | ||||
|  | ||||
| 	// Make sure numbers, slashes, dashes, and letters are parsed correctly | ||||
| 	assert.Equal(t, *keyedParameters["tf-image"].Value, "tensorflow/tensorflow:1.13.1-py3") | ||||
|  | ||||
| 	// Make sure integers are parsed as strings and not ignored or omitted | ||||
| 	assert.Equal(t, *keyedParameters["num-classes"].Value, "2") | ||||
|  | ||||
| 	// Make sure missing values have a nil value to show they are not there | ||||
| 	assert.Nil(t, keyedParameters["sys-node-pool"].Value, nil) | ||||
|  | ||||
| 	// Make sure options are parsed | ||||
| 	assert.Len(t, keyedParameters["sys-node-pool"].Options, 3) | ||||
|  | ||||
| 	// Make sure string values are correctly parsed | ||||
| 	assert.Equal(t, *keyedParameters["extras"].Value, "none") | ||||
| } | ||||
							
								
								
									
										116
									
								
								pkg/config.go
									
									
									
									
									
								
							
							
						
						
									
										116
									
								
								pkg/config.go
									
									
									
									
									
								
							| @@ -2,13 +2,92 @@ package v1 | ||||
|  | ||||
| import ( | ||||
| 	"encoding/base64" | ||||
| 	"fmt" | ||||
| 	"github.com/onepanelio/core/pkg/util" | ||||
| 	"github.com/onepanelio/core/pkg/util/ptr" | ||||
| 	log "github.com/sirupsen/logrus" | ||||
| 	"google.golang.org/grpc/codes" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"sigs.k8s.io/yaml" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // SystemConfig is configuration loaded from kubernetes config and secrets that includes information about the | ||||
| // database, server, etc. | ||||
| type SystemConfig map[string]string | ||||
|  | ||||
| // GetValue returns the value in the underlying map if it exists, otherwise nil is returned | ||||
| // If the value does not exist, it is also logged. | ||||
| func (s SystemConfig) GetValue(name string) *string { | ||||
| 	value, ok := s[name] | ||||
| 	if !ok { | ||||
| 		log.WithFields(log.Fields{ | ||||
| 			"Method": "SystemConfig.GetValue", | ||||
| 			"Name":   name, | ||||
| 			"Error":  "does not exist", | ||||
| 		}) | ||||
|  | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	return &value | ||||
| } | ||||
|  | ||||
| // Domain gets the ONEPANEL_DOMAIN value, or nil. | ||||
| func (s SystemConfig) Domain() *string { | ||||
| 	return s.GetValue("ONEPANEL_DOMAIN") | ||||
| } | ||||
|  | ||||
| // APIURL gets the ONEPANEL_API_URL, or nil. | ||||
| func (s SystemConfig) APIURL() *string { | ||||
| 	return s.GetValue("ONEPANEL_API_URL") | ||||
| } | ||||
|  | ||||
| // APIProtocol returns either http:// or https:// or nil. | ||||
| // It is based on the ONEPANEL_API_URL config value and checks if it has https or http | ||||
| func (s SystemConfig) APIProtocol() *string { | ||||
| 	url := s.APIURL() | ||||
| 	if url == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	if strings.HasPrefix(*url, "https://") { | ||||
| 		return ptr.String("https://") | ||||
| 	} | ||||
|  | ||||
| 	return ptr.String("http://") | ||||
| } | ||||
|  | ||||
| // FQDN gets the ONEPANEL_FQDN value or nil. | ||||
| func (s SystemConfig) FQDN() *string { | ||||
| 	return s.GetValue("ONEPANEL_FQDN") | ||||
| } | ||||
|  | ||||
| // NodePoolLabel gets the applicationNodePoolLabel from the config or returns nil. | ||||
| func (s SystemConfig) NodePoolLabel() (label *string) { | ||||
| 	return s.GetValue("applicationNodePoolLabel") | ||||
| } | ||||
|  | ||||
| // NodePoolOptions loads and parses the applicationNodePoolOptions from the config. | ||||
| // If there is no data, an error is returned. | ||||
| func (s SystemConfig) NodePoolOptions() (options []*ParameterOption, err error) { | ||||
| 	data := s.GetValue("applicationNodePoolOptions") | ||||
| 	if data == nil { | ||||
| 		return nil, fmt.Errorf("no nodePoolOptions in config") | ||||
| 	} | ||||
|  | ||||
| 	if err = yaml.Unmarshal([]byte(*data), &options); err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DatabaseDriverName gets the databaseDriverName value, or nil. | ||||
| func (s SystemConfig) DatabaseDriverName() *string { | ||||
| 	return s.GetValue("databaseDriverName") | ||||
| } | ||||
|  | ||||
| func (c *Client) getConfigMap(namespace, name string) (configMap *ConfigMap, err error) { | ||||
| 	cm, err := c.CoreV1().ConfigMaps(namespace).Get(name, metav1.GetOptions{}) | ||||
| 	if err != nil { | ||||
| @@ -36,19 +115,20 @@ func (c *Client) GetSystemConfig() (config SystemConfig, err error) { | ||||
| 	} | ||||
|  | ||||
| 	namespace := "onepanel" | ||||
| 	name := "onepanel" | ||||
|  | ||||
| 	configMap, err := c.getConfigMap(namespace, name) | ||||
| 	configMap, err := c.getConfigMap(namespace, "onepanel") | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	config = configMap.Data | ||||
|  | ||||
| 	secret, err := c.GetSecret(namespace, name) | ||||
| 	secret, err := c.GetSecret(namespace, "onepanel") | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	config, err = NewSystemConfig(configMap, secret) | ||||
| 	databaseUsername, _ := base64.StdEncoding.DecodeString(secret.Data["databaseUsername"]) | ||||
| 	config["databaseUsername"] = string(databaseUsername) | ||||
| 	databasePassword, _ := base64.StdEncoding.DecodeString(secret.Data["databasePassword"]) | ||||
| 	config["databasePassword"] = string(databasePassword) | ||||
|  | ||||
| 	c.systemConfig = config | ||||
|  | ||||
| @@ -72,11 +152,11 @@ func (c *Client) GetNamespaceConfig(namespace string) (config *NamespaceConfig, | ||||
| 		return | ||||
| 	} | ||||
| 	config = &NamespaceConfig{ | ||||
| 		ArtifactRepository: ArtifactRepositoryProvider{}, | ||||
| 		ArtifactRepository: ArtifactRepositoryConfig{}, | ||||
| 	} | ||||
|  | ||||
| 	err = yaml.Unmarshal([]byte(configMap.Data["artifactRepository"]), &config.ArtifactRepository) | ||||
| 	if err != nil || (config.ArtifactRepository.S3 == nil && config.ArtifactRepository.GCS == nil) { | ||||
| 	if err != nil || config.ArtifactRepository.S3 == nil { | ||||
| 		return nil, util.NewUserError(codes.NotFound, "Artifact repository config not found.") | ||||
| 	} | ||||
|  | ||||
| @@ -89,22 +169,14 @@ func (c *Client) GetNamespaceConfig(namespace string) (config *NamespaceConfig, | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	switch { | ||||
| 	case config.ArtifactRepository.S3 != nil: | ||||
| 		{ | ||||
| 			accessKey, _ := base64.StdEncoding.DecodeString(secret.Data[config.ArtifactRepository.S3.AccessKeySecret.Key]) | ||||
| 			config.ArtifactRepository.S3.AccessKey = string(accessKey) | ||||
| 			secretKey, _ := base64.StdEncoding.DecodeString(secret.Data[config.ArtifactRepository.S3.SecretKeySecret.Key]) | ||||
| 			config.ArtifactRepository.S3.Secretkey = string(secretKey) | ||||
| 		} | ||||
| 	case config.ArtifactRepository.GCS != nil: | ||||
| 		{ | ||||
| 			serviceJSON, _ := base64.StdEncoding.DecodeString(secret.Data[config.ArtifactRepository.GCS.ServiceAccountKeySecret.Key]) | ||||
| 			config.ArtifactRepository.GCS.ServiceAccountJSON = string(serviceJSON) | ||||
| 		} | ||||
| 	default: | ||||
| 	// TODO: replace with switch statement to support additional object storage | ||||
| 	if config.ArtifactRepository.S3 == nil { | ||||
| 		return nil, util.NewUserError(codes.NotFound, "Artifact repository config not found.") | ||||
| 	} | ||||
| 	accessKey, _ := base64.StdEncoding.DecodeString(secret.Data[config.ArtifactRepository.S3.AccessKeySecret.Key]) | ||||
| 	config.ArtifactRepository.S3.AccessKey = string(accessKey) | ||||
| 	secretKey, _ := base64.StdEncoding.DecodeString(secret.Data[config.ArtifactRepository.S3.SecretKeySecret.Key]) | ||||
| 	config.ArtifactRepository.S3.Secretkey = string(secretKey) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|   | ||||
| @@ -1,299 +1,27 @@ | ||||
| package v1 | ||||
|  | ||||
| import ( | ||||
| 	"encoding/base64" | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/onepanelio/core/pkg/util/ptr" | ||||
| 	log "github.com/sirupsen/logrus" | ||||
| 	"gopkg.in/yaml.v3" | ||||
| 	corev1 "k8s.io/api/core/v1" | ||||
| 	k8yaml "sigs.k8s.io/yaml" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| // SystemConfig is configuration loaded from kubernetes config and secrets that includes information about the | ||||
| // database, server, etc. | ||||
| type SystemConfig map[string]string | ||||
|  | ||||
| // NodePoolOption extends ParameterOption to support resourceRequirements | ||||
| type NodePoolOption struct { | ||||
| 	ParameterOption | ||||
| 	Resources corev1.ResourceRequirements | ||||
| } | ||||
|  | ||||
| // NewSystemConfig creates a System config by getting the required data from a ConfigMap and Secret | ||||
| func NewSystemConfig(configMap *ConfigMap, secret *Secret) (config SystemConfig, err error) { | ||||
| 	config = configMap.Data | ||||
|  | ||||
| 	databaseUsername, err := base64.StdEncoding.DecodeString(secret.Data["databaseUsername"]) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	config["databaseUsername"] = string(databaseUsername) | ||||
|  | ||||
| 	databasePassword, err := base64.StdEncoding.DecodeString(secret.Data["databasePassword"]) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	config["databasePassword"] = string(databasePassword) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GetValue returns the value in the underlying map if it exists, otherwise nil is returned | ||||
| // If the value does not exist, it is also logged. | ||||
| func (s SystemConfig) GetValue(name string) *string { | ||||
| 	value, ok := s[name] | ||||
| 	if !ok { | ||||
| 		log.WithFields(log.Fields{ | ||||
| 			"Method": "SystemConfig.GetValue", | ||||
| 			"Name":   name, | ||||
| 			"Error":  "does not exist", | ||||
| 		}) | ||||
|  | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	return &value | ||||
| } | ||||
|  | ||||
| // Domain gets the ONEPANEL_DOMAIN value, or nil. | ||||
| func (s SystemConfig) Domain() *string { | ||||
| 	return s.GetValue("ONEPANEL_DOMAIN") | ||||
| } | ||||
|  | ||||
| // APIURL gets the ONEPANEL_API_URL, or nil. | ||||
| func (s SystemConfig) APIURL() *string { | ||||
| 	return s.GetValue("ONEPANEL_API_URL") | ||||
| } | ||||
|  | ||||
| // APIProtocol returns either http:// or https:// or nil. | ||||
| // It is based on the ONEPANEL_API_URL config value and checks if it has https or http | ||||
| func (s SystemConfig) APIProtocol() *string { | ||||
| 	url := s.APIURL() | ||||
| 	if url == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	if strings.HasPrefix(*url, "https://") { | ||||
| 		return ptr.String("https://") | ||||
| 	} | ||||
|  | ||||
| 	return ptr.String("http://") | ||||
| } | ||||
|  | ||||
| // FQDN gets the ONEPANEL_FQDN value or nil. | ||||
| func (s SystemConfig) FQDN() *string { | ||||
| 	return s.GetValue("ONEPANEL_FQDN") | ||||
| } | ||||
|  | ||||
| // NodePoolLabel gets the applicationNodePoolLabel from the config or returns nil. | ||||
| func (s SystemConfig) NodePoolLabel() (label *string) { | ||||
| 	return s.GetValue("applicationNodePoolLabel") | ||||
| } | ||||
|  | ||||
| // NodePoolOptions loads and parses the applicationNodePoolOptions from the config. | ||||
| // If there is no data, an error is returned. | ||||
| func (s SystemConfig) NodePoolOptions() (options []*NodePoolOption, err error) { | ||||
| 	data := s.GetValue("applicationNodePoolOptions") | ||||
| 	if data == nil { | ||||
| 		return nil, fmt.Errorf("no nodePoolOptions in config") | ||||
| 	} | ||||
|  | ||||
| 	if err = k8yaml.Unmarshal([]byte(*data), &options); err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // NodePoolOptionByValue returns the nodePoolOption based on a given value | ||||
| func (s SystemConfig) NodePoolOptionByValue(value string) (option *NodePoolOption, err error) { | ||||
| 	options, err := s.NodePoolOptions() | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	for _, opt := range options { | ||||
| 		if opt.Value == value { | ||||
| 			option = opt | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // DatabaseDriverName gets the databaseDriverName value, or nil. | ||||
| func (s SystemConfig) DatabaseDriverName() *string { | ||||
| 	return s.GetValue("databaseDriverName") | ||||
| } | ||||
|  | ||||
| // DatabaseConnection returns system config information to connect to a database | ||||
| func (s SystemConfig) DatabaseConnection() (driverName, dataSourceName string) { | ||||
| 	dataSourceName = fmt.Sprintf("host=%v user=%v password=%v dbname=%v sslmode=disable", | ||||
| 		s["databaseHost"], s["databaseUsername"], s["databasePassword"], s["databaseName"]) | ||||
|  | ||||
| 	driverName = *s.DatabaseDriverName() | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // UpdateNodePoolOptions will update the sys-node-pool parameter's options with runtime values | ||||
| // The original slice is unmodified, the returned slice has the updated values | ||||
| // If sys-node-pool is not present, nothing happens. | ||||
| func (s SystemConfig) UpdateNodePoolOptions(parameters []Parameter) ([]Parameter, error) { | ||||
| 	result := make([]Parameter, 0) | ||||
|  | ||||
| 	var nodePoolParameter *Parameter | ||||
|  | ||||
| 	// Copy the original parameters, skipping sys-node-pool | ||||
| 	for i := range parameters { | ||||
| 		parameter := parameters[i] | ||||
| 		if parameter.Name == "sys-node-pool" { | ||||
| 			nodePoolParameter = ¶meter | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		result = append(result, parameter) | ||||
| 	} | ||||
|  | ||||
| 	if nodePoolParameter == nil { | ||||
| 		return result, nil | ||||
| 	} | ||||
|  | ||||
| 	nodePoolOptions, err := s.NodePoolOptions() | ||||
| 	if err != nil { | ||||
| 		return result, err | ||||
| 	} | ||||
|  | ||||
| 	options := make([]*ParameterOption, 0) | ||||
| 	for _, option := range nodePoolOptions { | ||||
| 		newOption := &ParameterOption{ | ||||
| 			Name:  option.Name, | ||||
| 			Value: option.Value, | ||||
| 		} | ||||
|  | ||||
| 		options = append(options, newOption) | ||||
| 	} | ||||
|  | ||||
| 	nodePoolParameter.Options = options | ||||
|  | ||||
| 	result = append(result, *nodePoolParameter) | ||||
|  | ||||
| 	return result, nil | ||||
| } | ||||
|  | ||||
| // ArtifactRepositoryS3Provider is meant to be used | ||||
| // by the CLI. CLI will marshal this struct into the correct | ||||
| // YAML structure for k8s configmap / secret. | ||||
| type ArtifactRepositoryS3Provider struct { | ||||
| 	KeyFormat       string `yaml:"keyFormat"` | ||||
| type ArtifactRepositoryS3Config struct { | ||||
| 	KeyFormat       string | ||||
| 	Bucket          string | ||||
| 	Endpoint        string | ||||
| 	Insecure        bool | ||||
| 	Region          string | ||||
| 	AccessKeySecret ArtifactRepositorySecret `yaml:"accessKeySecret"` | ||||
| 	SecretKeySecret ArtifactRepositorySecret `yaml:"secretKeySecret"` | ||||
| 	AccessKey       string                   `yaml:"accessKey,omitempty"` | ||||
| 	Secretkey       string                   `yaml:"secretKey,omitempty"` | ||||
| } | ||||
|  | ||||
| // ArtifactRepositoryGCSProvider is meant to be used | ||||
| // by the CLI. CLI will marshal this struct into the correct | ||||
| // YAML structure for k8s configmap / secret. | ||||
| type ArtifactRepositoryGCSProvider struct { | ||||
| 	KeyFormat               string `yaml:"keyFormat"` | ||||
| 	Bucket                  string | ||||
| 	Endpoint                string | ||||
| 	Insecure                bool | ||||
| 	ServiceAccountKey       string                   `yaml:"serviceAccountKey,omitempty"` | ||||
| 	ServiceAccountKeySecret ArtifactRepositorySecret `yaml:"serviceAccountKeySecret"` | ||||
| 	ServiceAccountJSON      string                   `yaml:"serviceAccountJSON,omitempty"` | ||||
| } | ||||
|  | ||||
| // ArtifactRepositoryProvider is used to setup access into AWS Cloud Storage | ||||
| // or Google Cloud storage. | ||||
| // - The relevant sub-struct (S3, GCS) is unmarshalled into from the cluster configmap. | ||||
| // Right now, either the S3 or GCS struct will be filled in. Multiple cloud | ||||
| // providers are not supported at the same time in params.yaml (manifests deployment). | ||||
| type ArtifactRepositoryProvider struct { | ||||
| 	S3  *ArtifactRepositoryS3Provider  `yaml:"s3,omitempty"` | ||||
| 	GCS *ArtifactRepositoryGCSProvider `yaml:"gcs,omitempty"` | ||||
| } | ||||
|  | ||||
| // ArtifactRepositorySecret holds information about a kubernetes Secret. | ||||
| // - The "key" is the specific key inside the Secret. | ||||
| // - The "name" is the name of the Secret. | ||||
| // Usually, this is used to figure out what secret to look into for a specific value. | ||||
| type ArtifactRepositorySecret struct { | ||||
| 	Key  string `yaml:"key"` | ||||
| 	Name string `yaml:"name"` | ||||
| } | ||||
|  | ||||
| // MarshalToYaml is used by the CLI to generate configmaps during deployment | ||||
| // or build operations. | ||||
| func (a *ArtifactRepositoryS3Provider) MarshalToYaml() (string, error) { | ||||
| 	builder := &strings.Builder{} | ||||
| 	encoder := yaml.NewEncoder(builder) | ||||
| 	encoder.SetIndent(6) | ||||
| 	defer encoder.Close() | ||||
| 	err := encoder.Encode(&ArtifactRepositoryProvider{ | ||||
| 		S3: &ArtifactRepositoryS3Provider{ | ||||
| 			KeyFormat: a.KeyFormat, | ||||
| 			Bucket:    a.Bucket, | ||||
| 			Endpoint:  a.Endpoint, | ||||
| 			Insecure:  a.Insecure, | ||||
| 			Region:    a.Region, | ||||
| 			AccessKeySecret: ArtifactRepositorySecret{ | ||||
| 				Name: a.AccessKeySecret.Name, | ||||
| 				Key:  a.AccessKeySecret.Key, | ||||
| 			}, | ||||
| 			SecretKeySecret: ArtifactRepositorySecret{ | ||||
| 				Name: a.SecretKeySecret.Name, | ||||
| 				Key:  a.SecretKeySecret.Key, | ||||
| 			}, | ||||
| 		}, | ||||
| 	}) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	return builder.String(), nil | ||||
| } | ||||
|  | ||||
| // MarshalToYaml is used by the CLI to generate configmaps during deployment | ||||
| // or build operations. | ||||
| func (g *ArtifactRepositoryGCSProvider) MarshalToYaml() (string, error) { | ||||
| 	builder := &strings.Builder{} | ||||
| 	encoder := yaml.NewEncoder(builder) | ||||
| 	encoder.SetIndent(6) | ||||
| 	defer encoder.Close() | ||||
| 	err := encoder.Encode(&ArtifactRepositoryProvider{ | ||||
| 		GCS: &ArtifactRepositoryGCSProvider{ | ||||
| 			KeyFormat: g.KeyFormat, | ||||
| 			Bucket:    g.Bucket, | ||||
| 			Endpoint:  g.Endpoint, | ||||
| 			Insecure:  g.Insecure, | ||||
| 			ServiceAccountKeySecret: ArtifactRepositorySecret{ | ||||
| 				Key:  "artifactRepositoryGCSServiceAccountKey", | ||||
| 				Name: "onepanel", | ||||
| 			}, | ||||
| 		}, | ||||
| 	}) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	return builder.String(), nil | ||||
| 	AccessKeySecret corev1.SecretKeySelector | ||||
| 	SecretKeySecret corev1.SecretKeySelector | ||||
| 	AccessKey       string | ||||
| 	Secretkey       string | ||||
| } | ||||
|  | ||||
| // FormatKey replaces placeholder values with their actual values and returns this string. | ||||
| // {{workflow.namespace}} -> namespace | ||||
| // {{workflow.name}} -> workflowName | ||||
| // {{pod.name}} -> podName | ||||
| func (a *ArtifactRepositoryS3Provider) FormatKey(namespace, workflowName, podName string) string { | ||||
| func (a *ArtifactRepositoryS3Config) FormatKey(namespace, workflowName, podName string) string { | ||||
| 	keyFormat := a.KeyFormat | ||||
|  | ||||
| 	keyFormat = strings.Replace(keyFormat, "{{workflow.namespace}}", namespace, -1) | ||||
| @@ -303,20 +31,10 @@ func (a *ArtifactRepositoryS3Provider) FormatKey(namespace, workflowName, podNam | ||||
| 	return keyFormat | ||||
| } | ||||
|  | ||||
| // FormatKey replaces placeholder values with their actual values and returns this string. | ||||
| // {{workflow.namespace}} -> namespace | ||||
| // {{workflow.name}} -> workflowName | ||||
| // {{pod.name}} -> podName | ||||
| func (g *ArtifactRepositoryGCSProvider) FormatKey(namespace, workflowName, podName string) string { | ||||
| 	keyFormat := g.KeyFormat | ||||
|  | ||||
| 	keyFormat = strings.Replace(keyFormat, "{{workflow.namespace}}", namespace, -1) | ||||
| 	keyFormat = strings.Replace(keyFormat, "{{workflow.name}}", workflowName, -1) | ||||
| 	keyFormat = strings.Replace(keyFormat, "{{pod.name}}", podName, -1) | ||||
|  | ||||
| 	return keyFormat | ||||
| type ArtifactRepositoryConfig struct { | ||||
| 	S3 *ArtifactRepositoryS3Config | ||||
| } | ||||
|  | ||||
| type NamespaceConfig struct { | ||||
| 	ArtifactRepository ArtifactRepositoryProvider | ||||
| 	ArtifactRepository ArtifactRepositoryConfig | ||||
| } | ||||
|   | ||||
| @@ -105,17 +105,45 @@ func (c *Client) UpdateCronWorkflow(namespace string, uid string, cronWorkflow * | ||||
| 	// Manifests could get big, don't return them in this case. | ||||
| 	cronWorkflow.WorkflowExecution.WorkflowTemplate.Manifest = "" | ||||
|  | ||||
| 	tx, err := c.DB.Begin() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	defer tx.Rollback() | ||||
|  | ||||
| 	_, err = sb.Update("cron_workflows"). | ||||
| 		SetMap(sq.Eq{ | ||||
| 			"manifest": cronWorkflow.Manifest, | ||||
| 			"labels":   cronWorkflow.Labels, | ||||
| 		}).Where(sq.Eq{"id": cronWorkflow.ID}). | ||||
| 		RunWith(c.DB). | ||||
| 		}).Where(sq.Eq{ | ||||
| 		"id": cronWorkflow.ID, | ||||
| 	}). | ||||
| 		RunWith(tx). | ||||
| 		Exec() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// delete all labels then replace | ||||
| 	_, err = sb.Delete("labels"). | ||||
| 		Where(sq.Eq{ | ||||
| 			"resource":    TypeCronWorkflow, | ||||
| 			"resource_id": cronWorkflow.ID, | ||||
| 		}). | ||||
| 		RunWith(tx). | ||||
| 		Exec() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	_, err = c.InsertLabelsRunner(tx, TypeCronWorkflow, cronWorkflow.ID, cronWorkflow.Labels) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if err := tx.Commit(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return cronWorkflow, nil | ||||
| } | ||||
|  | ||||
| @@ -131,7 +159,7 @@ func (c *Client) CreateCronWorkflow(namespace string, cronWorkflow *CronWorkflow | ||||
| 		return nil, util.NewUserError(codes.NotFound, "Error with getting workflow template.") | ||||
| 	} | ||||
|  | ||||
| 	// TODO: Need to pull system parameters from k8s config/secret here, example: HOST | ||||
| 	//// TODO: Need to pull system parameters from k8s config/secret here, example: HOST | ||||
| 	opts := &WorkflowExecutionOptions{ | ||||
| 		Labels: make(map[string]string), | ||||
| 	} | ||||
| @@ -211,6 +239,12 @@ func (c *Client) CreateCronWorkflow(namespace string, cronWorkflow *CronWorkflow | ||||
| 	// Manifests could get big, don't return them in this case. | ||||
| 	cronWorkflow.WorkflowExecution.WorkflowTemplate.Manifest = "" | ||||
|  | ||||
| 	tx, err := c.DB.Begin() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	defer tx.Rollback() | ||||
|  | ||||
| 	err = sb.Insert("cron_workflows"). | ||||
| 		SetMap(sq.Eq{ | ||||
| 			"uid":                          cronWorkflow.UID, | ||||
| @@ -219,25 +253,38 @@ func (c *Client) CreateCronWorkflow(namespace string, cronWorkflow *CronWorkflow | ||||
| 			"manifest":                     cronWorkflow.Manifest, | ||||
| 			"namespace":                    namespace, | ||||
| 			"is_archived":                  false, | ||||
| 			"labels":                       cronWorkflow.Labels, | ||||
| 		}). | ||||
| 		Suffix("RETURNING id"). | ||||
| 		RunWith(c.DB). | ||||
| 		RunWith(tx). | ||||
| 		QueryRow(). | ||||
| 		Scan(&cronWorkflow.ID) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if len(cronWorkflow.Labels) > 0 { | ||||
| 		_, err = c.InsertLabelsBuilder(TypeCronWorkflow, cronWorkflow.ID, cronWorkflow.Labels). | ||||
| 			RunWith(tx). | ||||
| 			Exec() | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if err := tx.Commit(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return cronWorkflow, nil | ||||
| } | ||||
|  | ||||
| // GetCronWorkflow gets information about a cron workflow uniquely identified by a namespace/uid | ||||
| func (c *Client) GetCronWorkflow(namespace, uid string) (cronWorkflow *CronWorkflow, err error) { | ||||
| 	cronWorkflow = &CronWorkflow{} | ||||
|  | ||||
| 	sb := c.cronWorkflowSelectBuilder(namespace, uid) | ||||
| 	err = c.Getx(cronWorkflow, sb) | ||||
| 	err = c.cronWorkflowSelectBuilderNoColumns(namespace, uid). | ||||
| 		RunWith(c.DB). | ||||
| 		QueryRow(). | ||||
| 		Scan(cronWorkflow) | ||||
|  | ||||
| 	return | ||||
| } | ||||
| @@ -308,7 +355,6 @@ func (c *Client) DeleteCronWorkflowLabel(namespace, name string, keysToDelete .. | ||||
| 	return wf.Labels, nil | ||||
| } | ||||
|  | ||||
| // ListCronWorkflows selects all of the cron workflows for the given namespace and workflow template uid | ||||
| func (c *Client) ListCronWorkflows(namespace, workflowTemplateUID string, pagination *pagination.PaginationRequest) (cronWorkflows []*CronWorkflow, err error) { | ||||
| 	sb := c.cronWorkflowSelectBuilder(namespace, workflowTemplateUID). | ||||
| 		OrderBy("cw.created_at DESC") | ||||
| @@ -317,6 +363,18 @@ func (c *Client) ListCronWorkflows(namespace, workflowTemplateUID string, pagina | ||||
| 	if err := c.DB.Selectx(&cronWorkflows, sb); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	labelsMap, err := c.GetDBLabelsMapped(TypeCronWorkflow, CronWorkflowsToIDs(cronWorkflows)...) | ||||
| 	if err != nil { | ||||
| 		log.WithFields(log.Fields{ | ||||
| 			"Namespace": namespace, | ||||
| 			"Error":     err.Error(), | ||||
| 		}).Error("Unable to get Cron Workflow Labels") | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	for _, resource := range cronWorkflows { | ||||
| 		resource.Labels = labelsMap[resource.ID] | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|   | ||||
| @@ -3,7 +3,6 @@ package v1 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"github.com/onepanelio/core/pkg/util/mapping" | ||||
| 	"github.com/onepanelio/core/pkg/util/types" | ||||
| 	"github.com/onepanelio/core/util/sql" | ||||
| 	"gopkg.in/yaml.v2" | ||||
| 	"time" | ||||
| @@ -18,28 +17,51 @@ type CronWorkflow struct { | ||||
| 	Name                      string | ||||
| 	GenerateName              string | ||||
| 	WorkflowExecution         *WorkflowExecution | ||||
| 	Labels                    types.JSONLabels | ||||
| 	Labels                    map[string]string | ||||
| 	Version                   int64 | ||||
| 	WorkflowTemplateVersionID uint64 `db:"workflow_template_version_id"` | ||||
| 	Manifest                  string | ||||
| 	Namespace                 string `db:"namespace"` | ||||
| } | ||||
|  | ||||
| // CronWorkflowManifest is a client representation of a CronWorkflowManifest | ||||
| // It is usually provided as YAML by a client and this struct helps to marshal/unmarshal it | ||||
| type CronWorkflowManifest struct { | ||||
| 	WorkflowExecutionSpec WorkflowExecutionSpec `json:"workflowSpec" yaml:"workflowSpec"` | ||||
| } | ||||
|  | ||||
| // GetParametersFromWorkflowSpec parses the parameters from the CronWorkflow's manifest | ||||
| func (cw *CronWorkflow) GetParametersFromWorkflowSpec() ([]Parameter, error) { | ||||
| 	manifestSpec := &CronWorkflowManifest{} | ||||
| 	var parameters []Parameter | ||||
|  | ||||
| 	if err := yaml.Unmarshal([]byte(cw.Manifest), manifestSpec); err != nil { | ||||
| 	mappedData := make(map[string]interface{}) | ||||
|  | ||||
| 	if err := yaml.Unmarshal([]byte(cw.Manifest), mappedData); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	parameters := manifestSpec.WorkflowExecutionSpec.Arguments.Parameters | ||||
| 	workflowSpec, ok := mappedData["workflowSpec"] | ||||
| 	if !ok { | ||||
| 		return parameters, nil | ||||
| 	} | ||||
|  | ||||
| 	workflowSpecMap := workflowSpec.(map[interface{}]interface{}) | ||||
| 	arguments, ok := workflowSpecMap["arguments"] | ||||
| 	if !ok { | ||||
| 		return parameters, nil | ||||
| 	} | ||||
|  | ||||
| 	argumentsMap := arguments.(map[interface{}]interface{}) | ||||
| 	parametersRaw, ok := argumentsMap["parameters"] | ||||
| 	if !ok { | ||||
| 		return parameters, nil | ||||
| 	} | ||||
|  | ||||
| 	parametersArray, ok := parametersRaw.([]interface{}) | ||||
| 	for _, parameter := range parametersArray { | ||||
| 		paramMap, ok := parameter.(map[interface{}]interface{}) | ||||
| 		if !ok { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		workflowParameter := ParameterFromMap(paramMap) | ||||
|  | ||||
| 		parameters = append(parameters, *workflowParameter) | ||||
| 	} | ||||
|  | ||||
| 	return parameters, nil | ||||
| } | ||||
| @@ -86,7 +108,7 @@ func (cw *CronWorkflow) AddToManifestSpec(key, manifest string) error { | ||||
| // getCronWorkflowColumns returns all of the columns for cronWorkflow modified by alias, destination. | ||||
| // see formatColumnSelect | ||||
| func getCronWorkflowColumns(aliasAndDestination ...string) []string { | ||||
| 	columns := []string{"id", "created_at", "uid", "name", "workflow_template_version_id", "manifest", "namespace", "labels"} | ||||
| 	columns := []string{"id", "created_at", "uid", "name", "workflow_template_version_id", "manifest", "namespace"} | ||||
| 	return sql.FormatColumnSelect(columns, aliasAndDestination...) | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,113 +0,0 @@ | ||||
| package v1 | ||||
|  | ||||
| import ( | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| // TestCronWorkflow_GetParametersFromWorkflowSpec makes sure the GetParametersFromWorkflowSpec method works | ||||
| func TestCronWorkflow_GetParametersFromWorkflowSpec(t *testing.T) { | ||||
| 	manifest := `concurrencyPolicy: Allow | ||||
| failedJobsHistoryLimit: 1 | ||||
| schedule: '* * * * 2' | ||||
| startingDeadlineSeconds: 0 | ||||
| successfulJobsHistoryLimit: 3 | ||||
| suspend: false | ||||
| timezone: Etc/UTC | ||||
| workflowSpec: | ||||
|   arguments: | ||||
|     parameters: | ||||
|     - displayname: "" | ||||
|       hint: "" | ||||
|       name: source | ||||
|       options: [] | ||||
|       required: false | ||||
|       type: "" | ||||
|       value: https://github.com/onepanelio/Mask_RCNN.git | ||||
|     - displayname: "" | ||||
|       hint: "" | ||||
|       name: dataset-path | ||||
|       options: [] | ||||
|       required: false | ||||
|       type: "" | ||||
|       value: datasets/test_05142020170720 | ||||
|     - displayname: "" | ||||
|       hint: "" | ||||
|       name: model-path | ||||
|       options: [] | ||||
|       required: false | ||||
|       type: "" | ||||
|       value: models/rush/cvat6-20 | ||||
|     - displayname: "" | ||||
|       hint: "" | ||||
|       name: extras | ||||
|       options: [] | ||||
|       required: false | ||||
|       type: "" | ||||
|       value: none | ||||
|     - displayname: "" | ||||
|       hint: "" | ||||
|       name: task-name | ||||
|       options: [] | ||||
|       required: false | ||||
|       type: "" | ||||
|       value: test | ||||
|     - displayname: "" | ||||
|       hint: "" | ||||
|       name: num-classes | ||||
|       options: [] | ||||
|       required: false | ||||
|       type: "" | ||||
|       value: "2" | ||||
|     - displayname: "" | ||||
|       hint: "" | ||||
|       name: stage-1-epochs | ||||
|       options: [] | ||||
|       required: false | ||||
|       type: "" | ||||
|       value: "1" | ||||
|     - displayname: "" | ||||
|       hint: "" | ||||
|       name: stage-2-epochs | ||||
|       options: [] | ||||
|       required: false | ||||
|       type: "" | ||||
|       value: "2" | ||||
|     - displayname: "" | ||||
|       hint: "" | ||||
|       name: stage-3-epochs | ||||
|       options: [] | ||||
|       required: false | ||||
|       type: "" | ||||
|       value: "3" | ||||
|     - displayname: "" | ||||
|       hint: "" | ||||
|       name: tf-image | ||||
|       options: [] | ||||
|       required: false | ||||
|       type: "" | ||||
|       value: tensorflow/tensorflow:1.13.1-py3 | ||||
|     - displayname: Node pool | ||||
|       hint: Name of node pool or group | ||||
|       name: sys-node-pool | ||||
|       options: | ||||
|       - name: 'CPU: 2, RAM: 8GB' | ||||
|         value: Standard_D2s_v3 | ||||
|       - name: 'CPU: 4, RAM: 16GB' | ||||
|         value: Standard_D4s_v3 | ||||
|       - name: 'GPU: 1xK80, CPU: 6, RAM: 56GB' | ||||
|         value: Standard_NC6 | ||||
|       required: true | ||||
|       type: select.select | ||||
|       value: cake` | ||||
|  | ||||
| 	cronWorkflow := CronWorkflow{ | ||||
| 		Manifest: manifest, | ||||
| 	} | ||||
|  | ||||
| 	parameters, err := cronWorkflow.GetParametersFromWorkflowSpec() | ||||
| 	assert.Nil(t, err) | ||||
| 	assert.NotNil(t, parameters) | ||||
|  | ||||
| 	assert.Len(t, parameters, 11) | ||||
| } | ||||
| @@ -1,11 +1,6 @@ | ||||
| package v1 | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| ) | ||||
| import "time" | ||||
|  | ||||
| // Label represents a database-backed label row. | ||||
| type Label struct { | ||||
| @@ -27,86 +22,3 @@ func LabelsToMapping(labels ...*Label) map[string]string { | ||||
|  | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| // LabelsFromString parses a string into labels | ||||
| // Format: key=<key>,value=<value>&key2=<key2>,value2=<value2> | ||||
| func LabelsFromString(value string) (labels []*Label, err error) { | ||||
| 	labels = make([]*Label, 0) | ||||
|  | ||||
| 	if value == "" { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	labelParts := strings.Split(value, "&") | ||||
| 	if len(labelParts) == 0 { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	for _, part := range labelParts { | ||||
| 		if part == "" { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		newLabel, err := LabelFromString(part) | ||||
| 		if err != nil { | ||||
| 			return labels, err | ||||
| 		} | ||||
| 		if newLabel == nil { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		labels = append(labels, newLabel) | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // LabelFromString converts a parses into a label | ||||
| // Format: key=<key>,value=<value> | ||||
| func LabelFromString(value string) (label *Label, err error) { | ||||
| 	parts := strings.Split(value, ",") | ||||
| 	if len(parts) != 2 { | ||||
| 		return nil, fmt.Errorf("label does not have two parts, key/value") | ||||
| 	} | ||||
|  | ||||
| 	label = &Label{} | ||||
|  | ||||
| 	first := parts[0] | ||||
| 	firstItems := strings.Split(first, "=") | ||||
| 	if len(firstItems) != 2 { | ||||
| 		return nil, fmt.Errorf(`incorrectly formatted label "%v"`, first) | ||||
| 	} | ||||
|  | ||||
| 	if firstItems[0] == "key" { | ||||
| 		label.Key = firstItems[1] | ||||
| 	} else if firstItems[0] == "value" { | ||||
| 		label.Value = firstItems[1] | ||||
| 	} | ||||
|  | ||||
| 	second := parts[1] | ||||
| 	secondItems := strings.Split(second, "=") | ||||
| 	if len(secondItems) != 2 { | ||||
| 		return nil, fmt.Errorf(`incorrectly formatted label "%v"`, second) | ||||
| 	} | ||||
|  | ||||
| 	if secondItems[0] == "key" { | ||||
| 		label.Key = secondItems[1] | ||||
| 	} else if secondItems[0] == "value" { | ||||
| 		label.Value = secondItems[1] | ||||
| 	} | ||||
|  | ||||
| 	return label, nil | ||||
| } | ||||
|  | ||||
| // LabelsToJSONString converts an array of labels to a json string representing an object | ||||
| // where the keys are the label keys and the values are the label values | ||||
| func LabelsToJSONString(labels []*Label) (string, error) { | ||||
| 	labelMap := LabelsToMapping(labels...) | ||||
|  | ||||
| 	resultBytes, err := json.Marshal(labelMap) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	return string(resultBytes), nil | ||||
| } | ||||
|   | ||||
| @@ -1,60 +0,0 @@ | ||||
| package v1 | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| // TestLabelFromString tests the LabelFromString function | ||||
| func TestLabelFromString(t *testing.T) { | ||||
| 	// Blank value gives us no label | ||||
| 	label, err := LabelFromString("") | ||||
| 	assert.NotNil(t, err) | ||||
| 	assert.Nil(t, label) | ||||
|  | ||||
| 	// Missing value, should give error | ||||
| 	label, err = LabelFromString("key=a") | ||||
| 	assert.NotNil(t, err) | ||||
|  | ||||
| 	// Missing value, but still have comma, should give error | ||||
| 	label, err = LabelFromString("key=a,") | ||||
| 	assert.NotNil(t, err) | ||||
|  | ||||
| 	// Missing key, should give error | ||||
| 	label, err = LabelFromString("value=a") | ||||
| 	assert.NotNil(t, err) | ||||
|  | ||||
| 	// Missing key, still have comma, should give error | ||||
| 	label, err = LabelFromString("value=a,") | ||||
| 	assert.NotNil(t, err) | ||||
|  | ||||
| 	// Correct, should not give an error | ||||
| 	label, err = LabelFromString("key=a,value=b") | ||||
| 	assert.Nil(t, err) | ||||
| 	assert.Equal(t, label.Key, "a") | ||||
| 	assert.Equal(t, label.Value, "b") | ||||
| } | ||||
|  | ||||
| // TestLabelsFromString tests the LabelsFromString function | ||||
| func TestLabelsFromString(t *testing.T) { | ||||
| 	// Empty should give no error and no labels | ||||
| 	labels, err := LabelsFromString("") | ||||
| 	assert.Nil(t, err) | ||||
| 	assert.Len(t, labels, 0) | ||||
|  | ||||
| 	// Bad data, should give no labels | ||||
| 	labels, err = LabelsFromString("&&&&") | ||||
| 	assert.Nil(t, err) | ||||
| 	assert.Len(t, labels, 0) | ||||
|  | ||||
| 	// Test just one label | ||||
| 	labels, err = LabelsFromString("key=a,value=b") | ||||
| 	assert.Nil(t, err) | ||||
| 	assert.Len(t, labels, 1) | ||||
|  | ||||
| 	// Test many labels | ||||
| 	labels, err = LabelsFromString("key=a,value=b&key=c,value=d&key=e,value=f") | ||||
| 	assert.Nil(t, err) | ||||
| 	assert.Len(t, labels, 3) | ||||
| } | ||||
							
								
								
									
										218
									
								
								pkg/labels.go
									
									
									
									
									
								
							
							
						
						
									
										218
									
								
								pkg/labels.go
									
									
									
									
									
								
							| @@ -1,55 +1,101 @@ | ||||
| package v1 | ||||
|  | ||||
| import ( | ||||
| 	"database/sql" | ||||
| 	"fmt" | ||||
| 	sq "github.com/Masterminds/squirrel" | ||||
| 	"github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" | ||||
| 	"github.com/onepanelio/core/pkg/util/label" | ||||
| 	"github.com/onepanelio/core/pkg/util/mapping" | ||||
| 	"github.com/onepanelio/core/pkg/util/types" | ||||
| 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| ) | ||||
|  | ||||
| func (c *Client) ListLabels(resource string, uid string) (labels []*Label, err error) { | ||||
| 	sb := sb.Select("labels"). | ||||
| 		From(TypeToTableName(resource)) | ||||
| 	sb := sb.Select("l.id", "l.created_at", "l.key", "l.value", "l.resource", "l.resource_id"). | ||||
| 		From("labels l"). | ||||
| 		Where(sq.Eq{ | ||||
| 			"resource": resource, | ||||
| 		}). | ||||
| 		OrderBy("l.created_at") | ||||
|  | ||||
| 	switch resource { | ||||
| 	case TypeWorkflowTemplate: | ||||
| 		sb = sb.Where(sq.Eq{"uid": uid}) | ||||
| 		sb = sb.Join("workflow_templates wt ON wt.id = l.resource_id"). | ||||
| 			Where(sq.Eq{"wt.uid": uid}) | ||||
| 	case TypeWorkflowExecution: | ||||
| 		sb = sb.Where(sq.Eq{"uid": uid}) | ||||
| 		sb = sb.Join("workflow_executions we ON we.id = l.resource_id"). | ||||
| 			Where(sq.Eq{"we.uid": uid}) | ||||
| 	case TypeCronWorkflow: | ||||
| 		sb = sb.Where(sq.Eq{"uid": uid}) | ||||
| 		sb = sb.Join("cron_workflows cw ON cw.id = l.resource_id"). | ||||
| 			Where(sq.Eq{"cw.uid": uid}) | ||||
| 	case TypeWorkspace: | ||||
| 		sb = sb.Where(sq.And{ | ||||
| 			sq.Eq{"uid": uid}, | ||||
| 			sq.NotEq{"phase": "Terminated"}, | ||||
| 		}) | ||||
| 		sb = sb.Join("workspaces ws ON ws.id = l.resource_id"). | ||||
| 			Where(sq.And{ | ||||
| 				sq.Eq{"ws.uid": uid}, | ||||
| 				sq.NotEq{"ws.phase": "Terminated"}, | ||||
| 			}) | ||||
| 	default: | ||||
| 		return nil, fmt.Errorf("unsupported label resource %v", resource) | ||||
| 	} | ||||
|  | ||||
| 	result := types.JSONLabels{} | ||||
| 	err = c.DB.Getx(&result, sb) | ||||
| 	if err != nil { | ||||
| 	query, args, sqlErr := sb.ToSql() | ||||
| 	if sqlErr != nil { | ||||
| 		err = sqlErr | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	for key, value := range result { | ||||
| 		newLabel := &Label{ | ||||
| 			Key:      key, | ||||
| 			Value:    value, | ||||
| 			Resource: resource, | ||||
| 		} | ||||
|  | ||||
| 		labels = append(labels, newLabel) | ||||
| 	} | ||||
| 	err = c.DB.Select(&labels, query, args...) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (c *Client) AddLabels(namespace, resource, uid string, keyValues map[string]string) error { | ||||
| 	tx, err := c.DB.Begin() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer tx.Rollback() | ||||
|  | ||||
| 	tableName := TypeToTableName(resource) | ||||
| 	if tableName == "" { | ||||
| 		return fmt.Errorf("unknown resources '%v'", resource) | ||||
| 	} | ||||
|  | ||||
| 	resourceId := uint64(0) | ||||
| 	err = sb.Select("id"). | ||||
| 		From(tableName). | ||||
| 		Where(sq.Eq{ | ||||
| 			"uid": uid, | ||||
| 		}). | ||||
| 		RunWith(tx). | ||||
| 		QueryRow(). | ||||
| 		Scan(&resourceId) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	_, err = sb.Delete("labels"). | ||||
| 		Where(sq.Eq{ | ||||
| 			"key":         mapping.PluckKeysStr(keyValues), | ||||
| 			"resource":    resource, | ||||
| 			"resource_id": resourceId, | ||||
| 		}).RunWith(tx). | ||||
| 		Exec() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	_, err = c.InsertLabelsBuilder(resource, resourceId, keyValues). | ||||
| 		RunWith(tx). | ||||
| 		Exec() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if err := tx.Commit(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	source, meta, err := c.GetK8sLabelResource(namespace, resource, uid) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| @@ -92,27 +138,49 @@ func (c *Client) ReplaceLabels(namespace, resource, uid string, keyValues map[st | ||||
| 			} | ||||
| 	} | ||||
|  | ||||
| 	_, err = sb.Update(tableName). | ||||
| 		SetMap(sq.Eq{ | ||||
| 			"labels": types.JSONLabels(keyValues), | ||||
| 		}). | ||||
| 	resourceID := uint64(0) | ||||
| 	err = sb.Select("id"). | ||||
| 		From(tableName). | ||||
| 		Where(whereCondition). | ||||
| 		RunWith(tx). | ||||
| 		QueryRow(). | ||||
| 		Scan(&resourceID) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return c.ReplaceLabelsUsingKnownID(namespace, resource, resourceID, uid, keyValues) | ||||
| } | ||||
|  | ||||
| func (c *Client) ReplaceLabelsUsingKnownID(namespace, resource string, resourceID uint64, uid string, keyValues map[string]string) error { | ||||
| 	tx, err := c.DB.Begin() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer tx.Rollback() | ||||
|  | ||||
| 	_, err = sb.Delete("labels"). | ||||
| 		Where(sq.Eq{ | ||||
| 			"resource":    resource, | ||||
| 			"resource_id": resourceID, | ||||
| 		}).RunWith(tx). | ||||
| 		Exec() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if len(keyValues) > 0 { | ||||
| 		_, err = c.InsertLabelsBuilder(resource, resourceID, keyValues). | ||||
| 			RunWith(tx). | ||||
| 			Exec() | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	if err := tx.Commit(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return c.ReplaceLabelsUsingKnownID(namespace, resource, uid, keyValues) | ||||
| } | ||||
|  | ||||
| // ReplaceLabelsUsingKnownID updates the k8s resource labels for the given resource/uid | ||||
| // deprecated | ||||
| func (c *Client) ReplaceLabelsUsingKnownID(namespace, resource string, uid string, keyValues map[string]string) error { | ||||
| 	source, meta, err := c.GetK8sLabelResource(namespace, resource, uid) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| @@ -193,22 +261,86 @@ func (c *Client) DeleteLabels(namespace, resource, uid string, keyValues map[str | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // DeleteResourceLabels deletes all of the labels for a specific resource, like workflow templates. | ||||
| // NOTE: this does NOT delete k8s labels, and is only meant to be used for special cases. | ||||
| func (c *Client) DeleteResourceLabels(runner sq.BaseRunner, resource string) error { | ||||
| 	tableName := TypeToTableName(resource) | ||||
| 	if tableName == "" { | ||||
| 		return fmt.Errorf("unknown resources '%v'", resource) | ||||
| func (c *Client) InsertLabelsBuilder(resource string, resourceID uint64, keyValues map[string]string) sq.InsertBuilder { | ||||
| 	sb := sb.Insert("labels"). | ||||
| 		Columns("resource", "resource_id", "key", "value") | ||||
|  | ||||
| 	for key, value := range keyValues { | ||||
| 		sb = sb.Values(resource, resourceID, key, value) | ||||
| 	} | ||||
|  | ||||
| 	_, err := sb.Delete("labels"). | ||||
| 		Where(sq.Eq{ | ||||
| 			"resource": resource, | ||||
| 		}). | ||||
| 	return sb | ||||
| } | ||||
|  | ||||
| // InsertLabelsRunner inserts the labels for the resource into the db using the provided runner. | ||||
| // If no labels are provided, does nothing and returns nil, nil. | ||||
| func (c *Client) InsertLabelsRunner(runner sq.BaseRunner, resource string, resourceID uint64, keyValues map[string]string) (sql.Result, error) { | ||||
| 	if len(keyValues) == 0 { | ||||
| 		return nil, nil | ||||
| 	} | ||||
|  | ||||
| 	return c.InsertLabelsBuilder(resource, resourceID, keyValues). | ||||
| 		RunWith(runner). | ||||
| 		Exec() | ||||
| } | ||||
|  | ||||
| 	return err | ||||
| // InsertLabels inserts the labels for the resource into the db using the client's DB. | ||||
| // If no labels are provided, does nothing and returns nil, nil. | ||||
| func (c *Client) InsertLabels(resource string, resourceID uint64, keyValues map[string]string) (sql.Result, error) { | ||||
| 	return c.InsertLabelsRunner(c.DB, resource, resourceID, keyValues) | ||||
| } | ||||
|  | ||||
| func (c *Client) GetDbLabels(resource string, ids ...uint64) (labels []*Label, err error) { | ||||
| 	if len(ids) == 0 { | ||||
| 		return make([]*Label, 0), nil | ||||
| 	} | ||||
|  | ||||
| 	tx, err := c.DB.Begin() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	defer tx.Rollback() | ||||
|  | ||||
| 	query, args, err := sb.Select("id", "created_at", "key", "value", "resource", "resource_id"). | ||||
| 		From("labels"). | ||||
| 		Where(sq.Eq{ | ||||
| 			"resource_id": ids, | ||||
| 			"resource":    resource, | ||||
| 		}). | ||||
| 		OrderBy("key"). | ||||
| 		ToSql() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	err = c.DB.Select(&labels, query, args...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GetDBLabelsMapped returns a map where the key is the id of the resource | ||||
| // and the value is the labels as a map[string]string | ||||
| func (c *Client) GetDBLabelsMapped(resource string, ids ...uint64) (result map[uint64]map[string]string, err error) { | ||||
| 	dbLabels, err := c.GetDbLabels(resource, ids...) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	result = make(map[uint64]map[string]string) | ||||
| 	for _, dbLabel := range dbLabels { | ||||
| 		_, ok := result[dbLabel.ResourceID] | ||||
| 		if !ok { | ||||
| 			result[dbLabel.ResourceID] = make(map[string]string) | ||||
| 		} | ||||
| 		result[dbLabel.ResourceID][dbLabel.Key] = dbLabel.Value | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (c *Client) GetK8sLabelResource(namespace, resource, uid string) (source interface{}, result *v1.ObjectMeta, err error) { | ||||
|   | ||||
| @@ -21,9 +21,8 @@ func testCreateNamespace(c *Client) { | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestClient_ListNamespace(t *testing.T) { | ||||
| 	c := DefaultTestClient() | ||||
| func TestListNamespace(t *testing.T) { | ||||
| 	c := NewTestClient() | ||||
|  | ||||
| 	testCreateNamespace(c) | ||||
|  | ||||
|   | ||||
| @@ -6,8 +6,8 @@ import ( | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestClient_CreateSecret(t *testing.T) { | ||||
| 	c := DefaultTestClient() | ||||
| func TestCreateSecret(t *testing.T) { | ||||
| 	c := NewTestClient() | ||||
|  | ||||
| 	err := c.CreateSecret("namespace", &Secret{ | ||||
| 		Name: "name", | ||||
| @@ -15,8 +15,8 @@ func TestClient_CreateSecret(t *testing.T) { | ||||
| 	assert.Nil(t, err) | ||||
| } | ||||
|  | ||||
| func TestClient_GetSecret(t *testing.T) { | ||||
| 	c := DefaultTestClient() | ||||
| func TestGetSecret(t *testing.T) { | ||||
| 	c := NewTestClient() | ||||
|  | ||||
| 	err := c.CreateSecret("namespace", &Secret{ | ||||
| 		Name: "name", | ||||
|   | ||||
| @@ -1,87 +0,0 @@ | ||||
| package v1 | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| ) | ||||
|  | ||||
| // generateServiceURL generates the url that the service is located at | ||||
| func (c *Client) generateServiceURL(namespace, name string) (string, error) { | ||||
| 	protocol := c.systemConfig.APIProtocol() | ||||
| 	if protocol == nil { | ||||
| 		return "", fmt.Errorf("unable to get the api protocol from the system config") | ||||
| 	} | ||||
|  | ||||
| 	domain := c.systemConfig.Domain() | ||||
| 	if domain == nil { | ||||
| 		return "", fmt.Errorf("unable to get a domain from the system config") | ||||
| 	} | ||||
|  | ||||
| 	// https://name--namespace.domain | ||||
| 	return fmt.Sprintf("%v%v--%v.%v", *protocol, name, namespace, *domain), nil | ||||
| } | ||||
|  | ||||
| // ListServices finds all of the services in the given namespace | ||||
| func (c *Client) ListServices(namespace string) ([]*Service, error) { | ||||
| 	if namespace == "" { | ||||
| 		return nil, fmt.Errorf("namespace is empty") | ||||
| 	} | ||||
|  | ||||
| 	labelSelect := fmt.Sprintf("%v=%v", "service.onepanel.io/part-of", "onepanel") | ||||
|  | ||||
| 	serviceList, err := c.CoreV1().Services(namespace).List(ListOptions{ | ||||
| 		LabelSelector: labelSelect, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	services := make([]*Service, 0) | ||||
| 	for _, serviceItem := range serviceList.Items { | ||||
| 		serviceName := serviceItem.Labels["service.onepanel.io/name"] | ||||
| 		serviceURL, err := c.generateServiceURL(namespace, serviceName) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		services = append(services, &Service{ | ||||
| 			Name: serviceName, | ||||
| 			URL:  serviceURL, | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	return services, nil | ||||
| } | ||||
|  | ||||
| // GetService gets a specific service identified by namespace, name. | ||||
| // If it is not found, nil, nil is returned | ||||
| func (c *Client) GetService(namespace, name string) (*Service, error) { | ||||
| 	labelSelect := fmt.Sprintf("%v=%v,%v=%v", "service.onepanel.io/part-of", "onepanel", "service.onepanel.io/name", name) | ||||
|  | ||||
| 	serviceList, err := c.CoreV1().Services(namespace).List(ListOptions{ | ||||
| 		LabelSelector: labelSelect, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if len(serviceList.Items) == 0 { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 	if len(serviceList.Items) > 1 { | ||||
| 		return nil, fmt.Errorf("non-unique result found for GetService %v,%v", namespace, name) | ||||
| 	} | ||||
|  | ||||
| 	serviceItem := serviceList.Items[0] | ||||
| 	serviceName := serviceItem.Labels["service.onepanel.io/name"] | ||||
| 	serviceURL, err := c.generateServiceURL(namespace, serviceName) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	service := &Service{ | ||||
| 		Name: serviceName, | ||||
| 		URL:  serviceURL, | ||||
| 	} | ||||
|  | ||||
| 	return service, nil | ||||
| } | ||||
| @@ -1,8 +0,0 @@ | ||||
| package v1 | ||||
|  | ||||
| // Service represents an installable "service" added to the system. | ||||
| // This can be something like modeldb, or some other service that complements the main system. | ||||
| type Service struct { | ||||
| 	Name string | ||||
| 	URL  string | ||||
| } | ||||
| @@ -46,13 +46,10 @@ func NewUserErrorWrap(err error, entity string) error { | ||||
| 		code    codes.Code | ||||
| 		message string | ||||
| 		pqErr   *pq.Error | ||||
| 		userErr *UserError | ||||
| 	) | ||||
| 	if errors.As(err, &pqErr) { | ||||
| 		code = pqError(pqErr) | ||||
| 		message = fmt.Sprintf("%v already exists.", entity) | ||||
| 	} else if errors.As(err, &userErr) { | ||||
| 		return err | ||||
| 	} else { | ||||
| 		code = codes.Unknown | ||||
| 		message = "Unknown error." | ||||
|   | ||||
| @@ -1,57 +0,0 @@ | ||||
| package gcs | ||||
|  | ||||
| import ( | ||||
| 	"cloud.google.com/go/storage" | ||||
| 	log "github.com/sirupsen/logrus" | ||||
| 	"golang.org/x/net/context" | ||||
| 	"golang.org/x/oauth2/google" | ||||
| 	"google.golang.org/api/option" | ||||
| 	"io" | ||||
| ) | ||||
|  | ||||
| // Client is a struct used for accessing Google Cloud Storage. | ||||
| type Client struct { | ||||
| 	*storage.Client | ||||
| } | ||||
|  | ||||
| // NewClient handles the details of initializing the connection to Google Cloud Storage. | ||||
| // - Note that the permissions are set to ReadWrite. | ||||
| func NewClient(namespace string, serviceAccountJSON string) (gcsClient *Client, err error) { | ||||
| 	ctx := context.Background() | ||||
| 	creds, err := google.CredentialsFromJSON(ctx, []byte(serviceAccountJSON), storage.ScopeReadWrite) | ||||
| 	if err != nil { | ||||
| 		log.WithFields(log.Fields{ | ||||
| 			"Namespace": namespace, | ||||
| 			"JSON":      serviceAccountJSON, | ||||
| 			"Error":     err.Error(), | ||||
| 		}).Error("GetGCSClient failed when initializing a new GCS client.") | ||||
| 		return | ||||
| 	} | ||||
| 	client, err := storage.NewClient(ctx, option.WithCredentials(creds)) | ||||
| 	if err != nil { | ||||
| 		log.WithFields(log.Fields{ | ||||
| 			"Namespace": namespace, | ||||
| 			"JSON":      serviceAccountJSON, | ||||
| 			"Error":     err.Error(), | ||||
| 		}).Error("GetGCSClient failed when initializing a new GCS client.") | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	return &Client{Client: client}, nil | ||||
| } | ||||
|  | ||||
| /* GetObject retrieves a specific object from Google Cloud Storage. | ||||
| - Function Name is meant to be consistent with S3's. | ||||
| */ | ||||
| func (c *Client) GetObject(bucket, key string) (stream io.ReadCloser, err error) { | ||||
| 	ctx := context.Background() | ||||
| 	stream, err = c.Client.Bucket(bucket).Object(key).NewReader(ctx) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	if stream == nil { | ||||
| 		defer stream.Close() | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
| @@ -17,12 +17,6 @@ const ( | ||||
| 	VersionLatest               = OnepanelPrefix + "version-latest" | ||||
| ) | ||||
|  | ||||
| // Label represents a Key/Value pair label | ||||
| type Label struct { | ||||
| 	Key   string | ||||
| 	Value string | ||||
| } | ||||
|  | ||||
| // Function that modifies an input string | ||||
| type StringModifier func(string) string | ||||
|  | ||||
|   | ||||
| @@ -25,20 +25,6 @@ func NewRequest(page, pageSize int32) PaginationRequest { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Start creates a new PaginationRequest that starts at the first page. | ||||
| // You can provide an optional pageSize argument. If none is provided, 15 is used. | ||||
| // All arguments apart from the first one are ignored. | ||||
| func Start(pageSize ...int32) *PaginationRequest { | ||||
| 	if len(pageSize) > 0 { | ||||
| 		pr := NewRequest(1, pageSize[0]) | ||||
| 		return &pr | ||||
| 	} | ||||
|  | ||||
| 	pr := NewRequest(1, 15) | ||||
|  | ||||
| 	return &pr | ||||
| } | ||||
|  | ||||
| func (pr *PaginationRequest) Offset() uint64 { | ||||
| 	// start at page 1. | ||||
| 	return (pr.Page - 1) * pr.PageSize | ||||
| @@ -58,11 +44,3 @@ func (pr *PaginationRequest) ApplyToSelect(sb *squirrel.SelectBuilder) *squirrel | ||||
|  | ||||
| 	return &result | ||||
| } | ||||
|  | ||||
| // Advance returns a new pagination request with the page incremented by 1 | ||||
| func (pr *PaginationRequest) Advance() *PaginationRequest { | ||||
| 	return &PaginationRequest{ | ||||
| 		Page:     pr.Page + 1, | ||||
| 		PageSize: pr.PageSize, | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,31 +0,0 @@ | ||||
| package router | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| ) | ||||
|  | ||||
| // Web provides methods to generate urls for the web client | ||||
| // this can be used to generate urls for workspaces or workflows when they are ready. | ||||
| type Web interface { | ||||
| 	WorkflowExecution(namespace, uid string) string | ||||
| } | ||||
|  | ||||
| // web is a basic implementation of WebRouter | ||||
| type web struct { | ||||
| 	protocol string | ||||
| 	fqdn     string | ||||
| } | ||||
|  | ||||
| // WorkflowExecution generates a url to view a specific workflow | ||||
| func (w *web) WorkflowExecution(namespace, uid string) string { | ||||
| 	// <protocol>:<fqdn>/<namespace>/workflows/<uid> | ||||
| 	return fmt.Sprintf("%v%v/%v/workflows/%v", w.protocol, w.fqdn, namespace, uid) | ||||
| } | ||||
|  | ||||
| // NewWebRouter creates a new web router used to generate urls for the web client | ||||
| func NewWebRouter(protocol, fqdn string) (Web, error) { | ||||
| 	return &web{ | ||||
| 		protocol: protocol, | ||||
| 		fqdn:     fqdn, | ||||
| 	}, nil | ||||
| } | ||||
| @@ -1,47 +0,0 @@ | ||||
| package types | ||||
|  | ||||
| import ( | ||||
| 	"database/sql/driver" | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| ) | ||||
|  | ||||
| // JSONLabels is a wrapper type to support JSONB database operations. | ||||
| // Add a JSONLabels type to a class field and use it with a JSONB column | ||||
| type JSONLabels map[string]string | ||||
|  | ||||
| // Unmarshal unmarshal's the json in j to v, as in json.Unmarshal. | ||||
| func (l *JSONLabels) Unmarshal(v interface{}) error { | ||||
| 	if len(*l) == 0 { | ||||
| 		*l = make(map[string]string) | ||||
| 	} | ||||
| 	v = l | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Value returns j as a value.  This does a validating unmarshal into another | ||||
| // RawMessage.  If j is invalid json, it returns an error. | ||||
| func (l JSONLabels) Value() (driver.Value, error) { | ||||
| 	return json.Marshal(l) | ||||
| } | ||||
|  | ||||
| // Scan stores the src in *j.  No validation is done. | ||||
| func (l *JSONLabels) Scan(src interface{}) error { | ||||
| 	var source []byte | ||||
| 	switch t := src.(type) { | ||||
| 	case string: | ||||
| 		source = []byte(t) | ||||
| 	case []byte: | ||||
| 		if len(t) == 0 { | ||||
| 			source = []byte("{}") | ||||
| 		} else { | ||||
| 			source = t | ||||
| 		} | ||||
| 	case nil: | ||||
| 		*l = make(map[string]string) | ||||
| 	default: | ||||
| 		return errors.New("incompatible type for JSONLabels") | ||||
| 	} | ||||
|  | ||||
| 	return json.Unmarshal(source, l) | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,99 +0,0 @@ | ||||
| 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,8 +3,6 @@ package v1 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" | ||||
| 	"github.com/onepanelio/core/pkg/util/types" | ||||
| 	uid2 "github.com/onepanelio/core/pkg/util/uid" | ||||
| 	"github.com/onepanelio/core/util/sql" | ||||
| 	"time" | ||||
| ) | ||||
| @@ -15,7 +13,6 @@ type WorkflowExecution struct { | ||||
| 	CreatedAt        time.Time `db:"created_at"` | ||||
| 	UID              string | ||||
| 	Name             string | ||||
| 	Namespace        string | ||||
| 	GenerateName     string | ||||
| 	Parameters       []Parameter | ||||
| 	ParametersBytes  []byte `db:"parameters"` // to load from database | ||||
| @@ -24,8 +21,7 @@ type WorkflowExecution struct { | ||||
| 	StartedAt        *time.Time        `db:"started_at"` | ||||
| 	FinishedAt       *time.Time        `db:"finished_at"` | ||||
| 	WorkflowTemplate *WorkflowTemplate `db:"workflow_template"` | ||||
| 	Labels           types.JSONLabels | ||||
| 	ArgoWorkflow     *wfv1.Workflow | ||||
| 	Labels           map[string]string | ||||
| } | ||||
|  | ||||
| // WorkflowExecutionOptions are options you have for an executing workflow | ||||
| @@ -59,18 +55,6 @@ type WorkflowExecutionStatus struct { | ||||
| 	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. | ||||
| func (we *WorkflowExecution) LoadParametersFromBytes() ([]Parameter, error) { | ||||
| 	loadedParameters := make([]Parameter, 0) | ||||
| @@ -91,20 +75,9 @@ func (we *WorkflowExecution) LoadParametersFromBytes() ([]Parameter, error) { | ||||
| 	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. | ||||
| // see formatColumnSelect | ||||
| func getWorkflowExecutionColumns(aliasAndDestination ...string) []string { | ||||
| 	columns := []string{"id", "created_at", "uid", "name", "parameters", "phase", "started_at", "finished_at", "labels"} | ||||
| 	columns := []string{"id", "created_at", "uid", "name", "parameters", "phase", "started_at", "finished_at"} | ||||
| 	return sql.FormatColumnSelect(columns, aliasAndDestination...) | ||||
| } | ||||
|   | ||||
| @@ -2,10 +2,10 @@ package v1 | ||||
|  | ||||
| import ( | ||||
| 	"database/sql" | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"github.com/onepanelio/core/pkg/util/pagination" | ||||
| 	uid2 "github.com/onepanelio/core/pkg/util/uid" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| @@ -21,120 +21,26 @@ import ( | ||||
| 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| ) | ||||
|  | ||||
| // WorkflowTemplateFilter represents the available ways we can filter WorkflowTemplates | ||||
| type WorkflowTemplateFilter struct { | ||||
| 	Labels []*Label | ||||
| } | ||||
|  | ||||
| // createWorkflowTemplateVersionDB inserts a record into workflow_template_versions using the current time accurate to nanoseconds | ||||
| // the data is returned in the resulting WorkflowTemplateVersion struct. | ||||
| func createWorkflowTemplateVersionDB(runner sq.BaseRunner, workflowTemplateVersion *WorkflowTemplateVersion, parameters []Parameter) (err error) { | ||||
| 	if workflowTemplateVersion == nil { | ||||
| 		return fmt.Errorf("workflowTemplateVersion is nil") | ||||
| 	} | ||||
| 	if workflowTemplateVersion.WorkflowTemplate == nil { | ||||
| 		return fmt.Errorf("workflowTemplateVersion.WorkflowTemplate is nil") | ||||
| 	} | ||||
| 	if workflowTemplateVersion.WorkflowTemplate.ID < 1 { | ||||
| 		return fmt.Errorf("workflowTemplateVersion.WorkflowTemplate.ID must be > 0. %v given", workflowTemplateVersion.WorkflowTemplate.ID) | ||||
| 	} | ||||
|  | ||||
| 	workflowTemplateVersion.Version = time.Now().UnixNano() | ||||
|  | ||||
| 	pj, err := json.Marshal(parameters) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if pj == nil { | ||||
| 		pj = []byte("[]") | ||||
| 	} | ||||
|  | ||||
| 	err = sb.Insert("workflow_template_versions"). | ||||
| 		SetMap(sq.Eq{ | ||||
| 			"workflow_template_id": workflowTemplateVersion.WorkflowTemplate.ID, | ||||
| 			"version":              workflowTemplateVersion.Version, | ||||
| 			"is_latest":            true, | ||||
| 			"manifest":             workflowTemplateVersion.Manifest, | ||||
| 			"parameters":           pj, | ||||
| 			"labels":               workflowTemplateVersion.Labels, | ||||
| 		}). | ||||
| 		Suffix("RETURNING id"). | ||||
| 		RunWith(runner). | ||||
| 		QueryRow(). | ||||
| 		Scan(&workflowTemplateVersion.ID) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // updateWorkflowTemplateVersionDB will update a WorkflowTemplateVersion row in the database. | ||||
| func updateWorkflowTemplateVersionDB(runner sq.BaseRunner, wtv *WorkflowTemplateVersion) (err error) { | ||||
| 	pj, err := json.Marshal(wtv.Parameters) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	_, err = sb.Update("workflow_template_versions"). | ||||
| 		SetMap(sq.Eq{ | ||||
| 			"manifest":   wtv.Manifest, | ||||
| 			"is_latest":  wtv.IsLatest, | ||||
| 			"parameters": string(pj), | ||||
| 		}). | ||||
| 		Where(sq.Eq{ | ||||
| 			"id": wtv.ID, | ||||
| 		}).RunWith(runner).Exec() | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // createLatestWorkflowTemplateVersionDB creates a new workflow template version and marks all previous versions as not latest. | ||||
| func createLatestWorkflowTemplateVersionDB(runner sq.BaseRunner, workflowTemplateVersion *WorkflowTemplateVersion) (err error) { | ||||
| 	if workflowTemplateVersion == nil { | ||||
| 		return fmt.Errorf("workflowTemplateVersion is nil") | ||||
| 	} | ||||
| 	if workflowTemplateVersion.WorkflowTemplate == nil { | ||||
| 		return fmt.Errorf("workflowTemplateVersion.WorkflowTemplate is nil") | ||||
| 	} | ||||
| 	if workflowTemplateVersion.WorkflowTemplate.ID < 1 { | ||||
| 		return fmt.Errorf("workflowTemplateVersion.WorkflowTemplate.ID must be > 0. %v given", workflowTemplateVersion.WorkflowTemplate.ID) | ||||
| 	} | ||||
|  | ||||
| 	_, err = sb.Update("workflow_template_versions"). | ||||
| 		Set("is_latest", false). | ||||
| 		Where(sq.Eq{ | ||||
| 			"workflow_template_id": workflowTemplateVersion.WorkflowTemplate.ID, | ||||
| 		}). | ||||
| 		RunWith(runner). | ||||
| 		Exec() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	params, err := ParseParametersFromManifest([]byte(workflowTemplateVersion.Manifest)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return createWorkflowTemplateVersionDB(runner, workflowTemplateVersion, params) | ||||
| } | ||||
|  | ||||
| // 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, util.NewUserError(codes.InvalidArgument, "Template name must be 30 characters or less") | ||||
| 	uid, err := uid2.GenerateUID(workflowTemplate.Name, 30) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
|  | ||||
| 	workflowTemplate.UID = uid | ||||
| 	tx, err := c.DB.Begin() | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	defer tx.Rollback() | ||||
|  | ||||
| 	versionUnix := time.Now().Unix() | ||||
|  | ||||
| 	err = sb.Insert("workflow_templates"). | ||||
| 		SetMap(sq.Eq{ | ||||
| 			"uid":       workflowTemplate.UID, | ||||
| 			"uid":       uid, | ||||
| 			"name":      workflowTemplate.Name, | ||||
| 			"namespace": namespace, | ||||
| 			"is_system": workflowTemplate.IsSystem, | ||||
| 			"labels":    workflowTemplate.Labels, | ||||
| 		}). | ||||
| 		Suffix("RETURNING id"). | ||||
| 		RunWith(tx). | ||||
| @@ -144,33 +50,33 @@ func (c *Client) createWorkflowTemplate(namespace string, workflowTemplate *Work | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
|  | ||||
| 	params, err := ParseParametersFromManifest([]byte(workflowTemplate.Manifest)) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, util.NewUserError(codes.InvalidArgument, err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	workflowTemplateVersion := &WorkflowTemplateVersion{ | ||||
| 		WorkflowTemplate: workflowTemplate, | ||||
| 		Manifest:         workflowTemplate.Manifest, | ||||
| 	} | ||||
| 	err = createWorkflowTemplateVersionDB(tx, workflowTemplateVersion, params) | ||||
| 	workflowTemplateVersion := &WorkflowTemplateVersion{} | ||||
| 	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 { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	workflowTemplate.WorkflowTemplateVersionID = workflowTemplateVersion.ID | ||||
|  | ||||
| 	// TODO remove this labels or update it to a generic version so we can update the labels table with recent data | ||||
| 	//_, err = c.InsertLabelsRunner(tx, TypeWorkflowTemplateVersion, workflowTemplateVersion.ID, workflowTemplate.Labels) | ||||
| 	//if err != nil { | ||||
| 	//	return nil, nil, err | ||||
| 	//} | ||||
| 	// | ||||
|  | ||||
| 	argoWft, err := createArgoWorkflowTemplate(workflowTemplate, workflowTemplateVersion.Version) | ||||
| 	_, err = c.InsertLabelsRunner(tx, TypeWorkflowTemplateVersion, workflowTemplateVersion.ID, workflowTemplate.Labels) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	argoWft.Labels[label.WorkflowTemplateVersionUid] = strconv.FormatInt(workflowTemplateVersion.Version, 10) | ||||
|  | ||||
| 	argoWft, err := createArgoWorkflowTemplate(workflowTemplate, versionUnix) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
|  | ||||
| 	argoWft.Labels[label.WorkflowTemplateVersionUid] = strconv.FormatInt(versionUnix, 10) | ||||
|  | ||||
| 	if workflowTemplate.Resource != nil && workflowTemplate.ResourceUID != nil { | ||||
| 		if *workflowTemplate.Resource == TypeWorkspaceTemplate { | ||||
| @@ -190,8 +96,7 @@ func (c *Client) createWorkflowTemplate(namespace string, workflowTemplate *Work | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
|  | ||||
| 	workflowTemplate.ArgoWorkflowTemplate = argoWft | ||||
| 	workflowTemplate.Version = workflowTemplateVersion.Version | ||||
| 	workflowTemplate.Version = versionUnix | ||||
|  | ||||
| 	return workflowTemplate, workflowTemplateVersion, nil | ||||
| } | ||||
| @@ -226,8 +131,6 @@ func (c *Client) countWorkflowTemplateSelectBuilder(namespace string) sq.SelectB | ||||
| 	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 { | ||||
| 	sb := sb.Select(getWorkflowTemplateVersionColumns("wtv")...). | ||||
| 		From("workflow_template_versions wtv"). | ||||
| @@ -239,21 +142,11 @@ func (c *Client) workflowTemplatesVersionSelectBuilder(namespace string) sq.Sele | ||||
| 	return sb | ||||
| } | ||||
|  | ||||
| // workflowTemplateVersionSelectBuilderAll | ||||
| func (c *Client) workflowTemplateVersionSelectBuilderAll() sq.SelectBuilder { | ||||
| 	sb := sb.Select(getWorkflowTemplateVersionColumns("wtv")...). | ||||
| 		From("workflow_template_versions wtv") | ||||
| 	return sb | ||||
| } | ||||
|  | ||||
| // 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) { | ||||
| 	workflowTemplate = &WorkflowTemplate{} | ||||
|  | ||||
| // GetWorkflowTemplateDB returns a WorkflowTemplate from the database | ||||
| func (c *Client) GetWorkflowTemplateDB(namespace, name string) (workflowTemplate *WorkflowTemplate, err error) { | ||||
| 	sb := c.workflowTemplatesSelectBuilder(namespace). | ||||
| 		Where(sq.Eq{ | ||||
| 			"wt.name":        name, | ||||
| 			"wt.is_archived": false, | ||||
| 			"name": name, | ||||
| 		}) | ||||
|  | ||||
| 	err = c.DB.Getx(workflowTemplate, sb) | ||||
| @@ -261,11 +154,9 @@ func (c *Client) getWorkflowTemplateDB(namespace, name string) (workflowTemplate | ||||
| 	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. | ||||
| func (c *Client) getWorkflowTemplateVersionDB(namespace, name, version string) (workflowTemplateVersion *WorkflowTemplateVersion, err error) { | ||||
| 	workflowTemplateVersion = &WorkflowTemplateVersion{} | ||||
|  | ||||
| func (c *Client) GetWorkflowTemplateVersionDB(namespace, name, version string) (workflowTemplateVersion *WorkflowTemplateVersion, err error) { | ||||
| 	whereMap := sq.Eq{ | ||||
| 		"wt.name": name, | ||||
| 	} | ||||
| @@ -281,21 +172,12 @@ func (c *Client) getWorkflowTemplateVersionDB(namespace, name, version string) ( | ||||
|  | ||||
| 	err = c.DB.Getx(workflowTemplateVersion, sb) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	workflowTemplateVersion.Parameters = make([]Parameter, 0) | ||||
| 	if err := json.Unmarshal(workflowTemplateVersion.ParametersBytes, &workflowTemplateVersion.Parameters); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // GetLatestWorkflowTemplateVersionDB returns the latest WorkflowTemplateVersion | ||||
| func (c *Client) getLatestWorkflowTemplateVersionDB(namespace, name string) (workflowTemplateVersion *WorkflowTemplateVersion, err error) { | ||||
| 	return c.getWorkflowTemplateVersionDB(namespace, name, "latest") | ||||
| func (c *Client) GetLatestWorkflowTemplateVersionDB(namespace, name string) (workflowTemplateVersion *WorkflowTemplateVersion, err error) { | ||||
| 	return c.GetWorkflowTemplateVersionDB(namespace, name, "latest") | ||||
| } | ||||
|  | ||||
| func (c *Client) getWorkflowTemplateById(id uint64) (workflowTemplate *WorkflowTemplate, err error) { | ||||
| @@ -315,16 +197,13 @@ func (c *Client) getWorkflowTemplateById(id uint64) (workflowTemplate *WorkflowT | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // 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 | ||||
| // If version is 0, the latest workflow template is fetched. | ||||
| func (c *Client) getWorkflowTemplate(namespace, uid string, version int64) (workflowTemplate *WorkflowTemplate, err error) { | ||||
| 	workflowTemplate = &WorkflowTemplate{ | ||||
| 		WorkflowExecutionStatisticReport: &WorkflowExecutionStatisticReport{}, | ||||
| 	} | ||||
|  | ||||
| 	// A new workflow template version is created upon a change, so we use it's created_at | ||||
| 	// A new workflow template version is created upon a change, so we use it's createdAt | ||||
| 	// as a modified_at for the workflow template. | ||||
| 	sb := c.workflowTemplatesSelectBuilder(namespace). | ||||
| 		Columns("wtv.manifest", "wtv.version", "wtv.id workflow_template_version_id", "wtv.created_at modified_at"). | ||||
| @@ -334,7 +213,7 @@ func (c *Client) getWorkflowTemplate(namespace, uid string, version int64) (work | ||||
| 			"wt.is_archived": false, | ||||
| 		}) | ||||
|  | ||||
| 	if version <= 0 { | ||||
| 	if version == 0 { | ||||
| 		sb = sb.Where(sq.Eq{"wtv.is_latest": true}) | ||||
| 	} else { | ||||
| 		sb = sb.Where(sq.Eq{"wtv.version": version}) | ||||
| @@ -366,23 +245,34 @@ func (c *Client) getWorkflowTemplate(namespace, uid string, version int64) (work | ||||
|  | ||||
| 	workflowTemplate.Version = templateVersion | ||||
|  | ||||
| 	wtv, err := c.getWorkflowTemplateVersionDB(namespace, workflowTemplate.Name, versionAsString) | ||||
| 	labelsMap, err := c.GetDBLabelsMapped(TypeWorkflowTemplateVersion, workflowTemplate.WorkflowTemplateVersionID) | ||||
| 	if err != nil { | ||||
| 		return workflowTemplate, err | ||||
| 	} | ||||
|  | ||||
| 	workflowTemplate.Parameters = wtv.Parameters | ||||
| 	workflowTemplate.Labels = labelsMap[workflowTemplate.WorkflowTemplateVersionID] | ||||
|  | ||||
| 	return workflowTemplate, nil | ||||
| } | ||||
|  | ||||
| // listWorkflowTemplateVersions grabs WorkflowTemplateVersions and returns them as WorkflowTemplates. | ||||
| func (c *Client) listWorkflowTemplateVersions(namespace, uid string) (workflowTemplateVersions []*WorkflowTemplate, err error) { | ||||
| 	dbVersions, err := c.selectWorkflowTemplateVersionsDB(namespace, uid) | ||||
| 	dbVersions, err := c.listDBWorkflowTemplateVersions(namespace, uid) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	labelsMap, err := c.GetDBLabelsMapped(TypeWorkflowTemplateVersion, WorkflowTemplateVersionsToIDs(dbVersions)...) | ||||
| 	if err != nil { | ||||
| 		log.WithFields(log.Fields{ | ||||
| 			"Namespace": namespace, | ||||
| 			"Error":     err.Error(), | ||||
| 		}).Error("Unable to get Workflow Template Version Labels") | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	for _, version := range dbVersions { | ||||
| 		version.Labels = labelsMap[version.ID] | ||||
|  | ||||
| 		newItem := WorkflowTemplate{ | ||||
| 			ID:         version.WorkflowTemplate.ID, | ||||
| 			CreatedAt:  version.CreatedAt.UTC(), | ||||
| @@ -401,74 +291,40 @@ func (c *Client) listWorkflowTemplateVersions(namespace, uid string) (workflowTe | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (c *Client) selectWorkflowTemplatesQuery(namespace string, paginator *pagination.PaginationRequest, filter *WorkflowTemplateFilter) (sb sq.SelectBuilder) { | ||||
| 	sb = c.workflowTemplatesSelectBuilder(namespace). | ||||
| func (c *Client) listWorkflowTemplates(namespace string, paginator *pagination.PaginationRequest) (workflowTemplateVersions []*WorkflowTemplate, err error) { | ||||
| 	workflowTemplateVersions = []*WorkflowTemplate{} | ||||
|  | ||||
| 	sb := c.workflowTemplatesSelectBuilder(namespace). | ||||
| 		Column("COUNT(wtv.*) versions, MAX(wtv.id) workflow_template_version_id"). | ||||
| 		Join("workflow_template_versions wtv ON wtv.workflow_template_id = wt.id"). | ||||
| 		GroupBy("wt.id", "wt.created_at", "wt.uid", "wt.name", "wt.is_archived"). | ||||
| 		OrderBy("wt.created_at DESC") | ||||
|  | ||||
| 	if filter != nil && len(filter.Labels) > 0 { | ||||
| 		labelsJSON, err := LabelsToJSONString(filter.Labels) | ||||
| 		if err != nil { | ||||
| 			log.Printf("[error] %v", err) | ||||
| 		} else { | ||||
| 			sb = sb.Where("wt.labels @> ?", labelsJSON) | ||||
| 		} | ||||
| 	} | ||||
| 	sb = *paginator.ApplyToSelect(&sb) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // selectWorkflowTemplatesDB loads non-archived and non-system workflow templates from the database for the input namespace | ||||
| // it also selects the total number of versions and latest version id | ||||
| func (c *Client) selectWorkflowTemplatesDB(namespace string, paginator *pagination.PaginationRequest, filter *WorkflowTemplateFilter) (workflowTemplates []*WorkflowTemplate, err error) { | ||||
| 	workflowTemplates = make([]*WorkflowTemplate, 0) | ||||
|  | ||||
| 	sb := c.selectWorkflowTemplatesQuery(namespace, paginator, filter). | ||||
| 		Where(sq.Eq{ | ||||
| 			"wt.is_archived": false, | ||||
| 			"wt.is_system":   false, | ||||
| 		}) | ||||
| 		}). | ||||
| 		OrderBy("wt.created_at DESC") | ||||
|  | ||||
| 	err = c.DB.Selectx(&workflowTemplates, sb) | ||||
| 	sb = *paginator.ApplyToSelect(&sb) | ||||
| 	query, args, err := sb.ToSql() | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	err = c.DB.Select(&workflowTemplateVersions, query, args...) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // selectAllWorkflowTemplatesDB loads all workflow templates from the database for the input namespace | ||||
| // it also selects the total number of versions and latest version id | ||||
| func (c *Client) selectAllWorkflowTemplatesDB(namespace string, paginator *pagination.PaginationRequest, filter *WorkflowTemplateFilter) (workflowTemplates []*WorkflowTemplate, err error) { | ||||
| 	workflowTemplates = make([]*WorkflowTemplate, 0) | ||||
|  | ||||
| 	sb := c.selectWorkflowTemplatesQuery(namespace, paginator, filter) | ||||
| 	err = c.DB.Selectx(&workflowTemplates, sb) | ||||
|  | ||||
| 	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, filter *WorkflowTemplateFilter) (count int, err error) { | ||||
| 	sb := sb.Select("COUNT(*)"). | ||||
| func (c *Client) CountWorkflowTemplates(namespace string) (count int, err error) { | ||||
| 	err = sb.Select("COUNT( DISTINCT( wt.id ))"). | ||||
| 		From("workflow_templates wt"). | ||||
| 		Join("workflow_template_versions wtv ON wtv.workflow_template_id = wt.id"). | ||||
| 		Where(sq.Eq{ | ||||
| 			"wt.namespace":   namespace, | ||||
| 			"wt.is_archived": false, | ||||
| 			"wt.is_system":   false, | ||||
| 		}) | ||||
|  | ||||
| 	if filter != nil && len(filter.Labels) > 0 { | ||||
| 		labelsJSON, err := LabelsToJSONString(filter.Labels) | ||||
| 		if err != nil { | ||||
| 			log.Printf("[error] %v", err) | ||||
| 		} else { | ||||
| 			sb = sb.Where("wt.labels @> ?", labelsJSON) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	err = sb.RunWith(c.DB). | ||||
| 		}). | ||||
| 		RunWith(c.DB.DB). | ||||
| 		QueryRow(). | ||||
| 		Scan(&count) | ||||
|  | ||||
| @@ -512,11 +368,6 @@ func (c *Client) CreateWorkflowTemplate(namespace string, workflowTemplate *Work | ||||
| 	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) { | ||||
| 	if workflowTemplate.UID == "" { | ||||
| 		return nil, fmt.Errorf("uid required for CreateWorkflowTemplateVersion") | ||||
| @@ -527,6 +378,8 @@ func (c *Client) CreateWorkflowTemplateVersion(namespace string, workflowTemplat | ||||
| 		return nil, util.NewUserError(codes.InvalidArgument, err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	versionUnix := time.Now().Unix() | ||||
|  | ||||
| 	tx, err := c.DB.Begin() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -538,32 +391,75 @@ func (c *Client) CreateWorkflowTemplateVersion(namespace string, workflowTemplat | ||||
| 			"wt.uid":         workflowTemplate.UID, | ||||
| 			"wt.is_archived": false, | ||||
| 		}) | ||||
| 	workflowTemplateDB := &WorkflowTemplate{} | ||||
| 	if err = c.DB.Getx(workflowTemplateDB, wftSb); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	workflowTemplateVersion := &WorkflowTemplateVersion{ | ||||
| 		WorkflowTemplate: workflowTemplateDB, | ||||
| 		Manifest:         workflowTemplate.Manifest, | ||||
| 		Labels:           workflowTemplate.Labels, | ||||
| 	} | ||||
|  | ||||
| 	err = createLatestWorkflowTemplateVersionDB(tx, workflowTemplateVersion) | ||||
| 	query, args, err := wftSb.ToSql() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	workflowTemplate.WorkflowTemplateVersionID = workflowTemplateVersion.ID | ||||
| 	workflowTemplateDb := &WorkflowTemplate{} | ||||
| 	if err = c.DB.Get(workflowTemplateDb, query, args...); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	updatedTemplate, err := createArgoWorkflowTemplate(workflowTemplate, workflowTemplateVersion.Version) | ||||
| 	_, err = sb.Update("workflow_template_versions"). | ||||
| 		Set("is_latest", false). | ||||
| 		Where(sq.Eq{ | ||||
| 			"workflow_template_id": workflowTemplateDb.ID, | ||||
| 		}). | ||||
| 		RunWith(tx). | ||||
| 		Exec() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	workflowTemplateVersionID := uint64(0) | ||||
| 	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 { | ||||
| 		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.ObjectMeta.ResourceVersion = "" | ||||
| 	updatedTemplate.ObjectMeta.SetSelfLink("") | ||||
| 	updatedTemplate.Labels[label.WorkflowTemplateVersionUid] = strconv.FormatInt(workflowTemplateVersion.Version, 10) | ||||
| 	updatedTemplate.Labels[label.WorkflowTemplateVersionUid] = strconv.FormatInt(versionUnix, 10) | ||||
|  | ||||
| 	parametersMap, err := workflowTemplate.GetParametersKeyString() | ||||
| 	if err != nil { | ||||
| @@ -577,59 +473,19 @@ func (c *Client) CreateWorkflowTemplateVersion(namespace string, workflowTemplat | ||||
| 		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 { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	latest, err = c.ArgoprojV1alpha1().WorkflowTemplates(namespace).Update(latest) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// Make sure the associated workflow template has the latest labels | ||||
| 	_, err = sb.Update("workflow_templates"). | ||||
| 		Set("labels", workflowTemplate.Labels). | ||||
| 		Where(sq.Eq{ | ||||
| 			"id": workflowTemplateDB.ID, | ||||
| 		}). | ||||
| 		RunWith(tx). | ||||
| 		Exec() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if err := tx.Commit(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	workflowTemplate.ID = workflowTemplateDB.ID | ||||
| 	workflowTemplate.Version = workflowTemplateVersion.Version | ||||
| 	workflowTemplate.Version = versionUnix | ||||
|  | ||||
| 	return workflowTemplate, nil | ||||
| } | ||||
|  | ||||
| // UpdateWorkflowTemplateVersion will update a given WorkflowTemplateVersion in the database. | ||||
| // The intent is to change specific database values for a WorkflowTemplateVersion. | ||||
| // - wtv.ID has to be set and greater than 0 | ||||
| func (c *Client) UpdateWorkflowTemplateVersion(wtv *WorkflowTemplateVersion) error { | ||||
| 	if wtv.ID <= 0 { | ||||
| 		return fmt.Errorf("id required for UpdateWorkflowTemplateVersionDB") | ||||
| 	} | ||||
| 	return updateWorkflowTemplateVersionDB(c.DB, wtv) | ||||
| } | ||||
|  | ||||
| // GetWorkflowTemplate returns a WorkflowTemplate with data loaded from various sources | ||||
| // If version is 0, it returns the latest version data. | ||||
| // | ||||
| @@ -693,7 +549,6 @@ func (c *Client) CountWorkflowTemplateVersions(namespace, uid string) (count uin | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // ListWorkflowTemplateVersions returns all the WorkflowTemplates for a given namespace and uid. | ||||
| func (c *Client) ListWorkflowTemplateVersions(namespace, uid string) (workflowTemplateVersions []*WorkflowTemplate, err error) { | ||||
| 	workflowTemplateVersions, err = c.listWorkflowTemplateVersions(namespace, uid) | ||||
| 	if err != nil { | ||||
| @@ -708,38 +563,8 @@ func (c *Client) ListWorkflowTemplateVersions(namespace, uid string) (workflowTe | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // ListWorkflowTemplateVersionsModels returns all the WorkflowTemplateVersions from the database. | ||||
| // This function is a work-around for ListWorkflowTemplateVersions. Once that function is refactored, | ||||
| // this function should no longer be necessary and removed. | ||||
| // See: https://github.com/onepanelio/core/issues/436 | ||||
| func (c *Client) ListWorkflowTemplateVersionsModels(namespace, uid string) (workflowTemplateVersions []*WorkflowTemplateVersion, err error) { | ||||
| 	workflowTemplateVersions, err = c.selectWorkflowTemplateVersionsDB(namespace, uid) | ||||
| 	if err != nil { | ||||
| 		log.WithFields(log.Fields{ | ||||
| 			"Namespace": namespace, | ||||
| 			"UID":       uid, | ||||
| 			"Error":     err.Error(), | ||||
| 		}).Error("Workflow template versions not found.") | ||||
| 		return nil, util.NewUserError(codes.NotFound, "Workflow template versions not found.") | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // ListWorkflowTemplateVersionsAll returns all WorkflowTemplateVersions with no filtering. | ||||
| func (c *Client) ListWorkflowTemplateVersionsAll(paginator *pagination.PaginationRequest) (workflowTemplateVersions []*WorkflowTemplateVersion, err error) { | ||||
| 	workflowTemplateVersions, err = c.selectAllWorkflowTemplateVersionsDB(paginator) | ||||
| 	if err != nil { | ||||
| 		log.WithFields(log.Fields{ | ||||
| 			"Error": err.Error(), | ||||
| 		}).Error("Workflow template versions not found.") | ||||
| 		return nil, util.NewUserError(codes.NotFound, "Workflow template versions not found.") | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // ListAllWorkflowTemplates lists all of the workflow templates, including archived and system specific | ||||
| func (c *Client) ListAllWorkflowTemplates(namespace string, paginator *pagination.PaginationRequest, filter *WorkflowTemplateFilter) (workflowTemplateVersions []*WorkflowTemplate, err error) { | ||||
| 	workflowTemplateVersions, err = c.selectAllWorkflowTemplatesDB(namespace, paginator, filter) | ||||
| func (c *Client) ListWorkflowTemplates(namespace string, paginator *pagination.PaginationRequest) (workflowTemplateVersions []*WorkflowTemplate, err error) { | ||||
| 	workflowTemplateVersions, err = c.listWorkflowTemplates(namespace, paginator) | ||||
| 	if err != nil { | ||||
| 		log.WithFields(log.Fields{ | ||||
| 			"Namespace": namespace, | ||||
| @@ -748,38 +573,13 @@ func (c *Client) ListAllWorkflowTemplates(namespace string, paginator *paginatio | ||||
| 		return nil, util.NewUserError(codes.NotFound, "Workflow templates not found.") | ||||
| 	} | ||||
|  | ||||
| 	err = c.appendExtraWorkflowTemplateData(namespace, workflowTemplateVersions) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // ListWorkflowTemplates returns all WorkflowTemplates where the results | ||||
| // are filtered by is_archived and is_System is false. | ||||
| func (c *Client) ListWorkflowTemplates(namespace string, paginator *pagination.PaginationRequest, filter *WorkflowTemplateFilter) (workflowTemplateVersions []*WorkflowTemplate, err error) { | ||||
| 	workflowTemplateVersions, err = c.selectWorkflowTemplatesDB(namespace, paginator, filter) | ||||
| 	if err != nil { | ||||
| 		log.WithFields(log.Fields{ | ||||
| 			"Namespace": namespace, | ||||
| 			"Error":     err.Error(), | ||||
| 		}).Error("Workflow templates not found.") | ||||
| 		return nil, util.NewUserError(codes.NotFound, "Workflow templates not found.") | ||||
| 	} | ||||
|  | ||||
| 	err = c.appendExtraWorkflowTemplateData(namespace, workflowTemplateVersions) | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // appendExtraWorkflowTemplateData adds extra information to workflow templates | ||||
| // * execution statistics (including cron) | ||||
| func (c *Client) appendExtraWorkflowTemplateData(namespace string, workflowTemplateVersions []*WorkflowTemplate) (err error) { | ||||
| 	err = c.GetWorkflowExecutionStatisticsForTemplates(workflowTemplateVersions...) | ||||
| 	if err != nil { | ||||
| 		log.WithFields(log.Fields{ | ||||
| 			"Namespace": namespace, | ||||
| 			"Error":     err.Error(), | ||||
| 		}).Error("Unable to get Workflow Execution Statistic for Templates.") | ||||
| 		return util.NewUserError(codes.NotFound, "Unable to get Workflow Execution Statistic for Templates.") | ||||
| 		return nil, util.NewUserError(codes.NotFound, "Unable to get Workflow Execution Statistic for Templates.") | ||||
| 	} | ||||
|  | ||||
| 	err = c.GetCronWorkflowStatisticsForTemplates(workflowTemplateVersions...) | ||||
| @@ -788,7 +588,20 @@ func (c *Client) appendExtraWorkflowTemplateData(namespace string, workflowTempl | ||||
| 			"Namespace": namespace, | ||||
| 			"Error":     err.Error(), | ||||
| 		}).Error("Unable to get Cron Workflow Statistic for Templates.") | ||||
| 		return util.NewUserError(codes.NotFound, "Unable to get Cron Workflow Statistic for Templates.") | ||||
| 		return nil, util.NewUserError(codes.NotFound, "Unable to get Cron Workflow Statistic for Templates.") | ||||
| 	} | ||||
|  | ||||
| 	labelsMap, err := c.GetDBLabelsMapped(TypeWorkflowTemplateVersion, WorkflowTemplatesToVersionIDs(workflowTemplateVersions)...) | ||||
| 	if err != nil { | ||||
| 		log.WithFields(log.Fields{ | ||||
| 			"Namespace": namespace, | ||||
| 			"Error":     err.Error(), | ||||
| 		}).Error("Unable to get Workflow Template Labels") | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	for _, workflowTemplate := range workflowTemplateVersions { | ||||
| 		workflowTemplate.Labels = labelsMap[workflowTemplate.WorkflowTemplateVersionID] | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| @@ -909,8 +722,6 @@ func (c *Client) ArchiveWorkflowTemplate(namespace, uid string) (archived bool, | ||||
| 	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) { | ||||
| 	var argoWft *v1alpha1.WorkflowTemplate | ||||
| 	var jsonOpts []argojson.JSONOpt | ||||
| @@ -926,14 +737,15 @@ func createArgoWorkflowTemplate(workflowTemplate *WorkflowTemplate, version int6 | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	if err := workflowTemplate.GenerateUID(workflowTemplate.Name); err != nil { | ||||
| 	worfklowTemplateName, err := uid2.GenerateUID(workflowTemplate.Name, 30) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	argoWft.Name = fmt.Sprintf("%v-v%v", workflowTemplate.UID, version) | ||||
| 	argoWft.Name = fmt.Sprintf("%v-v%v", worfklowTemplateName, version) | ||||
|  | ||||
| 	labels := map[string]string{ | ||||
| 		label.WorkflowTemplate:    workflowTemplate.UID, | ||||
| 		label.WorkflowTemplate:    worfklowTemplateName, | ||||
| 		label.WorkflowTemplateUid: workflowTemplate.UID, | ||||
| 		label.Version:             fmt.Sprintf("%v", version), | ||||
| 		label.VersionLatest:       "true", | ||||
| @@ -945,10 +757,9 @@ func createArgoWorkflowTemplate(workflowTemplate *WorkflowTemplate, version int6 | ||||
| 	return argoWft, nil | ||||
| } | ||||
|  | ||||
| // getArgoWorkflowTemplate will load the argo workflow template. | ||||
| // version "latest" will get the latest version, otherwise a number (as a string) will be used. | ||||
| func (c *Client) getArgoWorkflowTemplate(namespace, workflowTemplateUID, version string) (*v1alpha1.WorkflowTemplate, error) { | ||||
| 	labelSelect := fmt.Sprintf("%v=%v", label.WorkflowTemplateUid, workflowTemplateUID) | ||||
| // version "latest" will get the latest version. | ||||
| func (c *Client) getArgoWorkflowTemplate(namespace, workflowTemplateUid, version string) (*v1alpha1.WorkflowTemplate, error) { | ||||
| 	labelSelect := fmt.Sprintf("%v=%v", label.WorkflowTemplateUid, workflowTemplateUid) | ||||
| 	if version == "latest" { | ||||
| 		labelSelect += "," + label.VersionLatest + "=true" | ||||
| 	} else { | ||||
| @@ -988,33 +799,28 @@ func (c *Client) listArgoWorkflowTemplates(namespace, workflowTemplateUid string | ||||
| 	return &templates, nil | ||||
| } | ||||
|  | ||||
| // listDBWorkflowTemplateVersions gets all of the workflow template versions for a specified workflow template uid | ||||
| // 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) | ||||
| func (c *Client) listDBWorkflowTemplateVersions(namespace, workflowTemplateUID string) ([]*WorkflowTemplateVersion, error) { | ||||
| 	versions := make([]*WorkflowTemplateVersion, 0) | ||||
|  | ||||
| 	sb := c.workflowTemplatesVersionSelectBuilder(namespace). | ||||
| 		Columns(getWorkflowTemplateColumns("wt", "workflow_template")...). | ||||
| 		Columns(`wt.id "workflow_template.id"`, `wt.created_at "workflow_template.created_at"`). | ||||
| 		Columns(`wt.name "workflow_template.name"`, `wt.is_archived "workflow_template.is_archived"`). | ||||
| 		Where(sq.Eq{ | ||||
| 			"wt.uid":         workflowTemplateUID, | ||||
| 			"wt.is_archived": false, | ||||
| 		}). | ||||
| 		OrderBy("wtv.created_at DESC") | ||||
|  | ||||
| 	err = c.DB.Selectx(&versions, sb) | ||||
| 	query, args, err := sb.ToSql() | ||||
| 	if err != nil { | ||||
| 		return versions, err | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
| 	if err := c.DB.Select(&versions, query, args...); err != nil { | ||||
| 		return versions, err | ||||
| 	} | ||||
|  | ||||
| // selectAllWorkflowTemplateVersionsDB returns all WorkflowTemplateVersions from the database without filter. | ||||
| func (c *Client) selectAllWorkflowTemplateVersionsDB(paginator *pagination.PaginationRequest) (versions []*WorkflowTemplateVersion, err error) { | ||||
| 	versions = make([]*WorkflowTemplateVersion, 0) | ||||
|  | ||||
| 	sb := c.workflowTemplateVersionSelectBuilderAll() | ||||
| 	sb = *paginator.ApplyToSelect(&sb) | ||||
| 	err = c.DB.Selectx(&versions, sb) | ||||
|  | ||||
| 	return | ||||
| 	return versions, nil | ||||
| } | ||||
|  | ||||
| // prefix is the label prefix. | ||||
|   | ||||
| @@ -1,345 +0,0 @@ | ||||
| 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,8 +4,6 @@ import ( | ||||
| 	"encoding/json" | ||||
| 	wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" | ||||
| 	"github.com/onepanelio/core/pkg/util/mapping" | ||||
| 	"github.com/onepanelio/core/pkg/util/types" | ||||
| 	uid2 "github.com/onepanelio/core/pkg/util/uid" | ||||
| 	"github.com/onepanelio/core/util/sql" | ||||
| 	log "github.com/sirupsen/logrus" | ||||
| 	"gopkg.in/yaml.v2" | ||||
| @@ -15,9 +13,6 @@ import ( | ||||
|  | ||||
| // WorkflowTemplate represents a Workflow Template backed by a database row | ||||
| // 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 { | ||||
| 	ID                               uint64 | ||||
| 	CreatedAt                        time.Time  `db:"created_at"` | ||||
| @@ -32,25 +27,12 @@ type WorkflowTemplate struct { | ||||
| 	IsArchived                       bool `db:"is_archived"` | ||||
| 	IsSystem                         bool `db:"is_system"` | ||||
| 	ArgoWorkflowTemplate             *wfv1.WorkflowTemplate | ||||
| 	Labels                           types.JSONLabels | ||||
| 	Labels                           map[string]string | ||||
| 	WorkflowExecutionStatisticReport *WorkflowExecutionStatisticReport | ||||
| 	CronWorkflowsStatisticsReport    *CronWorkflowStatisticReport | ||||
| 	WorkflowTemplateVersionID        uint64  `db:"workflow_template_version_id"` // Reference to the associated workflow template version. | ||||
| 	Resource                         *string // utility in case we are specifying a workflow template for a specific resource | ||||
| 	ResourceUID                      *string // see Resource field | ||||
| 	Parameters                       []Parameter | ||||
| } | ||||
|  | ||||
| // 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 | ||||
| @@ -275,6 +257,6 @@ func (wt *WorkflowTemplate) AddWorkflowTemplateParametersFromAnnotations(spec ma | ||||
| // getWorkflowTemplateColumns returns all of the columns for workflowTemplate modified by alias, destination. | ||||
| // see formatColumnSelect | ||||
| func getWorkflowTemplateColumns(aliasAndDestination ...string) []string { | ||||
| 	columns := []string{"id", "created_at", "uid", "name", "namespace", "modified_at", "is_archived", "labels"} | ||||
| 	columns := []string{"id", "created_at", "uid", "name", "namespace", "modified_at", "is_archived"} | ||||
| 	return sql.FormatColumnSelect(columns, aliasAndDestination...) | ||||
| } | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user