From 243d055d8f525c5a1437bd43ff8ef2af0b34520b Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Fri, 21 Feb 2020 14:33:14 -0800 Subject: [PATCH 01/43] Move PHP executor to its own package --- ProcessMaker/ScriptRunners/PhpRunner.php | 22 --------- composer.json | 1 + composer.lock | 60 +++++++++++++++++------- config/script-runners.php | 7 --- 4 files changed, 45 insertions(+), 45 deletions(-) delete mode 100644 ProcessMaker/ScriptRunners/PhpRunner.php diff --git a/ProcessMaker/ScriptRunners/PhpRunner.php b/ProcessMaker/ScriptRunners/PhpRunner.php deleted file mode 100644 index 278a69403c..0000000000 --- a/ProcessMaker/ScriptRunners/PhpRunner.php +++ /dev/null @@ -1,22 +0,0 @@ - [ - 'name' => 'PHP', - 'runner' => 'PhpRunner', - 'mime_type' => 'application/x-php', - 'image' => env('SCRIPTS_PHP_IMAGE', 'processmaker4/executor-php'), - 'options' => ['invokerPackage' => "ProcessMaker\\Client"] - ], 'lua' => [ 'name' => 'Lua', 'runner' => 'LuaRunner', From 86add601758044abc03a51151d6a8537aa300971 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Fri, 21 Feb 2020 16:15:19 -0800 Subject: [PATCH 02/43] Add frontend resources to update user-editable dockerfile --- .../Admin/ScriptExecutorController.php | 14 +++++ .../Api/ScriptExecutorController.php | 51 +++++++++++++++++++ .../script-executors/ScriptExecutors.vue | 16 ++++++ resources/js/admin/script-executors/index.js | 6 +++ .../admin/script-executors/index.blade.php | 26 ++++++++++ routes/api.php | 4 ++ routes/web.php | 2 + tests/Feature/Api/ScriptExecutorTest.php | 42 +++++++++++++++ webpack.mix.js | 1 + 9 files changed, 162 insertions(+) create mode 100644 ProcessMaker/Http/Controllers/Admin/ScriptExecutorController.php create mode 100644 ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php create mode 100644 resources/js/admin/script-executors/ScriptExecutors.vue create mode 100644 resources/js/admin/script-executors/index.js create mode 100644 resources/views/admin/script-executors/index.blade.php create mode 100644 tests/Feature/Api/ScriptExecutorTest.php diff --git a/ProcessMaker/Http/Controllers/Admin/ScriptExecutorController.php b/ProcessMaker/Http/Controllers/Admin/ScriptExecutorController.php new file mode 100644 index 0000000000..671cb9b9ba --- /dev/null +++ b/ProcessMaker/Http/Controllers/Admin/ScriptExecutorController.php @@ -0,0 +1,14 @@ +checkAuth($request); + + $languages = []; + foreach (config('script-runners') as $key => $config) { + $userDockerfileContents = ''; + + $userDockerfilePath = storage_path("docker-build-config/Dockerfile-${key}"); + if (file_exists($userDockerfilePath)) { + $userDockerfileContents .= file_get_contents($userDockerfilePath); + } + + $languages[$key] = [ + 'userDockerfileContents' => $userDockerfileContents + ]; + } + + return ['languages' => $languages]; + } + + public function update(Request $request, $language) + { + $this->checkAuth($request); + if (!isset(config('script-runners')[$language])) { + throw new ModelNotFoundException; + } + + $userDockerfilePath = storage_path("docker-build-config/Dockerfile-${language}"); + + file_put_contents($userDockerfilePath, $request->input('userDockerfileContents')); + } + + private function checkAuth($request) + { + if (!$request->user()->is_administrator) { + throw new AuthorizationException; + } + } +} diff --git a/resources/js/admin/script-executors/ScriptExecutors.vue b/resources/js/admin/script-executors/ScriptExecutors.vue new file mode 100644 index 0000000000..4712c2d4c4 --- /dev/null +++ b/resources/js/admin/script-executors/ScriptExecutors.vue @@ -0,0 +1,16 @@ + + + \ No newline at end of file diff --git a/resources/js/admin/script-executors/index.js b/resources/js/admin/script-executors/index.js new file mode 100644 index 0000000000..437eb466eb --- /dev/null +++ b/resources/js/admin/script-executors/index.js @@ -0,0 +1,6 @@ +import ScriptExecutors from './ScriptExecutors'; + +new Vue({ + el: '#script-executors', + components: { ScriptExecutors }, +}); \ No newline at end of file diff --git a/resources/views/admin/script-executors/index.blade.php b/resources/views/admin/script-executors/index.blade.php new file mode 100644 index 0000000000..fd7b16c16c --- /dev/null +++ b/resources/views/admin/script-executors/index.blade.php @@ -0,0 +1,26 @@ +@extends('layouts.layout') + +@section('title') + {{ __('Script Executors') }} +@endsection + +@section('sidebar') + @include('layouts.sidebar', ['sidebar'=> Menu::get('sidebar_admin')]) +@endsection + +@section('breadcrumbs') + @include('shared.breadcrumbs', ['routes' => [ + __('Admin') => route('admin.index'), + __('Script Executors') => null, + ]]) +@endsection +@section('content') +
+ +
+@endsection + +@section('js') + +@endsection + diff --git a/routes/api.php b/routes/api.php index 93bdbe6cdd..67d911611c 100644 --- a/routes/api.php +++ b/routes/api.php @@ -169,6 +169,10 @@ //UI customization Route::post('customize-ui', 'CssOverrideController@store')->name('customize-ui.store'); + // Rebuild Script Executors + Route::get('script-executors', 'ScriptExecutorController@index')->name('script-executors.index'); + Route::put('script-executors/{language}', 'ScriptExecutorController@update')->name('script-executors.update'); + // debugging javascript errors Route::post('debug', 'DebugController@store')->name('debug.store')->middleware('throttle'); diff --git a/routes/web.php b/routes/web.php index 960c9178f0..f789cc1519 100644 --- a/routes/web.php +++ b/routes/web.php @@ -17,6 +17,8 @@ Route::get('auth-clients', 'AuthClientController@index')->name('auth-clients.index')->middleware('can:view-auth_clients'); Route::get('customize-ui', 'CssOverrideController@edit')->name('customize-ui.edit'); + + Route::get('script-executors', 'ScriptExecutorController@index')->name('script-executors.index'); }); Route::get('admin', 'AdminController@index')->name('admin.index'); diff --git a/tests/Feature/Api/ScriptExecutorTest.php b/tests/Feature/Api/ScriptExecutorTest.php new file mode 100644 index 0000000000..d488946c58 --- /dev/null +++ b/tests/Feature/Api/ScriptExecutorTest.php @@ -0,0 +1,42 @@ +apiCall('GET', route('api.script-executors.index')); + $result->assertStatus(200); + + $result = $result->json(); + $this->assertArrayHasKey('php', $result['languages']); + + $docker = $result['languages']['php']['userDockerfileContents']; + $this->assertEquals("Foo", $docker); + } + + public function testSetDockerfile() + { + $route = route('api.script-executors.update', ['language' => 'lua']); + $result = $this->apiCall('PUT', $route, ['userDockerfileContents' => 'Bar']); + + $result = $this->apiCall('GET', route('api.script-executors.index')); + $result = $result->json(); + $docker = $result['languages']['lua']['userDockerfileContents']; + $this->assertEquals('Bar', $docker); + } +} diff --git a/webpack.mix.js b/webpack.mix.js index cefaf82065..2223ea7bda 100644 --- a/webpack.mix.js +++ b/webpack.mix.js @@ -78,6 +78,7 @@ mix.js("resources/js/app-layout.js", "public/js") .js("resources/js/admin/queues/index.js", "public/js/admin/queues") .js("resources/js/admin/profile/edit.js", "public/js/admin/profile/edit.js") .js("resources/js/admin/cssOverride/edit.js", "public/js/admin/cssOverride/edit.js") + .js("resources/js/admin/script-executors/index.js", "public/js/admin/script-executors/index.js") .js("resources/js/processes/index.js", "public/js/processes") .js("resources/js/processes/edit.js", "public/js/processes") From a1f01c5bf03f4a63f8ebb17bb7f334d6ec7072e9 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Fri, 21 Feb 2020 16:15:33 -0800 Subject: [PATCH 03/43] Remove unused controller --- .../Controllers/Designer/ScriptController.php | 29 ------------------- 1 file changed, 29 deletions(-) delete mode 100644 ProcessMaker/Http/Controllers/Designer/ScriptController.php diff --git a/ProcessMaker/Http/Controllers/Designer/ScriptController.php b/ProcessMaker/Http/Controllers/Designer/ScriptController.php deleted file mode 100644 index 6bcbdf73d0..0000000000 --- a/ProcessMaker/Http/Controllers/Designer/ScriptController.php +++ /dev/null @@ -1,29 +0,0 @@ -id !== $script->process_id) { - request()->session()->flash('_alert', json_encode(['danger', __('The script does not belong to process.')])); - // @todo This should actually redirect to designer url - return view('designer.designer', compact('process')); - } - return view('designer.script', compact(['process', 'script'])); - } - -} \ No newline at end of file From d36daf3c670a2b44ded53a9fb474038f80d7a448 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Fri, 21 Feb 2020 16:16:11 -0800 Subject: [PATCH 04/43] Add artisan command to build executor containers --- .../Console/Commands/BuildScriptExecutors.php | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 ProcessMaker/Console/Commands/BuildScriptExecutors.php diff --git a/ProcessMaker/Console/Commands/BuildScriptExecutors.php b/ProcessMaker/Console/Commands/BuildScriptExecutors.php new file mode 100644 index 0000000000..b2f74c1e71 --- /dev/null +++ b/ProcessMaker/Console/Commands/BuildScriptExecutors.php @@ -0,0 +1,79 @@ +argument('lang'); + $this->info("Building for language: $lang"); + + $this->info("Generating SDK json document"); + \Artisan::call('l5-swagger:generate'); + + $dockerDir = sys_get_temp_dir() . "/pm4-docker-builds/${lang}"; + $sdkDir = $dockerDir . "/sdk"; + + if (!is_dir($sdkDir)) { + mkdir($sdkDir, 0755, true); + } + + $this->info("Building the SDK"); + \Artisan::call("processmaker:sdk", [ + 'language' => $lang, + 'output' => $sdkDir + ]); + + $dockerfile = ''; + $initDockerfile = config('script-runners.' . $lang . '.init_dockerfile'); + if ($initDockerfile) { + $dockerfile .= $initDockerfile; + } + $dockerfile .= "\n"; + $userDockerfilePath = storage_path("docker-build-config/Dockerfile-${lang}"); + if (file_exists($userDockerfilePath)) { + $dockerfile .= file_get_contents($userDockerfilePath); + } + + $this->info("Dockerfile:\n " . implode("\n ", explode("\n", $dockerfile))); + file_put_contents($dockerDir . '/Dockerfile', $dockerfile); + + $this->info("Building the docker executor"); + system("docker build -t processmaker4/executor-${lang}:latest ${dockerDir}"); + } +} From 4ec533893e16c13ef45a39ef363f89452483a903 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Mon, 24 Feb 2020 09:09:11 -0800 Subject: [PATCH 05/43] Add the storage folder for docker configs --- storage/api-docs/api-docs.json | 1488 +++++++++++--------- storage/docker-build-config/Dockerfile-php | 1 + 2 files changed, 822 insertions(+), 667 deletions(-) create mode 100644 storage/docker-build-config/Dockerfile-php diff --git a/storage/api-docs/api-docs.json b/storage/api-docs/api-docs.json index a679ca9ef6..f65bc95128 100644 --- a/storage/api-docs/api-docs.json +++ b/storage/api-docs/api-docs.json @@ -89,13 +89,13 @@ } } }, - "/data_sources": { + "/environment_variables": { "get": { "tags": [ - "Data Sources" + "Environment Variables" ], - "summary": "Returns all Data Sources that the user has access to", - "operationId": "getDataSources", + "summary": "Returns all environmentVariables that the user has access to", + "operationId": "getEnvironmentVariables", "parameters": [ { "$ref": "#/components/parameters/filter" @@ -115,18 +115,20 @@ ], "responses": { "200": { - "description": "list of Data Sources", + "description": "list of environmentVariables", "content": { "application/json": { "schema": { "properties": { "data": { - "description": "Get the list of records of a Data Source", + "description": "Fetch a collection of variables based on paged request and filter if provided", "type": "array", - "items": {} + "items": { + "$ref": "#/components/schemas/environment_variables" + } }, "meta": { - "description": "Get the list of records of a Data Source", + "description": "Fetch a collection of variables based on paged request and filter if provided", "type": "object", "allOf": [ { @@ -144,15 +146,17 @@ }, "post": { "tags": [ - "Data Sources" + "Environment Variables" ], - "summary": "Save a new Data Source", - "operationId": "createDataSource", + "summary": "Save a new environment_variables", + "operationId": "createEnvironmentVariables", "requestBody": { "required": true, "content": { "application/json": { - "schema": {} + "schema": { + "$ref": "#/components/schemas/create_environment_variablesEditable" + } } } }, @@ -161,25 +165,27 @@ "description": "success", "content": { "application/json": { - "schema": {} + "schema": { + "$ref": "#/components/schemas/environment_variables" + } } } } } } }, - "/data_sources/data_source_id": { + "/environment_variables/{environment_variables_id}": { "get": { "tags": [ - "Data Sources" + "Environment Variables" ], - "summary": "Get single Data Source by ID", - "operationId": "getDataSourceById", + "summary": "Get single environment_variables by ID", + "operationId": "getEnvironmentVariablesById", "parameters": [ { - "name": "data_source_id", + "name": "environment_variables_id", "in": "path", - "description": "ID of Data Source to return", + "description": "ID of environment_variables to return", "required": true, "schema": { "type": "string" @@ -188,50 +194,11 @@ ], "responses": { "200": { - "description": "Successfully found the Data Source", + "description": "Successfully found the environment variable", "content": { "application/json": { "schema": { - "properties": { - "id": { - "description": "Get a single Data Source.", - "type": "string", - "format": "id" - }, - "name": { - "description": "Get a single Data Source.", - "type": "string" - }, - "description": { - "description": "Get a single Data Source.", - "type": "string" - }, - "endpoints": { - "description": "Get a single Data Source.", - "type": "string" - }, - "mappings": { - "description": "Get a single Data Source.", - "type": "string" - }, - "authtype": { - "description": "Get a single Data Source.", - "type": "string" - }, - "credentials": { - "description": "Get a single Data Source.", - "type": "string" - }, - "status": { - "description": "Get a single Data Source.", - "type": "string" - }, - "data_source_category_id": { - "description": "Get a single Data Source.", - "type": "string" - } - }, - "type": "object" + "$ref": "#/components/schemas/environment_variables" } } } @@ -240,90 +207,15 @@ }, "put": { "tags": [ - "Data Sources" - ], - "summary": "Update a Data Source", - "operationId": "updateDataSource", - "parameters": [ - { - "name": "data_source_id", - "in": "path", - "description": "ID of Data Source to return", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": {} - } - } - }, - "responses": { - "204": { - "description": "success", - "content": { - "application/json": { - "schema": {} - } - } - } - } - }, - "delete": { - "tags": [ - "Data Sources" - ], - "summary": "Delete a Data Source", - "operationId": "deleteDataSource", - "parameters": [ - { - "name": "data_source_id", - "in": "path", - "description": "ID of Data Source to return", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "success", - "content": { - "application/json": { - "schema": {} - } - } - } - } - } - }, - "/request/{request_id}/data_source/{data_source_id}": { - "post": { - "tags": [ - "Data Sources" + "Environment Variables" ], - "summary": "execute Data Source", - "operationId": "executeDataSource", + "summary": "Update a environment_variables", + "operationId": "updateEnvironmentVariables", "parameters": [ { - "name": "request_id", - "in": "path", - "description": "ID of the request in whose context the datasource will be executed", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "data_source_id", + "name": "environment_variables_id", "in": "path", - "description": "ID of DataSource to be run", + "description": "ID of environment_variables to return", "required": true, "schema": { "type": "string" @@ -335,12 +227,7 @@ "content": { "application/json": { "schema": { - "properties": { - "config": { - "$ref": "#/components/schemas/DataSourceCallParameters" - } - }, - "type": "object" + "$ref": "#/components/schemas/environment_variablesEditable" } } } @@ -350,58 +237,52 @@ "description": "success", "content": { "application/json": { - "schema": {} + "schema": { + "$ref": "#/components/schemas/environment_variables" + } } } } } - } - }, - "/data_sources/data_source_id/test": { - "post": { + }, + "delete": { "tags": [ - "Data Sources" + "Environment Variables" ], - "summary": "Send a Data Source request", - "operationId": "sendDataSource", + "summary": "Delete a environment_variables", + "operationId": "deleteEnvironmentVariables", "parameters": [ { - "name": "data_source_id", + "name": "environment_variables_id", "in": "path", - "description": "ID of Data Source to return", + "description": "ID of environment_variables to return", "required": true, "schema": { "type": "string" } } ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": {} - } - } - }, "responses": { - "204": { + "200": { "description": "success", "content": { "application/json": { - "schema": {} + "schema": { + "$ref": "#/components/schemas/environment_variables" + } } } } } } }, - "/environment_variables": { + "/files": { "get": { "tags": [ - "Environment Variables" + "Files" ], - "summary": "Returns all environmentVariables that the user has access to", - "operationId": "getEnvironmentVariables", + "summary": "Returns the list of files", + "operationId": "getFiles", "parameters": [ { "$ref": "#/components/parameters/filter" @@ -414,27 +295,24 @@ }, { "$ref": "#/components/parameters/per_page" - }, - { - "$ref": "#/components/parameters/include" } ], "responses": { "200": { - "description": "list of environmentVariables", + "description": "list of files", "content": { "application/json": { "schema": { "properties": { "data": { - "description": "Fetch a collection of variables based on paged request and filter if provided", + "description": "Display a listing of the resource.", "type": "array", "items": { - "$ref": "#/components/schemas/environment_variables" + "$ref": "#/components/schemas/media" } }, "meta": { - "description": "Fetch a collection of variables based on paged request and filter if provided", + "description": "Display a listing of the resource.", "type": "object", "allOf": [ { @@ -452,245 +330,61 @@ }, "post": { "tags": [ - "Environment Variables" + "Files" + ], + "summary": "Save a new media file", + "operationId": "createFile", + "parameters": [ + { + "name": "model_id", + "in": "query", + "description": "ID of the model to which the file will be associated", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "model", + "in": "query", + "description": "Name of the class of the model", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "data_name", + "in": "query", + "description": "Name of the variable used in a request", + "required": false, + "schema": { + "type": "string" + } + } ], - "summary": "Save a new environment_variables", - "operationId": "createEnvironmentVariables", "requestBody": { "required": true, "content": { - "application/json": { + "multipart/form-data": { "schema": { - "$ref": "#/components/schemas/create_environment_variablesEditable" + "properties": { + "file": { + "description": "save a new media file", + "type": "file", + "items": { + "type": "string", + "format": "binary" + } + } + }, + "type": "object" } } } }, "responses": { - "201": { - "description": "success", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/environment_variables" - } - } - } - } - } - } - }, - "/environment_variables/{environment_variables_id}": { - "get": { - "tags": [ - "Environment Variables" - ], - "summary": "Get single environment_variables by ID", - "operationId": "getEnvironmentVariablesById", - "parameters": [ - { - "name": "environment_variables_id", - "in": "path", - "description": "ID of environment_variables to return", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Successfully found the environment variable", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/environment_variables" - } - } - } - } - } - }, - "put": { - "tags": [ - "Environment Variables" - ], - "summary": "Update a environment_variables", - "operationId": "updateEnvironmentVariables", - "parameters": [ - { - "name": "environment_variables_id", - "in": "path", - "description": "ID of environment_variables to return", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/environment_variablesEditable" - } - } - } - }, - "responses": { - "200": { - "description": "success", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/environment_variables" - } - } - } - } - } - }, - "delete": { - "tags": [ - "Environment Variables" - ], - "summary": "Delete a environment_variables", - "operationId": "deleteEnvironmentVariables", - "parameters": [ - { - "name": "environment_variables_id", - "in": "path", - "description": "ID of environment_variables to return", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "success", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/environment_variables" - } - } - } - } - } - } - }, - "/files": { - "get": { - "tags": [ - "Files" - ], - "summary": "Returns the list of files", - "operationId": "getFiles", - "parameters": [ - { - "$ref": "#/components/parameters/filter" - }, - { - "$ref": "#/components/parameters/order_by" - }, - { - "$ref": "#/components/parameters/order_direction" - }, - { - "$ref": "#/components/parameters/per_page" - } - ], - "responses": { - "200": { - "description": "list of files", - "content": { - "application/json": { - "schema": { - "properties": { - "data": { - "description": "Display a listing of the resource.", - "type": "array", - "items": { - "$ref": "#/components/schemas/media" - } - }, - "meta": { - "description": "Display a listing of the resource.", - "type": "object", - "allOf": [ - { - "$ref": "#/components/schemas/metadata" - } - ] - } - }, - "type": "object" - } - } - } - } - } - }, - "post": { - "tags": [ - "Files" - ], - "summary": "Save a new media file", - "operationId": "createFile", - "parameters": [ - { - "name": "model_id", - "in": "query", - "description": "ID of the model to which the file will be associated", - "required": false, - "schema": { - "type": "integer" - } - }, - { - "name": "model", - "in": "query", - "description": "Name of the class of the model", - "required": false, - "schema": { - "type": "string" - } - }, - { - "name": "data_name", - "in": "query", - "description": "Name of the variable used in a request", - "required": false, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "multipart/form-data": { - "schema": { - "properties": { - "file": { - "description": "save a new media file", - "type": "file", - "items": { - "type": "string", - "format": "binary" - } - } - }, - "type": "object" - } - } - } - }, - "responses": { - "200": { + "200": { "description": "success", "content": { "application/json": { @@ -3581,9 +3275,418 @@ "operationId": "updateScript", "parameters": [ { - "name": "script_id", + "name": "script_id", + "in": "path", + "description": "ID of script to return", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/scriptsEditable" + } + } + } + }, + "responses": { + "204": { + "description": "success" + } + } + }, + "delete": { + "tags": [ + "Scripts" + ], + "summary": "Delete a script", + "operationId": "deleteScript", + "parameters": [ + { + "name": "script_id", + "in": "path", + "description": "ID of script to return", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "success" + } + } + } + }, + "/scripts/{scripts_id}/duplicate": { + "put": { + "tags": [ + "scripts" + ], + "summary": "duplicate a script", + "operationId": "duplicateScreen", + "parameters": [ + { + "name": "scripts_id", + "in": "path", + "description": "ID of script to return", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/scriptsEditable" + } + } + } + }, + "responses": { + "201": { + "description": "success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/scripts" + } + } + } + } + } + } + }, + "/task_assignments": { + "post": { + "tags": [ + "Task Assignments" + ], + "summary": "Save a new task assignments", + "operationId": "createTaskAssignments", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/taskAssignmentsEditable" + } + } + } + }, + "responses": { + "201": { + "description": "success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/taskAssignments" + } + } + } + } + } + } + }, + "/task_assignments/{task_assignments_id}": { + "put": { + "tags": [ + "Task Assignments" + ], + "summary": "Update a task assignments", + "operationId": "updateTaskAssignments", + "parameters": [ + { + "name": "task_assignments_id", + "in": "path", + "description": "ID of task assignment to return", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/taskAssignmentsEditable" + } + } + } + }, + "responses": { + "200": { + "description": "success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/taskAssignments" + } + } + } + } + } + } + }, + "/tasks": { + "get": { + "tags": [ + "Tasks" + ], + "summary": "Returns all tasks that the user has access to", + "operationId": "getTasks", + "parameters": [ + { + "name": "process_request_id", + "in": "query", + "description": "Process request id", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "$ref": "#/components/parameters/filter" + }, + { + "$ref": "#/components/parameters/order_by" + }, + { + "$ref": "#/components/parameters/order_direction" + } + ], + "responses": { + "200": { + "description": "list of tasks", + "content": { + "application/json": { + "schema": { + "properties": { + "data": { + "description": "Display a listing of the resource.", + "type": "array", + "items": { + "$ref": "#/components/schemas/processRequestToken" + } + }, + "meta": { + "type": "object", + "$ref": "#/components/schemas/metadata" + } + }, + "type": "object" + } + } + } + } + } + } + }, + "/tasks/{task_id}": { + "get": { + "tags": [ + "Tasks" + ], + "summary": "Get a single task by ID", + "operationId": "getTasksById", + "parameters": [ + { + "name": "task_id", + "in": "path", + "description": "task id", + "required": true, + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/processRequestToken" + } + } + } + } + } + }, + "put": { + "tags": [ + "Tasks" + ], + "summary": "Update a task", + "operationId": "updateTask", + "parameters": [ + { + "name": "task_id", + "in": "path", + "description": "ID of task to update", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/processRequestTokenEditable" + } + } + } + }, + "responses": { + "200": { + "description": "success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/processRequestToken" + } + } + } + } + } + } + }, + "/users": { + "get": { + "tags": [ + "Users" + ], + "summary": "Returns all users", + "operationId": "getUsers", + "parameters": [ + { + "$ref": "#/components/parameters/filter" + }, + { + "$ref": "#/components/parameters/order_by" + }, + { + "$ref": "#/components/parameters/order_direction" + }, + { + "$ref": "#/components/parameters/per_page" + }, + { + "$ref": "#/components/parameters/include" + } + ], + "responses": { + "200": { + "description": "list of users", + "content": { + "application/json": { + "schema": { + "properties": { + "data": { + "description": "Display a listing of the resource.", + "type": "array", + "items": { + "$ref": "#/components/schemas/users" + } + }, + "meta": { + "type": "object", + "$ref": "#/components/schemas/metadata" + } + }, + "type": "object" + } + } + } + } + } + }, + "post": { + "tags": [ + "Users" + ], + "summary": "Save a new users", + "operationId": "createUser", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/usersEditable" + } + } + } + }, + "responses": { + "201": { + "description": "success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/users" + } + } + } + } + } + } + }, + "/users/{user_id}": { + "get": { + "tags": [ + "Users" + ], + "summary": "Get single user by ID", + "operationId": "getUserById", + "parameters": [ + { + "name": "user_id", + "in": "path", + "description": "ID of user to return", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successfully found the process", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/users" + } + } + } + } + } + }, + "put": { + "tags": [ + "Users" + ], + "summary": "Update a user", + "operationId": "updateUsers", + "parameters": [ + { + "name": "user_id", "in": "path", - "description": "ID of script to return", + "description": "ID of user to return", "required": true, "schema": { "type": "string" @@ -3595,28 +3698,35 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/scriptsEditable" + "$ref": "#/components/schemas/usersEditable" } } } }, "responses": { - "204": { - "description": "success" + "200": { + "description": "success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/users" + } + } + } } } }, "delete": { "tags": [ - "Scripts" + "Users" ], - "summary": "Delete a script", - "operationId": "deleteScript", + "summary": "Delete a user", + "operationId": "deleteUser", "parameters": [ { - "name": "script_id", + "name": "user_id", "in": "path", - "description": "ID of script to return", + "description": "ID of user to return", "required": true, "schema": { "type": "string" @@ -3625,23 +3735,30 @@ ], "responses": { "204": { - "description": "success" + "description": "success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/users" + } + } + } } } } }, - "/scripts/{scripts_id}/duplicate": { + "/users/{user_id}/groups": { "put": { "tags": [ - "scripts" + "Users" ], - "summary": "duplicate a script", - "operationId": "duplicateScreen", + "summary": "Update a user's groups", + "operationId": "updateUserGroups", "parameters": [ { - "name": "scripts_id", + "name": "user_id", "in": "path", - "description": "ID of script to return", + "description": "ID of user to return", "required": true, "schema": { "type": "string" @@ -3653,49 +3770,18 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/scriptsEditable" - } - } - } - }, - "responses": { - "201": { - "description": "success", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/scripts" - } - } - } - } - } - } - }, - "/task_assignments": { - "post": { - "tags": [ - "Task Assignments" - ], - "summary": "Save a new task assignments", - "operationId": "createTaskAssignments", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/taskAssignmentsEditable" + "$ref": "#/components/schemas/usersEditable" } } } }, "responses": { - "201": { + "200": { "description": "success", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/taskAssignments" + "$ref": "#/components/schemas/users" } } } @@ -3703,18 +3789,18 @@ } } }, - "/task_assignments/{task_assignments_id}": { + "/users/restore": { "put": { "tags": [ - "Task Assignments" + "Users" ], - "summary": "Update a task assignments", - "operationId": "updateTaskAssignments", + "summary": "Restore a soft deleted user", + "operationId": "restoreUser", "parameters": [ { - "name": "task_assignments_id", + "name": "user_id", "in": "path", - "description": "ID of task assignment to return", + "description": "ID of user to return", "required": true, "schema": { "type": "string" @@ -3726,7 +3812,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/taskAssignmentsEditable" + "$ref": "#/components/schemas/usersEditable" } } } @@ -3737,7 +3823,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/taskAssignments" + "$ref": "#/components/schemas/users" } } } @@ -3745,23 +3831,14 @@ } } }, - "/tasks": { + "/data_source_categories": { "get": { "tags": [ - "Tasks" + "Data Connector Categories" ], - "summary": "Returns all tasks that the user has access to", - "operationId": "getTasks", + "summary": "Returns all Data Connectors categories that the user has access to", + "operationId": "getDataSourceCategories", "parameters": [ - { - "name": "process_request_id", - "in": "query", - "description": "Process request id", - "required": false, - "schema": { - "type": "integer" - } - }, { "$ref": "#/components/parameters/filter" }, @@ -3770,25 +3847,33 @@ }, { "$ref": "#/components/parameters/order_direction" + }, + { + "$ref": "#/components/parameters/per_page" } ], "responses": { "200": { - "description": "list of tasks", + "description": "list of Data Connectors categories", "content": { "application/json": { "schema": { "properties": { "data": { - "description": "Display a listing of the resource.", + "description": "Display a listing of the Data Connector Categories.", "type": "array", "items": { - "$ref": "#/components/schemas/processRequestToken" + "$ref": "#/components/schemas/DataSourceCategory" } }, "meta": { + "description": "Display a listing of the Data Connector Categories.", "type": "object", - "$ref": "#/components/schemas/metadata" + "allOf": [ + { + "$ref": "#/components/schemas/metadata" + } + ] } }, "type": "object" @@ -3797,33 +3882,62 @@ } } } + }, + "post": { + "tags": [ + "Data Connector Categories" + ], + "summary": "Save a new Data Connector Category", + "operationId": "createDataSourceCategory", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataSourceCategoryEditable" + } + } + } + }, + "responses": { + "201": { + "description": "success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DataSourceCategory" + } + } + } + } + } } }, - "/tasks/{task_id}": { + "/data_source_categories/{data_source_category_id}": { "get": { "tags": [ - "Tasks" + "Data Connector Categories" ], - "summary": "Get a single task by ID", - "operationId": "getTasksById", + "summary": "Get single Data Connector category by ID", + "operationId": "getDatasourceCategoryById", "parameters": [ { - "name": "task_id", + "name": "data_source_category_id", "in": "path", - "description": "task id", + "description": "ID of Data Connector category to return", "required": true, "schema": { - "type": "integer" + "type": "string" } } ], "responses": { "200": { - "description": "success", + "description": "Successfully found the Data Connector", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/processRequestToken" + "$ref": "#/components/schemas/DataSourceCategory" } } } @@ -3832,15 +3946,15 @@ }, "put": { "tags": [ - "Tasks" + "Data Connector Categories" ], - "summary": "Update a task", - "operationId": "updateTask", + "summary": "Update a Data Connector Category", + "operationId": "updateDatasourceCategory", "parameters": [ { - "name": "task_id", + "name": "data_source_category_id", "in": "path", - "description": "ID of task to update", + "description": "ID of Data Connector category to return", "required": true, "schema": { "type": "string" @@ -3852,7 +3966,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/processRequestTokenEditable" + "$ref": "#/components/schemas/DataSourceCategoryEditable" } } } @@ -3863,21 +3977,44 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/processRequestToken" + "$ref": "#/components/schemas/DataSourceCategory" } } } } } + }, + "delete": { + "tags": [ + "Data Connector Categories" + ], + "summary": "Delete a Data Connector category", + "operationId": "deleteDataSourceCategory", + "parameters": [ + { + "name": "data_source_category_id", + "in": "path", + "description": "ID of Data Connector category to return", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "success" + } + } } }, - "/users": { + "/data_sources": { "get": { "tags": [ - "Users" + "Data Connectors" ], - "summary": "Returns all users", - "operationId": "getUsers", + "summary": "Returns all Data Connectors that the user has access to", + "operationId": "getDataSources", "parameters": [ { "$ref": "#/components/parameters/filter" @@ -3897,21 +4034,26 @@ ], "responses": { "200": { - "description": "list of users", + "description": "list of Data Connectors", "content": { "application/json": { "schema": { "properties": { "data": { - "description": "Display a listing of the resource.", + "description": "Get the list of records of a Data Connector", "type": "array", "items": { - "$ref": "#/components/schemas/users" + "$ref": "#/components/schemas/dataSource" } }, "meta": { + "description": "Get the list of records of a Data Connector", "type": "object", - "$ref": "#/components/schemas/metadata" + "allOf": [ + { + "$ref": "#/components/schemas/metadata" + } + ] } }, "type": "object" @@ -3923,16 +4065,16 @@ }, "post": { "tags": [ - "Users" + "Data Connectors" ], - "summary": "Save a new users", - "operationId": "createUser", + "summary": "Save a new Data Connector", + "operationId": "createDataSource", "requestBody": { "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/usersEditable" + "$ref": "#/components/schemas/dataSourceEditable" } } } @@ -3943,7 +4085,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/users" + "$ref": "#/components/schemas/dataSource" } } } @@ -3951,18 +4093,18 @@ } } }, - "/users/{user_id}": { + "/data_sources/data_source_id": { "get": { "tags": [ - "Users" + "Data Connectors" ], - "summary": "Get single user by ID", - "operationId": "getUserById", + "summary": "Get single Data Connector by ID", + "operationId": "getDataSourceById", "parameters": [ { - "name": "user_id", + "name": "data_source_id", "in": "path", - "description": "ID of user to return", + "description": "ID of Data Connector to return", "required": true, "schema": { "type": "string" @@ -3971,11 +4113,11 @@ ], "responses": { "200": { - "description": "Successfully found the process", + "description": "Successfully found the Data Connector", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/users" + "$ref": "#/components/schemas/dataSource" } } } @@ -3984,15 +4126,15 @@ }, "put": { "tags": [ - "Users" + "Data Connectors" ], - "summary": "Update a user", - "operationId": "updateUsers", + "summary": "Update a Data Connector", + "operationId": "updateDataSource", "parameters": [ { - "name": "user_id", + "name": "data_source_id", "in": "path", - "description": "ID of user to return", + "description": "ID of Data Connector to return", "required": true, "schema": { "type": "string" @@ -4004,18 +4146,18 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/usersEditable" + "$ref": "#/components/schemas/dataSourceEditable" } } } }, "responses": { - "200": { + "204": { "description": "success", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/users" + "$ref": "#/components/schemas/dataSource" } } } @@ -4024,15 +4166,15 @@ }, "delete": { "tags": [ - "Users" + "Data Connectors" ], - "summary": "Delete a user", - "operationId": "deleteUser", + "summary": "Delete a Data Connector", + "operationId": "deleteDataSource", "parameters": [ { - "name": "user_id", + "name": "data_source_id", "in": "path", - "description": "ID of user to return", + "description": "ID of Data Connector to return", "required": true, "schema": { "type": "string" @@ -4045,7 +4187,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/users" + "$ref": "#/components/schemas/dataSource" } } } @@ -4053,18 +4195,18 @@ } } }, - "/users/{user_id}/groups": { - "put": { + "/data_sources/data_source_id/test": { + "post": { "tags": [ - "Users" + "Data Connectors" ], - "summary": "Update a user's groups", - "operationId": "updateUserGroups", + "summary": "Send a Data Connector request", + "operationId": "sendDataSource", "parameters": [ { - "name": "user_id", + "name": "data_source_id", "in": "path", - "description": "ID of user to return", + "description": "ID of Data Connector to return", "required": true, "schema": { "type": "string" @@ -4076,18 +4218,18 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/usersEditable" + "$ref": "#/components/schemas/dataSourceEditable" } } } }, "responses": { - "200": { + "204": { "description": "success", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/users" + "$ref": "#/components/schemas/dataSource" } } } @@ -4095,18 +4237,27 @@ } } }, - "/users/restore": { - "put": { + "/request/{request_id}/data_source/{data_source_id}": { + "post": { "tags": [ - "Users" + "Data Sources" ], - "summary": "Restore a soft deleted user", - "operationId": "restoreUser", + "summary": "execute Data Source", + "operationId": "executeDataSource", "parameters": [ { - "name": "user_id", + "name": "request_id", "in": "path", - "description": "ID of user to return", + "description": "ID of the request in whose context the datasource will be executed", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "data_source_id", + "in": "path", + "description": "ID of DataSource to be run", "required": true, "schema": { "type": "string" @@ -4118,7 +4269,12 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/usersEditable" + "properties": { + "config": { + "$ref": "#/components/schemas/DataSourceCallParameters" + } + }, + "type": "object" } } } @@ -4128,9 +4284,7 @@ "description": "success", "content": { "application/json": { - "schema": { - "$ref": "#/components/schemas/users" - } + "schema": {} } } } @@ -4212,110 +4366,6 @@ } ] }, - "dataSourceEditable": { - "properties": { - "id": { - "description": "Class DataSource", - "type": "string", - "format": "id" - }, - "name": { - "description": "Class DataSource", - "type": "string" - }, - "description": { - "description": "Class DataSource", - "type": "string" - }, - "endpoints": { - "description": "Class DataSource", - "type": "string" - }, - "mappings": { - "description": "Class DataSource", - "type": "string" - }, - "authtype": { - "description": "Class DataSource", - "type": "string" - }, - "credentials": { - "description": "Class DataSource", - "type": "string" - }, - "status": { - "description": "Class DataSource", - "type": "string" - }, - "data_source_category_id": { - "description": "Class DataSource", - "type": "string" - } - }, - "type": "object" - }, - "dataSource": { - "properties": { - "created_at": { - "description": "Class DataSource", - "type": "string", - "format": "date-time" - }, - "updated_at": { - "description": "Class DataSource", - "type": "string", - "format": "date-time" - } - }, - "type": "object", - "allOf": [ - { - "$ref": "#/components/schemas/dataSourceEditable" - } - ] - }, - "DataSourceCategoryEditable": { - "properties": { - "name": { - "description": "Represents a business data Source category definition.", - "type": "string" - }, - "status": { - "description": "Represents a business data Source category definition.", - "type": "string", - "enum": [ - "ACTIVE", - "INACTIVE" - ] - } - }, - "type": "object" - }, - "DataSourceCategory": { - "properties": { - "id": { - "description": "Represents a business data Source category definition.", - "type": "string", - "format": "id" - }, - "created_at": { - "description": "Represents a business data Source category definition.", - "type": "string", - "format": "date-time" - }, - "updated_at": { - "description": "Represents a business data Source category definition.", - "type": "string", - "format": "date-time" - } - }, - "type": "object", - "allOf": [ - { - "$ref": "#/components/schemas/DataSourceCategoryEditable" - } - ] - }, "environment_variablesEditable": { "properties": { "name": { @@ -5638,15 +5688,6 @@ } ] }, - "DataSourceCallParameters": { - "properties": { - "endpoint": { - "description": "Execute a data Source endpoint", - "type": "string" - } - }, - "type": "object" - }, "metadata": { "properties": { "filter": { @@ -5746,6 +5787,119 @@ "type": "object" } ] + }, + "DataSourceCallParameters": { + "properties": { + "endpoint": { + "description": "Execute a data Source endpoint", + "type": "string" + } + }, + "type": "object" + }, + "dataSourceEditable": { + "properties": { + "id": { + "description": "Class DataSource", + "type": "string", + "format": "id" + }, + "name": { + "description": "Class DataSource", + "type": "string" + }, + "description": { + "description": "Class DataSource", + "type": "string" + }, + "endpoints": { + "description": "Class DataSource", + "type": "string" + }, + "mappings": { + "description": "Class DataSource", + "type": "string" + }, + "authtype": { + "description": "Class DataSource", + "type": "string" + }, + "credentials": { + "description": "Class DataSource", + "type": "string" + }, + "status": { + "description": "Class DataSource", + "type": "string" + }, + "data_source_category_id": { + "description": "Class DataSource", + "type": "string" + } + }, + "type": "object" + }, + "dataSource": { + "properties": { + "created_at": { + "description": "Class DataSource", + "type": "string", + "format": "date-time" + }, + "updated_at": { + "description": "Class DataSource", + "type": "string", + "format": "date-time" + } + }, + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/dataSourceEditable" + } + ] + }, + "DataSourceCategoryEditable": { + "properties": { + "name": { + "description": "Represents a business data Source category definition.", + "type": "string" + }, + "status": { + "description": "Represents a business data Source category definition.", + "type": "string", + "enum": [ + "ACTIVE", + "INACTIVE" + ] + } + }, + "type": "object" + }, + "DataSourceCategory": { + "properties": { + "id": { + "description": "Represents a business data Source category definition.", + "type": "string", + "format": "id" + }, + "created_at": { + "description": "Represents a business data Source category definition.", + "type": "string", + "format": "date-time" + }, + "updated_at": { + "description": "Represents a business data Source category definition.", + "type": "string", + "format": "date-time" + } + }, + "type": "object", + "allOf": [ + { + "$ref": "#/components/schemas/DataSourceCategoryEditable" + } + ] } }, "parameters": { diff --git a/storage/docker-build-config/Dockerfile-php b/storage/docker-build-config/Dockerfile-php new file mode 100644 index 0000000000..03296c75bc --- /dev/null +++ b/storage/docker-build-config/Dockerfile-php @@ -0,0 +1 @@ +RUN composer require aws/aws-sdk-php \ No newline at end of file From 69684fead5172efebcc7401413f70196056b4e10 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Fri, 6 Mar 2020 11:31:04 -0800 Subject: [PATCH 06/43] Rename userDockerfile to appDockerfile for clarity --- .../Console/Commands/BuildScriptExecutors.php | 6 +++--- .../Controllers/Api/ScriptExecutorController.php | 14 +++++++------- tests/Feature/Api/ScriptExecutorTest.php | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ProcessMaker/Console/Commands/BuildScriptExecutors.php b/ProcessMaker/Console/Commands/BuildScriptExecutors.php index b2f74c1e71..407f26da36 100644 --- a/ProcessMaker/Console/Commands/BuildScriptExecutors.php +++ b/ProcessMaker/Console/Commands/BuildScriptExecutors.php @@ -65,9 +65,9 @@ public function handle() $dockerfile .= $initDockerfile; } $dockerfile .= "\n"; - $userDockerfilePath = storage_path("docker-build-config/Dockerfile-${lang}"); - if (file_exists($userDockerfilePath)) { - $dockerfile .= file_get_contents($userDockerfilePath); + $appDockerfilePath = storage_path("docker-build-config/Dockerfile-${lang}"); + if (file_exists($appDockerfilePath)) { + $dockerfile .= file_get_contents($appDockerfilePath); } $this->info("Dockerfile:\n " . implode("\n ", explode("\n", $dockerfile))); diff --git a/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php b/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php index 0ac7cb6120..01abd4edef 100644 --- a/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php +++ b/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php @@ -15,15 +15,15 @@ public function index(Request $request) $languages = []; foreach (config('script-runners') as $key => $config) { - $userDockerfileContents = ''; + $appDockerfileContents = ''; - $userDockerfilePath = storage_path("docker-build-config/Dockerfile-${key}"); - if (file_exists($userDockerfilePath)) { - $userDockerfileContents .= file_get_contents($userDockerfilePath); + $appDockerfilePath = storage_path("docker-build-config/Dockerfile-${key}"); + if (file_exists($appDockerfilePath)) { + $appDockerfileContents .= file_get_contents($appDockerfilePath); } $languages[$key] = [ - 'userDockerfileContents' => $userDockerfileContents + 'appDockerfileContents' => $appDockerfileContents ]; } @@ -37,9 +37,9 @@ public function update(Request $request, $language) throw new ModelNotFoundException; } - $userDockerfilePath = storage_path("docker-build-config/Dockerfile-${language}"); + $appDockerfilePath = storage_path("docker-build-config/Dockerfile-${language}"); - file_put_contents($userDockerfilePath, $request->input('userDockerfileContents')); + file_put_contents($appDockerfilePath, $request->input('appDockerfileContents')); } private function checkAuth($request) diff --git a/tests/Feature/Api/ScriptExecutorTest.php b/tests/Feature/Api/ScriptExecutorTest.php index d488946c58..96d93a06b1 100644 --- a/tests/Feature/Api/ScriptExecutorTest.php +++ b/tests/Feature/Api/ScriptExecutorTest.php @@ -25,18 +25,18 @@ public function testGetScriptExecutors() $result = $result->json(); $this->assertArrayHasKey('php', $result['languages']); - $docker = $result['languages']['php']['userDockerfileContents']; + $docker = $result['languages']['php']['appDockerfileContents']; $this->assertEquals("Foo", $docker); } public function testSetDockerfile() { $route = route('api.script-executors.update', ['language' => 'lua']); - $result = $this->apiCall('PUT', $route, ['userDockerfileContents' => 'Bar']); + $result = $this->apiCall('PUT', $route, ['appDockerfileContents' => 'Bar']); $result = $this->apiCall('GET', route('api.script-executors.index')); $result = $result->json(); - $docker = $result['languages']['lua']['userDockerfileContents']; + $docker = $result['languages']['lua']['appDockerfileContents']; $this->assertEquals('Bar', $docker); } } From 3b55b6253583b5c83073115e0973c1fa2122f5bd Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Fri, 6 Mar 2020 15:23:24 -0800 Subject: [PATCH 07/43] Start on interface to rebuild script executors --- .../Console/Commands/BuildScriptExecutors.php | 51 +++++++++- ProcessMaker/Events/BuildScriptExecutor.php | 27 ++++++ .../Api/ScriptExecutorController.php | 6 +- ProcessMaker/Jobs/BuildScriptExecutor.php | 40 ++++++++ .../script-executors/ScriptExecutors.vue | 95 ++++++++++++++++++- 5 files changed, 214 insertions(+), 5 deletions(-) create mode 100644 ProcessMaker/Events/BuildScriptExecutor.php create mode 100644 ProcessMaker/Jobs/BuildScriptExecutor.php diff --git a/ProcessMaker/Console/Commands/BuildScriptExecutors.php b/ProcessMaker/Console/Commands/BuildScriptExecutors.php index 407f26da36..5251b7ead6 100644 --- a/ProcessMaker/Console/Commands/BuildScriptExecutors.php +++ b/ProcessMaker/Console/Commands/BuildScriptExecutors.php @@ -3,6 +3,7 @@ namespace ProcessMaker\Console\Commands; use Illuminate\Console\Command; +use ProcessMaker\Events\BuildScriptExecutor; use ProcessMaker\BuildSdk; use \Exception; @@ -14,7 +15,7 @@ class BuildScriptExecutors extends Command * * @var string */ - protected $signature = 'processmaker:build-script-executor {lang}'; + protected $signature = 'processmaker:build-script-executor {lang} {user?}'; /** * The console command description. @@ -22,6 +23,13 @@ class BuildScriptExecutors extends Command * @var string */ protected $description = ''; + + /** + * The user ID to send the broadcast event to. + * + * @var int + */ + protected $userId = null; /** * Create a new command instance. @@ -74,6 +82,45 @@ public function handle() file_put_contents($dockerDir . '/Dockerfile', $dockerfile); $this->info("Building the docker executor"); - system("docker build -t processmaker4/executor-${lang}:latest ${dockerDir}"); + + $command = "docker build -t processmaker4/executor-${lang}:latest ${dockerDir}"; + + $this->userId = $this->argument('user'); + if ($this->userId) { + $this->runProc( + $command, + function($output) { + // Command output callback + $this->sendEvent($output, 'running'); + }, + function() { + // Command finished callback + $this->sendEvent('', 'done'); + } + ); + } else { + system($command); + } + } + + private function sendEvent($output, $status) { + event(new BuildScriptExecutor($output, $this->userId, $status)); + } + + private function runProc($cmd, $callback, $done) + { + $dsc = [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']]; + $process = proc_open("($cmd) 2>&1", $dsc, $pipes); + + while(!feof($pipes[1])) { + $callback(fgets($pipes[1])); + } + + $done(); + + fclose($pipes[0]); + fclose($pipes[1]); + fclose($pipes[2]); + return proc_close($process); } } diff --git a/ProcessMaker/Events/BuildScriptExecutor.php b/ProcessMaker/Events/BuildScriptExecutor.php new file mode 100644 index 0000000000..d4cdb33c10 --- /dev/null +++ b/ProcessMaker/Events/BuildScriptExecutor.php @@ -0,0 +1,27 @@ +output = $output; + $this->userId = $userId; + $this->status = $status; + } + + public function broadcastAs() { + return 'BuildScriptExecutor'; + } + + public function broadcastOn() + { + return new PrivateChannel('ProcessMaker.Models.User.' . $this->userId); + } +} \ No newline at end of file diff --git a/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php b/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php index 01abd4edef..d1344bbaa2 100644 --- a/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php +++ b/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php @@ -6,6 +6,7 @@ use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Database\Eloquent\ModelNotFoundException; use ProcessMaker\Http\Controllers\Controller; +use ProcessMaker\Jobs\BuildScriptExecutor; class ScriptExecutorController extends Controller { @@ -38,8 +39,11 @@ public function update(Request $request, $language) } $appDockerfilePath = storage_path("docker-build-config/Dockerfile-${language}"); - file_put_contents($appDockerfilePath, $request->input('appDockerfileContents')); + + BuildScriptExecutor::dispatch($language, $request->user()->id); + + return ['status'=>'started']; } private function checkAuth($request) diff --git a/ProcessMaker/Jobs/BuildScriptExecutor.php b/ProcessMaker/Jobs/BuildScriptExecutor.php new file mode 100644 index 0000000000..ca4dc70346 --- /dev/null +++ b/ProcessMaker/Jobs/BuildScriptExecutor.php @@ -0,0 +1,40 @@ +lang = $lang; + $this->userId = $userId; + } + + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + \Log::info("Started artisan command to build script executor for language: " . $this->lang . " for user: " . $this->userId); + \Artisan::call('processmaker:build-script-executor ' . $this->lang . ' ' . $this->userId); + \Log::info("Finished running build script executor"); + } +} diff --git a/resources/js/admin/script-executors/ScriptExecutors.vue b/resources/js/admin/script-executors/ScriptExecutors.vue index 4712c2d4c4..3c713de44c 100644 --- a/resources/js/admin/script-executors/ScriptExecutors.vue +++ b/resources/js/admin/script-executors/ScriptExecutors.vue @@ -1,16 +1,107 @@ \ No newline at end of file + + \ No newline at end of file From dba2f92e94be3f0b6fc739dee3d082c0df326aa8 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Tue, 10 Mar 2020 12:12:38 -0700 Subject: [PATCH 08/43] Update build executor scripts --- .../Console/Commands/BuildScriptExecutors.php | 44 ++++-- .../Api/ScriptExecutorController.php | 6 +- ProcessMaker/Jobs/BuildScriptExecutor.php | 2 +- .../script-executors/ScriptExecutors.vue | 132 +++++++++++++++--- storage/docker-build-config/Dockerfile-php | 6 + 5 files changed, 156 insertions(+), 34 deletions(-) diff --git a/ProcessMaker/Console/Commands/BuildScriptExecutors.php b/ProcessMaker/Console/Commands/BuildScriptExecutors.php index 5251b7ead6..2f79011293 100644 --- a/ProcessMaker/Console/Commands/BuildScriptExecutors.php +++ b/ProcessMaker/Console/Commands/BuildScriptExecutors.php @@ -48,6 +48,8 @@ public function __construct() */ public function handle() { + $this->userId = $this->argument('user'); + $lang = $this->argument('lang'); $this->info("Building for language: $lang"); @@ -66,6 +68,7 @@ public function handle() 'language' => $lang, 'output' => $sdkDir ]); + $this->info("SDK is at ${sdkDir}"); $dockerfile = ''; $initDockerfile = config('script-runners.' . $lang . '.init_dockerfile'); @@ -83,9 +86,9 @@ public function handle() $this->info("Building the docker executor"); - $command = "docker build -t processmaker4/executor-${lang}:latest ${dockerDir}"; + $tag = 'v1.0.0'; // Hard coding this for now until we get versions set up + $command = "docker build --build-arg SDK_DIR=/sdk -t processmaker4/executor-instance-${lang}:${tag} ${dockerDir}"; - $this->userId = $this->argument('user'); if ($this->userId) { $this->runProc( $command, @@ -93,9 +96,13 @@ function($output) { // Command output callback $this->sendEvent($output, 'running'); }, - function() { + function($pidFilePath) { + // Command starting + $this->sendEvent($pidFilePath, 'starting'); + }, + function($exitCode) { // Command finished callback - $this->sendEvent('', 'done'); + $this->sendEvent($exitCode, 'done'); } ); } else { @@ -103,24 +110,43 @@ function() { } } - private function sendEvent($output, $status) { + public function info($text, $verbosity = null) { + if ($this->userId) { + $this->sendEvent($text . "\n", 'running'); + } + parent::info($text, $verbosity); + } + + private function sendEvent($output, $status) + { event(new BuildScriptExecutor($output, $this->userId, $status)); } - private function runProc($cmd, $callback, $done) + private function savePid($process) + { + $pid = proc_get_status($process)['pid']; + $pidFilePath = tempnam('/tmp', 'build_script_executor_'); + file_put_contents($pidFilePath, $pid); + return $pidFilePath; + } + + private function runProc($cmd, $callback, $start, $done) { $dsc = [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']]; $process = proc_open("($cmd) 2>&1", $dsc, $pipes); + $pidFilePath = $this->savePid($process); + $start($pidFilePath); + while(!feof($pipes[1])) { $callback(fgets($pipes[1])); } - $done(); - fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); - return proc_close($process); + unlink($pidFilePath); + $exitCode = proc_close($process); + $done($exitCode); } } diff --git a/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php b/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php index d1344bbaa2..7a1a5523bc 100644 --- a/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php +++ b/ProcessMaker/Http/Controllers/Api/ScriptExecutorController.php @@ -19,12 +19,16 @@ public function index(Request $request) $appDockerfileContents = ''; $appDockerfilePath = storage_path("docker-build-config/Dockerfile-${key}"); + $mtime = null; if (file_exists($appDockerfilePath)) { + $mtime = filemtime($appDockerfilePath); $appDockerfileContents .= file_get_contents($appDockerfilePath); } $languages[$key] = [ - 'appDockerfileContents' => $appDockerfileContents + 'mtime' => $mtime, + 'appDockerfileContents' => $appDockerfileContents, + 'initDockerfile' => isset($config['init_dockerfile']) ? $config['init_dockerfile'] : '', ]; } diff --git a/ProcessMaker/Jobs/BuildScriptExecutor.php b/ProcessMaker/Jobs/BuildScriptExecutor.php index ca4dc70346..86dad7006a 100644 --- a/ProcessMaker/Jobs/BuildScriptExecutor.php +++ b/ProcessMaker/Jobs/BuildScriptExecutor.php @@ -33,7 +33,7 @@ public function __construct(string $lang, $userId) */ public function handle() { - \Log::info("Started artisan command to build script executor for language: " . $this->lang . " for user: " . $this->userId); + \Log::info("Started artisan command to build script executor for language", ['lang'=>$this->lang, 'user'=>$this->userId]); \Artisan::call('processmaker:build-script-executor ' . $this->lang . ' ' . $this->userId); \Log::info("Finished running build script executor"); } diff --git a/resources/js/admin/script-executors/ScriptExecutors.vue b/resources/js/admin/script-executors/ScriptExecutors.vue index 3c713de44c..2f903f83da 100644 --- a/resources/js/admin/script-executors/ScriptExecutors.vue +++ b/resources/js/admin/script-executors/ScriptExecutors.vue @@ -1,25 +1,57 @@