2020-04-25 23:00:08 +03:00
< ? php
2020-10-02 00:11:13 +02:00
/*
### Description
This is a recipe that uses the [ cPanel 2 API ]( https :// documentation . cPanel . net / display / DD / Guide + to + cPanel + API + 2 ) .
Unfortunately the [ UAPI ]( https :// documentation . cPanel . net / display / DD / Guide + to + UAPI ) that is recommended does not have support for creating addon domains .
The main idea behind is for staging purposes but I guess you can use it for other interesting concepts .
The idea is , every branch possibly has its own staging domain / subdomain ( staging - neat - feature . project . com ) and database db_neat - feature_project so it can be tested .
This recipe can make the domain / subdomain and database creation part of the deployment process so you don ' t have to manually create them through an interface .
### Configuration
The example uses a . env file and Dotenv for configuration , but you can set the parameters as you wish
`` `
set ( 'cpanel' , [
'host' => getenv ( 'CPANEL_HOST' ),
'port' => getenv ( 'CPANEL_PORT' ),
'username' => getenv ( 'CPANEL_USERNAME' ),
'auth_type' => getenv ( 'CPANEL_AUTH_TYPE' ),
'token' => getenv ( 'CPANEL_TOKEN' ),
'user' => getenv ( 'CPANEL_USER' ),
'db_user' => getenv ( 'CPANEL_DB_USER' ),
'db_user_privileges' => getenv ( 'CPANEL_DB_PRIVILEGES' ),
'timeout' => 500 ,
'allowInStage' => [ 'staging' , 'beta' , 'alpha' ],
'create_domain_format' => '%s-%s-%s' ,
'create_domain_values' => [ 'staging' , 'master' , get ( 'application' )],
'subdomain_prefix' => substr ( md5 ( get ( 'application' )), 0 , 4 ) . '-' ,
'subdomain_suffix' => getenv ( 'SUDOMAIN_SUFFIX' ),
'create_db_format' => '%s_%s-%s-%s' ,
'create_db_values' => [ 'apps' , 'staging' , 'master' , get ( 'application' )],
]);
`` `
- `cpanel` – array with configuration for cPanel
- `username` – WHM account
- `user` – cPanel account that you want in charge of the domain
- `token` – WHM API token
- `create_domain_format` – Format for name creation of domain
- `create_domain_values` – The actual value reference for naming
- `subdomain_prefix` – cPanel has a weird way of dealing with addons and subdomains , you cannot create 2 addons with the same subdomain , so you need to change it in some way , example uses first 4 chars of md5 ( app_name )
- `subdomain_suffix` – cPanel has a weird way of dealing with addons and subdomains , so the suffix needs to be your main domain for that account for deletion purposes
- `addondir` – addon dir is different from the deploy path because cPanel " injects " / home / user / into the path , so tilde cannot be used
- `allowInStage` – Define the stages that cPanel recipe actions are allowed in
#### .env file example
`` `
CPANEL_HOST = xxx . xxx . xxx . xxx
CPANEL_PORT = 2087
CPANEL_USERNAME = root
CPANEL_TOKEN = xxxx
CPANEL_USER = xxx
CPANEL_AUTH_TYPE = hash
CPANEL_DB_USER = db_user
CPANEL_DB_PRIVILEGES = " ALL PRIVILEGES "
SUDOMAIN_SUFFIX =. mymaindomain . com
`` `
### Tasks
- `cpanel:createaddondomain` Creates an addon domain
- `cpanel:deleteaddondomain` Removes an addon domain
- `cpanel:createdb` Creates a new database
### Usage
A complete example with configs , staging and deployment
`` `
< ? php
namespace Deployer ;
use Dotenv\Dotenv ;
require 'vendor/autoload.php' ;
( Dotenv :: create ( __DIR__ )) -> load (); // this is used just so an .env file can be used for credentials
require 'cpanel.php' ;
// Project name
set ( 'application' , 'myproject.com' );
// Project repository
set ( 'repository' , 'git@github.com:myorg/myproject.com' );
set ( 'cpanel' , [
'host' => getenv ( 'CPANEL_HOST' ),
'port' => getenv ( 'CPANEL_PORT' ),
'username' => getenv ( 'CPANEL_USERNAME' ),
'auth_type' => getenv ( 'CPANEL_AUTH_TYPE' ),
'token' => getenv ( 'CPANEL_TOKEN' ),
'user' => getenv ( 'CPANEL_USER' ),
'db_user' => getenv ( 'CPANEL_DB_USER' ),
'db_user_privileges' => getenv ( 'CPANEL_DB_PRIVILEGES' ),
'timeout' => 500 ,
'allowInStage' => [ 'staging' , 'beta' , 'alpha' ],
'create_domain_format' => '%s-%s-%s' ,
'create_domain_values' => [ 'staging' , 'master' , get ( 'application' )],
'subdomain_prefix' => substr ( md5 ( get ( 'application' )), 0 , 4 ) . '-' ,
'subdomain_suffix' => getenv ( 'SUDOMAIN_SUFFIX' ),
'create_db_format' => '%s_%s-%s-%s' ,
'create_db_values' => [ 'apps' , 'staging' , 'master' , get ( 'application' )],
]);
host ( 'myproject.com' )
-> stage ( 'staging' )
-> set ( 'cpanel_createdb' , vsprintf ( get ( 'cpanel' )[ 'create_db_format' ], get ( 'cpanel' )[ 'create_db_values' ]))
-> set ( 'branch' , 'dev-branch' )
-> set ( 'deploy_path' , '~/staging/' . vsprintf ( get ( 'cpanel' )[ 'create_domain_format' ], get ( 'cpanel' )[ 'create_domain_values' ]))
-> set ( 'addondir' , 'staging/' . vsprintf ( get ( 'cpanel' )[ 'create_domain_format' ], get ( 'cpanel' )[ 'create_domain_values' ]));
// Tasks
task ( 'build' , function () {
run ( 'cd {{release_path}} && build' );
});
after ( 'deploy:prepare' , 'cpanel:createaddondomain' );
after ( 'deploy:prepare' , 'cpanel:createdb' );
`` `
*/
2020-04-25 23:00:08 +03:00
namespace Deployer ;
use Deployer\Task\Context ;
use \Gufy\CpanelPhp\Cpanel ;
/**
* @ return Cpanel
* @ throws Exception\Exception
*/
function getCpanel ()
{
$config = get ( 'cpanel' , []);
$allowInStage = $config [ 'allowInStage' ];
2021-11-03 15:48:48 +01:00
$stage = input () -> getArgument ( 'stage' );
2020-04-25 23:00:08 +03:00
if ( ! class_exists ( '\Gufy\CpanelPhp\Cpanel' )) {
throw new \RuntimeException ( " <comment>Please install php package</comment> <info>gufy/cpanel-php</info> <comment>to use CPanel API</comment> " );
}
if ( ! in_array ( $stage , $allowInStage )) {
throw new \RuntimeException ( sprintf ( " Since it creates addon domains and databases, CPanel recipe is available only in the %s environments " , implode ( $allowInStage )));
}
if ( ! is_array ( $config ) ||
! isset ( $config [ 'host' ]) ||
! isset ( $config [ 'port' ]) ||
! isset ( $config [ 'username' ]) ||
! isset ( $config [ 'token' ]) ||
! isset ( $config [ 'user' ]) ) {
throw new \RuntimeException ( " <comment>Please configure CPanel config:</comment> <info>set('cpanel', array('host' => 'xxx.xxx.xxx.xxx:', 'port' => 2087 , 'username' => 'root', 'token' => 'asdfasdf', 'cpaneluser' => 'guy'));</info> " );
}
$cpanel = new Cpanel ([
'host' => 'https://' . $config [ 'host' ] . ':' . $config [ 'port' ],
'username' => $config [ 'username' ],
'auth_type' => $config [ 'auth_type' ],
'password' => $config [ 'token' ],
]);
$cpanel -> setTimeout ( $config [ 'timeout' ]);
return $cpanel ;
}
function getDomainInfo ()
{
$domain = vsprintf ( get ( 'cpanel' )[ 'create_domain_format' ], get ( 'cpanel' )[ 'create_domain_values' ]);
$cleanDomain = str_replace ([ '.' , ',' , ' ' , '/' , '-' ], '' , $domain );
$subDomain = get ( 'cpanel' )[ 'subdomain_prefix' ] . $cleanDomain ;
return [
'domain' => $domain ,
'subDomain' => $subDomain ,
'subDomainWithSuffix' => $subDomain . get ( 'cpanel' )[ 'subdomain_suffix' ]
];
}
2021-11-08 22:59:39 +01:00
desc ( 'Creates database though CPanel API' );
2020-04-25 23:00:08 +03:00
task ( 'cpanel:createdb' , function () {
$cpanel = getCPanel ();
$config = get ( 'cpanel' , []);
2020-10-31 20:39:55 +01:00
if ( ! askConfirmation ( sprintf ( 'This will try to create the database %s on the host though CPanel API, ok?' , get ( 'cpanel_createdb' )), true )) {
2020-04-25 23:00:08 +03:00
return ;
}
$createDbDataResult = $cpanel -> cpanel ( 'MysqlFE' , 'createdb' , $config [ 'user' ], [ 'db' => get ( 'cpanel_createdb' )]);
$addPrivilegesDataResult = $cpanel -> cpanel ( 'MysqlFE' , 'setdbuserprivileges' , $config [ 'user' ], [ 'privileges' => $config [ 'db_user_privileges' ], 'db' => get ( 'cpanel_createdb' ), 'dbuser' => $config [ 'db_user' ]]);
$createDbData = json_decode ( $createDbDataResult , true );
$addPrivilegesData = json_decode ( $addPrivilegesDataResult , true );
if ( isset ( $createDbData [ 'cpanelresult' ][ 'error' ])) {
writeln ( $createDbData [ 'cpanelresult' ][ 'error' ]);
} else {
writeln ( 'Successfully created database!' );
}
if ( isset ( $addPrivilegesData [ 'cpanelresult' ][ 'error' ])) {
writeln ( $addPrivilegesData [ 'cpanelresult' ][ 'error' ]);
} else {
writeln ( 'Successfully added privileges to database!' );
}
});
2021-11-08 22:59:39 +01:00
desc ( 'Creates addon domain though CPanel API' );
2020-04-25 23:00:08 +03:00
task ( 'cpanel:createaddondomain' , function () {
$cpanel = getCPanel ();
$config = get ( 'cpanel' , []);
$domain = getDomainInfo ()[ 'domain' ];
$subDomain = getDomainInfo ()[ 'subDomain' ];
if ( ! askConfirmation ( sprintf ( 'This will try to create the addon domain %s and point it to %s and subdomain %s, ok?' , $domain , get ( 'addondir' ), $subDomain ), true )) {
return ;
}
2021-11-08 22:59:39 +01:00
writeln ( sprintf ( 'Creates addon domain %s and pointing it to %s' , $domain , get ( 'addondir' )));
2020-04-25 23:00:08 +03:00
$addAddonDomainResult = $cpanel -> cpanel ( 'AddonDomain' , 'addaddondomain' , $config [ 'user' ], [ 'dir' => get ( 'addondir' ), 'newdomain' => $domain , 'subdomain' => $subDomain ]);
$addAddonDomainData = json_decode ( $addAddonDomainResult , true );
2020-10-31 20:39:55 +01:00
if ( isset ( $addAddonDomainResult [ 'cpanelresult' ][ 'error' ])) {
2020-04-25 23:00:08 +03:00
writeln ( $addAddonDomainData [ 'cpanelresult' ][ 'error' ]);
} else {
writeln ( 'Successfully created addon domain!' );
writeln ( $addAddonDomainData [ 'cpanelresult' ][ 'data' ][ 0 ][ 'reason' ]);
}
});
2021-11-08 22:59:39 +01:00
desc ( 'Deletes addon domain though CPanel API' );
2020-04-25 23:00:08 +03:00
task ( 'cpanel:deleteaddondomain' , function () {
$cpanel = getCPanel ();
$config = get ( 'cpanel' , []);
$domain = getDomainInfo ()[ 'domain' ];
$subDomain = getDomainInfo ()[ 'subDomain' ];
$subDomainWithSuffix = getDomainInfo ()[ 'subDomainWithSuffix' ];
if ( ! askConfirmation ( sprintf ( 'This will delete the addon domain %s with corresponding subdomain %s, ok?' , $domain , $subDomain ), true )) {
return ;
}
writeln ( sprintf ( 'Deleting addon domain %s' , $domain ));
$delAddonDomainResult = $cpanel -> cpanel ( 'AddonDomain' , 'deladdondomain' , $config [ 'user' ], [ 'domain' => $domain , 'subdomain' => $subDomainWithSuffix ]);
$delAddonDomainResult = json_decode ( $delAddonDomainResult , true );
if ( isset ( $delAddonDomainResult [ 'cpanelresult' ][ 'error' ])) {
writeln ( $delAddonDomainResult [ 'cpanelresult' ][ 'error' ]);
} else {
writeln ( 'Successfully deleted addon domain!' );
writeln ( $delAddonDomainResult [ 'cpanelresult' ][ 'data' ][ 0 ][ 'reason' ]);
}
});