{"id":20677763,"url":"https://github.com/clivern/monkey","last_synced_at":"2025-07-30T05:33:23.709Z","repository":{"id":30664640,"uuid":"123699421","full_name":"Clivern/Monkey","owner":"Clivern","description":":monkey_face: Apache CloudStack SDK in PHP that supports sync calls, async calls and multiple dependent calls.","archived":false,"fork":false,"pushed_at":"2025-07-11T08:47:23.000Z","size":169,"stargazers_count":3,"open_issues_count":7,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-22T01:28:23.188Z","etag":null,"topics":["apache-cloudstack","cloud-computing","cloudstack","cloudstack-api","php","php-library"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Clivern.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-03-03T14:30:37.000Z","updated_at":"2024-12-02T21:58:36.000Z","dependencies_parsed_at":"2023-01-14T17:25:48.808Z","dependency_job_id":"84daec51-b663-4d74-ac8c-f34bbf49af6a","html_url":"https://github.com/Clivern/Monkey","commit_stats":{"total_commits":107,"total_committers":4,"mean_commits":26.75,"dds":0.06542056074766356,"last_synced_commit":"11157992e92eaefbe36bf4a2c0dec9701307f92d"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/Clivern/Monkey","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Clivern%2FMonkey","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Clivern%2FMonkey/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Clivern%2FMonkey/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Clivern%2FMonkey/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Clivern","download_url":"https://codeload.github.com/Clivern/Monkey/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Clivern%2FMonkey/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267815187,"owners_count":24148356,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-30T02:00:09.044Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apache-cloudstack","cloud-computing","cloudstack","cloudstack-api","php","php-library"],"created_at":"2024-11-16T21:16:58.179Z","updated_at":"2025-07-30T05:33:23.682Z","avatar_url":"https://github.com/Clivern.png","language":"PHP","readme":"Monkey\n======\n\nApache CloudStack SDK in PHP.\n\n[![Build Status](https://github.com/Clivern/Monkey/workflows/Build/badge.svg)](https://github.com/Clivern/Monkey/actions)\n[![License](https://poser.pugx.org/clivern/monkey/license.svg)](https://packagist.org/packages/clivern/monkey)\n[![Latest Stable Version](https://poser.pugx.org/clivern/monkey/v/stable.svg)](https://packagist.org/packages/clivern/monkey)\n\n\nInstallation\n------------\n\nTo install the package via `composer`, use the following:\n\n```php\n$ composer require clivern/monkey\n```\n\nThis command requires you to have Composer installed globally.\n\n\nCloudStack Simulator\n---------------------\n\n### Install Docker\n\nTo install docker on Ubuntu.\n\n```bash\n$ apt-get update\n$ sudo apt install docker.io\n```\n\nThen ensure that it is enabled to start after reboot:\n\n```bash\n$ sudo systemctl enable docker\n```\n\nThen Run CloudStack Simulator.\n\n```bash\n$ docker pull cloudstack/simulator\n$ docker run --name simulator -p 8080:8080 -d cloudstack/simulator\n$ docker exec -ti simulator python /root/tools/marvin/marvin/deployDataCenter.py -i /root/setup/dev/basic.cfg\n```\n\n\nUsage\n-----\n\nAfter adding the package as a dependency, Please read the following steps:\n\n### Configure CloudStack Credentials\n\n```php\ninclude_once dirname(__FILE__) . '/vendor/autoload.php';\n\nuse Clivern\\Monkey\\Util\\Config;\n\n$config = new Config();\n$config-\u003eaddCloudStackServer(\"us_dc_clsk_01\", [\n    \"api_url\"   =\u003e \"http://clsk_url.com:8080/client/api\",\n    \"api_key\"    =\u003e \"api_key_here\",\n    \"secret_key\" =\u003e \"secret_key_here\"\n]);\n\n// OR\n\n$config = new Config([\n    \"us_dc_clsk_01\" =\u003e [\n        \"api_url\"   =\u003e \"http://clsk_url.com:8080/client/api\",\n        \"api_key\"    =\u003e \"api_key_here\",\n        \"secret_key\" =\u003e \"secret_key_here\"\n    ]\n]);\n\n// To use self-signed or invalid SSL for connecting to CloudStack\n\n$config = new Config([\n    \"us_dc_clsk_01\" =\u003e [\n        \"api_url\"   =\u003e \"https://clsk_url.com:8443/client/api\",\n        \"api_key\"    =\u003e \"api_key_here\",\n        \"secret_key\" =\u003e \"secret_key_here\",\n        \"verify_ssl\" =\u003e false\n    ]\n]);\n\n// To Check if CloudStack Server Credentials Exists\n$config-\u003eisCloudStackServerExists(\"us_dc_clsk_01\"); // Return Boolean\n\n// To Get CloudStack Server Credentials\n$config-\u003egetCloudStackServer(\"us_dc_clsk_01\"); // Return array \u0026 May be empty if not exist\n\n// To Get All CloudStack Servers Credentials\n$config-\u003egetCloudStackServers(); // Return Array\n\n// To Remove CloudStack Server\n$config-\u003eremoveCloudStackServer(\"us_dc_clsk_01\"); // Return Boolean\n```\n\n### Running Sync Calls\n\nIn order to run sync calls, Like creating a new user, [you need to check cloudstack api to get the command and the required parameters](http://cloudstack.apache.org/api/apidocs-4.11/apis/createUser.html). First lets create a call that will fail due to missing parametes and see the response data:\n\n```php\ninclude_once dirname(__FILE__) . '/vendor/autoload.php';\n\nuse Clivern\\Monkey\\Util\\Config;\nuse Clivern\\Monkey\\API\\Request\\PlainRequest;\nuse Clivern\\Monkey\\API\\Response\\PlainResponse;\nuse Clivern\\Monkey\\API\\Request\\RequestMethod;\nuse Clivern\\Monkey\\API\\Request\\RequestType;\nuse Clivern\\Monkey\\API\\Caller;\n\n\n// Create a cloudStack credentials config\n$config = new Config();\n$config-\u003eaddCloudStackServer(\"us_dc_clsk_01\", [\n    \"api_url\"   =\u003e \"http://clsk_url.com:8080/client/api\",\n    \"api_key\"    =\u003e \"api_key_here\",\n    \"secret_key\" =\u003e \"secret_key_here\"\n]);\n\n// Create request object with a missing parameter account :(\n$request = new PlainRequest();\n$request-\u003esetMethod(RequestMethod::$GET)\n        -\u003esetType(RequestType::$SYNCHRONOUS)\n        -\u003eaddParameter(\"command\", \"createUser\")\n        -\u003eaddParameter(\"email\", \"hello@clivern.com\")\n        -\u003eaddParameter(\"firstname\", \"John\")\n        -\u003eaddParameter(\"lastname\", \"Doe\")\n        -\u003eaddParameter(\"password\", \"clivern\")\n        -\u003eaddParameter(\"username\", \"clivern\");\n\n// Create response object without callbacks\n$response = new PlainResponse();\n\n// Create a caller object with the request and response and ident create_account\n$caller = new Caller($request, $response, \"create_account\", $config-\u003egetCloudStackServer(\"us_dc_clsk_01\"));\n\n// Run the call\n$caller-\u003eexecute();\n\n// Debug the caller status and response data\nvar_dump($caller-\u003egetStatus()); // Return string(6) \"FAILED\"\nvar_dump($caller-\u003eresponse()-\u003egetResponse()); // Returns array(0) { }\nvar_dump($caller-\u003eresponse()-\u003egetErrorCode()); // Returns int(431)\nvar_dump($caller-\u003eresponse()-\u003egetErrorMessage()); // Returns string(73) \"Unable to execute API command createuser due to missing parameter account\"\n```\n\nNow let's create a successful call:\n\n```php\ninclude_once dirname(__FILE__) . '/vendor/autoload.php';\n\nuse Clivern\\Monkey\\Util\\Config;\nuse Clivern\\Monkey\\API\\Request\\PlainRequest;\nuse Clivern\\Monkey\\API\\Response\\PlainResponse;\nuse Clivern\\Monkey\\API\\Request\\RequestMethod;\nuse Clivern\\Monkey\\API\\Request\\RequestType;\nuse Clivern\\Monkey\\API\\Caller;\n\n\n// Create a cloudStack credentials config\n$config = new Config();\n$config-\u003eaddCloudStackServer(\"us_dc_clsk_01\", [\n    \"api_url\"   =\u003e \"http://clsk_url.com:8080/client/api\",\n    \"api_key\"    =\u003e \"api_key_here\",\n    \"secret_key\" =\u003e \"secret_key_here\"\n]);\n\n// Create request object\n$request = new PlainRequest();\n$request-\u003esetMethod(RequestMethod::$GET)\n        -\u003esetType(RequestType::$SYNCHRONOUS)\n        -\u003eaddParameter(\"command\", \"createUser\")\n        -\u003eaddParameter(\"account\", \"admin\")\n        -\u003eaddParameter(\"email\", \"hello@clivern.com\")\n        -\u003eaddParameter(\"firstname\", \"John\")\n        -\u003eaddParameter(\"lastname\", \"Doe\")\n        -\u003eaddParameter(\"password\", \"clivern\")\n        -\u003eaddParameter(\"username\", \"clivern\");\n\n// Create response object without callbacks\n$response = new PlainResponse();\n\n// Create a caller object with the request and response and ident create_account\n$caller = new Caller($request, $response, \"create_account\", $config-\u003egetCloudStackServer(\"us_dc_clsk_01\"));\n\n// Run the call\n$caller-\u003eexecute();\n\n// Debug the caller status and response data\nvar_dump($caller-\u003egetStatus()); // Return string(9) \"SUCCEEDED\"\nvar_dump($caller-\u003eresponse()-\u003egetResponse()); // Returns array(1) { [\"createuserresponse\"]=\u003e array(1) { [\"user\"]=\u003e array(18) { [\"id\"]=\u003e string(36) \"6980f41b-73e5-4848-ad90-7859efb613ad\" .....}}}\nvar_dump($caller-\u003eresponse()-\u003egetErrorCode()); // Returns string(0) \"\"\nvar_dump($caller-\u003eresponse()-\u003egetErrorMessage()); // Returns string(0) \"\"\n```\n\n### Running Async Jobs\n\nIn case of async calls, we need to use another class called `Job` to execute our caller(s). The `Job` class can be exported as json encoded string and stored in database and reloaded again from the last state. This means that we can build a job that hold a lot of sync and async calls and the job class will continue every time we reload it and complete the main request.\n\nAlso `Job` class can retry to run your caller(s) if it failed and once it succeeded, it will move to the next caller. and for sure you will provide the number of trials for each job or per each caller.\n\nFirst let's [create a job that will stop a virtual machine](http://cloudstack.apache.org/api/apidocs-4.11/apis/stopVirtualMachine.html). This job needs to run at least two times, one to create the machine and another to check the job status. Since we don't use database to store job state, we will do this manually. But for sure in real world we will store job in database and run in background.\n\n```php\ninclude_once dirname(__FILE__) . '/vendor/autoload.php';\n\nuse Clivern\\Monkey\\Util\\Config;\nuse Clivern\\Monkey\\API\\Request\\PlainRequest;\nuse Clivern\\Monkey\\API\\Response\\PlainResponse;\nuse Clivern\\Monkey\\API\\Request\\RequestMethod;\nuse Clivern\\Monkey\\API\\Request\\RequestType;\nuse Clivern\\Monkey\\API\\Caller;\nuse Clivern\\Monkey\\API\\Job;\nuse Clivern\\Monkey\\API\\DumpType;\nuse Clivern\\Monkey\\API\\Factory;\nuse Clivern\\Monkey\\API\\JobStatus;\n\n\n$config = new Config();\n$config-\u003eaddCloudStackServer(\"us_dc_clsk_01\", [\n    \"api_url\"   =\u003e \"http://clsk_url.com:8080/client/api\",\n    \"api_key\"    =\u003e \"api_key_here\",\n    \"secret_key\" =\u003e \"secret_key_here\"\n]);\n\n$request = new PlainRequest();\n$request-\u003esetMethod(RequestMethod::$GET)\n        -\u003esetType(RequestType::$ASYNCHRONOUS)\n        -\u003eaddParameter(\"command\", \"stopVirtualMachine\")\n        -\u003eaddParameter(\"id\", \"4c9c8759-de26-41bb-9a22-fe51b9f0c9af\");\n\n$response = new PlainResponse();\n\n$caller = new Caller($request, $response, \"stop_virtual_machine\", $config-\u003egetCloudStackServer(\"us_dc_clsk_01\"));\n\n\n// Create a job with one caller and 4 default trials in case of failure\n$job = new Job([\n    $caller\n], 4);\n\n// Job initial state to store in database\n$initialJobState = $job-\u003edump(DumpType::$JSON);\nvar_dump($initialJobState);\n\n$currentJobState = $initialJobState;\n$finished = false;\n$currentJob = null;\n\nwhile (!$finished) {\n    $currentJob = Factory::job()-\u003ereload($currentJobState, DumpType::$JSON);\n    $currentJob-\u003eexecute();\n    $finished = (($currentJob-\u003egetStatus() == JobStatus::$FAILED) || ($currentJob-\u003egetStatus() == JobStatus::$SUCCEEDED)) ? true : false;\n    $currentJobState = $currentJob-\u003edump(DumpType::$JSON);\n    sleep(5);\n}\n\nif( $currentJob != null ){\n    var_dump($currentJob-\u003egetStatus());\n    var_dump($currentJob-\u003egetCaller(\"stop_virtual_machine\")-\u003egetStatus());\n    var_dump($currentJob-\u003egetCaller(\"stop_virtual_machine\")-\u003eresponse()-\u003egetResponse());\n    var_dump($currentJob-\u003egetCaller(\"stop_virtual_machine\")-\u003eresponse()-\u003egetErrorCode());\n    var_dump($currentJob-\u003egetCaller(\"stop_virtual_machine\")-\u003eresponse()-\u003egetErrorMessage());\n    var_dump($currentJob-\u003edump(DumpType::$JSON));\n}\n```\n\nAlso [we can start the virtual machine again](http://cloudstack.apache.org/api/apidocs-4.11/apis/startVirtualMachine.html)\n\n```php\ninclude_once dirname(__FILE__) . '/vendor/autoload.php';\n\nuse Clivern\\Monkey\\Util\\Config;\nuse Clivern\\Monkey\\API\\Request\\PlainRequest;\nuse Clivern\\Monkey\\API\\Response\\PlainResponse;\nuse Clivern\\Monkey\\API\\Request\\RequestMethod;\nuse Clivern\\Monkey\\API\\Request\\RequestType;\nuse Clivern\\Monkey\\API\\Caller;\nuse Clivern\\Monkey\\API\\Job;\nuse Clivern\\Monkey\\API\\DumpType;\nuse Clivern\\Monkey\\API\\Factory;\nuse Clivern\\Monkey\\API\\JobStatus;\n\n\n$config = new Config();\n$config-\u003eaddCloudStackServer(\"us_dc_clsk_01\", [\n    \"api_url\"   =\u003e \"http://clsk_url.com:8080/client/api\",\n    \"api_key\"    =\u003e \"api_key_here\",\n    \"secret_key\" =\u003e \"secret_key_here\"\n]);\n\n$request = new PlainRequest();\n$request-\u003esetMethod(RequestMethod::$GET)\n        -\u003esetType(RequestType::$ASYNCHRONOUS)\n        -\u003eaddParameter(\"command\", \"startVirtualMachine\")\n        -\u003eaddParameter(\"id\", \"4c9c8759-de26-41bb-9a22-fe51b9f0c9af\");\n\n$response = new PlainResponse();\n\n$caller = new Caller($request, $response, \"start_virtual_machine\", $config-\u003egetCloudStackServer(\"us_dc_clsk_01\"));\n\n\n// Create a job with one caller and 4 default trials in case of failure\n$job = new Job([\n    $caller\n], 4);\n\n// Job initial state to store in database\n$initialJobState = $job-\u003edump(DumpType::$JSON);\nvar_dump($initialJobState);\n\n$currentJobState = $initialJobState;\n$finished = false;\n$currentJob = null;\n\nwhile (!$finished) {\n    $currentJob = Factory::job()-\u003ereload($currentJobState, DumpType::$JSON);\n    $currentJob-\u003eexecute();\n    $finished = (($currentJob-\u003egetStatus() == JobStatus::$FAILED) || ($currentJob-\u003egetStatus() == JobStatus::$SUCCEEDED)) ? true : false;\n    $currentJobState = $currentJob-\u003edump(DumpType::$JSON);\n    sleep(5);\n}\n\nif( $currentJob != null ){\n    var_dump($currentJob-\u003egetStatus());\n    var_dump($currentJob-\u003egetCaller(\"start_virtual_machine\")-\u003egetStatus());\n    var_dump($currentJob-\u003egetCaller(\"start_virtual_machine\")-\u003eresponse()-\u003egetResponse());\n    var_dump($currentJob-\u003egetCaller(\"start_virtual_machine\")-\u003eresponse()-\u003egetErrorCode());\n    var_dump($currentJob-\u003egetCaller(\"start_virtual_machine\")-\u003eresponse()-\u003egetErrorMessage());\n    var_dump($currentJob-\u003edump(DumpType::$JSON));\n}\n```\n\n### Running Complex Jobs\n\nIf we want to run two calls but they are independent on each other, it is all about the order. We just need to run one then another like stop and start the virtual machine. In this case we will create two callers and create a job with the two callers like the following:\n\n```php\ninclude_once dirname(__FILE__) . '/vendor/autoload.php';\n\nuse Clivern\\Monkey\\Util\\Config;\nuse Clivern\\Monkey\\API\\Request\\PlainRequest;\nuse Clivern\\Monkey\\API\\Response\\PlainResponse;\nuse Clivern\\Monkey\\API\\Request\\RequestMethod;\nuse Clivern\\Monkey\\API\\Request\\RequestType;\nuse Clivern\\Monkey\\API\\Caller;\nuse Clivern\\Monkey\\API\\Job;\nuse Clivern\\Monkey\\API\\DumpType;\nuse Clivern\\Monkey\\API\\Factory;\nuse Clivern\\Monkey\\API\\JobStatus;\n\n\n$config = new Config();\n$config-\u003eaddCloudStackServer(\"us_dc_clsk_01\", [\n    \"api_url\"   =\u003e \"http://clsk_url.com:8080/client/api\",\n    \"api_key\"    =\u003e \"api_key_here\",\n    \"secret_key\" =\u003e \"secret_key_here\"\n]);\n\n$request1 = new PlainRequest();\n$request1-\u003esetMethod(RequestMethod::$GET)\n        -\u003esetType(RequestType::$ASYNCHRONOUS)\n        -\u003eaddParameter(\"command\", \"stopVirtualMachine\")\n        -\u003eaddParameter(\"id\", \"4c9c8759-de26-41bb-9a22-fe51b9f0c9af\");\n\n$response1 = new PlainResponse();\n\n$caller1 = new Caller($request1, $response1, \"stop_virtual_machine\", $config-\u003egetCloudStackServer(\"us_dc_clsk_01\"));\n\n\n$request2 = new PlainRequest();\n$request2-\u003esetMethod(RequestMethod::$GET)\n        -\u003esetType(RequestType::$ASYNCHRONOUS)\n        -\u003eaddParameter(\"command\", \"startVirtualMachine\")\n        -\u003eaddParameter(\"id\", \"4c9c8759-de26-41bb-9a22-fe51b9f0c9af\");\n\n$response2 = new PlainResponse();\n\n$caller2 = new Caller($request2, $response2, \"start_virtual_machine\", $config-\u003egetCloudStackServer(\"us_dc_clsk_01\"));\n\n\n// Create a job with two callers and 4 default trials in case of failure\n$job = new Job([\n    $caller1,\n    $caller2\n], 4);\n\n// Job initial state to store in database\n$initialJobState = $job-\u003edump(DumpType::$JSON);\nvar_dump($initialJobState);\n\n$currentJobState = $initialJobState;\n$finished = false;\n$currentJob = null;\n\nwhile (!$finished) {\n    $currentJob = Factory::job()-\u003ereload($currentJobState, DumpType::$JSON);\n    $currentJob-\u003eexecute();\n    $finished = (($currentJob-\u003egetStatus() == JobStatus::$FAILED) || ($currentJob-\u003egetStatus() == JobStatus::$SUCCEEDED)) ? true : false;\n    $currentJobState = $currentJob-\u003edump(DumpType::$JSON);\n    sleep(5);\n}\n\nif( $currentJob != null ){\n    var_dump($currentJob-\u003egetStatus());\n    var_dump($currentJob-\u003egetCaller(\"stop_virtual_machine\")-\u003egetStatus());\n    var_dump($currentJob-\u003egetCaller(\"stop_virtual_machine\")-\u003eresponse()-\u003egetResponse());\n    var_dump($currentJob-\u003egetCaller(\"stop_virtual_machine\")-\u003eresponse()-\u003egetErrorCode());\n    var_dump($currentJob-\u003egetCaller(\"stop_virtual_machine\")-\u003eresponse()-\u003egetErrorMessage());\n    var_dump($currentJob-\u003egetCaller(\"start_virtual_machine\")-\u003egetStatus());\n    var_dump($currentJob-\u003egetCaller(\"start_virtual_machine\")-\u003eresponse()-\u003egetResponse());\n    var_dump($currentJob-\u003egetCaller(\"start_virtual_machine\")-\u003eresponse()-\u003egetErrorCode());\n    var_dump($currentJob-\u003egetCaller(\"start_virtual_machine\")-\u003eresponse()-\u003egetErrorMessage());\n    var_dump($currentJob-\u003edump(DumpType::$JSON));\n}\n```\n\n### More Complex Usage\n\nLet's make it more complex, Now we need to deploy a virtual server with these data:\n\n- Template `CentOS 5.6 (64-bit) no GUI (Simulator)`\n- Service Offering: `Small Instance`\n- Zone: `Sandbox-simulator`\n\nAnd as you know [from API we need the id of the template, service offering and zone](http://cloudstack.apache.org/api/apidocs-4.11/apis/deployVirtualMachine.html). In this case we will create a separate callers to get these ids before we deploy the virtual server. and we will use response callbacks to store these ids in the caller shared data to be used by the job object.\n\n\n```php\ninclude_once dirname(__FILE__) . '/vendor/autoload.php';\n\nuse Clivern\\Monkey\\Util\\Config;\nuse Clivern\\Monkey\\API\\Request\\PlainRequest;\nuse Clivern\\Monkey\\API\\Response\\PlainResponse;\nuse Clivern\\Monkey\\API\\Request\\RequestMethod;\nuse Clivern\\Monkey\\API\\Request\\RequestType;\nuse Clivern\\Monkey\\API\\Caller;\nuse Clivern\\Monkey\\API\\Job;\nuse Clivern\\Monkey\\API\\DumpType;\nuse Clivern\\Monkey\\API\\Factory;\nuse Clivern\\Monkey\\API\\JobStatus;\nuse Clivern\\Monkey\\API\\CallerStatus;\n\n\nclass TemplatesFilter\n{\n    public static function addTemplateId($caller, $arguments)\n    {\n        if ($caller-\u003egetStatus() !=  CallerStatus::$SUCCEEDED) {\n            return false;\n        }\n        $response = $caller-\u003eresponse()-\u003egetResponse();\n        if( !is_array($response) || !isset($response[\"listtemplatesresponse\"]) || !isset($response[\"listtemplatesresponse\"][\"template\"]) ){\n            return false;\n        }\n        foreach ($response[\"listtemplatesresponse\"][\"template\"] as $template) {\n            if(isset($arguments['template_name']) \u0026\u0026 ($template['name'] == $arguments['template_name'])) {\n                $caller-\u003eaddItem(\"templateid\", $template['id']);\n                break;\n            }elseif(!isset($arguments['template_name'])){\n                $caller-\u003eaddItem(\"templateid\", $template['id']);\n                break;\n            }\n        }\n\n        if( empty($caller-\u003egetItem(\"templateid\")) ){\n            $caller-\u003esetStatus(CallerStatus::$FAILED);\n            $caller-\u003eresponse()-\u003esetErrorCode(\"M200\");\n            $caller-\u003eresponse()-\u003esetErrorMessage((isset($arguments['template_name']))\n                ? sprintf(\"Error! Can't find template with name: %s\", $arguments['template_name'])\n                : \"Error! Can't find any template.\"\n            );\n        }\n    }\n}\n\nclass ServiceOfferingsFilter\n{\n    public static function addServiceOfferId($caller, $arguments)\n    {\n        if ($caller-\u003egetStatus() !=  CallerStatus::$SUCCEEDED) {\n            return false;\n        }\n        $response = $caller-\u003eresponse()-\u003egetResponse();\n        if( !is_array($response) || !isset($response[\"listserviceofferingsresponse\"]) || !isset($response[\"listserviceofferingsresponse\"][\"serviceoffering\"]) ){\n            return false;\n        }\n        foreach ($response[\"listserviceofferingsresponse\"][\"serviceoffering\"] as $serviceoffering) {\n            if(isset($arguments['serviceoffering_name']) \u0026\u0026 ($serviceoffering['name'] == $arguments['serviceoffering_name'])) {\n                $caller-\u003eaddItem(\"serviceofferingid\", $serviceoffering['id']);\n                break;\n            }elseif(!isset($arguments['serviceoffering_name'])){\n                $caller-\u003eaddItem(\"serviceofferingid\", $serviceoffering['id']);\n                break;\n            }\n        }\n        if( empty($caller-\u003egetItem(\"serviceofferingid\")) ){\n            $caller-\u003esetStatus(CallerStatus::$FAILED);\n            $caller-\u003eresponse()-\u003esetErrorCode(\"M200\");\n            $caller-\u003eresponse()-\u003esetErrorMessage((isset($arguments['serviceoffering_name']))\n                ? sprintf(\"Error! Can't find service offering with name: %s\", $arguments['serviceoffering_name'])\n                : \"Error! Can't find any service offering.\"\n            );\n        }\n    }\n}\n\nclass ZoneFilter\n{\n    public static function addZoneId($caller, $arguments)\n    {\n        if ($caller-\u003egetStatus() !=  CallerStatus::$SUCCEEDED) {\n            return false;\n        }\n        $response = $caller-\u003eresponse()-\u003egetResponse();\n        if( !is_array($response) || !isset($response[\"listzonesresponse\"]) || !isset($response[\"listzonesresponse\"][\"zone\"]) ){\n            return false;\n        }\n        foreach ($response[\"listzonesresponse\"][\"zone\"] as $zone) {\n            if(isset($arguments['zone_name']) \u0026\u0026 ($zone['name'] == $arguments['zone_name'])) {\n                $caller-\u003eaddItem(\"zoneid\", $zone['id']);\n                break;\n            }elseif(!isset($arguments['zone_name'])){\n                $caller-\u003eaddItem(\"zoneid\", $zone['id']);\n                break;\n            }\n        }\n        if( empty($caller-\u003egetItem(\"zoneid\")) ){\n            $caller-\u003esetStatus(CallerStatus::$FAILED);\n            $caller-\u003eresponse()-\u003esetErrorCode(\"M200\");\n            $caller-\u003eresponse()-\u003esetErrorMessage((isset($arguments['zone_name']))\n                ? sprintf(\"Error! Can't find zone with name: %s\", $arguments['zone_name'])\n                : \"Error! Can't find any zone.\"\n            );\n        }\n    }\n}\n\n$config = new Config();\n$config-\u003eaddCloudStackServer(\"us_dc_clsk_01\", [\n    \"api_url\"   =\u003e \"http://clsk_url.com:8080/client/api\",\n    \"api_key\"    =\u003e \"api_key_here\",\n    \"secret_key\" =\u003e \"secret_key_here\"\n]);\n\n$request1 = new PlainRequest();\n$request1-\u003esetMethod(RequestMethod::$GET)\n        -\u003esetType(RequestType::$SYNCHRONOUS)\n        -\u003eaddParameter(\"command\", \"listTemplates\")\n        -\u003eaddParameter(\"templatefilter\", \"featured\");\n\n$response1 = new PlainResponse(\"\\TemplatesFilter::addTemplateId\", [\"template_name\" =\u003e \"CentOS 5.6 (64-bit) no GUI (Simulator)\"]);\n\n$caller1 = new Caller($request1, $response1, \"list_templates\", $config-\u003egetCloudStackServer(\"us_dc_clsk_01\"));\n\n\n$request2 = new PlainRequest();\n$request2-\u003esetMethod(RequestMethod::$GET)\n        -\u003esetType(RequestType::$SYNCHRONOUS)\n        -\u003eaddParameter(\"command\", \"listServiceOfferings\");\n\n$response2 = new PlainResponse(\"\\ServiceOfferingsFilter::addServiceOfferId\", [\"serviceoffering_name\" =\u003e \"Small Instance\"]);\n\n$caller2 = new Caller($request2, $response2, \"list_service_offering\", $config-\u003egetCloudStackServer(\"us_dc_clsk_01\"));\n\n\n$request3 = new PlainRequest();\n$request3-\u003esetMethod(RequestMethod::$GET)\n        -\u003esetType(RequestType::$SYNCHRONOUS)\n        -\u003eaddParameter(\"command\", \"listZones\");\n\n$response3 = new PlainResponse(\"\\ZoneFilter::addZoneId\", [\"zone_name\" =\u003e \"Sandbox-simulator\"]);\n\n$caller3 = new Caller($request3, $response3, \"list_zone\", $config-\u003egetCloudStackServer(\"us_dc_clsk_01\"));\n\n\n$request4 = new PlainRequest();\n$request4-\u003esetMethod(RequestMethod::$GET)\n        -\u003esetType(RequestType::$ASYNCHRONOUS)\n        -\u003eaddParameter(\"command\", \"deployVirtualMachine\")\n        -\u003eaddParameter(\"serviceofferingid\", \"@list_service_offering-\u003eserviceofferingid\")\n        -\u003eaddParameter(\"templateid\", \"@list_templates-\u003etemplateid\")\n        -\u003eaddParameter(\"zoneid\", \"@list_zone-\u003ezoneid\");\n\n$response4 = new PlainResponse();\n\n$caller4 = new Caller($request4, $response4, \"deploy_virtual_machine\", $config-\u003egetCloudStackServer(\"us_dc_clsk_01\"));\n\n\n// Create a job with four callers and 4 default trials in case of failure\n$job = new Job([\n    $caller1,\n    $caller2,\n    $caller3,\n    $caller4\n], 4);\n\n// Job initial state to store in database\n$initialJobState = $job-\u003edump(DumpType::$JSON);\nvar_dump($initialJobState);\n\n$currentJobState = $initialJobState;\n$finished = false;\n$currentJob = null;\n\nwhile (!$finished) {\n    $currentJob = Factory::job()-\u003ereload($currentJobState, DumpType::$JSON);\n    $currentJob-\u003eexecute();\n    $finished = (($currentJob-\u003egetStatus() == JobStatus::$FAILED) || ($currentJob-\u003egetStatus() == JobStatus::$SUCCEEDED)) ? true : false;\n    $currentJobState = $currentJob-\u003edump(DumpType::$JSON);\n    sleep(5);\n}\n\nif( $currentJob != null ){\n    var_dump($currentJob-\u003egetStatus());\n\n    var_dump($currentJob-\u003egetCaller(\"list_service_offering\")-\u003egetStatus());\n    var_dump($currentJob-\u003egetCaller(\"list_service_offering\")-\u003eresponse()-\u003egetResponse());\n    var_dump($currentJob-\u003egetCaller(\"list_service_offering\")-\u003eresponse()-\u003egetErrorCode());\n    var_dump($currentJob-\u003egetCaller(\"list_service_offering\")-\u003eresponse()-\u003egetErrorMessage());\n\n    var_dump($currentJob-\u003egetCaller(\"list_templates\")-\u003egetStatus());\n    var_dump($currentJob-\u003egetCaller(\"list_templates\")-\u003eresponse()-\u003egetResponse());\n    var_dump($currentJob-\u003egetCaller(\"list_templates\")-\u003eresponse()-\u003egetErrorCode());\n    var_dump($currentJob-\u003egetCaller(\"list_templates\")-\u003eresponse()-\u003egetErrorMessage());\n\n    var_dump($currentJob-\u003egetCaller(\"list_zone\")-\u003egetStatus());\n    var_dump($currentJob-\u003egetCaller(\"list_zone\")-\u003eresponse()-\u003egetResponse());\n    var_dump($currentJob-\u003egetCaller(\"list_zone\")-\u003eresponse()-\u003egetErrorCode());\n    var_dump($currentJob-\u003egetCaller(\"list_zone\")-\u003eresponse()-\u003egetErrorMessage());\n\n    var_dump($currentJob-\u003egetCaller(\"deploy_virtual_machine\")-\u003egetStatus());\n    var_dump($currentJob-\u003egetCaller(\"deploy_virtual_machine\")-\u003eresponse()-\u003egetResponse());\n    var_dump($currentJob-\u003egetCaller(\"deploy_virtual_machine\")-\u003eresponse()-\u003egetErrorCode());\n    var_dump($currentJob-\u003egetCaller(\"deploy_virtual_machine\")-\u003eresponse()-\u003egetErrorMessage());\n    var_dump($currentJob-\u003edump(DumpType::$JSON));\n}\n```\n\n### Monkey on Production\n\nHere I was trying to describe different usage cases of monkey but in case of production, we must have a database table(s) for our jobs and executer to run our jobs in background.\n\nWe will need custom request classes for each specific command so we don't need to provide command data every time we create a request.\n\n```php\nuse Clivern\\Monkey\\API\\Contract\\RequestInterface;\nuse Clivern\\Monkey\\API\\Request\\PlainRequest;\n\n\nclass CreateUser extends PlainRequest implements RequestInterface {\n\n}\n```\n\nWe will need custom response classes for each specific command so we don't need to parse the response to fetch the useful response data and has a direct method to do that.\n\n```php\nuse Clivern\\Monkey\\API\\Contract\\ResponseInterface;\nuse Clivern\\Monkey\\API\\Response\\PlainResponse;\n\n\nclass CreateUser extends PlainResponse implements ResponseInterface {\n\n}\n```\n\nAlso build our response callbacks for calls so when we use it, we will be sure that these data will be available for other callers within the job.\n\n### Usage as Command Line Tool\n\nCreate an executable file `run`\n```bash\n$ touch run\n$ chmod u+x run\n```\n\n```php\n#!/usr/bin/env php\n\u003c?php\n\ninclude_once dirname(__FILE__) . '/vendor/autoload.php';\n\nuse Clivern\\Monkey\\Util\\Config;\nuse Clivern\\Monkey\\API\\Request\\PlainRequest;\nuse Clivern\\Monkey\\API\\Response\\PlainResponse;\nuse Clivern\\Monkey\\API\\Request\\RequestMethod;\nuse Clivern\\Monkey\\API\\Request\\RequestType;\nuse Clivern\\Monkey\\API\\Caller;\n\n$platform = false;\n\nforeach ($argv as $value) {\n    if(strpos($value, \"platform=\") !== false){\n        $platform = str_replace(\"platform=\", \"\", $value);\n    }\n}\n\n$command = false;\n\nforeach ($argv as $value) {\n    if(strpos($value, \"command=\") !== false){\n        $command = str_replace(\"command=\", \"\", $value);\n    }\n}\n\nif(empty($command) || empty($platform)){\n    die(\"Please Provide Command and The Platform ID\");\n}\n\n$config = new Config();\n$config-\u003eaddCloudStackServer(\"us_dc_clsk_01\", [\n    \"api_url\"   =\u003e \"http://clsk_url.com:8080/client/api\",\n    \"api_key\"    =\u003e \"api_key_here\",\n    \"secret_key\" =\u003e \"secret_key_here\"\n]);\n\n\n$request = new PlainRequest();\n$request-\u003esetMethod(RequestMethod::$GET)\n        -\u003esetType(RequestType::$SYNCHRONOUS)\n        -\u003eaddParameter(\"command\", $command);\n\n\nforeach ($argv as $value) {\n    if((strpos($value, \"command=\") === false) \u0026\u0026 (strpos($value, \"platform=\") === false) \u0026\u0026 strpos($value, \"=\")){\n        $parameter = explode(\"=\", $value);\n        $request-\u003eaddParameter($parameter[0], $parameter[1]);\n    }\n}\n\n// Create response object without callbacks\n$response = new PlainResponse();\n\n// Create a caller object with the request and response and ident\n$caller = new Caller($request, $response, $command, $config-\u003egetCloudStackServer($platform));\n\n// Run the call\n$caller-\u003eexecute();\n\n$data = $caller-\u003eresponse()-\u003egetResponse();\n\necho json_encode($data);\n```\n\n```\n$ ./run platform=us_dc_clsk_01 command=$$ arg=$$\n$ ./run platform=us_dc_clsk_01 command=$$ arg=$$ | python -m json.tool\n```\n\n\nMisc\n====\n\nChangelog\n---------\nVersion 1.1.0:\n```\nUpdate dependencies.\n```\n\nVersion 1.0.6:\n```\nEnhance code style.\nAutomate code fixes and linting.\n```\n\nVersion 1.0.5:\n```\nDocs Updated.\n```\n\nVersion 1.0.4:\n```\nDocs Updated.\n```\n\nVersion 1.0.3:\n```\nDocs Updated.\n```\n\nVersion 1.0.2:\n```\nForce caller failure in callbacks in case of unexpected response.\n```\n\nVersion 1.0.1:\n```\nAdd More Test Cases.\n```\n\nVersion 1.0.0:\n```\nInitial Release.\n```\n\nAcknowledgements\n----------------\n\n© 2018, Clivern. Released under [MIT License](https://opensource.org/licenses/mit-license.php).\n\n**Monkey** is authored and maintained by [@clivern](http://github.com/clivern).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclivern%2Fmonkey","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclivern%2Fmonkey","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclivern%2Fmonkey/lists"}