laravel / forge-sdk Goto Github PK
View Code? Open in Web Editor NEWThe official Laravel Forge PHP SDK.
Home Page: https://forge.laravel.com
License: MIT License
The official Laravel Forge PHP SDK.
Home Page: https://forge.laravel.com
License: MIT License
I cannot seem to find a way to reboot a server using this SDK.
Hello,
I used laravel/forge-sdk 3.3, for this pretty simple creation script:
$forge = new Laravel\Forge\Forge($API_TOKEN);
$server = $forge->createServer([
"provider"=> "custom",
"name"=> "xxx",
"ip_address"=> "x.x.x.x",
"private_ip_address"=> "x.x.x.x",
"php_version"=> "php74"
]);
?>
As Response I simply get this:
PHP Fatal error: Uncaught Laravel\Forge\Exceptions\ValidationException: The given data failed to pass validation. in /home/technik/forge-api/vendor/laravel/forge-sdk/src/MakesHttpRequests.php:98
Stack trace:
#0 /home/technik/forge-api/vendor/laravel/forge-sdk/src/MakesHttpRequests.php(76): Laravel\Forge\Forge->handleRequestError()
#1 /home/technik/forge-api/vendor/laravel/forge-sdk/src/MakesHttpRequests.php(34): Laravel\Forge\Forge->request()
#2 /home/technik/forge-api/vendor/laravel/forge-sdk/src/Actions/ManagesServers.php(44): Laravel\Forge\Forge->post()
#3 /home/technik/forge-api/create-server.php(10): Laravel\Forge\Forge->createServer()
#4 {main}
thrown in /home/technik/forge-api/vendor/laravel/forge-sdk/src/MakesHttpRequests.php on line 98
Actually I wanted to create type node_balancer, but I have no clue which fields are required and which are optional. I have only two types of devices, load balancers or web servers. Can someone give me an hint in the right direction?
Best Regards
Matthias
Can't add use enableHipchatNotifications
method and no methods/properties for other webhooks like Discord and Teams.
When using the HipChat method there is a The resource you are looking for could not be found.
response.
(new Forge('apiKey'))->enableHipchatNotifications('serverId', 'siteId', ["webhook_url": "webhook.com"])
I might be setting the data incorrectly but there is also no explination on usage.
The following API endpoints seem to require a valid CSRF token:
PUT /servers/{id}/php/cli
PUT /servers/{id}/php/default
DELETE /servers/{id}/php
Could they be made available for programmatic use, i.e. without CSRF tokens?
Would be nice to have command line calls so we could include some forge-commands in an automated docker/ci setup for example.
There are a couple of options available like: https://github.com/svenluijten/forge-cli
But I think this is useful enough to be included in the API.
When executing the installGitRepositoryOnSite()
method and setting the $wait
parameter to false the following error is thrown: Unsupported operand types
. Thrown in: src/Actions/ManagesSites.php
line 188.
The problem is that POST /api/v1/servers/{serverId}/sites/{siteId}/git
returns an empty response, causing the $site
variable to be ""
. Then, on line 188 a new Site resource is being created using the union operator: $site + ['server_id' => $serverId]
. We can't add an array to a string using the union operator. Also, should it be possible to have a site resource with only the server_id
attribute?
I can make a fix, but I'm not sure what the expected behaviour should be. Make another API call to get the site resource? Something like:
$this->post("servers/$serverId/sites/$siteId/git", $data);
if ($wait) {
return $this->retry($this->getTimeout(), function () use ($serverId, $siteId) {
$site = $this->site($serverId, $siteId);
return $site->repositoryStatus === 'installed' ? $site : null;
});
}
$site = $this->get("servers/$serverId/sites/$siteId");;
return new Site($site + ['server_id' => $serverId], $this);
Call the following method:
$forge->installGitRepositoryOnSite(1, 1, false);
When running $site->deploySite()
it throws this exception:
TypeError
Laravel\Forge\Exceptions\TimeoutException::__construct(): Argument #1 ($output) must be of type array, null given, called in vendor/laravel/forge-sdk/src/MakesHttpRequests.php on line 138
at vendor/laravel/forge-sdk/src/Exceptions/TimeoutException.php:22
18▕ *
19▕ * @param array $output
20▕ * @return void
21▕ */
➜ 22▕ public function __construct(array $output)
23▕ {
24▕ parent::__construct('Script timed out while waiting for the process to complete.');
25▕
26▕ $this->output = $output;
$forge = new Forge('api_key');
$server = $forge->servers()[0];
$site = $forge->sites($server->id)[0];
$site->deploySite();
3.13.3
9.52.4
8.1.17
No response
Activating a new certificate on a Forge server could take longer than the default timeout of 30 seconds which leads to a timeout error. To avoid this i have increased the timeout by using the Forge::setTimeout() function. However, when calling the ManagesCertificates::activateCertificate() function the timeout still occurs after 30 seconds. Looking into its code shows, that a timeout of 30 is passed to the retry() function as hard coded value. This applies to ManagesCertificates::installCertificate(), ManagesDaemons::restartDaemon() and ManagesWorkers::restartWorker() as well. All other calls to retry() use $this->getTimeout() to determine the timeout which is the expected bahaviour.
I'll check this out and see if a PR is needed, but at first look it feel like the return inside the $wait
conditional needs to be a Site
object and not just return $site
public function createSite($serverId, array $data, $wait = true)
{
$site = $this->post("servers/$serverId/sites", $data)['site'];
if ($wait) {
return $this->retry($this->getTimeout(), function () use ($serverId, $site) {
$site = $this->site($serverId, $site['id']);
return $site->status == 'installed' ? $site : null;
});
}
return new Site($site + ['server_id' => $serverId], $this);
}
i try to use this sdk and passing data like in documentation but i got validation errors
( new Forge(token was passing))->createDatabaseUser(123, ['name' => 'name', 'password' => 'password, "databases" =>[123]])
errors
production.ERROR: The given data failed to pass validation. {"exception":"[object] (Laravel\\Forge\\Exceptions\\ValidationException(code: 0): The given data failed to pass validation. at /vendor/laravel/forge-sdk/src/MakesHttpRequests.php:104)
in docs like this
[⊖](https://forge.laravel.com/api-documentation#){
"name": "forge",
"password": "dolores",
"databases": [⊖](https://forge.laravel.com/api-documentation#)[
1
]
}
i really appreciate your help thanks
I'm using the SDK to create a database backup configuration, and it returns no data because of an error. However, the configuration backup is created on Forge Panel.
[2020-06-19 17:59:28] local.ERROR: array_map(): Expected parameter 2 to be an array, null given {"exception":"[object] (ErrorException(code: 0): array_map(): Expected parameter 2 to be an array, null given at /Sites/vendor/themsaid/forge-sdk/src/Resources/Resource.php:80)
[stacktrace]
#0 [internal function]: Illuminate\\Foundation\\Bootstrap\\HandleExceptions->handleError(2, 'array_map(): Ex...', '/Sites...', 80, Array)
#1 /Sites/vendor/themsaid/forge-sdk/src/Resources/Resource.php(80): array_map(Object(Closure), NULL)
#2 /Sites/vendor/themsaid/forge-sdk/src/Resources/BackupConfiguration.php(92): Themsaid\\Forge\\Resources\\Resource->transformCollection(NULL, 'Themsaid\\\\Forge\\\\...', Array)
#3 /Sites/vendor/themsaid/forge-sdk/src/Actions/ManagesBackups.php(51): Themsaid\\Forge\\Resources\\BackupConfiguration->__construct(Array, Object(Themsaid\\Forge\\Forge))
#4 /Sites/app/Jobs/Master/Domains/Database/SetupForgeBackup.php(91): Themsaid\\Forge\\Forge->createBackupConfiguration('(reserved)', Array)
#5 [internal function]: App\\Jobs\\Master\\Domains\\Database\\SetupForgeBackup->handle()
Any idea?
The $apiKey in the Forge class constructor should be optional along with having a setApiKey method.
I am working with multiple Forge tokens, so I need to be able to change the api key dynamically.
Let me know if you'll accept a PR for this.
Hi,
it seems that forge have updated their API with regards to restarting PHP. You now need to include the Version of PHP that you want to restart (as forge servers can now handle multiple versions of PHP on the same server).
If you do not provide the PHP version then you get a validation error when trying the API request.
Can you please update the SDK so that it supports this.
Thanks :)
Retrieving the Ubuntu version from the server using the undeclared ubuntuVersion property does not return a version below 20.04. We have many servers and are developing a tool to tell us which ones are EOL to streamline the migration process.
This may have more to do with the Forge platform itself than the SDK, but I believe if this could be fixed in Forge's core it could make a great addition to the Forge SDK.
Hi,
I managed to run following methods:
$forge->createSite($server_id,$site_data, true);
$forge->installGitRepositoryOnSite($server_id, $site_id, $repository_data);
$forge->updateSiteDeploymentScript($server_id, $site_id, $content);
But following commands doesn't take any effects. Is there any specific needs to run the following commands:
$forge->updateSiteEnvironmentFile($server_id, $site_id, $content);
$forge->deploySite($server_id,$site_id);
I send a api request from localhost to forge. It works create, your package create the site, ssl, gitrepo..All works!!
But this works only on localhost. If i make this from a real site on forge, i get only 1 error:
"502 Bad Gateway Nginx". This error is not a part from the api documentation. I dont know, why it works from localhost, but not from forge :(
Thanks for help :)
The server provider was unable to create your server
When creating a new server on Digital Ocean.
I've written a script that basically exports everything from the forge api and stores it in a local database and with 10 servers and 160 sites I am running into the 429 Too Many Attempts error.
However in the api docs I am unable to see anything about a rate limit, and also I don't have experience with setting a rate limit locally so I don't hammer the api.
Any chance you could introduce this? Or at least provide some directions on how I could easily achieve this (the proper way) so I can run my "populate" script in the future and not fear of running into the "Too many attempts" limit?
Many thanks
When requesting the log for a deployment (giving server id, site id and deployment id). I always get the same deployment log.
I see that you are calling the right api endpoint for this, but i guess it might be more of an issue with Forge itself. The Forge UI works great but the same info using the API is wrong, all the time.
Request 2 different logs of 2 different deployments.
When a site has only one alias and update that site with empty aliases array that last alias is not removed.
The FPM Pool can be updated from the forge web interface, and this option must be available in the SDK.
Hi,
i want to store data in cache to avoid hit everytime to the server API
public function index(Forge $forge)
{
$servers = Cache::rememberForever('servers', function () use ($forge) {
return $forge->servers();
});
}
I'm getting this error
Exception: Serialization of 'Closure' is not allowed
any solution you have?
regards
$forge->servers();
includes "archived" servers.
Perhaps that's because GET /api/v1/servers
doesn't indicate whether a server is archived vs active?
I’m automatically creating a site (createSite()
), installing git (installGitRepository()
), creating a database (createDatabase()
) and setting all the environment variables (updateSiteEnvironmentFile()
). I perform the API requests in this order as well, but I check if the site status, git status and database status is correct before going to the next step. When coming to the last step I retrieve the default content of the environment file using siteEnvironmentFile()
. Then, I change the variables which need to change. At last, I update the env file using updateSiteEnvironmentFile()
.
Now if I go to the site on Forge and check the Environment tab, I see the original/default content of the env file. It seems/feels like Forge updates the env file one more time with the default content right after everything is installed. A few things which come to mind: maybe I’m updating the .env
file too fast or maybe the .env
file is not created yet? But this is a wild guess. If I execute the exact same code after (let’s say) 30 seconds, it does work. That’s why I think Forge updates/overrides it.
The code for updating the env file:
protected function updateEnvFile(Site $site)
{
$env = ForgeManager::api()->siteEnvironmentFile($site->serverId, $site->id);
dump($env); // First line outputs: APP_NAME={{app_name}}\n
$attributes = collect([
'APP_NAME' => $this->catalog->id,
'APP_ENV' => 'production',
'APP_DEBUG' => 'true',
'APP_URL' => "https://{$site->name}",
'DB_DATABASE' => data_get($this->attributes, 'database.name'),
'DB_USERNAME' => data_get($this->attributes, 'database.user'),
'DB_PASSWORD' => data_get($this->attributes, 'database.password'),
]);
foreach ($attributes as $key => $value) {
$env = preg_replace("/^{$key}=(.*)\n/m", "$key=$value\n", $env);
}
ForgeManager::api()->updateSiteEnvironmentFile($site->serverId, $site->id, $env);
dump($env); // First line outputs: APP_NAME=38\n
}
So if you check what the dump outputs on the last line, it seems like the content which is sent to the API is correct.
Hi,
in docs I can't found a way to create a database using api with specific collation.
There is a way to do this ?
if not maybe can be improved.
regards.
ErrorException : Illegal string offset 'site'
at /Users/christiangiupponi/Dev/Projects/ZerounoToolbox/vendor/themsaid/forge-sdk/src/Actions/ManagesSites.php:48
44| * @return Site
45| */
46| public function createSite($serverId, array $data, $wait = true)
47| {
> 48| $site = $this->post("servers/$serverId/sites", $data)['site'];
49|
50| if ($wait) {
51| return $this->retry($this->getTimeout(), function () use ($serverId, $site) {
52| $site = $this->site($serverId, $site['id']);
Exception trace:
1 Illuminate\Foundation\Bootstrap\HandleExceptions::handleError("Illegal string offset 'site'", "/Users/christiangiupponi/Dev/Projects/ZerounoToolbox/vendor/themsaid/forge-sdk/src/Actions/ManagesSites.ph
p", [])
/Users/christiangiupponi/Dev/Projects/ZerounoToolbox/vendor/themsaid/forge-sdk/src/Actions/ManagesSites.php:48
2 Themsaid\Forge\Forge::createSite(["prova-completa.example.com", "/public", "php"])
/Users/christiangiupponi/Dev/Projects/ZerounoToolbox/app/Commands/SetUpStaging.php:203
Please use the argument -v to see more details.
Unable to create the database on a live server.
`namespace App\Jobs;
use Themsaid\Forge\Forge;
$forge = new \Themsaid\Forge\Forge(config('app.forge_access_token'));
$databaseCreated = $forge->createMysqlDatabase(
config('app.forge_server_id'), array('name' => 'test_1234'), $wait = true
);
Error: Class 'Themsaid\Forge\Forge' not found in /home/forge/website.com/app/Jobs/CreateDatabase.php:47`
Heya 🙂
I know the lib is still in beta / not even 1.0.0, but I figured I'd give it a shot and I'm immediately encountering the infamous Guzzle error:
[GuzzleHttp\Exception\RequestException]
cURL error 60: SSL certificate problem: unable to get local issuer certificate (see http://curl.haxx.se/libcu
rl/c/libcurl-errors.html)
Can this be resolved in the scope of this package or should something be done on my end to make it work?
Thanks!
Hi there,
I get this error when calling $forge->installCertificate
but not much information is shown about the error: The given data failed to pass validation. {"exception":"[object] (Themsaid\Forge\Exceptions\ValidationException(code: 0): The given data failed to pass validation. at /vendor/themsaid/forge-sdk/src/MakesHttpRequests.php:90)
Error doesn't specify why it failed validation.
I believe there is a similar ticket but this is for a different api method.
UPDATE1: 0 => "The certificate field is required."
But I'm definitely passing the certificate id.
UPDATE2: I might be using the sdk wrong. What I want to do is: I already have a certificate installed for my a site and want to install it for other sites. Is there a specific API workflow I should follow? The official api docs says: "certificate": "certificate content", but I have no idea what "certificate content" means or where to get it from?
When trying to find a server (or anything else) i've this error (on my local):
Don't know, i can't reproduce it in production.
Do you have any idea to solve this ?
Thanks for your help !
When retry method is used (Like in installCertificate, activateCertificate, etc) callback sent a boolean as result
This boolean is being sent to TimeoutException
constructor (MakesHttpRequests->retry method) which causes a fatal error, becasue TimeoutException expects null or array values, not booleans.
This was reported and handled partially in #109, but not fixed for all the cases.
Just replace any retry callback to return false and wait the timeout :)
Undefined index: provision_command in /Actions/ManagesServers.php on line 45
I'm getting this error with createServer()
https://github.com/themsaid/forge-sdk/blob/2.0/src/Actions/ManagesServers.php#L38
I keep getting this error when attempting to create a new server on forge using the code below
The given data failed to pass validation.
$this->forge->createServer([
'provider' => 'aws',
'credential_id' => 1,
'name' => 'fancy-mist',
'size' => '1GB',
'php_version' => 'php72',
'region' => 'London',
]);
I can use the following code on the same setup successfully and I don't get this error.
$this->forge->servers();
Not sure why this is happening, if there is any more info you need please ask and i'll provide it.
Just wondering how you can run a recipe on a specific server or set of servers
in the api docs the payload is described as
⊖{
"servers": ⊖[
1,
2
]
}
but according to your docs the runRecipe() only accepts a recipeId?
Add webhook management to the package.
I noticed there's no way to remove Blackfire from the server as it stands, but the API documentation does mention it.
When I wanted to add the function and send in a PR (#4), I noticed some little inconsistencies in the Forge docs or this package. The installBlackfire()
method makes a POST
request to /servers/$serverId/blackfire/install
, while the docs say that you have to post to blackfire/install
and pass the server ID in the request payload.
There are options in the forge API to make a get request and get a list of webhooks on a website, but its not in your SDK, is there a particular reason for this? Would be useful if it were implemented for sure
According to docs there's no way to update the databases selected in an existing Backup Configuration? There's an option in the web gui to do this, at least with Provider set as Custom (S3 Compatible). You can edit and include additional databases.
This would be great to have for automated provisioning scripts.
Using CreateSite method and isolation = true
website goes on 502 error.
Create Site
$siteParams = [
"domain" => $siteSlug .".socialdrinks.it",
"project_type" => "php",
"directory" => "/public",
"isolated" => true,
"php_version" => "php74"
];
$forge = new Laravel\Forge\Forge($token,$guzzleClient);
$forge->createSite($serverId, $siteParams,false);
Site is created but the website response is 502 bad gateway.
regards.
.g
Would you accept a PR on adding this?
Right now I have to manually ensure that the $site->repositoryStatus !== 'installing'
Installing an SSL certificate accepts a payload (as documented here), but the SDK doesn't seem to do so. I'm unsure whether or not this is an issue with Forge's documentation or an issue on this SDK, I'll let you decide that 😉
Thanks in advance.
I have a deployment script that creates a database with a couple of tables and I was hoping I could run some php code after the deployment to populate those tables. Is there a way to sync to forge's deployment?
Hello,
Is there a reason why it is not possible to restart the php-fpm service from this sdk?
It is just a personal idea (and preference) to hold all the relevant options inside classes, this gives, at least for me somehow a consistency layer on the right way of passing options as strings to the API.
Given the example on a request for creating a server:
I will like to add classes under the namespace Themsaid\Forge\Helpers
to hold constants of valid options to pass to the API, as follows:
<?php
namespace Themsaid\Forge\Helpers;
class ProvisionableServers
{
const VULTR = 'vultr'
const DIGITAL_OCEAN = 'ocean2'
}
That way when the users are creating a request, they can Reference the helper class instead of typing the option by themselves and having the risk of making a mistake. Also this turns options into a versionable element that can reflect adittions and changes to the API signature in the future.
<?php
// Import autoload and so on ...
$server = $forge->createServer([
"provider"=> ProvisionableServers::DIGITAL_OCEAN,
"credential_id"=> 1,
"name"=> "test-via-api",
"size"=> ServerSize::512MB,
"database"=> "test123",
"php_version"=> InstallableServices::PHP_71,
"region"=> AvailableRegions::DIGITAL_OCEAN_AMS2,
]);
I will be able to crate a PR and also modify the sdk docs if you think this is something you will like to have it here 😄
Hello,
When I make a new site and in the same request edit the new site nginx file I get 502 error :(
I hope you can help me with that
Thanks
Is it possible to stop a server without rebooting? And starting it later using a different call? Eg. for scaling extra servers using an API?
Updated to 3.1.0 and am now receiving "The given data failed to pass validation." when using updateNodeBalancingConfiguration()
Was working previously under version 2.2
$server_data = [
'servers' => [
'id' => $server_id
],
'method' => 'least_conn'
];
$forge->updateNodeBalancingConfiguration(config('settings.forge_lb_id'), $site_id, $server_data);
PHP Warning: Undefined array key "provision_command" in /Users/richardhedges/Sites/hubv2/vendor/laravel/forge-sdk/src/Actions/ManagesServers.php on line 49
Run the createServer
method, as in the example in the docs.
Making a call to a wordpress api, I receive an error wich I didn't received in local development:
Handled error
Illuminate\Http\Client\ConnectionException: cURL error 35: error:14094458:SSL routines:ssl3_read_bytes:tlsv1 unrecognized name
It is a simple call with Http Client to an open wordpress API:
https://ilindy.com/wp-json/wp/v2/tags?per_page=100&page=1
This call is inside a Job, and I have installed Laravel Horizon.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.