From 22e74d2f487573184150f19b9c104cfaee92d1eb Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi Date: Wed, 25 Jul 2018 17:16:15 +0530 Subject: [PATCH 01/52] Remove service functions Signed-off-by: Riddhesh Sanghvi --- src/Site_Command.php | 82 -------------------------------------------- 1 file changed, 82 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 6fc52948..dd255d30 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -421,88 +421,6 @@ public function info( $args ) { \EE\Utils\delem_log( 'site info end' ); } - /** - * Starts containers associated with site. - * When no service(--nginx etc.) is specified, all containers will be restarted. - * - * - * : Name of the site. - * - * [--all] - * : Start all containers of site. - * - * [--nginx] - * : Start nginx container of site. - * - * [--php] - * : Start php container of site. - * - * [--mysql] - * : Start mysql container of site. - * - * [--redis] - * : Start redis container of site. - * - * [--mailhog] - * : Start mailhog container of site. - * - * [--phpmyadmin] - * : Start phpmyadmin container of site. - * - * [--phpredisadmin] - * : Start phpredisadmin container of site. - * - * [--adminer] - * : Start adminer container of site. - * - * [--anemometer] - * : Start anemometer container of site. - */ - public function start( $args, $assoc_args ) { - $this->site_docker_compose_execute( $args[0], 'start', $args, $assoc_args); - } - - /** - * Stops containers associated with site. - * When no service(--nginx etc.) is specified, all containers will be stopped. - * - * - * : Name of the site. - * - * [--all] - * : Stop all containers of site. - * - * [--nginx] - * : Stop nginx container of site. - * - * [--php] - * : Stop php container of site. - * - * [--mysql] - * : Stop mysql container of site. - * - * [--redis] - * : Stop redis container of site. - * - * [--mailhog] - * : Stop mailhog container of site. - * - * [--phpmyadmin] - * : Stop phpmyadmin container of site. - * - * [--phpredisadmin] - * : Stop phpredisadmin container of site. - * - * [--adminer] - * : Stop adminer container of site. - * - * [--anemometer] - * : Stop anemometer container of site. - */ - public function stop( $args, $assoc_args ) { - $this->site_docker_compose_execute( $args[0], 'stop', $args, $assoc_args); - } - /** * Restarts containers associated with site. * When no service(--nginx etc.) is specified, all containers will be restarted. From 5cf01b82e8a931b5ea002c99c749d48d1f545e75 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi Date: Wed, 25 Jul 2018 17:18:20 +0530 Subject: [PATCH 02/52] Remove remote db connection check function Signed-off-by: Riddhesh Sanghvi --- src/Site_Command.php | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index dd255d30..b55ae338 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -746,34 +746,6 @@ private function create_site_root() { return true; } - private function maybe_verify_remote_db_connection() { - if( 'db' === $this->db_host ) { - return; - } - - // Docker needs special handling if we want to connect to host machine. - // The since we're inside the container and we want to access host machine, - // we would need to replace localhost with default gateway - if( $this->db_host === '127.0.0.1' || $this->db_host === 'localhost' ) { - $launch = EE::launch( "docker network inspect $this->site_name --format='{{ (index .IPAM.Config 0).Gateway }}'", false, true ); - \EE\Utils\default_debug( $launch ); - - if( ! $launch->return_code ) { - $this->db_host = trim( $launch->stdout, "\n" ); - } - else { - throw new Exception( 'There was a problem inspecting network. Please check the logs' ); - } - } - \EE::log( 'Verifying connection to remote database' ); - - if( ! \EE\Utils\default_launch( "docker run -it --rm --network='$this->site_name' mysql sh -c \"mysql --host='$this->db_host' --port='$this->db_port' --user='$this->db_user' --password='$this->db_pass' --execute='EXIT'\"" ) ) { - throw new Exception( 'Unable to connect to remote db' ); - } - - \EE::success( 'Connection to remote db verified' ); - } - /** * Function to create the site. */ From f82167bff41bee477f7677b14678d8248df6ad10 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi Date: Wed, 25 Jul 2018 17:19:18 +0530 Subject: [PATCH 03/52] Remove wordpress download and configuration Signed-off-by: Riddhesh Sanghvi --- src/Site_Command.php | 89 -------------------------------------------- 1 file changed, 89 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index b55ae338..81c0d544 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -928,95 +928,6 @@ private function setup_site_network() { } } - private function wp_download_and_config( $assoc_args ) { - $core_download_args = array( - 'version', - 'skip-content', - ); - - $config_args = array( - 'dbprefix', - 'dbcharset', - 'dbcollate', - 'skip-check', - ); - - $core_download_arguments = ''; - if ( ! empty( $assoc_args ) ) { - foreach ( $assoc_args as $key => $value ) { - if ( in_array( $key, $core_download_args, true ) ) { - $core_download_arguments .= ' --' . $key . '=' . $value; - } - } - } - - $config_arguments = ''; - if ( ! empty( $assoc_args ) ) { - foreach ( $assoc_args as $key => $value ) { - if ( in_array( $key, $config_args, true ) ) { - $config_arguments .= ' --' . $key . '=' . $value; - } - } - } - - EE::log( 'Downloading and configuring WordPress.' ); - - $chown_command = "docker-compose exec --user=root php chown -R www-data: /var/www/"; - \EE\Utils\default_launch( $chown_command ); - - $core_download_command = "docker-compose exec --user='www-data' php wp core download --locale='" . $this->locale . "' " . $core_download_arguments; - \EE\Utils\default_launch( $core_download_command ); - - // TODO: Look for better way to handle mysql healthcheck - if ( 'db' === $this->db_host ) { - $mysql_unhealthy = true; - $health_chk = "docker-compose exec --user='www-data' php mysql --user='root' --password='$this->db_root_pass' --host='db' -e exit"; - $count = 0; - while ( $mysql_unhealthy ) { - $mysql_unhealthy = ! \EE\Utils\default_launch( $health_chk ); - if ( $count ++ > 30 ) { - break; - } - sleep( 1 ); - } - } - - $db_host = is_null( $this->db_port ) ? $this->db_host : "$this->db_host:$this->db_port"; - $wp_config_create_command = "docker-compose exec --user='www-data' php wp config create --dbuser='$this->db_user' --dbname='$this->db_name' --dbpass='$this->db_pass' --dbhost='$db_host' $config_arguments " . '--extra-php="if ( isset( \$_SERVER[\'HTTP_X_FORWARDED_PROTO\'] ) && \$_SERVER[\'HTTP_X_FORWARDED_PROTO\'] == \'https\'){\$_SERVER[\'HTTPS\']=\'on\';}"'; - - try { - if ( ! \EE\Utils\default_launch( $wp_config_create_command ) ) { - throw new Exception( "Couldn't connect to $this->db_host:$this->db_port or there was issue in `wp config create`. Please check logs." ); - } - if ( 'db' !== $this->db_host ) { - $name = str_replace( '_', '\_', $this->db_name ); - $check_db_exists = "docker-compose exec php bash -c \"mysqlshow --user='$this->db_user' --password='$this->db_pass' --host='$this->db_host' --port='$this->db_port' '$name'"; - - if ( ! \EE\Utils\default_launch( $check_db_exists ) ) { - EE::log( "Database `$this->db_name` does not exist. Attempting to create it." ); - $create_db_command = "docker-compose exec php bash -c \"mysql --host=$this->db_host --port=$this->db_port --user=$this->db_user --password=$this->db_pass --execute='CREATE DATABASE $this->db_name;'\""; - - if ( ! \EE\Utils\default_launch( $create_db_command ) ) { - throw new Exception( "Could not create database `$this->db_name` on `$this->db_host:$this->db_port`. Please check if $this->db_user has rights to create database or manually create a database and pass with `--dbname` parameter." ); - } - $this->level = 4; - } else { - if ( $this->force ) { - \EE\Utils\default_launch( "docker-compose exec --user='www-data' php wp db reset --yes" ); - } - $check_tables = "docker-compose exec --user='www-data' php wp db tables"; - if ( \EE\Utils\default_launch( $check_tables ) ) { - throw new Exception( "WordPress tables already seem to exist. Please backup and reset the database or use `--force` in the site create command to reset it." ); - } - } - } - } - catch ( Exception $e ) { - $this->catch_clean( $e ); - } - - } - /** * Function to create entry in /etc/hosts. */ From 4a426efff2ccdd0c98aaee02c196b77def41c532 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi Date: Wed, 25 Jul 2018 17:19:47 +0530 Subject: [PATCH 04/52] Remove wordpress installation Signed-off-by: Riddhesh Sanghvi --- src/Site_Command.php | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 81c0d544..8885d204 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -947,33 +947,6 @@ private function create_etc_hosts_entry() { } - /** - * Install wordpress with given credentials. - */ - private function install_wp() { - EE::log( "\nInstalling WordPress site." ); - chdir( $this->site_root ); - - $wp_install_command = 'install'; - $maybe_multisite_type = ''; - - if ( 'wpsubdom' === $this->site_type || 'wpsubdir' === $this->site_type ) { - $wp_install_command = 'multisite-install'; - $maybe_multisite_type = $this->site_type === 'wpsubdom' ? '--subdomains' : ''; - } - - $install_command = "docker-compose exec --user='www-data' php wp core $wp_install_command --url='$this->site_name' --title='$this->site_title' --admin_user='$this->site_user'" . ( $this->site_pass ? " --admin_password='$this->site_pass'" : '' ) . " --admin_email='$this->site_email' $maybe_multisite_type"; - - $core_install = \EE\Utils\default_launch( $install_command ); - - if ( ! $core_install ) { - EE::warning( 'WordPress install failed. Please check logs.' ); - } - - $prefix = ( $this->le ) ? 'https://' : 'http://'; - EE::success( $prefix . $this->site_name . " has been created successfully!" ); - } - /** * Function to save the site configuration entry into database. */ From 19dc0495186521e2cea2a4900a167aab69597e08 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi Date: Wed, 25 Jul 2018 17:34:28 +0530 Subject: [PATCH 05/52] Move init_checks to site utils Signed-off-by: Riddhesh Sanghvi --- src/Site_Command.php | 35 +---------------------------------- 1 file changed, 1 insertion(+), 34 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 8885d204..bcc0d014 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -179,7 +179,7 @@ public function create( $args, $assoc_args ) { $this->skip_chk = \EE\Utils\get_flag_value( $assoc_args, 'skip-status-check' ); $this->force = \EE\Utils\get_flag_value( $assoc_args, 'force' ); - $this->init_checks(); + \EE\SiteUtils\init_checks(); EE::log( 'Configuring project.' ); @@ -547,39 +547,6 @@ private function map_args_to_service( $arg ) { return in_array( $arg, array_keys( $services_map ) ) ? $services_map[ $arg ] : $arg ; } - /** - * Function to check all the required configurations needed to create the site. - * - * Boots up the container if it is stopped or not running. - */ - private function init_checks() { - if ( 'running' !== $this->docker::container_status( $this->proxy_type ) ) { - /** - * Checking ports. - */ - @fsockopen( 'localhost', 80, $port_80_exit_status ); - @fsockopen( 'localhost', 443, $port_443_exit_status ); - - // if any/both the port/s is/are occupied. - if ( ! ( $port_80_exit_status && $port_443_exit_status ) ) { - EE::error( 'Cannot create/start proxy container. Please make sure port 80 and 443 are free.' ); - } else { - $EE_CONF_ROOT = EE_CONF_ROOT; - $ee_proxy_command = "docker run --name $this->proxy_type -e LOCAL_USER_ID=`id -u` -e LOCAL_GROUP_ID=`id -g` --restart=always -d -p 80:80 -p 443:443 -v $EE_CONF_ROOT/nginx/certs:/etc/nginx/certs -v $EE_CONF_ROOT/nginx/dhparam:/etc/nginx/dhparam -v $EE_CONF_ROOT/nginx/conf.d:/etc/nginx/conf.d -v $EE_CONF_ROOT/nginx/htpasswd:/etc/nginx/htpasswd -v $EE_CONF_ROOT/nginx/vhost.d:/etc/nginx/vhost.d -v /var/run/docker.sock:/tmp/docker.sock:ro -v $EE_CONF_ROOT:/app/ee4 -v /usr/share/nginx/html easyengine/nginx-proxy:v" . EE_VERSION; - - - if ( $this->docker::boot_container( $this->proxy_type, $ee_proxy_command ) ) { - EE::success( "$this->proxy_type container is up." ); - } else { - EE::error( "There was some error in starting $this->proxy_type container. Please check logs." ); - } - } - } - - $this->site_root = WEBROOT . $this->site_name; - $this->create_site_root(); - } - /** * Function to configure site and copy all the required files. */ From fe0bb2982f19dd8a8d9c50770389ce787428a070 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi Date: Wed, 25 Jul 2018 17:37:19 +0530 Subject: [PATCH 06/52] Move auto_site_name to site utils Signed-off-by: Riddhesh Sanghvi --- src/Site_Command.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index bcc0d014..a6f0563a 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -13,6 +13,7 @@ * @package ee-cli */ class Site_Command extends EE_Command { + private $command; private $site_name; private $site_root; private $site_type; @@ -41,6 +42,7 @@ class Site_Command extends EE_Command { public function __construct() { $this->level = 0; + $this->command = 'site'; pcntl_signal( SIGTERM, [ $this, "rollback" ] ); pcntl_signal( SIGHUP, [ $this, "rollback" ] ); pcntl_signal( SIGUSR1, [ $this, "rollback" ] ); @@ -348,7 +350,7 @@ public function le( $args = [], $assoc_args = [] ) { */ public function enable( $args ) { \EE\Utils\delem_log( 'site enable start' ); - $args = \EE\Utils\set_site_arg( $args, 'site enable' ); + $args = \EE\SiteUtils\auto_site_name( $args, $this->command, __FUNCTION__ ); $this->populate_site_info( $args ); EE::log( "Enabling site $this->site_name." ); if ( $this->docker::docker_compose_up( $this->site_root ) ) { @@ -370,7 +372,7 @@ public function enable( $args ) { */ public function disable( $args ) { \EE\Utils\delem_log( 'site disable start' ); - $args = \EE\Utils\set_site_arg( $args, 'site disable' ); + $args = \EE\SiteUtils\auto_site_name( $args, $this->command, __FUNCTION__ ); $this->populate_site_info( $args ); EE::log( "Disabling site $this->site_name." ); if ( $this->docker::docker_compose_down( $this->site_root ) ) { @@ -391,7 +393,7 @@ public function disable( $args ) { public function info( $args ) { \EE\Utils\delem_log( 'site info start' ); if ( ! isset( $this->site_name ) ) { - $args = \EE\Utils\set_site_arg( $args, 'site info' ); + $args = \EE\SiteUtils\auto_site_name( $args, $this->command, __FUNCTION__ ); $this->populate_site_info( $args ); } $ssl = $this->le ? 'Enabled' : 'Not Enabled'; From efa9d0d25269e9961b73e100ab7aac95c6597a30 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi Date: Wed, 25 Jul 2018 17:38:59 +0530 Subject: [PATCH 07/52] Move running of compose commands to site utils Signed-off-by: Riddhesh Sanghvi --- src/Site_Command.php | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index a6f0563a..5ff3e14e 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -497,7 +497,7 @@ private function site_docker_compose_execute( $site, $action, $args, $assoc_args $this->reload_services( [ 'nginx', 'php' ] ); return; } - $this->run_compose_command( $action, '', null, 'all services' ); + \EE\SiteUtils\run_compose_command( $action, '', null, 'all services' ); } else { $services = array_map( [$this, 'map_args_to_service'], array_keys( $assoc_args ) ); @@ -508,23 +508,11 @@ private function site_docker_compose_execute( $site, $action, $args, $assoc_args } foreach( $services as $service ) { - $this->run_compose_command( $action, $service ); + \EE\SiteUtils\run_compose_command( $action, $service ); } } } - - /** - * Generic function to run a docker compose command. Must be ran inside correct directory. - */ - private function run_compose_command( $action, $container, $action_to_display = null, $service_to_display = null) { - $display_action = $action_to_display ? $action_to_display : $action; - $display_service = $service_to_display ? $service_to_display : $container; - - \EE::log( ucfirst( $display_action ) . 'ing ' . $display_service ); - \EE\Utils\default_launch( "docker-compose $action $container" ); - } - /** * Executes reload commands. It needs seperate handling as commands to reload each service is different. */ @@ -535,7 +523,7 @@ private function reload_services( $services ) { ]; foreach( $services as $service ) { - $this->run_compose_command( 'exec', $reload_command[ $service ], 'reload', $service ); + \EE\SiteUtils\run_compose_command( 'exec', $reload_command[ $service ], 'reload', $service ); } } From 912851fb6d5b762d7fc5f06a171a05b493f4623d Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi Date: Wed, 25 Jul 2018 17:40:00 +0530 Subject: [PATCH 08/52] Move add redirects to site utils Signed-off-by: Riddhesh Sanghvi --- src/Site_Command.php | 59 +------------------------------------------- 1 file changed, 1 insertion(+), 58 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 5ff3e14e..b93f69fb 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -579,7 +579,7 @@ private function configure_site() { $env_content = \EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/config/.env.mustache', $env_data ); $php_ini_content = \EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/config/php-fpm/php.ini.mustache', [] ); - $this->add_site_redirects(); + \EE\SiteUtils\add_site_redirects(); try { if ( ! ( file_put_contents( $site_docker_yml, $docker_compose_content ) @@ -598,63 +598,6 @@ private function configure_site() { } } - /** - * Adds www to non-www redirection to site - */ - private function add_site_redirects() { - $confd_path = EE_CONF_ROOT . '/nginx/conf.d/'; - $config_file_path = $confd_path . $this->site_name . '-redirect.conf'; - $has_www = strpos( $this->site_name, 'www.' ) === 0; - $content = ''; - - if( $has_www ) { - $site_name_without_www = ltrim( $this->site_name, '.www' ); - // ee site create www.example.com --le - if( $this->le ) { - $content = " -server { - listen 80; - listen 443; - server_name $site_name_without_www; - return 301 https://$this->site_name\$request_uri; -}"; - } - // ee site create www.example.com - else { - $content = " -server { - listen 80; - server_name $site_name_without_www; - return 301 http://$this->site_name\$request_uri; -}"; - } - } - else { - $site_name_with_www = 'www.' . $this->site_name; - // ee site create example.com --le - if( $this->le ) { - - $content = " -server { - listen 80; - listen 443; - server_name $site_name_with_www; - return 301 https://$this->site_name\$request_uri; -}"; - } - // ee site create example.com - else { - $content = " -server { - listen 80; - server_name $site_name_with_www; - return 301 http://$this->site_name\$request_uri; -}"; - } - } - file_put_contents( $config_file_path, ltrim( $content, PHP_EOL ) ); - } - /** * Function to generate default.conf from mustache templates. * From 650435e6e564246535f54582a049431c7ccf5924 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi Date: Wed, 25 Jul 2018 17:41:07 +0530 Subject: [PATCH 09/52] Move site root creation to site utils Signed-off-by: Riddhesh Sanghvi --- src/Site_Command.php | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index b93f69fb..31910d5b 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -615,37 +615,6 @@ private function generate_default_conf( $site_type, $cache_type, $server_name ) return \EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/config/nginx/default.conf.mustache', $default_conf_data ); } - /** - * Creates site root directory if does not exist. - * Throws error if it does exist. - */ - private function create_site_root() { - - if ( is_dir( $this->site_root ) ) { - EE::error( "Webroot directory for site $this->site_name already exists." ); - } - - if ( ! \EE\Utils\default_launch( "mkdir $this->site_root" ) ) { - EE::error( "Cannot create directory $this->site_root. Please check that folder permission allows easyengine to create directory there." ); - } - - try { - $this->level = 1; - $whoami = EE::launch( "whoami", false, true ); - - $terminal_username = rtrim( $whoami->stdout ); - - if ( ! chown( $this->site_root, $terminal_username ) ) { - throw new Exception( 'Could not change ownership of the site root. Please make sure you have appropriate rights.' ); - } - } - catch ( Exception $e ) { - $this->catch_clean( $e ); - } - - return true; - } - /** * Function to create the site. */ From 5a0457469fbe281ab397fb0abcd24392548eed88 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi Date: Wed, 25 Jul 2018 17:41:41 +0530 Subject: [PATCH 10/52] Move site network setup to site utils Signed-off-by: Riddhesh Sanghvi --- src/Site_Command.php | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 31910d5b..db99e19e 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -775,28 +775,6 @@ private function site_status_check() { } - /** - * Function to setup site network. - */ - private function setup_site_network() { - - $this->level = 2; - - try { - if ( $this->docker::create_network( $this->site_name ) ) { - EE::success( 'Network started.' ); - } else { - throw new Exception( 'There was some error in starting the network.' ); - } - $this->level = 3; - - $this->docker::connect_site_network_to( $this->site_name, $this->proxy_type ); - } - catch ( Exception $e ) { - $this->catch_clean( $e ); - } - } - /** * Function to create entry in /etc/hosts. */ From b99099dc6f946dc0161bdef557efb35f0288d966 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi Date: Wed, 25 Jul 2018 17:42:31 +0530 Subject: [PATCH 11/52] Move etc host entry creation to site utils Signed-off-by: Riddhesh Sanghvi --- src/Site_Command.php | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index db99e19e..34c2c8af 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -775,25 +775,6 @@ private function site_status_check() { } - /** - * Function to create entry in /etc/hosts. - */ - private function create_etc_hosts_entry() { - - $host_line = LOCALHOST_IP . "\t$this->site_name"; - $etc_hosts = file_get_contents( '/etc/hosts' ); - if ( ! preg_match( "/\s+$this->site_name\$/m", $etc_hosts ) ) { - if ( \EE\Utils\default_launch( "/bin/bash -c 'echo \"$host_line\" >> /etc/hosts'" ) ) { - EE::success( 'Host entry successfully added.' ); - } else { - EE::warning( "Failed to add $this->site_name in host entry, Please do it manually!" ); - } - } else { - EE::log( 'Host entry already exists.' ); - } - } - - /** * Function to save the site configuration entry into database. */ From 825e1d212d1cff09b5000da35a2d8d1dfe7ab070 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi Date: Wed, 25 Jul 2018 17:43:00 +0530 Subject: [PATCH 12/52] Move site status check to site utils Signed-off-by: Riddhesh Sanghvi --- src/Site_Command.php | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 34c2c8af..bd7179ed 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -740,41 +740,6 @@ private function delete_site() { EE::log( "Site $this->site_name deleted." ); } - - /** - * Checking site is running or not [TESTING] - */ - private function site_status_check() { - $this->level = 4; - EE::log( 'Checking and verifying site-up status. This may take some time.' ); - $httpcode = '000'; - $ch = curl_init( $this->site_name ); - curl_setopt( $ch, CURLOPT_HEADER, true ); - curl_setopt( $ch, CURLOPT_NOBODY, true ); - curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); - curl_setopt( $ch, CURLOPT_TIMEOUT, 10 ); - - $i = 0; - try { - while ( 200 !== $httpcode && 302 !== $httpcode ) { - curl_exec( $ch ); - $httpcode = curl_getinfo( $ch, CURLINFO_HTTP_CODE ); - echo '.'; - sleep( 2 ); - if ( $i ++ > 60 ) { - break; - } - } - if ( 200 !== $httpcode && 302 !== $httpcode ) { - throw new Exception( 'Problem connecting to site!' ); - } - } - catch ( Exception $e ) { - $this->catch_clean( $e ); - } - - } - /** * Function to save the site configuration entry into database. */ From ae5993a7b15f0b75dcc58e27a7d6ab6985b4ab4b Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi Date: Wed, 25 Jul 2018 17:46:28 +0530 Subject: [PATCH 13/52] Update create method for html Remove WordPress specific things --- src/Site_Command.php | 111 ++++--------------------------------------- 1 file changed, 10 insertions(+), 101 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index bd7179ed..147b5cbb 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -62,80 +62,14 @@ public function __construct() { * * : Name of website. * - * [--wp] - * : WordPress website. - * - * [--wpredis] - * : Use redis for WordPress. - * - * [--wpsubdir] - * : WordPress sub-dir Multi-site. - * - * [--wpsubdom] - * : WordPress sub-domain Multi-site. - * - * [--title=] - * : Title of your site. - * - * [--admin_user=<admin_user>] - * : Username of the administrator. - * - * [--admin_pass=<admin_pass>] - * : Password for the the administrator. - * - * [--admin_email=<admin_email>] - * : E-Mail of the administrator. - * - * [--dbname=<dbname>] - * : Set the database name. - * --- - * default: wordpress - * --- - * - * [--dbuser=<dbuser>] - * : Set the database user. - * - * [--dbpass=<dbpass>] - * : Set the database password. - * - * [--dbhost=<dbhost>] - * : Set the database host. Pass value only when remote dbhost is required. - * --- - * default: db - * --- - * - * [--dbprefix=<dbprefix>] - * : Set the database table prefix. - * - * [--dbcharset=<dbcharset>] - * : Set the database charset. - * --- - * default: utf8 - * --- - * - * [--dbcollate=<dbcollate>] - * : Set the database collation. - * - * [--skip-check] - * : If set, the database connection is not checked. - * - * [--version=<version>] - * : Select which wordpress version you want to download. Accepts a version number, ‘latest’ or ‘nightly’. - * - * [--skip-content] - * : Download WP without the default themes and plugins. + * [--letsencrypt] + * : Enables ssl via letsencrypt certificate. * - * [--skip-install] - * : Skips wp-core install. + * [--type=<type>] + * : Type of the site to be created. Values: html,php,wp. * * [--skip-status-check] * : Skips site status check. - - * [--letsencrypt] - * : Enables ssl via letsencrypt certificate. - * - * [--force] - * : Resets the remote database if it is not empty. */ public function create( $args, $assoc_args ) { @@ -144,48 +78,23 @@ public function create( $args, $assoc_args ) { $this->logger->debug( 'args:', $args ); $this->logger->debug( 'assoc_args:', empty( $assoc_args ) ? array( 'NULL' ) : $assoc_args ); $this->site_name = strtolower( \EE\Utils\remove_trailing_slash( $args[0] ) ); - $this->site_type = \EE\Utils\get_type( $assoc_args, [ 'wp', 'wpsubdom', 'wpsubdir' ], 'wp' ); - if ( false === $this->site_type ) { - EE::error( 'Invalid arguments' ); + $this->site_type = \EE\Utils\get_flag_value( $assoc_args, 'type', 'html' ); + if ( 'html' !== $this->site_type ) { + EE::error( "Invalid site-type: $this->site_type" ); } if ( $this->db::site_in_db( $this->site_name ) ) { EE::error( "Site $this->site_name already exists. If you want to re-create it please delete the older one using:\n`ee site delete $this->site_name`" ); } - $this->proxy_type = 'ee-nginx-proxy'; - $this->cache_type = ! empty( $assoc_args['wpredis'] ) ? 'wpredis' : 'none'; - $this->le = \EE\Utils\get_flag_value( $assoc_args, 'letsencrypt' ); - $this->site_title = \EE\Utils\get_flag_value( $assoc_args, 'title', $this->site_name ); - $this->site_user = \EE\Utils\get_flag_value( $assoc_args, 'admin_user', 'admin' ); - $this->site_pass = \EE\Utils\get_flag_value( $assoc_args, 'admin_pass', \EE\Utils\random_password() ); - $this->db_name = str_replace( [ '.', '-' ], '_', $this->site_name ); - $this->db_host = \EE\Utils\get_flag_value( $assoc_args, 'dbhost' ); - $this->db_user = \EE\Utils\get_flag_value( $assoc_args, 'dbuser', 'wordpress' ); - $this->db_pass = \EE\Utils\get_flag_value( $assoc_args, 'dbpass', \EE\Utils\random_password() ); - $this->locale = \EE\Utils\get_flag_value( $assoc_args, 'locale', EE::get_config( 'locale' ) ); - $this->db_root_pass = \EE\Utils\random_password(); - - // If user wants to connect to remote database - if ( 'db' !== $this->db_host ) { - if ( ! isset( $assoc_args['dbuser'] ) || ! isset( $assoc_args['dbpass'] ) ) { - EE::error( '`--dbuser` and `--dbpass` are required for remote db host.' ); - } - $arg_host_port = explode( ':', $this->db_host ); - $this->db_host = $arg_host_port[0]; - $this->db_port = empty( $arg_host_port[1] ) ? '3306' : $arg_host_port[1]; - } - - $this->site_email = \EE\Utils\get_flag_value( $assoc_args, 'admin_email', strtolower( 'mail@' . $this->site_name ) ); - $this->skip_install = \EE\Utils\get_flag_value( $assoc_args, 'skip-install' ); - $this->skip_chk = \EE\Utils\get_flag_value( $assoc_args, 'skip-status-check' ); - $this->force = \EE\Utils\get_flag_value( $assoc_args, 'force' ); + $this->le = \EE\Utils\get_flag_value( $assoc_args, 'letsencrypt' ); + $this->skip_chk = \EE\Utils\get_flag_value( $assoc_args, 'skip-status-check' ); \EE\SiteUtils\init_checks(); EE::log( 'Configuring project.' ); - $this->create_site( $assoc_args ); + $this->create_site(); \EE\Utils\delem_log( 'site create end' ); } From 6c6a3ec1054c7a2a096708973b0825583e129a6e Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 25 Jul 2018 17:51:04 +0530 Subject: [PATCH 14/52] Update parameters and function names acc to abstract class Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Command.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 147b5cbb..58b0ed05 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -12,7 +12,7 @@ * * @package ee-cli */ -class Site_Command extends EE_Command { +class Site_Command extends EE_Site_Command { private $command; private $site_name; private $site_root; @@ -257,7 +257,7 @@ public function le( $args = [], $assoc_args = [] ) { * [<site-name>] * : Name of website to be enabled. */ - public function enable( $args ) { + public function up( $args, $assoc_args ) { \EE\Utils\delem_log( 'site enable start' ); $args = \EE\SiteUtils\auto_site_name( $args, $this->command, __FUNCTION__ ); $this->populate_site_info( $args ); @@ -279,7 +279,7 @@ public function enable( $args ) { * [<site-name>] * : Name of website to be disabled. */ - public function disable( $args ) { + public function down( $args, $assoc_args ) { \EE\Utils\delem_log( 'site disable start' ); $args = \EE\SiteUtils\auto_site_name( $args, $this->command, __FUNCTION__ ); $this->populate_site_info( $args ); @@ -299,7 +299,7 @@ public function disable( $args ) { * [<site-name>] * : Name of the website whose info is required. */ - public function info( $args ) { + public function info( $args, $assoc_args ) { \EE\Utils\delem_log( 'site info start' ); if ( ! isset( $this->site_name ) ) { $args = \EE\SiteUtils\auto_site_name( $args, $this->command, __FUNCTION__ ); From edee2ca4ba900df75cdff4cb9a8a96a9b12e425e Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 25 Jul 2018 17:58:42 +0530 Subject: [PATCH 15/52] Update site creation and configuration Switch to appropriate site utils Switch from nativ php functions to Symfony Filesystem --- src/Site_Command.php | 115 +++++++---------- templates/config/nginx/default.conf.mustache | 124 +------------------ 2 files changed, 45 insertions(+), 194 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 58b0ed05..9ca7fbec 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -12,6 +12,9 @@ * * @package ee-cli */ + +use \Symfony\Component\Filesystem\Filesystem; + class Site_Command extends EE_Site_Command { private $command; private $site_name; @@ -39,6 +42,7 @@ class Site_Command extends EE_Site_Command { private $skip_chk; private $force; private $le_mail; + private $fs; public function __construct() { $this->level = 0; @@ -52,6 +56,7 @@ public function __construct() { $this->db = EE::db(); $this->docker = EE::docker(); $this->logger = EE::get_file_logger()->withName( 'site_command' ); + $this->fs = new Filesystem(); } /** @@ -449,57 +454,47 @@ private function map_args_to_service( $arg ) { /** * Function to configure site and copy all the required files. */ - private function configure_site() { + private function configure_site_files() { $site_conf_dir = $this->site_root . '/config'; $site_docker_yml = $this->site_root . '/docker-compose.yml'; $site_conf_env = $this->site_root . '/.env'; $site_nginx_default_conf = $site_conf_dir . '/nginx/default.conf'; - $site_php_ini = $site_conf_dir . '/php-fpm/php.ini'; - $server_name = ( 'wpsubdom' === $this->site_type ) ? "$this->site_name *.$this->site_name" : $this->site_name; + $server_name = $this->site_name; + $site_src_dir = $this->site_root . '/app/src'; $process_user = posix_getpwuid( posix_geteuid() ); - EE::log( "Creating WordPress site $this->site_name." ); + EE::log( "Creating site $this->site_name." ); EE::log( 'Copying configuration files.' ); $filter = array(); $filter[] = $this->site_type; - $filter[] = $this->cache_type; $filter[] = $this->le; - $filter[] = $this->db_host; $site_docker = new Site_Docker(); $docker_compose_content = $site_docker->generate_docker_compose_yml( $filter ); - $default_conf_content = $this->generate_default_conf( $this->site_type, $this->cache_type, $server_name ); - $local = ( 'db' === $this->db_host ) ? true : false; - $env_data = [ - 'local' => $local, - 'virtual_host' => $this->site_name, - 'root_password' => $this->db_root_pass, - 'database_name' => $this->db_name, - 'database_user' => $this->db_user, - 'user_password' => $this->db_pass, - 'wp_db_host' => "$this->db_host:$this->db_port", - 'wp_db_user' => $this->db_user, - 'wp_db_name' => $this->db_name, - 'wp_db_pass' => $this->db_pass, - 'user_id' => $process_user['uid'], - 'group_id' => $process_user['gid'], - ]; - $env_content = \EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/config/.env.mustache', $env_data ); - $php_ini_content = \EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/config/php-fpm/php.ini.mustache', [] ); + $default_conf_content = $default_conf_content = \EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/config/nginx/default.conf.mustache', [ $this->site_name ] ); - \EE\SiteUtils\add_site_redirects(); + $env_data = [ + 'virtual_host' => $this->site_name, + 'user_id' => $process_user['uid'], + 'group_id' => $process_user['gid'], + ]; + $env_content = \EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/config/.env.mustache', $env_data ); try { - if ( ! ( file_put_contents( $site_docker_yml, $docker_compose_content ) - && file_put_contents( $site_conf_env, $env_content ) - && mkdir( $site_conf_dir ) - && mkdir( $site_conf_dir . '/nginx' ) - && file_put_contents( $site_nginx_default_conf, $default_conf_content ) - && mkdir( $site_conf_dir . '/php-fpm' ) - && file_put_contents( $site_php_ini, $php_ini_content ) ) ) { - throw new Exception( 'Could not copy configuration files.' ); - } + $this->fs->dumpFile( $site_docker_yml, $docker_compose_content ); + $this->fs->dumpFile( $site_conf_env, $env_content ); + $this->fs->mkdir( $site_conf_dir ); + $this->fs->mkdir( $site_conf_dir . '/nginx' ); + $this->fs->dumpFile( $site_nginx_default_conf, $default_conf_content ); + + $index_data = ['v'.EE_VERSION,$this->site_root]; + $index_html = \EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/index.html.mustache', $index_data ); + $this->fs->mkdir( $site_src_dir ); + $this->fs->dumpFile( $site_src_dir . '/index.html', $index_html ); + + EE\Siteutils\add_site_redirects( $this->site_name, $this->le ); + EE::success( 'Configuration files copied.' ); } catch ( Exception $e ) { @@ -507,57 +502,35 @@ private function configure_site() { } } - /** - * Function to generate default.conf from mustache templates. - * - * @param string $site_type Type of site (wpsubdom, wpredis etc..) - * @param string $cache_type Type of cache(wpredis or none) - * @param string $server_name Name of server to use in virtual_host - */ - private function generate_default_conf( $site_type, $cache_type, $server_name ) { - $default_conf_data['site_type'] = $site_type; - $default_conf_data['server_name'] = $server_name; - $default_conf_data['include_php_conf'] = $cache_type !== 'wpredis'; - $default_conf_data['include_wpsubdir_conf'] = $site_type === 'wpsubdir'; - $default_conf_data['include_redis_conf'] = $cache_type === 'wpredis'; - - return \EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/config/nginx/default.conf.mustache', $default_conf_data ); - } - /** * Function to create the site. */ - private function create_site( $assoc_args ) { - $this->setup_site_network(); + private function create_site() { + $this->site_root = WEBROOT . $this->site_name; + $this->level = 1; try { - $this->maybe_verify_remote_db_connection(); - $this->configure_site(); + EE\Siteutils\create_site_root( $this->site_root, $this->site_name ); + $this->level = 2; + EE\Siteutils\setup_site_network( $this->site_name ); $this->level = 3; - EE::log( 'Pulling latest images. This may take some time.' ); - chdir( $this->site_root ); - \EE\Utils\default_launch( 'docker-compose pull' ); - EE::log( 'Starting site\'s services.' ); - if ( ! $this->docker::docker_compose_up( $this->site_root ) ) { - throw new Exception( 'There was some error in docker-compose up.' ); + $this->configure_site_files(); + + EE\Siteutils\start_site_containers( $this->site_root ); + + EE\Siteutils\create_etc_hosts_entry( $this->site_name ); + if ( ! $this->skip_chk ) { + $this->level = 4; + EE\Siteutils\site_status_check( $this->site_name ); } } catch ( Exception $e ) { $this->catch_clean( $e ); } - $this->wp_download_and_config( $assoc_args ); - - if ( ! $this->skip_install ) { - $this->create_etc_hosts_entry(); - if ( ! $this->skip_chk ) { - $this->site_status_check(); - } - $this->install_wp(); - } if ( $this->le ) { $this->init_le(); } - $this->info( array( $this->site_name ) ); + $this->info( [ $this->site_name ], [] ); $this->create_site_db_entry(); } diff --git a/templates/config/nginx/default.conf.mustache b/templates/config/nginx/default.conf.mustache index f19ec679..281bec9f 100644 --- a/templates/config/nginx/default.conf.mustache +++ b/templates/config/nginx/default.conf.mustache @@ -9,118 +9,7 @@ server { server_name {{server_name}}; - index index.php index.html index.htm; - - {{#include_redis_conf}} - # Redis NGINX CONFIGURATION - set $skip 0; - # POST requests and URL with a query string should always go to php - if ($request_method = POST) { - set $skip 1; - } - if ($query_string != "") { - set $skip 1; - } - # Don't cache URL containing the following segments - if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|wp-.*.php|index.php|/feed/|sitemap(_index)?.xml|[a-z0-9_-]+-sitemap([0-9]+)?.xml)") { - set $skip 1; - } - # Don't use the cache for logged in users or recent commenter or customer with items in cart - if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in|woocommerce_items_in_cart") { - set $skip 1; - } - # Use cached or actual file if they exists, Otherwise pass request to WordPress - location / { - try_files $uri $uri/ /index.php?$args; - } - - location /redis-fetch { - internal ; - set $redis_key $args; - redis_pass redis:6379; - } - location /redis-store { - internal ; - set_unescape_uri $key $arg_key ; - redis2_query set $key $echo_request_body; - redis2_query expire $key 14400; - redis2_pass redis:6379; - } - - location ~ \.php$ { - # add_header Cache-Control "max-age=0, no-cache, no-store, must-revalidate"; - set $key "nginx-cache:$scheme$request_method$host$request_uri"; - try_files $uri =404; - - srcache_fetch_skip $skip; - srcache_store_skip $skip; - - srcache_response_cache_control off; - - set_escape_uri $escaped_key $key; - - srcache_fetch GET /redis-fetch $key; - srcache_store PUT /redis-store key=$escaped_key; - - more_set_headers 'X-SRCache-Fetch-Status $srcache_fetch_status'; - more_set_headers 'X-SRCache-Store-Status $srcache_store_status'; - - include fastcgi_params; - fastcgi_pass php:9000; - } - - {{/include_redis_conf}} - - {{#include_wpsubdir_conf}} - # WPSUBDIRECTORY NGINX CONFIGURATION - if (!-e $request_filename) { - - # Redirect wp-admin to wp-admin/ - rewrite /wp-admin$ $scheme://$host$uri/ permanent; - - # Redirect wp-* files/folders - rewrite ^(/[^/]+)?(/wp-.*) $2 last; - - # Redirect other php files - rewrite ^(/[^/]+)?(/.*\.php) $2 last; - } - {{/include_wpsubdir_conf}} - - {{#include_php_conf}} - # PHP NGINX CONFIGURATION - location / { - try_files $uri $uri/ /index.php?$args; - } - location ~ \.php$ { - try_files $uri =404; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - include fastcgi_params; - fastcgi_pass php:9000; - } - {{/include_php_conf}} - - {{! wpcommon.conf }} - # WordPress COMMON SETTINGS - # Limit access to avoid brute force attack - location = /wp-login.php { - limit_req zone=one burst=1 nodelay; - include fastcgi_params; - fastcgi_pass php:9000; - } - # Disable wp-config.txt - location = /wp-config.txt { - deny all; - access_log off; - log_not_found off; - } - # Disallow php in upload folder - location /wp-content/uploads/ { - location ~ \.php$ { - #Prevent Direct Access Of PHP Files From Web Browsers - deny all; - } - } - {{! /wpcommon.conf }} + index index.html index.htm; {{! locations.conf }} # NGINX CONFIGURATION FOR COMMON LOCATION @@ -131,13 +20,6 @@ server { expires max; } - location = /robots.txt { - # Some WordPress plugin gererate robots.txt file - # Refer #340 issue - try_files $uri $uri/ /index.php?$args; - access_log off; - log_not_found off; - } # Cache static files location ~* \.(ogg|ogv|svg|svgz|eot|otf|woff|woff2|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|swf)$ { add_header "Access-Control-Allow-Origin" "*"; @@ -175,10 +57,6 @@ server { stub_status on; access_log off; } - location ~ ^/(status|ping) { - include fastcgi_params; - fastcgi_pass php:9000; - } location ~* \.(css|js)$ { expires 1d; add_header Cache-Control "public, must-revalidate"; From b063f59c85a7dbe7da16881d20997f120ecb795e Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 25 Jul 2018 18:02:43 +0530 Subject: [PATCH 16/52] Update restart for html Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Command.php | 52 ++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 9ca7fbec..8de22b97 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -337,11 +337,11 @@ public function info( $args, $assoc_args ) { \EE\Utils\delem_log( 'site info end' ); } - /** + /** * Restarts containers associated with site. - * When no service(--nginx etc.) is specified, all containers will be restarted. + * When no service(--nginx etc.) is specified, all site containers will be restarted. * - * <site-name> + * [<site-name>] * : Name of the site. * * [--all] @@ -349,35 +349,29 @@ public function info( $args, $assoc_args ) { * * [--nginx] * : Restart nginx container of site. - * - * [--php] - * : Restart php container of site. - * - * [--mysql] - * : Restart mysql container of site. - * - * [--redis] - * : Restart redis container of site. - * - * [--mailhog] - * : Restart mailhog container of site. - * - * [--phpmyadmin] - * : Restart phpmyadmin container of site. - * - * [--phpredisadmin] - * : Restart phpredisadmin container of site. - * - * [--adminer] - * : Restart adminer container of site. - * - * [--anemometer] - * : Restart anemometer container of site. */ public function restart( $args, $assoc_args ) { - $this->site_docker_compose_execute( $args[0], 'restart', $args, $assoc_args); - } + \EE\Utils\delem_log( 'site restart start' ); + $args = \EE\SiteUtils\auto_site_name( $args, $this->command, __FUNCTION__ ); + $all = \EE\Utils\get_flag_value( $assoc_args, 'all' ); + $no_service_specified = count( $assoc_args ) === 0; + + $this->populate_site_info( $args ); + + chdir( $this->site_root ); + if ( $all || $no_service_specified ) { + $containers = [ 'nginx' ]; + } else { + $containers = array_keys( $assoc_args ); + } + + foreach ( $containers as $container ) { + EE\Siteutils\run_compose_command( 'restart', $container, null, 'all services' ); + } + \EE\Utils\delem_log( 'site restart stop' ); + } + /** * Reload services in containers without restarting container(s) associated with site. * When no service(--nginx etc.) is specified, all services will be reloaded. From 9a90e0ab6cbd937742c282a90ae4909447c98598 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 25 Jul 2018 18:04:14 +0530 Subject: [PATCH 17/52] Update reload for html Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Command.php | 54 +++++++++++--------------------------------- 1 file changed, 13 insertions(+), 41 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 8de22b97..c44b4a18 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -371,8 +371,8 @@ public function restart( $args, $assoc_args ) { } \EE\Utils\delem_log( 'site restart stop' ); } - - /** + + /** * Reload services in containers without restarting container(s) associated with site. * When no service(--nginx etc.) is specified, all services will be reloaded. * @@ -385,40 +385,23 @@ public function restart( $args, $assoc_args ) { * [--nginx] * : Reload nginx service in container. * - * [--php] - * : Start php service in container. */ public function reload( $args, $assoc_args ) { - $this->site_docker_compose_execute( $args[0], 'reload', $args, $assoc_args); - } - - private function site_docker_compose_execute( $site, $action, $args, $assoc_args ) { - $all = \EE\Utils\get_flag_value( $assoc_args, 'all' ); - $no_service_specified = count( $assoc_args ) === 0 ; + \EE\Utils\delem_log( 'site reload start' ); + $args = \EE\SiteUtils\auto_site_name( $args, $this->command, __FUNCTION__ ); + $all = \EE\Utils\get_flag_value( $assoc_args, 'all' ); + $no_service_specified = count( $assoc_args ) === 0; $this->populate_site_info( $args ); chdir( $this->site_root ); - if( $all || $no_service_specified ) { - if( $action === 'reload' ) { - $this->reload_services( [ 'nginx', 'php' ] ); - return; - } - \EE\SiteUtils\run_compose_command( $action, '', null, 'all services' ); - } - else { - $services = array_map( [$this, 'map_args_to_service'], array_keys( $assoc_args ) ); - - if( $action === 'reload' ) { - $this->reload_services( $services ); - return; - } - - foreach( $services as $service ) { - \EE\SiteUtils\run_compose_command( $action, $service ); - } + if ( $all || $no_service_specified ) { + $this->reload_services( [ 'nginx' ] ); + } else { + $this->reload_services( array_keys( $assoc_args ) ); } + \EE\Utils\delem_log( 'site reload stop' ); } /** @@ -427,24 +410,13 @@ private function site_docker_compose_execute( $site, $action, $args, $assoc_args private function reload_services( $services ) { $reload_command = [ 'nginx' => 'nginx sh -c \'nginx -t && service openresty reload\'', - 'php' => 'php kill -USR2 1' ]; - foreach( $services as $service ) { - \EE\SiteUtils\run_compose_command( 'exec', $reload_command[ $service ], 'reload', $service ); + foreach ( $services as $service ) { + $this->run_compose_command( 'exec', $reload_command[$service], 'reload', $service ); } } - /** - * Maps argument passed from cli to docker-compose service name - */ - private function map_args_to_service( $arg ) { - $services_map = [ - 'mysql' => 'db', - ]; - return in_array( $arg, array_keys( $services_map ) ) ? $services_map[ $arg ] : $arg ; - } - /** * Function to configure site and copy all the required files. */ From 8d46aa8df0c9e03296a7e7b3528b0ba9183a4438 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 25 Jul 2018 18:05:26 +0530 Subject: [PATCH 18/52] Update site entry in db for html Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Command.php | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index c44b4a18..d5b2efbe 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -592,30 +592,15 @@ private function delete_site() { * Function to save the site configuration entry into database. */ private function create_site_db_entry() { - $ssl = $this->le ? 1 : 0; + $ssl = $this->le ? 1 : 0; $data = array( - 'sitename' => $this->site_name, - 'site_type' => $this->site_type, - 'site_title' => $this->site_title, - 'proxy_type' => $this->proxy_type, - 'cache_type' => $this->cache_type, - 'site_path' => $this->site_root, - 'db_name' => $this->db_name, - 'db_user' => $this->db_user, - 'db_host' => $this->db_host, - 'db_port' => $this->db_port, - 'db_password' => $this->db_pass, - 'db_root_password' => $this->db_root_pass, - 'email' => $this->site_email, - 'is_ssl' => $ssl, - 'created_on' => date( 'Y-m-d H:i:s', time() ), + 'sitename' => $this->site_name, + 'site_type' => $this->site_type, + 'site_path' => $this->site_root, + 'is_ssl' => $ssl, + 'created_on' => date( 'Y-m-d H:i:s', time() ), ); - if ( ! $this->skip_install ) { - $data['wp_user'] = $this->site_user; - $data['wp_pass'] = $this->site_pass; - } - try { if ( $this->db::insert( $data ) ) { EE::log( 'Site entry created.' ); From 3480db0cc1ded53497bed5088e5df3c9050343f4 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 25 Jul 2018 18:06:08 +0530 Subject: [PATCH 19/52] Update site info population for html Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Command.php | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index d5b2efbe..81ad305c 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -622,25 +622,11 @@ private function populate_site_info( $args ) { if ( $this->db::site_in_db( $this->site_name ) ) { - $data = array( 'site_type', 'site_title', 'proxy_type', 'cache_type', 'site_path', 'db_name', 'db_user', 'db_host', 'db_port', 'db_password', 'db_root_password', 'wp_user', 'wp_pass', 'email', 'is_ssl' ); - - $db_select = $this->db::select( $data, array( 'sitename' => $this->site_name ) ); - - $this->site_type = $db_select[0]['site_type']; - $this->site_title = $db_select[0]['site_title']; - $this->proxy_type = $db_select[0]['proxy_type']; - $this->cache_type = $db_select[0]['cache_type']; - $this->site_root = $db_select[0]['site_path']; - $this->db_user = $db_select[0]['db_user']; - $this->db_name = $db_select[0]['db_name']; - $this->db_host = $db_select[0]['db_host']; - $this->db_port = $db_select[0]['db_port']; - $this->db_pass = $db_select[0]['db_password']; - $this->db_root_pass = $db_select[0]['db_root_password']; - $this->site_user = $db_select[0]['wp_user']; - $this->site_pass = $db_select[0]['wp_pass']; - $this->site_email = $db_select[0]['email']; - $this->le = $db_select[0]['is_ssl']; + $db_select = $this->db::select( [], array( 'sitename' => $this->site_name ) ); + + $this->site_type = $db_select[0]['site_type']; + $this->site_root = $db_select[0]['site_path']; + $this->le = $db_select[0]['is_ssl']; } else { EE::error( "Site $this->site_name does not exist." ); From f3258093ea72a0a01a7d1ac1d088ef42d56211c6 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 25 Jul 2018 18:07:52 +0530 Subject: [PATCH 20/52] Update site deletion Remove additional Remote db deletion Switch to Symfony Filesystem --- src/Site_Command.php | 48 ++++++++++++++++---------------------------- 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 81ad305c..6ffbc97b 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -513,21 +513,7 @@ private function create_site() { * Level - 5: Remove db entry. */ private function delete_site() { - - // Commented below block intentionally as they need change in DB - // which should be discussed with the team - if ( 'db' !== $this->db_host && $this->level >= 4 ) { - - chdir( $this->site_root ); - $delete_db_command = "docker-compose exec php bash -c \"mysql --host=$this->db_host --port=$this->db_port --user=$this->db_user --password=$this->db_pass --execute='DROP DATABASE $this->db_name'\""; - - if ( \EE\Utils\default_launch( $delete_db_command ) ) { - EE::log( 'Database deleted.' ); - } else { - EE::warning( 'Could not remove the database.' ); - } - } - + $proxy_type = EE_PROXY_TYPE; if ( $this->level >= 3 ) { if ( $this->docker::docker_compose_down( $this->site_root ) ) { EE::log( "[$this->site_name] Docker Containers removed." ); @@ -538,21 +524,25 @@ private function delete_site() { } } - $this->docker::disconnect_site_network_from( $this->site_name, $this->proxy_type ); + $this->docker::disconnect_site_network_from( $this->site_name, $proxy_type ); } if ( $this->level >= 2 ) { if ( $this->docker::rm_network( $this->site_name ) ) { - EE::log( "[$this->site_name] Docker container removed from network $this->proxy_type." ); + EE::log( "[$this->site_name] Docker container removed from network $proxy_type." ); } else { if ( $this->level > 2 ) { - EE::warning( "Error in removing Docker container from network $this->proxy_type" ); + EE::warning( "Error in removing Docker container from network $proxy_type" ); } } } - if ( is_dir( $this->site_root ) ) { - if ( ! \EE\Utils\default_launch( "rm -rf $this->site_root" ) ) { + if ( $this->fs->exists( $this->site_root ) ) { + try { + $this->fs->remove( $this->site_root ); + } + catch ( Exception $e ) { + EE::debug( $e ); EE::error( 'Could not remove site root. Please check if you have sufficient rights.' ); } EE::log( "[$this->site_name] site root removed." ); @@ -565,19 +555,15 @@ private function delete_site() { $key_file = EE_CONF_ROOT . "/nginx/certs/$this->site_name.key"; $conf_certs = EE_CONF_ROOT . "/acme-conf/certs/$this->site_name"; $conf_var = EE_CONF_ROOT . "/acme-conf/var/$this->site_name"; - // TODO: Change all these operations to use symfony filesystem - if ( file_exists( $conf_certs ) ) { - \EE\Utils\delete_dir( $conf_certs ); - } - if ( file_exists( $conf_var ) ) { - \EE\Utils\delete_dir( $conf_var ); - } - if ( file_exists( $crt_file ) ) { - unlink( $crt_file ); + + $cert_files = [ $conf_certs, $conf_var, $crt_file, $key_file ]; + try { + $this->fs->remove( $cert_files ); } - if ( file_exists( $key_file ) ) { - unlink( $key_file ); + catch ( Exception $e ) { + EE::warning( $e ); } + } if ( $this->db::delete( array( 'sitename' => $this->site_name ) ) ) { EE::log( 'Removing database entry.' ); From e21593849fec514feba35339ddc51616e9d56474 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 25 Jul 2018 18:09:18 +0530 Subject: [PATCH 21/52] Remove extra variables Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Command.php | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 6ffbc97b..87f4ca94 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -20,27 +20,12 @@ class Site_Command extends EE_Site_Command { private $site_name; private $site_root; private $site_type; - private $site_title; - private $site_user; - private $site_pass; - private $site_email; - private $proxy_type; - private $cache_type; private $db; private $docker; private $level; private $logger; private $le; - private $db_name; - private $db_user; - private $db_root_pass; - private $db_pass; - private $db_host; - private $db_port; - private $locale; - private $skip_install; private $skip_chk; - private $force; private $le_mail; private $fs; From af8d7f1674eb006f6c048a9840e29d011056defe Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 25 Jul 2018 18:10:13 +0530 Subject: [PATCH 22/52] Update info for html Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Command.php | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 87f4ca94..8632992a 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -300,23 +300,11 @@ public function info( $args, $assoc_args ) { $prefix = ( $this->le ) ? 'https://' : 'http://'; $info = array( array( 'Site', $prefix . $this->site_name ), - array( 'Access phpMyAdmin', $prefix . $this->site_name . '/ee-admin/pma/' ), array( 'Access mailhog', $prefix . $this->site_name . '/ee-admin/mailhog/' ), - array( 'Site Title', $this->site_title ), - array( 'DB Root Password', $this->db_root_pass ), - array( 'DB Name', $this->db_name ), - array( 'DB User', $this->db_user ), - array( 'DB Password', $this->db_pass ), - array( 'E-Mail', $this->site_email ), - array( 'Cache Type', $this->cache_type ), + array( 'Site Root', $this->site_root ), array( 'SSL', $ssl ), ); - if ( ! empty( $this->site_user ) && ! $this->skip_install ) { - $info[] = array( 'WordPress Username', $this->site_user ); - $info[] = array( 'WordPress Password', $this->site_pass ); - } - \EE\Utils\format_table( $info ); \EE\Utils\delem_log( 'site info end' ); @@ -357,7 +345,7 @@ public function restart( $args, $assoc_args ) { \EE\Utils\delem_log( 'site restart stop' ); } - /** + /** * Reload services in containers without restarting container(s) associated with site. * When no service(--nginx etc.) is specified, all services will be reloaded. * From d2096cd990a1dc63921585c6a29c5064c28ae2bc Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 25 Jul 2018 18:15:57 +0530 Subject: [PATCH 23/52] phpcbf run Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Command.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 8632992a..82e839b5 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -30,7 +30,7 @@ class Site_Command extends EE_Site_Command { private $fs; public function __construct() { - $this->level = 0; + $this->level = 0; $this->command = 'site'; pcntl_signal( SIGTERM, [ $this, "rollback" ] ); pcntl_signal( SIGHUP, [ $this, "rollback" ] ); @@ -181,7 +181,7 @@ public function delete( $args, $assoc_args ) { */ private function init_le() { $client = new Site_Letsencrypt(); - $this->le_mail = EE::get_runner()->config[ 'le-mail' ] ?? EE::input( 'Enter your mail id: ' ); + $this->le_mail = EE::get_runner()->config['le-mail'] ?? EE::input( 'Enter your mail id: ' ); EE::get_runner()->ensure_present_in_config( 'le-mail', $this->le_mail ); if ( ! $client->register( $this->le_mail ) ) { $this->le = false; @@ -310,7 +310,7 @@ public function info( $args, $assoc_args ) { \EE\Utils\delem_log( 'site info end' ); } - /** + /** * Restarts containers associated with site. * When no service(--nginx etc.) is specified, all site containers will be restarted. * @@ -411,7 +411,7 @@ private function configure_site_files() { $filter[] = $this->le; $site_docker = new Site_Docker(); $docker_compose_content = $site_docker->generate_docker_compose_yml( $filter ); - $default_conf_content = $default_conf_content = \EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/config/nginx/default.conf.mustache', [ $this->site_name ] ); + $default_conf_content = $default_conf_content = \EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/config/nginx/default.conf.mustache', [ $this->site_name ] ); $env_data = [ 'virtual_host' => $this->site_name, @@ -427,7 +427,7 @@ private function configure_site_files() { $this->fs->mkdir( $site_conf_dir . '/nginx' ); $this->fs->dumpFile( $site_nginx_default_conf, $default_conf_content ); - $index_data = ['v'.EE_VERSION,$this->site_root]; + $index_data = [ 'v' . EE_VERSION, $this->site_root ]; $index_html = \EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/index.html.mustache', $index_data ); $this->fs->mkdir( $site_src_dir ); $this->fs->dumpFile( $site_src_dir . '/index.html', $index_html ); From 39c7f2b63e0b6fc063ff7b4995ecc5d728fe85bf Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 25 Jul 2018 18:16:53 +0530 Subject: [PATCH 24/52] Update docker-compose generation for html Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Docker.php | 111 ++------------------------------------------ 1 file changed, 3 insertions(+), 108 deletions(-) diff --git a/src/Site_Docker.php b/src/Site_Docker.php index 8f25370d..56f37177 100644 --- a/src/Site_Docker.php +++ b/src/Site_Docker.php @@ -7,9 +7,7 @@ class Site_Docker { /** * Generate docker-compose.yml according to requirement. * - * @param array $filters Array of flags to determine the docker-compose.yml generation. - * Empty/Default -> Generates default WordPress docker-compose.yml - * ['le'] -> Enables letsencrypt in the generation. + * @param array $filters Array to determine the docker-compose.yml generation. * * @return String docker-compose.yml content string. */ @@ -19,73 +17,12 @@ public function generate_docker_compose_yml( array $filters = [] ) { $restart_default = array( 'name' => 'always' ); $network_default = array( 'name' => 'site-network' ); - // db configuration. - $db['service_name'] = array( 'name' => 'db' ); - $db['image'] = array( 'name' => 'easyengine/mariadb:v' . EE_VERSION ); - $db['restart'] = $restart_default; - $db['labels'] = array( - array( - 'label' => array( - 'name' => 'io.easyengine.site=${VIRTUAL_HOST}', - ), - ), - ); - $db['volumes'] = array( - array( - 'vol' => array( - 'name' => './app/db:/var/lib/mysql', - ), - ), - ); - $db['environment'] = array( - 'env' => array( - array( 'name' => 'MYSQL_ROOT_PASSWORD' ), - array( 'name' => 'MYSQL_DATABASE' ), - array( 'name' => 'MYSQL_USER' ), - array( 'name' => 'MYSQL_PASSWORD' ), - ), - ); - $db['networks'] = $network_default; - // PHP configuration. - $php['service_name'] = array( 'name' => 'php' ); - $php['image'] = array( 'name' => 'easyengine/php:v' . EE_VERSION ); - $php['depends_on'] = array( 'name' => 'db' ); - $php['restart'] = $restart_default; - $php['labels'] = array( - array( - 'label' => array( - 'name' => 'io.easyengine.site=${VIRTUAL_HOST}', - ), - ), - ); - $php['volumes'] = array( - array( - 'vol' => array( - array( 'name' => './app/src:/var/www/htdocs' ), - array( 'name' => './config/php-fpm/php.ini:/usr/local/etc/php/php.ini' ), - ), - ), - ); - $php['environment'] = array( - 'env' => array( - array( 'name' => 'WORDPRESS_DB_HOST' ), - array( 'name' => 'WORDPRESS_DB_NAME' ), - array( 'name' => 'WORDPRESS_DB_USER' ), - array( 'name' => 'WORDPRESS_DB_PASSWORD' ), - array( 'name' => 'USER_ID' ), - array( 'name' => 'GROUP_ID' ), - array( 'name' => 'VIRTUAL_HOST' ), - ), - ); - $php['networks'] = $network_default; - // nginx configuration. $nginx['service_name'] = array( 'name' => 'nginx' ); $nginx['image'] = array( 'name' => 'easyengine/nginx:v' . EE_VERSION ); - $nginx['depends_on'] = array( 'name' => 'php' ); $nginx['restart'] = $restart_default; - $v_host = in_array( 'wpsubdom', $filters, true ) ? 'VIRTUAL_HOST=${VIRTUAL_HOST},*.${VIRTUAL_HOST}' : 'VIRTUAL_HOST'; + $v_host = 'VIRTUAL_HOST'; $nginx['environment'] = array( 'env' => array( @@ -111,26 +48,6 @@ public function generate_docker_compose_yml( array $filters = [] ) { ); $nginx['networks'] = $network_default; - // PhpMyAdmin configuration. - $phpmyadmin['service_name'] = array( 'name' => 'phpmyadmin' ); - $phpmyadmin['image'] = array( 'name' => 'easyengine/phpmyadmin:v' . EE_VERSION ); - $phpmyadmin['restart'] = $restart_default; - $phpmyadmin['environment'] = array( - 'env' => array( - array( 'name' => 'PMA_ABSOLUTE_URI=http://${VIRTUAL_HOST}/ee-admin/pma/' ), - array( 'name' => $v_host ), - array( 'name' => 'VIRTUAL_PATH=/ee-admin/pma/' ), - ), - ); - $phpmyadmin['labels'] = array( - array( - 'label' => array( - 'name' => 'io.easyengine.site=${VIRTUAL_HOST}', - ), - ), - ); - $phpmyadmin['networks'] = $network_default; - // mailhog configuration. $mailhog['service_name'] = array( 'name' => 'mailhog' ); $mailhog['image'] = array( 'name' => 'easyengine/mailhog:v' . EE_VERSION ); @@ -143,7 +60,7 @@ public function generate_docker_compose_yml( array $filters = [] ) { array( 'name' => 'VIRTUAL_PORT=8025' ), ), ); - $mailhog['labels'] = array( + $mailhog['labels'] = array( array( 'label' => array( 'name' => 'io.easyengine.site=${VIRTUAL_HOST}', @@ -152,30 +69,8 @@ public function generate_docker_compose_yml( array $filters = [] ) { ); $mailhog['networks'] = $network_default; - // redis configuration. - $redis['service_name'] = array( 'name' => 'redis' ); - $redis['image'] = array( 'name' => 'easyengine/redis:v' . EE_VERSION ); - $redis['labels'] = array( - array( - 'label' => array( - 'name' => 'io.easyengine.site=${VIRTUAL_HOST}', - ), - ), - ); - $redis['networks'] = $network_default; - - if ( in_array( 'db', $filters, true ) ) { - $base[] = $db; - } - - $base[] = $php; $base[] = $nginx; $base[] = $mailhog; - $base[] = $phpmyadmin; - - if ( in_array( 'wpredis', $filters, true ) ) { - $base[] = $redis; - } $binding = array( 'services' => $base, From 41eac22ea7fb3020fa41f0f97261b56df3d05bd9 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 25 Jul 2018 18:19:03 +0530 Subject: [PATCH 25/52] Add index page mustache Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- templates/index.html.mustache | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 templates/index.html.mustache diff --git a/templates/index.html.mustache b/templates/index.html.mustache new file mode 100644 index 00000000..5ec3f583 --- /dev/null +++ b/templates/index.html.mustache @@ -0,0 +1,3 @@ +<h1>Congratulations! Your html site with EasyEngine {{version}} is working perfectly.</h1> +<br/> +<h4>You can copy your site files to {{site_src_root}}.</h4> From 8c5eeafd9bdb4e6faccda76ef0e70b545c0dbe15 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 25 Jul 2018 18:19:28 +0530 Subject: [PATCH 26/52] Update env for html Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- templates/config/.env.mustache | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/templates/config/.env.mustache b/templates/config/.env.mustache index 3e2c283b..6d6c2f57 100644 --- a/templates/config/.env.mustache +++ b/templates/config/.env.mustache @@ -1,13 +1,3 @@ -{{#local}} -MYSQL_ROOT_PASSWORD={{root_password}} -MYSQL_DATABASE={{database_name}} -MYSQL_USER={{database_user}} -MYSQL_PASSWORD={{user_password}} -{{/local}} -WORDPRESS_DB_HOST={{wp_db_host}} -WORDPRESS_DB_USER={{wp_db_user}} -WORDPRESS_DB_NAME={{wp_db_name}} -WORDPRESS_DB_PASSWORD={{wp_db_pass}} VIRTUAL_HOST={{virtual_host}} VIRTUAL_HOST_EMAIL=example@{{virtual_host}} USER_ID={{user_id}} From d5dade39e223194f61c2f29db4635acbfb378ce3 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 25 Jul 2018 18:39:37 +0530 Subject: [PATCH 27/52] Update server name for nginx config Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 82e839b5..9f83e922 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -411,7 +411,7 @@ private function configure_site_files() { $filter[] = $this->le; $site_docker = new Site_Docker(); $docker_compose_content = $site_docker->generate_docker_compose_yml( $filter ); - $default_conf_content = $default_conf_content = \EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/config/nginx/default.conf.mustache', [ $this->site_name ] ); + $default_conf_content = $default_conf_content = \EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/config/nginx/default.conf.mustache', [ 'server_name' => $this->site_name ] ); $env_data = [ 'virtual_host' => $this->site_name, From f9dbad02f96bf36cc2cbe46ece44eb977e7e489e Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 25 Jul 2018 18:45:18 +0530 Subject: [PATCH 28/52] Update index template data Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Command.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 9f83e922..907381a5 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -427,7 +427,10 @@ private function configure_site_files() { $this->fs->mkdir( $site_conf_dir . '/nginx' ); $this->fs->dumpFile( $site_nginx_default_conf, $default_conf_content ); - $index_data = [ 'v' . EE_VERSION, $this->site_root ]; + $index_data = [ + 'version' => 'v' . EE_VERSION, + 'site_src_root' => $this->site_root . '/app/src', + ]; $index_html = \EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/index.html.mustache', $index_data ); $this->fs->mkdir( $site_src_dir ); $this->fs->dumpFile( $site_src_dir . '/index.html', $index_html ); From 63c72e4eabecfd76fe96e07116defebe06b70ab1 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Thu, 26 Jul 2018 20:49:09 +0530 Subject: [PATCH 29/52] Remove letsencrypt files and dependencies Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- .../Cli/Exception/AcmeCliActionException.php | 23 - AcmePhp/Cli/Exception/AcmeCliException.php | 23 - .../Exception/AcmeDnsResolutionException.php | 23 - .../Cli/Exception/CommandFlowException.php | 55 -- AcmePhp/Cli/Repository/Repository.php | 439 -------------- .../Cli/Repository/RepositoryInterface.php | 198 ------- .../Cli/Repository/RepositoryV2Interface.php | 51 -- AcmePhp/Cli/Serializer/PemEncoder.php | 55 -- AcmePhp/Cli/Serializer/PemNormalizer.php | 55 -- composer.json | 8 - src/Site_Letsencrypt.php | 537 ------------------ 11 files changed, 1467 deletions(-) delete mode 100644 AcmePhp/Cli/Exception/AcmeCliActionException.php delete mode 100644 AcmePhp/Cli/Exception/AcmeCliException.php delete mode 100644 AcmePhp/Cli/Exception/AcmeDnsResolutionException.php delete mode 100644 AcmePhp/Cli/Exception/CommandFlowException.php delete mode 100644 AcmePhp/Cli/Repository/Repository.php delete mode 100644 AcmePhp/Cli/Repository/RepositoryInterface.php delete mode 100644 AcmePhp/Cli/Repository/RepositoryV2Interface.php delete mode 100644 AcmePhp/Cli/Serializer/PemEncoder.php delete mode 100644 AcmePhp/Cli/Serializer/PemNormalizer.php delete mode 100644 src/Site_Letsencrypt.php diff --git a/AcmePhp/Cli/Exception/AcmeCliActionException.php b/AcmePhp/Cli/Exception/AcmeCliActionException.php deleted file mode 100644 index a18f3e6f..00000000 --- a/AcmePhp/Cli/Exception/AcmeCliActionException.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of the Acme PHP project. - * - * (c) Titouan Galopin <galopintitouan@gmail.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace AcmePhp\Cli\Exception; - -/** - * @author Titouan Galopin <galopintitouan@gmail.com> - */ -class AcmeCliActionException extends AcmeCliException -{ - public function __construct($actionName, \Exception $previous = null) - { - parent::__construct(sprintf('An exception was thrown during action "%s"', $actionName), $previous); - } -} diff --git a/AcmePhp/Cli/Exception/AcmeCliException.php b/AcmePhp/Cli/Exception/AcmeCliException.php deleted file mode 100644 index b5f4c0c7..00000000 --- a/AcmePhp/Cli/Exception/AcmeCliException.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of the Acme PHP project. - * - * (c) Titouan Galopin <galopintitouan@gmail.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace AcmePhp\Cli\Exception; - -/** - * @author Titouan Galopin <galopintitouan@gmail.com> - */ -class AcmeCliException extends \RuntimeException -{ - public function __construct($message, \Exception $previous = null) - { - parent::__construct($message, 0, $previous); - } -} diff --git a/AcmePhp/Cli/Exception/AcmeDnsResolutionException.php b/AcmePhp/Cli/Exception/AcmeDnsResolutionException.php deleted file mode 100644 index a1137999..00000000 --- a/AcmePhp/Cli/Exception/AcmeDnsResolutionException.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -/* - * This file is part of the Acme PHP project. - * - * (c) Titouan Galopin <galopintitouan@gmail.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace AcmePhp\Cli\Exception; - -/** - * @author Jérémy Derussé <jeremy@derusse.com> - */ -class AcmeDnsResolutionException extends AcmeCliException -{ - public function __construct($message, \Exception $previous = null) - { - parent::__construct(null === $message ? 'An exception was thrown during resolution of DNS' : $message, $previous); - } -} diff --git a/AcmePhp/Cli/Exception/CommandFlowException.php b/AcmePhp/Cli/Exception/CommandFlowException.php deleted file mode 100644 index f03b5b29..00000000 --- a/AcmePhp/Cli/Exception/CommandFlowException.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -/* - * This file is part of the Acme PHP project. - * - * (c) Titouan Galopin <galopintitouan@gmail.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace AcmePhp\Cli\Exception; - -/** - * @author Jérémy Derussé <jeremy@derusse.com> - */ -class CommandFlowException extends AcmeCliException -{ - /** - * @var string - */ - private $missing; - /** - * @var string - */ - private $command; - /** - * @var array - */ - private $arguments; - - /** - * @param string $missing Missing requirement to fix the flow - * @param string $command Name of the command to run in order to fix the flow - * @param array $arguments Optional list of missing arguments - * @param \Exception|null $previous - */ - public function __construct($missing, $command, array $arguments = [], \Exception $previous = null) - { - $this->missing = $missing; - $this->command = $command; - $this->arguments = $arguments; - - $message = trim(sprintf( - 'You have to %s first. Run the command%sphp %s %s %s', - $missing, - PHP_EOL.PHP_EOL, - $_SERVER['PHP_SELF'], - $command, - implode(' ', $arguments) - )); - - parent::__construct($message, $previous); - } -} diff --git a/AcmePhp/Cli/Repository/Repository.php b/AcmePhp/Cli/Repository/Repository.php deleted file mode 100644 index 29a54c18..00000000 --- a/AcmePhp/Cli/Repository/Repository.php +++ /dev/null @@ -1,439 +0,0 @@ -<?php - -/* - * This file is part of the Acme PHP project. - * - * (c) Titouan Galopin <galopintitouan@gmail.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace AcmePhp\Cli\Repository; - -use AcmePhp\Cli\Exception\AcmeCliException; -use AcmePhp\Cli\Serializer\PemEncoder; -use AcmePhp\Core\Protocol\AuthorizationChallenge; -use AcmePhp\Core\Protocol\CertificateOrder; -use AcmePhp\Ssl\Certificate; -use AcmePhp\Ssl\CertificateResponse; -use AcmePhp\Ssl\DistinguishedName; -use AcmePhp\Ssl\KeyPair; -use AcmePhp\Ssl\PrivateKey; -use AcmePhp\Ssl\PublicKey; -use League\Flysystem\FilesystemInterface; -use Symfony\Component\Serializer\Encoder\JsonEncoder; -use Symfony\Component\Serializer\SerializerInterface; - -/** - * @author Titouan Galopin <galopintitouan@gmail.com> - */ -class Repository implements RepositoryV2Interface -{ - const PATH_ACCOUNT_KEY_PRIVATE = 'account/key.private.pem'; - const PATH_ACCOUNT_KEY_PUBLIC = 'account/key.public.pem'; - - const PATH_DOMAIN_KEY_PUBLIC = 'certs/{domain}/private/key.public.pem'; - const PATH_DOMAIN_KEY_PRIVATE = 'certs/{domain}/private/key.private.pem'; - const PATH_DOMAIN_CERT_CERT = 'certs/{domain}/public/cert.pem'; - const PATH_DOMAIN_CERT_CHAIN = 'certs/{domain}/public/chain.pem'; - const PATH_DOMAIN_CERT_FULLCHAIN = 'certs/{domain}/public/fullchain.pem'; - const PATH_DOMAIN_CERT_COMBINED = 'certs/{domain}/private/combined.pem'; - - const PATH_CACHE_AUTHORIZATION_CHALLENGE = 'var/{domain}/authorization_challenge.json'; - const PATH_CACHE_DISTINGUISHED_NAME = 'var/{domain}/distinguished_name.json'; - const PATH_CACHE_CERTIFICATE_ORDER = 'var/{domains}/certificate_order.json'; - - /** - * @var SerializerInterface - */ - private $serializer; - - /** - * @var FilesystemInterface - */ - private $master; - - /** - * @var FilesystemInterface - */ - private $backup; - - /** - * @var bool - */ - private $enableBackup; - - /** - * @param SerializerInterface $serializer - * @param FilesystemInterface $master - * @param FilesystemInterface $backup - * @param bool $enableBackup - */ - public function __construct(SerializerInterface $serializer, FilesystemInterface $master, FilesystemInterface $backup, $enableBackup) - { - $this->serializer = $serializer; - $this->master = $master; - $this->backup = $backup; - $this->enableBackup = $enableBackup; - } - - /** - * {@inheritdoc} - */ - public function storeCertificateResponse(CertificateResponse $certificateResponse) - { - $distinguishedName = $certificateResponse->getCertificateRequest()->getDistinguishedName(); - $domain = $distinguishedName->getCommonName(); - - $this->storeDomainKeyPair($domain, $certificateResponse->getCertificateRequest()->getKeyPair()); - $this->storeDomainDistinguishedName($domain, $distinguishedName); - $this->storeDomainCertificate($domain, $certificateResponse->getCertificate()); - } - - /** - * {@inheritdoc} - */ - public function storeAccountKeyPair(KeyPair $keyPair) - { - try { - $this->save( - self::PATH_ACCOUNT_KEY_PUBLIC, - $this->serializer->serialize($keyPair->getPublicKey(), PemEncoder::FORMAT) - ); - - $this->save( - self::PATH_ACCOUNT_KEY_PRIVATE, - $this->serializer->serialize($keyPair->getPrivateKey(), PemEncoder::FORMAT) - ); - } catch (\Exception $e) { - throw new AcmeCliException('Storing of account key pair failed', $e); - } - } - - private function getPathForDomain($path, $domain) - { - return strtr($path, ['{domain}' => $this->normalizeDomain($domain)]); - } - - private function getPathForDomainList($path, array $domains) - { - return strtr($path, ['{domains}' => $this->normalizeDomainList($domains)]); - } - - /** - * {@inheritdoc} - */ - public function hasAccountKeyPair() - { - return $this->master->has(self::PATH_ACCOUNT_KEY_PRIVATE); - } - - /** - * {@inheritdoc} - */ - public function loadAccountKeyPair() - { - try { - $publicKeyPem = $this->master->read(self::PATH_ACCOUNT_KEY_PUBLIC); - $privateKeyPem = $this->master->read(self::PATH_ACCOUNT_KEY_PRIVATE); - - return new KeyPair( - $this->serializer->deserialize($publicKeyPem, PublicKey::class, PemEncoder::FORMAT), - $this->serializer->deserialize($privateKeyPem, PrivateKey::class, PemEncoder::FORMAT) - ); - } catch (\Exception $e) { - throw new AcmeCliException('Loading of account key pair failed', $e); - } - } - - /** - * {@inheritdoc} - */ - public function storeDomainKeyPair($domain, KeyPair $keyPair) - { - try { - $this->save( - $this->getPathForDomain(self::PATH_DOMAIN_KEY_PUBLIC, $domain), - $this->serializer->serialize($keyPair->getPublicKey(), PemEncoder::FORMAT) - ); - - $this->save( - $this->getPathForDomain(self::PATH_DOMAIN_KEY_PRIVATE, $domain), - $this->serializer->serialize($keyPair->getPrivateKey(), PemEncoder::FORMAT) - ); - } catch (\Exception $e) { - throw new AcmeCliException(sprintf('Storing of domain %s key pair failed', $domain), $e); - } - } - - /** - * {@inheritdoc} - */ - public function hasDomainKeyPair($domain) - { - return $this->master->has($this->getPathForDomain(self::PATH_DOMAIN_KEY_PRIVATE, $domain)); - } - - /** - * {@inheritdoc} - */ - public function loadDomainKeyPair($domain) - { - try { - $publicKeyPem = $this->master->read($this->getPathForDomain(self::PATH_DOMAIN_KEY_PUBLIC, $domain)); - $privateKeyPem = $this->master->read($this->getPathForDomain(self::PATH_DOMAIN_KEY_PRIVATE, $domain)); - - return new KeyPair( - $this->serializer->deserialize($publicKeyPem, PublicKey::class, PemEncoder::FORMAT), - $this->serializer->deserialize($privateKeyPem, PrivateKey::class, PemEncoder::FORMAT) - ); - } catch (\Exception $e) { - throw new AcmeCliException(sprintf('Loading of domain %s key pair failed', $domain), $e); - } - } - - /** - * {@inheritdoc} - */ - public function storeDomainAuthorizationChallenge($domain, AuthorizationChallenge $authorizationChallenge) - { - try { - $this->save( - $this->getPathForDomain(self::PATH_CACHE_AUTHORIZATION_CHALLENGE, $domain), - $this->serializer->serialize($authorizationChallenge, JsonEncoder::FORMAT) - ); - } catch (\Exception $e) { - throw new AcmeCliException(sprintf('Storing of domain %s authorization challenge failed', $domain), $e); - } - } - - /** - * {@inheritdoc} - */ - public function hasDomainAuthorizationChallenge($domain) - { - return $this->master->has($this->getPathForDomain(self::PATH_CACHE_AUTHORIZATION_CHALLENGE, $domain)); - } - - /** - * {@inheritdoc} - */ - public function loadDomainAuthorizationChallenge($domain) - { - try { - $json = $this->master->read($this->getPathForDomain(self::PATH_CACHE_AUTHORIZATION_CHALLENGE, $domain)); - - return $this->serializer->deserialize($json, AuthorizationChallenge::class, JsonEncoder::FORMAT); - } catch (\Exception $e) { - throw new AcmeCliException(sprintf('Loading of domain %s authorization challenge failed', $domain), $e); - } - } - - /** - * {@inheritdoc} - */ - public function storeDomainDistinguishedName($domain, DistinguishedName $distinguishedName) - { - try { - $this->save( - $this->getPathForDomain(self::PATH_CACHE_DISTINGUISHED_NAME, $domain), - $this->serializer->serialize($distinguishedName, JsonEncoder::FORMAT) - ); - } catch (\Exception $e) { - throw new AcmeCliException(sprintf('Storing of domain %s distinguished name failed', $domain), $e); - } - } - - /** - * {@inheritdoc} - */ - public function hasDomainDistinguishedName($domain) - { - return $this->master->has($this->getPathForDomain(self::PATH_CACHE_DISTINGUISHED_NAME, $domain)); - } - - /** - * {@inheritdoc} - */ - public function loadDomainDistinguishedName($domain) - { - try { - $json = $this->master->read($this->getPathForDomain(self::PATH_CACHE_DISTINGUISHED_NAME, $domain)); - - return $this->serializer->deserialize($json, DistinguishedName::class, JsonEncoder::FORMAT); - } catch (\Exception $e) { - throw new AcmeCliException(sprintf('Loading of domain %s distinguished name failed', $domain), $e); - } - } - - /** - * {@inheritdoc} - */ - public function storeDomainCertificate($domain, Certificate $certificate) - { - // Simple certificate - $certPem = $this->serializer->serialize($certificate, PemEncoder::FORMAT); - - // Issuer chain - $issuerChain = []; - $issuerCertificate = $certificate->getIssuerCertificate(); - - while (null !== $issuerCertificate) { - $issuerChain[] = $this->serializer->serialize($issuerCertificate, PemEncoder::FORMAT); - $issuerCertificate = $issuerCertificate->getIssuerCertificate(); - } - - $chainPem = implode("\n", $issuerChain); - - // Full chain - $fullChainPem = $certPem.$chainPem; - - // Combined - $keyPair = $this->loadDomainKeyPair($domain); - $combinedPem = $fullChainPem.$this->serializer->serialize($keyPair->getPrivateKey(), PemEncoder::FORMAT); - - // Save - $this->save($this->getPathForDomain(self::PATH_DOMAIN_CERT_CERT, $domain), $certPem); - $this->save($this->getPathForDomain(self::PATH_DOMAIN_CERT_CHAIN, $domain), $chainPem); - $this->save($this->getPathForDomain(self::PATH_DOMAIN_CERT_FULLCHAIN, $domain), $fullChainPem); - $this->save($this->getPathForDomain(self::PATH_DOMAIN_CERT_COMBINED, $domain), $combinedPem); - } - - /** - * {@inheritdoc} - */ - public function hasDomainCertificate($domain) - { - return $this->master->has($this->getPathForDomain(self::PATH_DOMAIN_CERT_FULLCHAIN, $domain)); - } - - /** - * {@inheritdoc} - */ - public function loadDomainCertificate($domain) - { - try { - $pems = explode('-----BEGIN CERTIFICATE-----', $this->master->read($this->getPathForDomain(self::PATH_DOMAIN_CERT_FULLCHAIN, $domain))); - } catch (\Exception $e) { - throw new AcmeCliException(sprintf('Loading of domain %s certificate failed', $domain), $e); - } - - $pems = array_map(function ($item) { - return trim(str_replace('-----END CERTIFICATE-----', '', $item)); - }, $pems); - array_shift($pems); - $pems = array_reverse($pems); - - $certificate = null; - - foreach ($pems as $pem) { - $certificate = new Certificate( - "-----BEGIN CERTIFICATE-----\n".$pem."\n-----END CERTIFICATE-----", - $certificate - ); - } - - return $certificate; - } - - /** - * {@inheritdoc} - */ - public function storeCertificateOrder(array $domains, CertificateOrder $order) - { - try { - $this->save( - $this->getPathForDomainList(self::PATH_CACHE_CERTIFICATE_ORDER, $domains), - $this->serializer->serialize($order, JsonEncoder::FORMAT) - ); - } catch (\Exception $e) { - throw new AcmeCliException(sprintf('Storing of domains %s certificate order failed', implode(', ', $domains)), $e); - } - } - - /** - * {@inheritdoc} - */ - public function hasCertificateOrder(array $domains) - { - return $this->master->has($this->getPathForDomainList(self::PATH_CACHE_CERTIFICATE_ORDER, $domains)); - } - - /** - * {@inheritdoc} - */ - public function loadCertificateOrder(array $domains) - { - try { - $json = $this->master->read($this->getPathForDomainList(self::PATH_CACHE_CERTIFICATE_ORDER, $domains)); - - return $this->serializer->deserialize($json, CertificateOrder::class, JsonEncoder::FORMAT); - } catch (\Exception $e) { - throw new AcmeCliException(sprintf('Loading of domains %s certificate order failed', implode(', ', $domains)), $e); - } - } - - /** - * {@inheritdoc} - */ - public function save($path, $content, $visibility = self::VISIBILITY_PRIVATE) - { - if (!$this->master->has($path)) { - // File creation: remove from backup if it existed and warm-up both master and backup - $this->createAndBackup($path, $content); - } else { - // File update: backup before writing - $this->backupAndUpdate($path, $content); - } - - if ($this->enableBackup) { - $this->backup->setVisibility($path, $visibility); - } - - $this->master->setVisibility($path, $visibility); - } - - private function createAndBackup($path, $content) - { - if ($this->enableBackup) { - if ($this->backup->has($path)) { - $this->backup->delete($path); - } - - $this->backup->write($path, $content); - } - - $this->master->write($path, $content); - } - - private function backupAndUpdate($path, $content) - { - if ($this->enableBackup) { - $oldContent = $this->master->read($path); - - if (false !== $oldContent) { - if ($this->backup->has($path)) { - $this->backup->update($path, $oldContent); - } else { - $this->backup->write($path, $oldContent); - } - } - } - - $this->master->update($path, $content); - } - - private function normalizeDomain($domain) - { - return $domain; - } - - private function normalizeDomainList(array $domains) - { - $normalizedDomains = array_unique(array_map([$this, 'normalizeDomain'], $domains)); - sort($normalizedDomains); - - return (isset($domains[0]) ? $this->normalizeDomain($domains[0]) : '-').'/'.sha1(json_encode($normalizedDomains)); - } -} diff --git a/AcmePhp/Cli/Repository/RepositoryInterface.php b/AcmePhp/Cli/Repository/RepositoryInterface.php deleted file mode 100644 index f42c5277..00000000 --- a/AcmePhp/Cli/Repository/RepositoryInterface.php +++ /dev/null @@ -1,198 +0,0 @@ -<?php - -/* - * This file is part of the Acme PHP project. - * - * (c) Titouan Galopin <galopintitouan@gmail.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace AcmePhp\Cli\Repository; - -use AcmePhp\Cli\Exception\AcmeCliException; -use AcmePhp\Core\Protocol\AuthorizationChallenge; -use AcmePhp\Ssl\Certificate; -use AcmePhp\Ssl\CertificateResponse; -use AcmePhp\Ssl\DistinguishedName; -use AcmePhp\Ssl\KeyPair; - -/** - * @author Titouan Galopin <galopintitouan@gmail.com> - */ -interface RepositoryInterface -{ - const VISIBILITY_PUBLIC = 'public'; - const VISIBILITY_PRIVATE = 'private'; - - /** - * Extract important elements from the given certificate response and store them - * in the repository. - * - * This method will use the distinguished name common name as a domain to store: - * - the key pair - * - the certificate request - * - the certificate - * - * @param CertificateResponse $certificateResponse - * - * @throws AcmeCliException - */ - public function storeCertificateResponse(CertificateResponse $certificateResponse); - - /** - * Store a given key pair as the account key pair (the global key pair used to - * interact with the ACME server). - * - * @param KeyPair $keyPair - * - * @throws AcmeCliException - */ - public function storeAccountKeyPair(KeyPair $keyPair); - - /** - * Check if there is an account key pair in the repository. - * - * @return bool - */ - public function hasAccountKeyPair(); - - /** - * Load the account key pair. - * - * @throws AcmeCliException - * - * @return KeyPair - */ - public function loadAccountKeyPair(); - - /** - * Store a given key pair as associated to a given domain. - * - * @param string $domain - * @param KeyPair $keyPair - * - * @throws AcmeCliException - */ - public function storeDomainKeyPair($domain, KeyPair $keyPair); - - /** - * Check if there is a key pair associated to the given domain in the repository. - * - * @param string $domain - * - * @return bool - */ - public function hasDomainKeyPair($domain); - - /** - * Load the key pair associated to a given domain. - * - * @param string $domain - * - * @throws AcmeCliException - * - * @return KeyPair - */ - public function loadDomainKeyPair($domain); - - /** - * Store a given authorization challenge as associated to a given domain. - * - * @param string $domain - * @param AuthorizationChallenge $authorizationChallenge - * - * @throws AcmeCliException - */ - public function storeDomainAuthorizationChallenge($domain, AuthorizationChallenge $authorizationChallenge); - - /** - * Check if there is an authorization challenge associated to the given domain in the repository. - * - * @param string $domain - * - * @return bool - */ - public function hasDomainAuthorizationChallenge($domain); - - /** - * Load the authorization challenge associated to a given domain. - * - * @param string $domain - * - * @throws AcmeCliException - * - * @return AuthorizationChallenge - */ - public function loadDomainAuthorizationChallenge($domain); - - /** - * Store a given distinguished name as associated to a given domain. - * - * @param string $domain - * @param DistinguishedName $distinguishedName - * - * @throws AcmeCliException - */ - public function storeDomainDistinguishedName($domain, DistinguishedName $distinguishedName); - - /** - * Check if there is a distinguished name associated to the given domain in the repository. - * - * @param string $domain - * - * @return bool - */ - public function hasDomainDistinguishedName($domain); - - /** - * Load the distinguished name associated to a given domain. - * - * @param string $domain - * - * @throws AcmeCliException - * - * @return DistinguishedName - */ - public function loadDomainDistinguishedName($domain); - - /** - * Store a given certificate as associated to a given domain. - * - * @param string $domain - * @param Certificate $certificate - * - * @throws AcmeCliException - */ - public function storeDomainCertificate($domain, Certificate $certificate); - - /** - * Check if there is a certificate associated to the given domain in the repository. - * - * @param string $domain - * - * @return bool - */ - public function hasDomainCertificate($domain); - - /** - * Load the certificate associated to a given domain. - * - * @param string $domain - * - * @throws AcmeCliException - * - * @return Certificate - */ - public function loadDomainCertificate($domain); - - /** - * Save a given string into a given path handling backup. - * - * @param string $path - * @param string $content - * @param string $visibility the visibilty to use for this file - */ - public function save($path, $content, $visibility = self::VISIBILITY_PRIVATE); -} diff --git a/AcmePhp/Cli/Repository/RepositoryV2Interface.php b/AcmePhp/Cli/Repository/RepositoryV2Interface.php deleted file mode 100644 index f3b67e03..00000000 --- a/AcmePhp/Cli/Repository/RepositoryV2Interface.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -/* - * This file is part of the Acme PHP project. - * - * (c) Titouan Galopin <galopintitouan@gmail.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace AcmePhp\Cli\Repository; - -use AcmePhp\Cli\Exception\AcmeCliException; -use AcmePhp\Core\Protocol\CertificateOrder; - -/** - * @author Titouan Galopin <galopintitouan@gmail.com> - */ -interface RepositoryV2Interface extends RepositoryInterface -{ - /** - * Store a given certificate as associated to a given domain. - * - * @param array $domains - * @param CertificateOrder $order - * - * @throws AcmeCliException - */ - public function storeCertificateOrder(array $domains, CertificateOrder $order); - - /** - * Check if there is a certificate associated to the given domain in the repository. - * - * @param string $domain - * - * @return bool - */ - public function hasCertificateOrder(array $domains); - - /** - * Load the certificate associated to a given domain. - * - * @param string $domain - * - * @throws AcmeCliException - * - * @return CertificateOrder - */ - public function loadCertificateOrder(array $domains); -} diff --git a/AcmePhp/Cli/Serializer/PemEncoder.php b/AcmePhp/Cli/Serializer/PemEncoder.php deleted file mode 100644 index 01d3a15d..00000000 --- a/AcmePhp/Cli/Serializer/PemEncoder.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -/* - * This file is part of the Acme PHP project. - * - * (c) Titouan Galopin <galopintitouan@gmail.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace AcmePhp\Cli\Serializer; - -use Symfony\Component\Serializer\Encoder\DecoderInterface; -use Symfony\Component\Serializer\Encoder\EncoderInterface; - -/** - * @author Titouan Galopin <galopintitouan@gmail.com> - */ -class PemEncoder implements EncoderInterface, DecoderInterface -{ - const FORMAT = 'pem'; - - /** - * {@inheritdoc} - */ - public function encode($data, $format, array $context = []) - { - return trim($data)."\n"; - } - - /** - * {@inheritdoc} - */ - public function decode($data, $format, array $context = []) - { - return trim($data)."\n"; - } - - /** - * {@inheritdoc} - */ - public function supportsEncoding($format) - { - return self::FORMAT === $format; - } - - /** - * {@inheritdoc} - */ - public function supportsDecoding($format) - { - return self::FORMAT === $format; - } -} diff --git a/AcmePhp/Cli/Serializer/PemNormalizer.php b/AcmePhp/Cli/Serializer/PemNormalizer.php deleted file mode 100644 index 564f1b93..00000000 --- a/AcmePhp/Cli/Serializer/PemNormalizer.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php - -/* - * This file is part of the Acme PHP project. - * - * (c) Titouan Galopin <galopintitouan@gmail.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace AcmePhp\Cli\Serializer; - -use AcmePhp\Ssl\Certificate; -use AcmePhp\Ssl\Key; -use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; -use Symfony\Component\Serializer\Normalizer\NormalizerInterface; - -/** - * @author Titouan Galopin <galopintitouan@gmail.com> - */ -class PemNormalizer implements NormalizerInterface, DenormalizerInterface -{ - /** - * {@inheritdoc} - */ - public function normalize($object, $format = null, array $context = []) - { - return $object->getPEM(); - } - - /** - * {@inheritdoc} - */ - public function denormalize($data, $class, $format = null, array $context = []) - { - return new $class($data); - } - - /** - * {@inheritdoc} - */ - public function supportsNormalization($data, $format = null) - { - return is_object($data) && ($data instanceof Certificate || $data instanceof Key); - } - - /** - * {@inheritdoc} - */ - public function supportsDenormalization($data, $type, $format = null) - { - return is_string($data); - } -} diff --git a/composer.json b/composer.json index cb29b74f..8faa7653 100644 --- a/composer.json +++ b/composer.json @@ -25,13 +25,5 @@ "site list", "site delete" ] - }, - "require": { - "acmephp/core": "dev-master", - "ext-openssl": "*", - "guzzlehttp/guzzle": "^6.0", - "league/flysystem": "^1.0.19", - "symfony/serializer": "^3.0", - "webmozart/assert": "^1.0" } } diff --git a/src/Site_Letsencrypt.php b/src/Site_Letsencrypt.php deleted file mode 100644 index 21dc8909..00000000 --- a/src/Site_Letsencrypt.php +++ /dev/null @@ -1,537 +0,0 @@ -<?php - -use AcmePhp\Cli\Repository\Repository; -use AcmePhp\Cli\Serializer\PemEncoder; -use AcmePhp\Cli\Serializer\PemNormalizer; -use AcmePhp\Core\AcmeClient; -use AcmePhp\Core\Challenge\ChainValidator; -use AcmePhp\Core\Challenge\WaitingValidator; -use AcmePhp\Core\Challenge\Http\SimpleHttpSolver; -use AcmePhp\Core\Challenge\Http\HttpValidator; -use AcmePhp\Core\Challenge\Dns\SimpleDnsSolver; -use AcmePhp\Core\Challenge\Dns\DnsValidator; -use AcmePhp\Core\Exception\Protocol\ChallengeNotSupportedException; -use AcmePhp\Core\Http\SecureHttpClient; -use AcmePhp\Core\Http\Base64SafeEncoder; -use AcmePhp\Core\Http\ServerErrorHandler; -use AcmePhp\Ssl\Certificate; -use AcmePhp\Ssl\CertificateRequest; -use AcmePhp\Ssl\CertificateResponse; -use AcmePhp\Ssl\DistinguishedName; -use AcmePhp\Ssl\Parser\KeyParser; -use AcmePhp\Ssl\Parser\CertificateParser; -use AcmePhp\Ssl\Generator\KeyPairGenerator; -use AcmePhp\Ssl\Signer\CertificateRequestSigner; -use AcmePhp\Ssl\Signer\DataSigner; -use Symfony\Component\Console\Helper\Table; -use Symfony\Component\Console\Output\ConsoleOutput; -use Symfony\Component\Serializer\Encoder\JsonEncoder; -use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer; -use Symfony\Component\Serializer\Serializer; -use League\Flysystem\Filesystem; -use League\Flysystem\Adapter\Local; -use League\Flysystem\Adapter\NullAdapter; -use GuzzleHttp\Client; - - -class Site_Letsencrypt { - - private $accountKeyPair; - private $httpClient; - private $base64SafeEncoder; - private $keyParser; - private $dataSigner; - private $serverErrorHandler; - private $serializer; - private $master; - private $backup; - private $client; - private $repository; - private $conf_dir; - - function __construct() { - $this->conf_dir = EE_CONF_ROOT . '/acme-conf'; - $this->setRepository(); - $this->setAcmeClient(); - } - - private function setAcmeClient() { - - if ( ! $this->repository->hasAccountKeyPair() ) { - EE::debug( 'No account key pair was found, generating one.' ); - EE::debug( 'Generating a key pair' ); - - $keygen = new KeyPairGenerator(); - $accountKeyPair = $keygen->generateKeyPair(); - EE::debug( 'Key pair generated, storing' ); - $this->repository->storeAccountKeyPair( $accountKeyPair ); - } else { - EE::debug( 'Loading account keypair' ); - $accountKeyPair = $this->repository->loadAccountKeyPair(); - } - - $this->accountKeyPair ?? $this->accountKeyPair = $accountKeyPair; - - $secureHttpClient = $this->getSecureHttpClient(); - $csrSigner = new CertificateRequestSigner(); - - $this->client = new AcmeClient( $secureHttpClient, 'https://acme-v02.api.letsencrypt.org/directory', $csrSigner ); - - } - - private function setRepository( $enable_backup = false ) { - $this->serializer ?? $this->serializer = new Serializer( - [ new PemNormalizer(), new GetSetMethodNormalizer() ], - [ new PemEncoder(), new JsonEncoder() ] - ); - $this->master ?? $this->master = new Filesystem( new Local( $this->conf_dir ) ); - $this->backup ?? $this->backup = new Filesystem( new NullAdapter() ); - - $this->repository = new Repository( $this->serializer, $this->master, $this->backup, $enable_backup ); - } - - private function getSecureHttpClient() { - $this->httpClient ?? $this->httpClient = new Client(); - $this->base64SafeEncoder ?? $this->base64SafeEncoder = new Base64SafeEncoder(); - $this->keyParser ?? $this->keyParser = new KeyParser(); - $this->dataSigner ?? $this->dataSigner = new DataSigner(); - $this->serverErrorHandler ?? $this->serverErrorHandler = new ServerErrorHandler(); - - return new SecureHttpClient( - $this->accountKeyPair, - $this->httpClient, - $this->base64SafeEncoder, - $this->keyParser, - $this->dataSigner, - $this->serverErrorHandler - ); - } - - - public function register( $email ) { - try { - $this->client->registerAccount( null, $email ); - } - catch ( Exception $e ) { - EE::warning( $e->getMessage() ); - EE::warning( 'It seems you\'re in local environment or there is some issue with network, please check logs. Skipping letsencrypt.' ); - - return false; - } - EE::debug( "Account with email id: $email registered successfully!" ); - return true; - } - - public function authorize( Array $domains, $site_root, $wildcard = false ) { - $solver = $wildcard ? new SimpleDnsSolver( null, new ConsoleOutput() ) : new SimpleHttpSolver(); - $solverName = $wildcard ? 'dns-01' : 'http-01'; - try { - $order = $this->client->requestOrder( $domains ); - } - catch ( Exception $e ) { - EE::warning( $e->getMessage() ); - EE::warning( 'It seems you\'re in local environment or using non-public domain, please check logs. Skipping letsencrypt.' ); - - return false; - } - - $authorizationChallengesToSolve = []; - foreach ( $order->getAuthorizationsChallenges() as $domainKey => $authorizationChallenges ) { - $authorizationChallenge = null; - foreach ( $authorizationChallenges as $candidate ) { - if ( $solver->supports( $candidate ) ) { - $authorizationChallenge = $candidate; - EE::debug( 'Authorization challenge supported by solver. Solver: ' . $solverName . ' Challenge: ' . $candidate->getType() ); - break; - } - // Should not get here as we are handling it. - EE::debug( 'Authorization challenge not supported by solver. Solver: ' . $solverName . ' Challenge: ' . $candidate->getType() ); - } - if ( null === $authorizationChallenge ) { - throw new ChallengeNotSupportedException(); - } - EE::debug( 'Storing authorization challenge. Domain: ' . $domainKey . ' Challenge: ' . print_r( $authorizationChallenge->toArray(), true ) ); - - $this->repository->storeDomainAuthorizationChallenge( $domainKey, $authorizationChallenge ); - $authorizationChallengesToSolve[] = $authorizationChallenge; - } - - /** @var AuthorizationChallenge $authorizationChallenge */ - foreach ( $authorizationChallengesToSolve as $authorizationChallenge ) { - EE::debug( 'Solving authorization challenge: Domain: ' . $authorizationChallenge->getDomain() . ' Challenge: ' . print_r( $authorizationChallenge->toArray(), true ) ); - $solver->solve( $authorizationChallenge ); - } - - $this->repository->storeCertificateOrder( $domains, $order ); - - if ( ! $wildcard ) { - $token = $authorizationChallenge->toArray()['token']; - $payload = $authorizationChallenge->toArray()['payload']; - EE::launch( "mkdir -p $site_root/app/src/.well-known/acme-challenge/" ); - EE::debug( "Creating challange file $site_root/app/src/.well-known/acme-challenge/$token" ); - file_put_contents( "$site_root/app/src/.well-known/acme-challenge/$token", $payload ); - EE::launch( "chown www-data: $site_root/app/src/.well-known/acme-challenge/$token" ); - } - return true; - } - - public function check( Array $domains, $wildcard = false ) { - EE::debug( 'Starting check with solver ' . $wildcard ? 'dns' : 'http' ); - $solver = $wildcard ? new SimpleDnsSolver( null, new ConsoleOutput() ) : new SimpleHttpSolver(); - $validator = new ChainValidator( - [ - new WaitingValidator( new HttpValidator() ), - new WaitingValidator( new DnsValidator() ) - ] - ); - - $order = null; - if ( $this->repository->hasCertificateOrder( $domains ) ) { - $order = $this->repository->loadCertificateOrder( $domains ); - EE::debug( sprintf( 'Loading the authorization token for domains %s ...', implode( ', ', $domains ) ) ); - } - - $authorizationChallengeToCleanup = []; - foreach ( $domains as $domain ) { - if ( $order ) { - $authorizationChallenge = null; - $authorizationChallenges = $order->getAuthorizationChallenges( $domain ); - foreach ( $authorizationChallenges as $challenge ) { - if ( $solver->supports( $challenge ) ) { - $authorizationChallenge = $challenge; - break; - } - } - if ( null === $authorizationChallenge ) { - throw new ChallengeNotSupportedException(); - } - } else { - if ( ! $this->repository->hasDomainAuthorizationChallenge( $domain ) ) { - EE::error( "Domain: $domain not yet authorized/has not been started of with EasyEngine letsencrypt site creation." ); - } - $authorizationChallenge = $this->repository->loadDomainAuthorizationChallenge( $domain ); - if ( ! $solver->supports( $authorizationChallenge ) ) { - throw new ChallengeNotSupportedException(); - } - } - EE::debug( 'Challenge loaded.' ); - - $authorizationChallenge = $this->client->reloadAuthorization( $authorizationChallenge ); - if ( ! $authorizationChallenge->isValid() ) { - EE::debug( sprintf( 'Testing the challenge for domain %s', $domain ) ); - if ( ! $validator->isValid( $authorizationChallenge ) ) { - EE::warning( sprintf( 'Can not valid challenge for domain %s', $domain ) ); - } - - EE::debug( sprintf( 'Requesting authorization check for domain %s', $domain ) ); - try { - $this->client->challengeAuthorization( $authorizationChallenge ); - } - catch ( Exception $e ) { - EE::debug( $e->getMessage() ); - EE::warning( 'Challange Authorization failed. Check logs and check if your domain is pointed correctly to this server.' ); - $site_name = isset( $domains[1] ) ? $domains[1] : $domains[0]; - EE::log( "Re-run `ee site le $site_name` after fixing the issue." ); - - return false; - } - $authorizationChallengeToCleanup[] = $authorizationChallenge; - } - } - - EE::log( 'The authorization check was successful!' ); - - if ( $solver instanceof MultipleChallengesSolverInterface ) { - $solver->cleanupAll( $authorizationChallengeToCleanup ); - } else { - /** @var AuthorizationChallenge $authorizationChallenge */ - foreach ( $authorizationChallengeToCleanup as $authorizationChallenge ) { - $solver->cleanup( $authorizationChallenge ); - } - } - return true; - } - - public function request( $domain, $altNames = [], $email, $force=false ) { - $alternativeNames = array_unique( $altNames ); - sort( $alternativeNames ); - - // Certificate renewal - if ( $this->hasValidCertificate( $domain, $alternativeNames ) ) { - EE::debug( "Certificate found for $domain, executing renewal" ); - - return $this->executeRenewal( $domain, $alternativeNames, $force ); - } - - EE::debug( "No certificate found, executing first request for $domain" ); - - // Certificate first request - return $this->executeFirstRequest( $domain, $alternativeNames, $email ); - } - - /** - * Request a first certificate for the given domain. - * - * @param string $domain - * @param array $alternativeNames - */ - private function executeFirstRequest( $domain, array $alternativeNames, $email ) { - EE::log( 'Executing first request.' ); - - // Generate domain key pair - $keygen = new KeyPairGenerator(); - $domainKeyPair = $keygen->generateKeyPair(); - $this->repository->storeDomainKeyPair( $domain, $domainKeyPair ); - - EE::debug( "$domain Domain key pair generated and stored" ); - - $distinguishedName = $this->getOrCreateDistinguishedName( $domain, $alternativeNames, $email ); - // TODO: ask them ;) - EE::debug( 'Distinguished name informations have been stored locally for this domain (they won\'t be asked on renewal).' ); - - // Order - $domains = array_merge( [ $domain ], $alternativeNames ); - EE::debug( sprintf( 'Loading the order related to the domains %s .', implode( ', ', $domains ) ) ); - if ( ! $this->repository->hasCertificateOrder( $domains ) ) { - EE::error( "$domain has not yet been authorized." ); - } - $order = $this->repository->loadCertificateOrder( $domains ); - - // Request - EE::log( sprintf( 'Requesting first certificate for domain %s.', $domain ) ); - $csr = new CertificateRequest( $distinguishedName, $domainKeyPair ); - $response = $this->client->finalizeOrder( $order, $csr ); - EE::log( 'Certificate received' ); - - // Store - $this->repository->storeDomainCertificate( $domain, $response->getCertificate() ); - EE::log( 'Certificate stored' ); - - // Post-generate actions - $this->moveCertsToNginxProxy( $response ); - } - - private function moveCertsToNginxProxy( CertificateResponse $response ) { - $domain = $response->getCertificateRequest()->getDistinguishedName()->getCommonName(); - $privateKey = $response->getCertificateRequest()->getKeyPair()->getPrivateKey(); - $certificate = $response->getCertificate(); - - // To handle wildcard certs - $domain = ltrim( $domain, '*.' ); - - file_put_contents( EE_CONF_ROOT . '/nginx/certs/' . $domain . '.key', $privateKey->getPEM() ); - - // Issuer chain - $issuerChain = array_map( - function ( Certificate $certificate ) { - return $certificate->getPEM(); - }, $certificate->getIssuerChain() - ); - - // Full chain - $fullChainPem = $certificate->getPEM() . "\n" . implode( "\n", $issuerChain ); - - file_put_contents( EE_CONF_ROOT . '/nginx/certs/' . $domain . '.crt', $fullChainPem ); - } - - /** - * Renew a given domain certificate. - * - * @param string $domain - * @param array $alternativeNames - * @param bool $force - */ - private function executeRenewal( $domain, array $alternativeNames, $force = false ) { - try { - // Check expiration date to avoid too much renewal - EE::log( "Loading current certificate for $domain" ); - - $certificate = $this->repository->loadDomainCertificate( $domain ); - - if ( ! $force ) { - $certificateParser = new CertificateParser(); - $parsedCertificate = $certificateParser->parse( $certificate ); - - if ( $parsedCertificate->getValidTo()->format( 'U' ) - time() >= 604800 ) { - - EE::log( - sprintf( - 'Current certificate is valid until %s, renewal is not necessary.', - $parsedCertificate->getValidTo()->format( 'Y-m-d H:i:s' ) - ) - ); - - return; - } - - EE::log( - sprintf( - 'Current certificate will expire in less than a week (%s), renewal is required.', - $parsedCertificate->getValidTo()->format( 'Y-m-d H:i:s' ) - ) - ); - } else { - EE::log( 'Forced renewal.' ); - } - - // Key pair - EE::debug( 'Loading domain key pair...' ); - $domainKeyPair = $this->repository->loadDomainKeyPair( $domain ); - - // Distinguished name - EE::debug( 'Loading domain distinguished name...' ); - $distinguishedName = $this->getOrCreateDistinguishedName( $domain, $alternativeNames ); - - // Order - $domains = array_merge( [ $domain ], $alternativeNames ); - EE::debug( sprintf( 'Loading the order related to the domains %s.', implode( ', ', $domains ) ) ); - if ( ! $this->repository->hasCertificateOrder( $domains ) ) { - EE::error( "$domain has not yet been authorized." ); - } - $order = $this->repository->loadCertificateOrder( $domains ); - - // Renewal - EE::log( sprintf( 'Renewing certificate for domain %s.', $domain ) ); - $csr = new CertificateRequest( $distinguishedName, $domainKeyPair ); - $response = $this->client->finalizeOrder( $order, $csr ); - EE::log( 'Certificate received' ); - - $this->repository->storeDomainCertificate( $domain, $response->getCertificate() ); - $this->log( 'Certificate stored' ); - - // Post-generate actions - $this->moveCertsToNginxProxy( $response ); - EE::log( 'Certificate renewed successfully!' ); - - } - catch ( \Exception $e ) { - EE::warning( 'A critical error occured during certificate renewal' ); - EE::debug( print_r( $e, true ) ); - - throw $e; - } - catch ( \Throwable $e ) { - EE::warning( 'A critical error occured during certificate renewal' ); - EE::debug( print_r( $e, true ) ); - - throw $e; - } - } - - private function hasValidCertificate( $domain, array $alternativeNames ) { - if ( ! $this->repository->hasDomainCertificate( $domain ) ) { - return false; - } - - if ( ! $this->repository->hasDomainKeyPair( $domain ) ) { - return false; - } - - if ( ! $this->repository->hasDomainDistinguishedName( $domain ) ) { - return false; - } - - if ( $this->repository->loadDomainDistinguishedName( $domain )->getSubjectAlternativeNames() !== $alternativeNames ) { - return false; - } - - return true; - } - - /** - * Retrieve the stored distinguishedName or create a new one if needed. - * - * @param string $domain - * @param array $alternativeNames - * - * @return DistinguishedName - */ - private function getOrCreateDistinguishedName( $domain, array $alternativeNames, $email ) { - if ( $this->repository->hasDomainDistinguishedName( $domain ) ) { - $original = $this->repository->loadDomainDistinguishedName( $domain ); - - $distinguishedName = new DistinguishedName( - $domain, - $original->getCountryName(), - $original->getStateOrProvinceName(), - $original->getLocalityName(), - $original->getOrganizationName(), - $original->getOrganizationalUnitName(), - $original->getEmailAddress(), - $alternativeNames - ); - } else { - // Ask DistinguishedName - $distinguishedName = new DistinguishedName( - $domain, - // TODO: Ask and fill these values properly - 'US', - 'CA', - 'Mountain View', - 'Let\'s Encrypt', - 'Let\'s Encrypt Authority X3', - $email, - $alternativeNames - ); - - } - - $this->repository->storeDomainDistinguishedName( $domain, $distinguishedName ); - - return $distinguishedName; - } - - - public function status() { - $this->master ?? $this->master = new Filesystem( new Local( $this->conf_dir ) ); - - $certificateParser = new CertificateParser(); - - $table = new Table( $output ); - $table->setHeaders( [ 'Domain', 'Issuer', 'Valid from', 'Valid to', 'Needs renewal?' ] ); - - $directories = $this->master->listContents( 'certs' ); - - foreach ( $directories as $directory ) { - if ( 'dir' !== $directory['type'] ) { - continue; - } - - $parsedCertificate = $certificateParser->parse( $this->repository->loadDomainCertificate( $directory['basename'] ) ); - if ( ! $input->getOption( 'all' ) && $parsedCertificate->isExpired() ) { - continue; - } - $domainString = $parsedCertificate->getSubject(); - - $alternativeNames = array_diff( $parsedCertificate->getSubjectAlternativeNames(), [ $parsedCertificate->getSubject() ] ); - if ( count( $alternativeNames ) ) { - sort( $alternativeNames ); - $last = array_pop( $alternativeNames ); - foreach ( $alternativeNames as $alternativeName ) { - $domainString .= "\n ├── " . $alternativeName; - } - $domainString .= "\n └── " . $last; - } - - $table->addRow( - [ - $domainString, - $parsedCertificate->getIssuer(), - $parsedCertificate->getValidFrom()->format( 'Y-m-d H:i:s' ), - $parsedCertificate->getValidTo()->format( 'Y-m-d H:i:s' ), - ( $parsedCertificate->getValidTo()->format( 'U' ) - time() < 604800 ) ? '<comment>Yes</comment>' : 'No', - ] - ); - } - - $table->render(); - } - - public function cleanup( $site_root ) { - $challange_dir = "$site_root/app/src/.well-known"; - if ( file_exists( "$site_root/app/src/.well-known" ) ) { - EE::debug( 'Cleaning up webroot files.' ); - EE\Utils\delete_dir( $challange_dir ); - } - } -} From ea2de77c650bc51151d56d4eec76ae23e4667bdc Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Thu, 26 Jul 2018 20:49:57 +0530 Subject: [PATCH 30/52] Move common functions to abstract class Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Command.php | 353 +++++-------------------------------------- 1 file changed, 34 insertions(+), 319 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 907381a5..58c58e84 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -89,198 +89,60 @@ public function create( $args, $assoc_args ) { } /** - * Lists the created websites. - * - * [--enabled] - * : List only enabled sites. - * - * [--disabled] - * : List only disabled sites. - * - * [--format=<format>] - * : Render output in a particular format. - * --- - * default: table - * options: - * - table - * - csv - * - yaml - * - json - * - count - * - text - * --- - * - * @subcommand list + * @inheritdoc */ - public function _list( $args, $assoc_args ) { - \EE\Utils\delem_log( 'site list start' ); - - $format = \EE\Utils\get_flag_value( $assoc_args, 'format' ); - $enabled = \EE\Utils\get_flag_value( $assoc_args, 'enabled' ); - $disabled = \EE\Utils\get_flag_value( $assoc_args, 'disabled' ); - - $where = array(); - - if ( $enabled && ! $disabled ) { - $where['is_enabled'] = 1; - } elseif ( $disabled && ! $enabled ) { - $where['is_enabled'] = 0; - } - - $sites = $this->db::select( array( 'sitename', 'is_enabled' ), $where ); - - if ( ! $sites ) { - EE::error( 'No sites found!' ); - } - - if ( 'text' === $format ) { - foreach ( $sites as $site ) { - EE::log( $site['sitename'] ); - } - } else { - $result = array_map( - function ( $site ) { - $site['site'] = $site['sitename']; - $site['status'] = $site['is_enabled'] ? 'enabled' : 'disabled'; - - return $site; - }, $sites - ); - - $formatter = new \EE\Formatter( $assoc_args, [ 'site', 'status' ] ); + public function init_le( $site_name, $site_root, $wildcard = false ) { + return parent::init_le( $site_name, $site_root, $wildcard ); + } - $formatter->display_items( $result ); - } + /** + * @inheritdoc + */ + public function le( $args = [], $assoc_args = [], $wildcard = false ) { + return parent::le( $args, $assoc_args, $wildcard ); + } - \EE\Utils\delem_log( 'site list end' ); + /** + * @inheritdoc + */ + public function _list( $args, $assoc_args ) { + parent::_list( $args, $assoc_args ); } /** - * Deletes a website. - * - * ## OPTIONS - * - * <site-name> - * : Name of website to be deleted. - * - * [--yes] - * : Do not prompt for confirmation. + * @inheritdoc */ public function delete( $args, $assoc_args ) { - \EE\Utils\delem_log( 'site delete start' ); - $this->populate_site_info( $args ); - EE::confirm( "Are you sure you want to delete $this->site_name?", $assoc_args ); - $this->level = 5; - $this->delete_site(); - \EE\Utils\delem_log( 'site delete end' ); + parent::delete( $args, $assoc_args ); } - /** - * Runs the acme le registration and authorization. + * @inheritdoc */ - private function init_le() { - $client = new Site_Letsencrypt(); - $this->le_mail = EE::get_runner()->config['le-mail'] ?? EE::input( 'Enter your mail id: ' ); - EE::get_runner()->ensure_present_in_config( 'le-mail', $this->le_mail ); - if ( ! $client->register( $this->le_mail ) ) { - $this->le = false; - - return; - } - $wildcard = 'wpsubdom' === $this->site_type ? true : false; - $domains = $wildcard ? [ "*.$this->site_name", $this->site_name ] : [ $this->site_name ]; - if ( ! $client->authorize( $domains, $this->site_root, $wildcard ) ) { - $this->le = false; - - return; - } - if ( $wildcard ) { - echo \cli\Colors::colorize( "%YIMPORTANT:%n Run `ee site le $this->site_name` once the dns changes have propogated to complete the certification generation and installation.", null ); - } else { - $this->le(); - } + public function restart( $args, $assoc_args ) { + parent::restart( $args, $assoc_args ); } - /** - * Runs the acme le. - * - * ## OPTIONS - * - * <site-name> - * : Name of website. - * - * [--force] - * : Force renewal. + * @inheritdoc */ - public function le( $args = [], $assoc_args = [] ) { - if ( ! isset( $this->site_name ) ) { - $this->populate_site_info( $args ); - } - if ( ! isset( $this->le_mail ) ) { - $this->le_mail = EE::get_config( 'le-mail' ) ?? EE::input( 'Enter your mail id: ' ); - } - $force = \EE\Utils\get_flag_value( $assoc_args, 'force' ); - $wildcard = 'wpsubdom' === $this->site_type ? true : false; - $domains = $wildcard ? [ "*.$this->site_name", $this->site_name ] : [ $this->site_name ]; - $client = new Site_Letsencrypt(); - if ( ! $client->check( $domains, $wildcard ) ) { - $this->le = false; - - return; - } - if ( $wildcard ) { - $client->request( "*.$this->site_name", [ $this->site_name ], $this->le_mail, $force ); - } else { - $client->request( $this->site_name, [], $this->le_mail, $force ); - $client->cleanup( $this->site_root ); - } - EE::launch( 'docker exec ee-nginx-proxy sh -c "/app/docker-entrypoint.sh /usr/local/bin/docker-gen /app/nginx.tmpl /etc/nginx/conf.d/default.conf; /usr/sbin/nginx -s reload"' ); + public function reload( $args, $assoc_args ) { + parent::reload( $args, $assoc_args ); } + /** - * Enables a website. It will start the docker containers of the website if they are stopped. - * - * ## OPTIONS - * - * [<site-name>] - * : Name of website to be enabled. + * @inheritdoc */ public function up( $args, $assoc_args ) { - \EE\Utils\delem_log( 'site enable start' ); - $args = \EE\SiteUtils\auto_site_name( $args, $this->command, __FUNCTION__ ); - $this->populate_site_info( $args ); - EE::log( "Enabling site $this->site_name." ); - if ( $this->docker::docker_compose_up( $this->site_root ) ) { - $this->db::update( [ 'is_enabled' => '1' ], [ 'sitename' => $this->site_name ] ); - EE::success( "Site $this->site_name enabled." ); - } else { - EE::error( "There was error in enabling $this->site_name. Please check logs." ); - } - \EE\Utils\delem_log( 'site enable end' ); + parent::up( $args, $assoc_args ); } /** - * Disables a website. It will stop and remove the docker containers of the website if they are running. - * - * ## OPTIONS - * - * [<site-name>] - * : Name of website to be disabled. + * @inheritdoc */ public function down( $args, $assoc_args ) { - \EE\Utils\delem_log( 'site disable start' ); - $args = \EE\SiteUtils\auto_site_name( $args, $this->command, __FUNCTION__ ); - $this->populate_site_info( $args ); - EE::log( "Disabling site $this->site_name." ); - if ( $this->docker::docker_compose_down( $this->site_root ) ) { - $this->db::update( [ 'is_enabled' => '0' ], [ 'sitename' => $this->site_name ] ); - EE::success( "Site $this->site_name disabled." ); - } else { - EE::error( "There was error in disabling $this->site_name. Please check logs." ); - } - \EE\Utils\delem_log( 'site disable end' ); + parent::down( $args, $assoc_args ); } /** @@ -310,85 +172,6 @@ public function info( $args, $assoc_args ) { \EE\Utils\delem_log( 'site info end' ); } - /** - * Restarts containers associated with site. - * When no service(--nginx etc.) is specified, all site containers will be restarted. - * - * [<site-name>] - * : Name of the site. - * - * [--all] - * : Restart all containers of site. - * - * [--nginx] - * : Restart nginx container of site. - */ - public function restart( $args, $assoc_args ) { - \EE\Utils\delem_log( 'site restart start' ); - $args = \EE\SiteUtils\auto_site_name( $args, $this->command, __FUNCTION__ ); - $all = \EE\Utils\get_flag_value( $assoc_args, 'all' ); - $no_service_specified = count( $assoc_args ) === 0; - - $this->populate_site_info( $args ); - - chdir( $this->site_root ); - - if ( $all || $no_service_specified ) { - $containers = [ 'nginx' ]; - } else { - $containers = array_keys( $assoc_args ); - } - - foreach ( $containers as $container ) { - EE\Siteutils\run_compose_command( 'restart', $container, null, 'all services' ); - } - \EE\Utils\delem_log( 'site restart stop' ); - } - - /** - * Reload services in containers without restarting container(s) associated with site. - * When no service(--nginx etc.) is specified, all services will be reloaded. - * - * <site-name> - * : Name of the site. - * - * [--all] - * : Reload all services of site(which are supported). - * - * [--nginx] - * : Reload nginx service in container. - * - */ - public function reload( $args, $assoc_args ) { - \EE\Utils\delem_log( 'site reload start' ); - $args = \EE\SiteUtils\auto_site_name( $args, $this->command, __FUNCTION__ ); - $all = \EE\Utils\get_flag_value( $assoc_args, 'all' ); - $no_service_specified = count( $assoc_args ) === 0; - - $this->populate_site_info( $args ); - - chdir( $this->site_root ); - - if ( $all || $no_service_specified ) { - $this->reload_services( [ 'nginx' ] ); - } else { - $this->reload_services( array_keys( $assoc_args ) ); - } - \EE\Utils\delem_log( 'site reload stop' ); - } - - /** - * Executes reload commands. It needs seperate handling as commands to reload each service is different. - */ - private function reload_services( $services ) { - $reload_command = [ - 'nginx' => 'nginx sh -c \'nginx -t && service openresty reload\'', - ]; - - foreach ( $services as $service ) { - $this->run_compose_command( 'exec', $reload_command[$service], 'reload', $service ); - } - } /** * Function to configure site and copy all the required files. @@ -399,7 +182,6 @@ private function configure_site_files() { $site_docker_yml = $this->site_root . '/docker-compose.yml'; $site_conf_env = $this->site_root . '/.env'; $site_nginx_default_conf = $site_conf_dir . '/nginx/default.conf'; - $server_name = $this->site_name; $site_src_dir = $this->site_root . '/app/src'; $process_user = posix_getpwuid( posix_geteuid() ); @@ -470,84 +252,17 @@ private function create_site() { } if ( $this->le ) { - $this->init_le(); + $this->init_le($this->site_name,$this->site_root,false); } $this->info( [ $this->site_name ], [] ); $this->create_site_db_entry(); } /** - * Function to delete the given site. - * - * $this->level: - * Level of deletion. - * Level - 0: No need of clean-up. - * Level - 1: Clean-up only the site-root. - * Level - 2: Try to remove network. The network may or may not have been created. - * Level - 3: Disconnect & remove network and try to remove containers. The containers may not have been created. - * Level - 4: Remove containers. - * Level - 5: Remove db entry. + * @inheritdoc */ - private function delete_site() { - $proxy_type = EE_PROXY_TYPE; - if ( $this->level >= 3 ) { - if ( $this->docker::docker_compose_down( $this->site_root ) ) { - EE::log( "[$this->site_name] Docker Containers removed." ); - } else { - \EE\Utils\default_launch( "docker rm -f $(docker ps -q -f=label=created_by=EasyEngine -f=label=site_name=$this->site_name)" ); - if ( $this->level > 3 ) { - EE::warning( 'Error in removing docker containers.' ); - } - } - - $this->docker::disconnect_site_network_from( $this->site_name, $proxy_type ); - } - - if ( $this->level >= 2 ) { - if ( $this->docker::rm_network( $this->site_name ) ) { - EE::log( "[$this->site_name] Docker container removed from network $proxy_type." ); - } else { - if ( $this->level > 2 ) { - EE::warning( "Error in removing Docker container from network $proxy_type" ); - } - } - } - - if ( $this->fs->exists( $this->site_root ) ) { - try { - $this->fs->remove( $this->site_root ); - } - catch ( Exception $e ) { - EE::debug( $e ); - EE::error( 'Could not remove site root. Please check if you have sufficient rights.' ); - } - EE::log( "[$this->site_name] site root removed." ); - } - - if ( $this->level > 4 ) { - if ( $this->le ) { - EE::log( 'Removing ssl certs.' ); - $crt_file = EE_CONF_ROOT . "/nginx/certs/$this->site_name.crt"; - $key_file = EE_CONF_ROOT . "/nginx/certs/$this->site_name.key"; - $conf_certs = EE_CONF_ROOT . "/acme-conf/certs/$this->site_name"; - $conf_var = EE_CONF_ROOT . "/acme-conf/var/$this->site_name"; - - $cert_files = [ $conf_certs, $conf_var, $crt_file, $key_file ]; - try { - $this->fs->remove( $cert_files ); - } - catch ( Exception $e ) { - EE::warning( $e ); - } - - } - if ( $this->db::delete( array( 'sitename' => $this->site_name ) ) ) { - EE::log( 'Removing database entry.' ); - } else { - EE::error( 'Could not remove the database entry' ); - } - } - EE::log( "Site $this->site_name deleted." ); + public function delete_site( $level, $site_name, $site_root ) { + parent::delete_site( $level, $site_name, $site_root ); } /** @@ -604,7 +319,7 @@ private function catch_clean( $e ) { \EE\Utils\delem_log( 'site cleanup start' ); EE::warning( $e->getMessage() ); EE::warning( 'Initiating clean-up.' ); - $this->delete_site(); + $this->delete_site( $this->level, $this->site_name, $this->site_root ); \EE\Utils\delem_log( 'site cleanup end' ); exit; } @@ -615,7 +330,7 @@ private function catch_clean( $e ) { private function rollback() { EE::warning( 'Exiting gracefully after rolling back. This may take some time.' ); if ( $this->level > 0 ) { - $this->delete_site(); + $this->delete_site( $this->level, $this->site_name, $this->site_root ); } EE::success( 'Rollback complete. Exiting now.' ); exit; From 606d621b8b0c26dabccc29426eb323396bab7546 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Fri, 27 Jul 2018 12:29:53 +0530 Subject: [PATCH 31/52] Move shutdown handler to core Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Shutdown_Handler.php | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 src/Shutdown_Handler.php diff --git a/src/Shutdown_Handler.php b/src/Shutdown_Handler.php deleted file mode 100644 index 2df3c30e..00000000 --- a/src/Shutdown_Handler.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/** - * Class Shutdown_Handler - */ -class Shutdown_Handler { - - /** - * Handle fatal errors. This function was created as the register_shutdown_function requires the callable function to be public and any public function inside site-command would be callable directly through command-line. - * - * @param array $site_command having Site_Command object. - */ - public function cleanup( $site_command ) { - $reflector = new ReflectionObject( $site_command[0] ); - $method = $reflector->getMethod( 'shutDownFunction' ); - $method->setAccessible( true ); - $method->invoke( $site_command[0] ); - } -} From e6fac3b45856317d124931b912c0e11da8eb6a7a Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Fri, 27 Jul 2018 12:31:06 +0530 Subject: [PATCH 32/52] Update restart and reload Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Command.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 58c58e84..d87e274d 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -119,15 +119,17 @@ public function delete( $args, $assoc_args ) { /** * @inheritdoc */ - public function restart( $args, $assoc_args ) { - parent::restart( $args, $assoc_args ); + public function restart( $args, $assoc_args, $whitelisted_containers = [] ) { + $whitelisted_containers = [ 'nginx' ]; + parent::restart( $args, $assoc_args, $whitelisted_containers ); } /** * @inheritdoc */ - public function reload( $args, $assoc_args ) { - parent::reload( $args, $assoc_args ); + public function reload( $args, $assoc_args, $whitelisted_containers = [] ) { + $whitelisted_containers = [ 'nginx' ]; + parent::reload( $args, $assoc_args, $whitelisted_containers = [] ); } From 2268a0665e665f521e707c75bf3f3a54822930d9 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Fri, 27 Jul 2018 12:38:59 +0530 Subject: [PATCH 33/52] Restructure order of functions Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Command.php | 136 +++++++++++++++++++++---------------------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index d87e274d..a14cf932 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -26,7 +26,6 @@ class Site_Command extends EE_Site_Command { private $logger; private $le; private $skip_chk; - private $le_mail; private $fs; public function __construct() { @@ -88,65 +87,6 @@ public function create( $args, $assoc_args ) { \EE\Utils\delem_log( 'site create end' ); } - /** - * @inheritdoc - */ - public function init_le( $site_name, $site_root, $wildcard = false ) { - return parent::init_le( $site_name, $site_root, $wildcard ); - } - - /** - * @inheritdoc - */ - public function le( $args = [], $assoc_args = [], $wildcard = false ) { - return parent::le( $args, $assoc_args, $wildcard ); - } - - /** - * @inheritdoc - */ - public function _list( $args, $assoc_args ) { - parent::_list( $args, $assoc_args ); - } - - /** - * @inheritdoc - */ - public function delete( $args, $assoc_args ) { - parent::delete( $args, $assoc_args ); - } - - /** - * @inheritdoc - */ - public function restart( $args, $assoc_args, $whitelisted_containers = [] ) { - $whitelisted_containers = [ 'nginx' ]; - parent::restart( $args, $assoc_args, $whitelisted_containers ); - } - - /** - * @inheritdoc - */ - public function reload( $args, $assoc_args, $whitelisted_containers = [] ) { - $whitelisted_containers = [ 'nginx' ]; - parent::reload( $args, $assoc_args, $whitelisted_containers = [] ); - } - - - /** - * @inheritdoc - */ - public function up( $args, $assoc_args ) { - parent::up( $args, $assoc_args ); - } - - /** - * @inheritdoc - */ - public function down( $args, $assoc_args ) { - parent::down( $args, $assoc_args ); - } - /** * Display all the relevant site information, credentials and useful links. * @@ -254,19 +194,12 @@ private function create_site() { } if ( $this->le ) { - $this->init_le($this->site_name,$this->site_root,false); + $this->init_le( $this->site_name, $this->site_root, false ); } $this->info( [ $this->site_name ], [] ); $this->create_site_db_entry(); } - /** - * @inheritdoc - */ - public function delete_site( $level, $site_name, $site_root ) { - parent::delete_site( $level, $site_name, $site_root ); - } - /** * Function to save the site configuration entry into database. */ @@ -312,6 +245,73 @@ private function populate_site_info( $args ) { } } + /** + * @inheritdoc + */ + public function _list( $args, $assoc_args ) { + parent::_list( $args, $assoc_args ); + } + + /** + * @inheritdoc + */ + public function delete( $args, $assoc_args ) { + parent::delete( $args, $assoc_args ); + } + + /** + * @inheritdoc + */ + public function delete_site( $level, $site_name, $site_root ) { + parent::delete_site( $level, $site_name, $site_root ); + } + + /** + * @inheritdoc + */ + public function restart( $args, $assoc_args, $whitelisted_containers = [] ) { + $whitelisted_containers = [ 'nginx' ]; + parent::restart( $args, $assoc_args, $whitelisted_containers ); + } + + /** + * @inheritdoc + */ + public function reload( $args, $assoc_args, $whitelisted_containers = [] ) { + $whitelisted_containers = [ 'nginx' ]; + parent::reload( $args, $assoc_args, $whitelisted_containers ); + } + + + /** + * @inheritdoc + */ + public function up( $args, $assoc_args ) { + parent::up( $args, $assoc_args ); + } + + /** + * @inheritdoc + */ + public function down( $args, $assoc_args ) { + parent::down( $args, $assoc_args ); + } + + /** + * @inheritdoc + */ + public function init_le( $site_name, $site_root, $wildcard = false ) { + return parent::init_le( $site_name, $site_root, $wildcard ); + } + + /** + * @inheritdoc + */ + public function le( $args = [], $assoc_args = [], $wildcard = false ) { + return parent::le( $args, $assoc_args, $wildcard ); + } + + /** * Catch and clean exceptions. * From b5c8859ad2c4a6a60c13fa51b61074b4ac956e4c Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Fri, 27 Jul 2018 14:19:22 +0530 Subject: [PATCH 34/52] Update reload acc to core changes Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Command.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index a14cf932..3f300549 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -277,12 +277,11 @@ public function restart( $args, $assoc_args, $whitelisted_containers = [] ) { /** * @inheritdoc */ - public function reload( $args, $assoc_args, $whitelisted_containers = [] ) { + public function reload( $args, $assoc_args, $whitelisted_containers = [], $reload_commands = [] ) { $whitelisted_containers = [ 'nginx' ]; - parent::reload( $args, $assoc_args, $whitelisted_containers ); + parent::reload( $args, $assoc_args, $whitelisted_containers, $reload_commands = [] ); } - /** * @inheritdoc */ From 10849c1aabdf1c037ee2a54255547bb053af3207 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Mon, 30 Jul 2018 02:56:04 +0530 Subject: [PATCH 35/52] Add command type registration and update site doc Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Command.php | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 3f300549..8f8efbe8 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -3,12 +3,12 @@ declare( ticks=1 ); /** - * Creates a simple WordPress Website. + * Creates a simple html Website. * * ## EXAMPLES * - * # Create simple WordPress site - * $ ee site create example.com --wp + * # Create simple html site + * $ ee site create example.com * * @package ee-cli */ @@ -206,11 +206,12 @@ private function create_site() { private function create_site_db_entry() { $ssl = $this->le ? 1 : 0; $data = array( - 'sitename' => $this->site_name, - 'site_type' => $this->site_type, - 'site_path' => $this->site_root, - 'is_ssl' => $ssl, - 'created_on' => date( 'Y-m-d H:i:s', time() ), + 'sitename' => $this->site_name, + 'site_type' => $this->site_type, + 'site_path' => $this->site_root, + 'site_command' => $this->command, + 'is_ssl' => $ssl, + 'created_on' => date( 'Y-m-d H:i:s', time() ), ); try { From e2b422f7c9f1b50a01c69a438c601a01eba2bebc Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Mon, 30 Jul 2018 12:33:21 +0530 Subject: [PATCH 36/52] Update readme Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- README.md | 45 +++++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index fd54319a..0e59a1a8 100644 --- a/README.md +++ b/README.md @@ -3,28 +3,23 @@ Performs basic site functions in easyengine. `site` command contains following subcommand - * [create](#ee-site-create) - * [delete](#ee-site-delete) - * [disable](#ee-site-disable) - * [enable](#ee-site-enable) - * [info](#ee-site-info) - * [list](#ee-site-list) - * [start](#ee-site-start) - * [stop](#ee-site-stop) - * [restart](#ee-site-restart) - * [reload](#ee-site-reload) + * [create](#create) + * [delete](#delete) + * [disable](#disable) + * [enable](#enable) + * [info](#info) + * [list](#list) + * [up](#up) + * [down](#down) + * [restart](#restart) + * [reload](#reload) ## create Runs the site creation. - +Check [this](https://github.com/EasyEngine/site-wp-command) for `--type=wp` support package. ```bash -ee site create example.com # install wordpress without any page caching (default) -ee site create example.com --wp # install wordpress without any page caching -ee site create example.com --wpredis # install wordpress with page caching -ee site create example.com --wpsubir # install wpmu-subdirectory without any page caching -ee site create example.com --wpsubir --wpredis # install wpmu-subdirectory with page caching -ee site create example.com --wpsubdom # install wpmu-subdomain without any page caching -ee site create example.com --wpsubdom --wpredis # install wpmu-subdomain with page cache +ee site create example.com # install html site (default) +ee site create example.com --type=wp # install wp site ``` Let's Encrypt SSL @@ -32,8 +27,6 @@ Let's Encrypt SSL # Enable SSL using Let’s Encrypt (You can add --letsencrypt along with any other flag.) ee site create example.com [--letsencrypt|--le] ee site create example.com --le # install wordpress without any page caching + letsencrypt ssl -ee site create example.com --wpredis --le # install wordpress with page caching + letsencrypt ssl -ee site create example.com --wpsubdom --le # install wordpress wpmu-subdomain + wildcard letsencrypt ssl ``` ## delete @@ -75,20 +68,20 @@ ee site list --enabled # List enabled sites ee site list --disabled # List disabled sites ``` -## start +## up Starts services associated with site. ```bash -ee site start example.com # Defaults to all services -ee site start example.com --nginx +ee site up example.com # Defaults to all services +ee site up example.com --nginx ``` -## stop +## down Stops services associated with site. ```bash -ee site stop example.com # Defaults to all services -ee site stop example.com --mailhog +ee site down example.com # Defaults to all services +ee site down example.com --mailhog ``` ## restart From 0a0d9fdd62b262cf8d0d7e0d268b941fe76359a1 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Mon, 30 Jul 2018 15:42:55 +0530 Subject: [PATCH 37/52] Update tests for html site Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- features/labels.feature | 2 +- features/site.feature | 48 ++++++++++------------------------------- 2 files changed, 12 insertions(+), 38 deletions(-) diff --git a/features/labels.feature b/features/labels.feature index c67f188e..acef3ce3 100644 --- a/features/labels.feature +++ b/features/labels.feature @@ -3,7 +3,7 @@ Feature: Container Labels Scenario: All easyengine containers are tagged Given I run "bin/ee site create labels.test" - Then There should be 5 containers with labels + Then There should be 2 containers with labels """ io.easyengine.site=labels.test """ diff --git a/features/site.feature b/features/site.feature index a8f54279..42bb717c 100644 --- a/features/site.feature +++ b/features/site.feature @@ -25,31 +25,11 @@ Feature: Site Command usage: ee site """ - Scenario: Create wp site successfully - When I run 'sudo bin/ee site create wp.test --wp' - Then The site 'wp.test' should have webroot - And The site 'wp.test' should have WordPress - And Request on 'wp.test' should contain following headers: - | header | - | HTTP/1.1 200 OK | - - Scenario: Create wpsubdir site successfully - When I run 'sudo bin/ee site create wpsubdir.test --wpsubdir' - And I create subsite '1' in 'wpsubdir.test' - Then The site 'wpsubdir.test' should have webroot - And The site 'wpsubdir.test' should have WordPress - And The site 'wpsubdir.test' should be 'subdir' multisite - And Request on 'wpsubdir.test' should contain following headers: - | header | - | HTTP/1.1 200 OK | - - Scenario: Create wpsubdom site successfully - When I run 'sudo bin/ee site create wpsubdom.test --wpsubdom' - And I create subsite '1' in 'wpsubdom.test' - Then The site 'wpsubdom.test' should have webroot - And The site 'wpsubdom.test' should have WordPress - And The site 'wpsubdom.test' should be 'subdomain' multisite - And Request on 'wpsubdom.test' should contain following headers: + Scenario: Create html site successfully + When I run 'sudo bin/ee site create site.test --html' + Then The site 'site.test' should have webroot + And The site 'site.test' should have WordPress + And Request on 'site.test' should contain following headers: | header | | HTTP/1.1 200 OK | @@ -57,26 +37,20 @@ Feature: Site Command When I run 'sudo bin/ee site list --format=text' Then STDOUT should return exactly """ - wp.test - wpsubdir.test - wpsubdom.test + site.test """ Scenario: Delete the sites - When I run 'sudo bin/ee site delete wp.test --yes' + When I run 'sudo bin/ee site delete site.test --yes' Then STDOUT should return something like """ - Site wp.test deleted. + Site site.test deleted. """ And STDERR should return exactly """ """ - And The 'wp.test' db entry should be removed - And The 'wp.test' webroot should be removed - And Following containers of site 'wp.test' should be removed: + And The 'site.test' db entry should be removed + And The 'site.test' webroot should be removed + And Following containers of site 'site.test' should be removed: | container | | nginx | - | php | - | db | - | redis | - | phpmyadmin | From e9f1b66000517c3099ccfe39912eaf1d3b774832 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Tue, 31 Jul 2018 23:51:55 +0530 Subject: [PATCH 38/52] Refactoring and update for unification of code --- src/Site_Command.php | 95 ++++++++++++++++++++++---------------------- src/Site_Docker.php | 88 ++++++++++++++++++++-------------------- 2 files changed, 90 insertions(+), 93 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 8f8efbe8..483e6f2f 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -29,6 +29,7 @@ class Site_Command extends EE_Site_Command { private $fs; public function __construct() { + $this->level = 0; $this->command = 'site'; pcntl_signal( SIGTERM, [ $this, "rollback" ] ); @@ -62,12 +63,12 @@ public function __construct() { */ public function create( $args, $assoc_args ) { - \EE\Utils\delem_log( 'site create start' ); + EE\Utils\delem_log( 'site create start' ); EE::warning( 'This is a beta version. Please don\'t use it in production.' ); $this->logger->debug( 'args:', $args ); - $this->logger->debug( 'assoc_args:', empty( $assoc_args ) ? array( 'NULL' ) : $assoc_args ); - $this->site_name = strtolower( \EE\Utils\remove_trailing_slash( $args[0] ) ); - $this->site_type = \EE\Utils\get_flag_value( $assoc_args, 'type', 'html' ); + $this->logger->debug( 'assoc_args:', empty( $assoc_args ) ? [ 'NULL' ] : $assoc_args ); + $this->site_name = strtolower( EE\Utils\remove_trailing_slash( $args[0] ) ); + $this->site_type = EE\Utils\get_flag_value( $assoc_args, 'type', 'html' ); if ( 'html' !== $this->site_type ) { EE::error( "Invalid site-type: $this->site_type" ); } @@ -76,15 +77,15 @@ public function create( $args, $assoc_args ) { EE::error( "Site $this->site_name already exists. If you want to re-create it please delete the older one using:\n`ee site delete $this->site_name`" ); } - $this->le = \EE\Utils\get_flag_value( $assoc_args, 'letsencrypt' ); - $this->skip_chk = \EE\Utils\get_flag_value( $assoc_args, 'skip-status-check' ); + $this->le = EE\Utils\get_flag_value( $assoc_args, 'letsencrypt' ); + $this->skip_chk = EE\Utils\get_flag_value( $assoc_args, 'skip-status-check' ); - \EE\SiteUtils\init_checks(); + EE\SiteUtils\init_checks(); EE::log( 'Configuring project.' ); $this->create_site(); - \EE\Utils\delem_log( 'site create end' ); + EE\Utils\delem_log( 'site create end' ); } /** @@ -94,24 +95,25 @@ public function create( $args, $assoc_args ) { * : Name of the website whose info is required. */ public function info( $args, $assoc_args ) { - \EE\Utils\delem_log( 'site info start' ); + + EE\Utils\delem_log( 'site info start' ); if ( ! isset( $this->site_name ) ) { - $args = \EE\SiteUtils\auto_site_name( $args, $this->command, __FUNCTION__ ); + $args = EE\SiteUtils\auto_site_name( $args, $this->command, __FUNCTION__ ); $this->populate_site_info( $args ); } $ssl = $this->le ? 'Enabled' : 'Not Enabled'; EE::log( "Details for site $this->site_name:" ); $prefix = ( $this->le ) ? 'https://' : 'http://'; - $info = array( - array( 'Site', $prefix . $this->site_name ), - array( 'Access mailhog', $prefix . $this->site_name . '/ee-admin/mailhog/' ), - array( 'Site Root', $this->site_root ), - array( 'SSL', $ssl ), - ); + $info = [ + [ 'Site', $prefix . $this->site_name ], + [ 'Access mailhog', $prefix . $this->site_name . '/ee-admin/mailhog/' ], + [ 'Site Root', $this->site_root ], + [ 'SSL', $ssl ], + ]; - \EE\Utils\format_table( $info ); + EE\Utils\format_table( $info ); - \EE\Utils\delem_log( 'site info end' ); + EE\Utils\delem_log( 'site info end' ); } @@ -130,19 +132,19 @@ private function configure_site_files() { EE::log( "Creating site $this->site_name." ); EE::log( 'Copying configuration files.' ); - $filter = array(); + $filter = []; $filter[] = $this->site_type; $filter[] = $this->le; $site_docker = new Site_Docker(); $docker_compose_content = $site_docker->generate_docker_compose_yml( $filter ); - $default_conf_content = $default_conf_content = \EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/config/nginx/default.conf.mustache', [ 'server_name' => $this->site_name ] ); + $default_conf_content = $default_conf_content = EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/config/nginx/default.conf.mustache', [ 'server_name' => $this->site_name ] ); $env_data = [ 'virtual_host' => $this->site_name, 'user_id' => $process_user['uid'], 'group_id' => $process_user['gid'], ]; - $env_content = \EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/config/.env.mustache', $env_data ); + $env_content = EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/config/.env.mustache', $env_data ); try { $this->fs->dumpFile( $site_docker_yml, $docker_compose_content ); @@ -155,15 +157,14 @@ private function configure_site_files() { 'version' => 'v' . EE_VERSION, 'site_src_root' => $this->site_root . '/app/src', ]; - $index_html = \EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/index.html.mustache', $index_data ); + $index_html = EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/index.html.mustache', $index_data ); $this->fs->mkdir( $site_src_dir ); $this->fs->dumpFile( $site_src_dir . '/index.html', $index_html ); EE\Siteutils\add_site_redirects( $this->site_name, $this->le ); EE::success( 'Configuration files copied.' ); - } - catch ( Exception $e ) { + } catch ( Exception $e ) { $this->catch_clean( $e ); } } @@ -172,6 +173,7 @@ private function configure_site_files() { * Function to create the site. */ private function create_site() { + $this->site_root = WEBROOT . $this->site_name; $this->level = 1; try { @@ -188,8 +190,7 @@ private function create_site() { $this->level = 4; EE\Siteutils\site_status_check( $this->site_name ); } - } - catch ( Exception $e ) { + } catch ( Exception $e ) { $this->catch_clean( $e ); } @@ -204,15 +205,16 @@ private function create_site() { * Function to save the site configuration entry into database. */ private function create_site_db_entry() { + $ssl = $this->le ? 1 : 0; - $data = array( + $data = [ 'sitename' => $this->site_name, 'site_type' => $this->site_type, 'site_path' => $this->site_root, 'site_command' => $this->command, 'is_ssl' => $ssl, 'created_on' => date( 'Y-m-d H:i:s', time() ), - ); + ]; try { if ( $this->db::insert( $data ) ) { @@ -220,8 +222,7 @@ private function create_site_db_entry() { } else { throw new Exception( 'Error creating site entry in database.' ); } - } - catch ( Exception $e ) { + } catch ( Exception $e ) { $this->catch_clean( $e ); } } @@ -231,15 +232,15 @@ private function create_site_db_entry() { */ private function populate_site_info( $args ) { - $this->site_name = \EE\Utils\remove_trailing_slash( $args[0] ); + $this->site_name = EE\Utils\remove_trailing_slash( $args[0] ); if ( $this->db::site_in_db( $this->site_name ) ) { - $db_select = $this->db::select( [], array( 'sitename' => $this->site_name ) ); + $db_select = $this->db::select( [], [ 'sitename' => $this->site_name ], 'sites', 1 ); - $this->site_type = $db_select[0]['site_type']; - $this->site_root = $db_select[0]['site_path']; - $this->le = $db_select[0]['is_ssl']; + $this->site_type = $db_select['site_type']; + $this->site_root = $db_select['site_path']; + $this->le = $db_select['is_ssl']; } else { EE::error( "Site $this->site_name does not exist." ); @@ -311,18 +312,18 @@ public function le( $args = [], $assoc_args = [], $wildcard = false ) { return parent::le( $args, $assoc_args, $wildcard ); } - /** * Catch and clean exceptions. * * @param Exception $e */ private function catch_clean( $e ) { - \EE\Utils\delem_log( 'site cleanup start' ); + + EE\Utils\delem_log( 'site cleanup start' ); EE::warning( $e->getMessage() ); EE::warning( 'Initiating clean-up.' ); $this->delete_site( $this->level, $this->site_name, $this->site_root ); - \EE\Utils\delem_log( 'site cleanup end' ); + EE\Utils\delem_log( 'site cleanup end' ); exit; } @@ -330,6 +331,7 @@ private function catch_clean( $e ) { * Roll back on interrupt. */ private function rollback() { + EE::warning( 'Exiting gracefully after rolling back. This may take some time.' ); if ( $this->level > 0 ) { $this->delete_site( $this->level, $this->site_name, $this->site_root ); @@ -342,16 +344,15 @@ private function rollback() { * Shutdown function to catch and rollback from fatal errors. */ private function shutDownFunction() { + $error = error_get_last(); - if ( isset( $error ) ) { - if ( $error['type'] === E_ERROR ) { - EE::warning( 'An Error occurred. Initiating clean-up.' ); - $this->logger->error( 'Type: ' . $error['type'] ); - $this->logger->error( 'Message: ' . $error['message'] ); - $this->logger->error( 'File: ' . $error['file'] ); - $this->logger->error( 'Line: ' . $error['line'] ); - $this->rollback(); - } + if ( isset( $error ) && $error['type'] === E_ERROR ) { + EE::warning( 'An Error occurred. Initiating clean-up.' ); + $this->logger->error( 'Type: ' . $error['type'] ); + $this->logger->error( 'Message: ' . $error['message'] ); + $this->logger->error( 'File: ' . $error['file'] ); + $this->logger->error( 'Line: ' . $error['line'] ); + $this->rollback(); } } } diff --git a/src/Site_Docker.php b/src/Site_Docker.php index 56f37177..8a2cd269 100644 --- a/src/Site_Docker.php +++ b/src/Site_Docker.php @@ -12,70 +12,66 @@ class Site_Docker { * @return String docker-compose.yml content string. */ public function generate_docker_compose_yml( array $filters = [] ) { - $base = array(); + $base = []; - $restart_default = array( 'name' => 'always' ); - $network_default = array( 'name' => 'site-network' ); + $restart_default = [ 'name' => 'always' ]; + $network_default = [ 'name' => 'site-network' ]; // nginx configuration. - $nginx['service_name'] = array( 'name' => 'nginx' ); - $nginx['image'] = array( 'name' => 'easyengine/nginx:v' . EE_VERSION ); + $nginx['service_name'] = [ 'name' => 'nginx' ]; + $nginx['image'] = [ 'name' => 'easyengine/nginx:v' . EE_VERSION ]; $nginx['restart'] = $restart_default; $v_host = 'VIRTUAL_HOST'; - $nginx['environment'] = array( - 'env' => array( - array( 'name' => $v_host ), - array( 'name' => 'VIRTUAL_PATH=/' ), - array( 'name' => 'HSTS=off' ), - ), - ); - $nginx['volumes'] = array( - 'vol' => array( - array( 'name' => './app/src:/var/www/htdocs' ), - array( 'name' => './config/nginx/default.conf:/etc/nginx/conf.d/default.conf' ), - array( 'name' => './logs/nginx:/var/log/nginx' ), - array( 'name' => './config/nginx/common:/usr/local/openresty/nginx/conf/common' ), - ), - ); - $nginx['labels'] = array( - array( - 'label' => array( - 'name' => 'io.easyengine.site=${VIRTUAL_HOST}', - ), - ), - ); + $nginx['environment'] = [ + 'env' => [ + [ 'name' => $v_host ], + [ 'name' => 'VIRTUAL_PATH=/' ], + [ 'name' => 'HSTS=off' ], + ], + ]; + $nginx['volumes'] = [ + 'vol' => [ + [ 'name' => './app/src:/var/www/htdocs' ], + [ 'name' => './config/nginx/default.conf:/etc/nginx/conf.d/default.conf' ], + [ 'name' => './logs/nginx:/var/log/nginx' ], + [ 'name' => './config/nginx/common:/usr/local/openresty/nginx/conf/common' ], + ], + ]; + $nginx['labels'] = [ + 'label' => [ + 'name' => 'io.easyengine.site=${VIRTUAL_HOST}', + ], + ]; $nginx['networks'] = $network_default; // mailhog configuration. - $mailhog['service_name'] = array( 'name' => 'mailhog' ); - $mailhog['image'] = array( 'name' => 'easyengine/mailhog:v' . EE_VERSION ); + $mailhog['service_name'] = [ 'name' => 'mailhog' ]; + $mailhog['image'] = [ 'name' => 'easyengine/mailhog:v' . EE_VERSION ]; $mailhog['restart'] = $restart_default; - $mailhog['command'] = array( 'name' => '["-invite-jim=false"]' ); - $mailhog['environment'] = array( - 'env' => array( - array( 'name' => $v_host ), - array( 'name' => 'VIRTUAL_PATH=/ee-admin/mailhog/' ), - array( 'name' => 'VIRTUAL_PORT=8025' ), - ), - ); - $mailhog['labels'] = array( - array( - 'label' => array( - 'name' => 'io.easyengine.site=${VIRTUAL_HOST}', - ), - ), - ); + $mailhog['command'] = [ 'name' => '["-invite-jim=false"]' ]; + $mailhog['environment'] = [ + 'env' => [ + [ 'name' => $v_host ], + [ 'name' => 'VIRTUAL_PATH=/ee-admin/mailhog/' ], + [ 'name' => 'VIRTUAL_PORT=8025' ], + ], + ]; + $mailhog['labels'] = [ + 'label' => [ + 'name' => 'io.easyengine.site=${VIRTUAL_HOST}', + ], + ]; $mailhog['networks'] = $network_default; $base[] = $nginx; $base[] = $mailhog; - $binding = array( + $binding = [ 'services' => $base, 'network' => true, - ); + ]; $docker_compose_yml = mustache_render( SITE_TEMPLATE_ROOT . '/docker-compose.mustache', $binding ); From 18031251d496bffe58cd33e9b88eecf0ec703dd3 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Tue, 31 Jul 2018 23:55:07 +0530 Subject: [PATCH 39/52] Remove extra functions Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Command.php | 49 -------------------------------------------- 1 file changed, 49 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 483e6f2f..5ba61860 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -247,27 +247,6 @@ private function populate_site_info( $args ) { } } - /** - * @inheritdoc - */ - public function _list( $args, $assoc_args ) { - parent::_list( $args, $assoc_args ); - } - - /** - * @inheritdoc - */ - public function delete( $args, $assoc_args ) { - parent::delete( $args, $assoc_args ); - } - - /** - * @inheritdoc - */ - public function delete_site( $level, $site_name, $site_root ) { - parent::delete_site( $level, $site_name, $site_root ); - } - /** * @inheritdoc */ @@ -284,34 +263,6 @@ public function reload( $args, $assoc_args, $whitelisted_containers = [], $reloa parent::reload( $args, $assoc_args, $whitelisted_containers, $reload_commands = [] ); } - /** - * @inheritdoc - */ - public function up( $args, $assoc_args ) { - parent::up( $args, $assoc_args ); - } - - /** - * @inheritdoc - */ - public function down( $args, $assoc_args ) { - parent::down( $args, $assoc_args ); - } - - /** - * @inheritdoc - */ - public function init_le( $site_name, $site_root, $wildcard = false ) { - return parent::init_le( $site_name, $site_root, $wildcard ); - } - - /** - * @inheritdoc - */ - public function le( $args = [], $assoc_args = [], $wildcard = false ) { - return parent::le( $args, $assoc_args, $wildcard ); - } - /** * Catch and clean exceptions. * From 13b8a995ec7899bfac0016928979942409ab01b2 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 1 Aug 2018 12:46:38 +0530 Subject: [PATCH 40/52] Add comments and update variables Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Command.php | 127 +++++++++++++++++++++++++++---------------- 1 file changed, 80 insertions(+), 47 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index 5ba61860..afa0311d 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -16,18 +16,52 @@ use \Symfony\Component\Filesystem\Filesystem; class Site_Command extends EE_Site_Command { + + /** + * @var string $command Name of the command being run. + */ private $command; - private $site_name; - private $site_root; - private $site_type; - private $db; + + /** + * @var array $site Associative array containing essential site related information. + */ + private $site; + + /** + * @var object $docker Object to access `EE::docker()` functions. + */ private $docker; + + /** + * @var int $level The level of creation in progress. Essential for rollback in case of failure. + */ private $level; + + /** + * @var object $logger Object of logger. + */ private $logger; + + /** + * @var bool $le Whether the site is letsencrypt or not. + */ private $le; + + /** + * @var bool $skip_chk To skip site status check pre-installation. + */ private $skip_chk; + + /** + * @var Filesystem $fs Symfony Filesystem object. + */ private $fs; + /** + * @var Object $db Object to access `EE::db()` functions. + */ + private $db; + public function __construct() { $this->level = 0; @@ -67,14 +101,14 @@ public function create( $args, $assoc_args ) { EE::warning( 'This is a beta version. Please don\'t use it in production.' ); $this->logger->debug( 'args:', $args ); $this->logger->debug( 'assoc_args:', empty( $assoc_args ) ? [ 'NULL' ] : $assoc_args ); - $this->site_name = strtolower( EE\Utils\remove_trailing_slash( $args[0] ) ); - $this->site_type = EE\Utils\get_flag_value( $assoc_args, 'type', 'html' ); - if ( 'html' !== $this->site_type ) { - EE::error( "Invalid site-type: $this->site_type" ); + $this->site['name'] = strtolower( EE\Utils\remove_trailing_slash( $args[0] ) ); + $this->site['type'] = EE\Utils\get_flag_value( $assoc_args, 'type', 'html' ); + if ( 'html' !== $this->site['type'] ) { + EE::error( sprintf( 'Invalid site-type: %s', $this->site['type'] ) ); } - if ( $this->db::site_in_db( $this->site_name ) ) { - EE::error( "Site $this->site_name already exists. If you want to re-create it please delete the older one using:\n`ee site delete $this->site_name`" ); + if ( $this->db::site_in_db( $this->site['name'] ) ) { + EE::error( sprintf( "Site %1\$s already exists. If you want to re-create it please delete the older one using:\n`ee site delete %1\$s`", $this->site['name'] ) ); } $this->le = EE\Utils\get_flag_value( $assoc_args, 'letsencrypt' ); @@ -97,17 +131,16 @@ public function create( $args, $assoc_args ) { public function info( $args, $assoc_args ) { EE\Utils\delem_log( 'site info start' ); - if ( ! isset( $this->site_name ) ) { + if ( ! isset( $this->site['name'] ) ) { $args = EE\SiteUtils\auto_site_name( $args, $this->command, __FUNCTION__ ); $this->populate_site_info( $args ); } - $ssl = $this->le ? 'Enabled' : 'Not Enabled'; - EE::log( "Details for site $this->site_name:" ); + $ssl = $this->le ? 'Enabled' : 'Not Enabled'; $prefix = ( $this->le ) ? 'https://' : 'http://'; $info = [ - [ 'Site', $prefix . $this->site_name ], - [ 'Access mailhog', $prefix . $this->site_name . '/ee-admin/mailhog/' ], - [ 'Site Root', $this->site_root ], + [ 'Site', $prefix . $this->site['name'] ], + [ 'Access mailhog', $prefix . $this->site['name'] . '/ee-admin/mailhog/' ], + [ 'Site Root', $this->site['root'] ], [ 'SSL', $ssl ], ]; @@ -122,25 +155,25 @@ public function info( $args, $assoc_args ) { */ private function configure_site_files() { - $site_conf_dir = $this->site_root . '/config'; - $site_docker_yml = $this->site_root . '/docker-compose.yml'; - $site_conf_env = $this->site_root . '/.env'; + $site_conf_dir = $this->site['root'] . '/config'; + $site_docker_yml = $this->site['root'] . '/docker-compose.yml'; + $site_conf_env = $this->site['root'] . '/.env'; $site_nginx_default_conf = $site_conf_dir . '/nginx/default.conf'; - $site_src_dir = $this->site_root . '/app/src'; + $site_src_dir = $this->site['root'] . '/app/src'; $process_user = posix_getpwuid( posix_geteuid() ); - EE::log( "Creating site $this->site_name." ); + EE::log( sprintf( 'Creating site %s.', $this->site['name'] ) ); EE::log( 'Copying configuration files.' ); $filter = []; - $filter[] = $this->site_type; + $filter[] = $this->site['type']; $filter[] = $this->le; $site_docker = new Site_Docker(); $docker_compose_content = $site_docker->generate_docker_compose_yml( $filter ); - $default_conf_content = $default_conf_content = EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/config/nginx/default.conf.mustache', [ 'server_name' => $this->site_name ] ); + $default_conf_content = $default_conf_content = EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/config/nginx/default.conf.mustache', [ 'server_name' => $this->site['name'] ] ); $env_data = [ - 'virtual_host' => $this->site_name, + 'virtual_host' => $this->site['name'], 'user_id' => $process_user['uid'], 'group_id' => $process_user['gid'], ]; @@ -155,13 +188,13 @@ private function configure_site_files() { $index_data = [ 'version' => 'v' . EE_VERSION, - 'site_src_root' => $this->site_root . '/app/src', + 'site_src_root' => $this->site['root'] . '/app/src', ]; $index_html = EE\Utils\mustache_render( SITE_TEMPLATE_ROOT . '/index.html.mustache', $index_data ); $this->fs->mkdir( $site_src_dir ); $this->fs->dumpFile( $site_src_dir . '/index.html', $index_html ); - EE\Siteutils\add_site_redirects( $this->site_name, $this->le ); + EE\Siteutils\add_site_redirects( $this->site['name'], $this->le ); EE::success( 'Configuration files copied.' ); } catch ( Exception $e ) { @@ -174,30 +207,30 @@ private function configure_site_files() { */ private function create_site() { - $this->site_root = WEBROOT . $this->site_name; - $this->level = 1; + $this->site['root'] = WEBROOT . $this->site['name']; + $this->level = 1; try { - EE\Siteutils\create_site_root( $this->site_root, $this->site_name ); + EE\Siteutils\create_site_root( $this->site['root'], $this->site['name'] ); $this->level = 2; - EE\Siteutils\setup_site_network( $this->site_name ); + EE\Siteutils\setup_site_network( $this->site['name'] ); $this->level = 3; $this->configure_site_files(); - EE\Siteutils\start_site_containers( $this->site_root ); + EE\Siteutils\start_site_containers( $this->site['root'] ); - EE\Siteutils\create_etc_hosts_entry( $this->site_name ); + EE\Siteutils\create_etc_hosts_entry( $this->site['name'] ); if ( ! $this->skip_chk ) { $this->level = 4; - EE\Siteutils\site_status_check( $this->site_name ); + EE\Siteutils\site_status_check( $this->site['name'] ); } } catch ( Exception $e ) { $this->catch_clean( $e ); } if ( $this->le ) { - $this->init_le( $this->site_name, $this->site_root, false ); + $this->init_le( $this->site['name'], $this->site['root'], false ); } - $this->info( [ $this->site_name ], [] ); + $this->info( [ $this->site['name'] ], [] ); $this->create_site_db_entry(); } @@ -208,9 +241,9 @@ private function create_site_db_entry() { $ssl = $this->le ? 1 : 0; $data = [ - 'sitename' => $this->site_name, - 'site_type' => $this->site_type, - 'site_path' => $this->site_root, + 'sitename' => $this->site['name'], + 'site_type' => $this->site['type'], + 'site_path' => $this->site['root'], 'site_command' => $this->command, 'is_ssl' => $ssl, 'created_on' => date( 'Y-m-d H:i:s', time() ), @@ -232,18 +265,18 @@ private function create_site_db_entry() { */ private function populate_site_info( $args ) { - $this->site_name = EE\Utils\remove_trailing_slash( $args[0] ); + $this->site['name'] = EE\Utils\remove_trailing_slash( $args[0] ); - if ( $this->db::site_in_db( $this->site_name ) ) { + if ( $this->db::site_in_db( $this->site['name'] ) ) { - $db_select = $this->db::select( [], [ 'sitename' => $this->site_name ], 'sites', 1 ); + $db_select = $this->db::select( [], [ 'sitename' => $this->site['name'] ], 'sites', 1 ); - $this->site_type = $db_select['site_type']; - $this->site_root = $db_select['site_path']; - $this->le = $db_select['is_ssl']; + $this->site['type'] = $db_select['site_type']; + $this->site['root'] = $db_select['site_path']; + $this->le = $db_select['is_ssl']; } else { - EE::error( "Site $this->site_name does not exist." ); + EE::error( sprintf( 'Site %s does not exist.', $this->site['name'] ) ); } } @@ -273,7 +306,7 @@ private function catch_clean( $e ) { EE\Utils\delem_log( 'site cleanup start' ); EE::warning( $e->getMessage() ); EE::warning( 'Initiating clean-up.' ); - $this->delete_site( $this->level, $this->site_name, $this->site_root ); + $this->delete_site( $this->level, $this->site['name'], $this->site['root'] ); EE\Utils\delem_log( 'site cleanup end' ); exit; } @@ -285,7 +318,7 @@ private function rollback() { EE::warning( 'Exiting gracefully after rolling back. This may take some time.' ); if ( $this->level > 0 ) { - $this->delete_site( $this->level, $this->site_name, $this->site_root ); + $this->delete_site( $this->level, $this->site['name'], $this->site['root'] ); } EE::success( 'Rollback complete. Exiting now.' ); exit; From 160d26cba0372ee0451a343632c8e9f9b679050b Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 1 Aug 2018 12:46:59 +0530 Subject: [PATCH 41/52] Add phpcs rules Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- phpcs.xml.dist | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 phpcs.xml.dist diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 00000000..34d60459 --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,43 @@ +<?xml version="1.0"?> +<ruleset name="EE"> + <description>WordPress Coding Standards for EE</description> + + <!-- Show sniff codes in all reports, and progress while running --> + <arg value="sp"/> + <!-- Check all PHP files in directory tree by default. --> + <arg name="extensions" value="php"/> + <!-- Run different reports --> + <arg name="report" value="full"/> + <arg name="report" value="summary"/> + <arg name="report" value="source"/> + + <file>.</file> + <exclude-pattern>*/ci/*</exclude-pattern> + <exclude-pattern>*/features/*</exclude-pattern> + <exclude-pattern>*/packages/*</exclude-pattern> + <exclude-pattern>*/tests/*</exclude-pattern> + <exclude-pattern>*/utils/*</exclude-pattern> + <exclude-pattern>*/vendor/*</exclude-pattern> + + <rule ref="PHPCompatibility"> + <!-- Polyfill package is used so array_column() is available for PHP 5.4- --> + <exclude name="PHPCompatibility.PHP.NewFunctions.array_columnFound"/> + <!-- Both magic quotes directives set in wp-settings-cli.php to provide consistent starting point. --> + <exclude name="PHPCompatibility.PHP.DeprecatedIniDirectives.magic_quotes_runtimeDeprecatedRemoved"/> + <exclude name="PHPCompatibility.PHP.DeprecatedIniDirectives.magic_quotes_sybaseDeprecatedRemoved"/> + </rule> + <config name="testVersion" value="7.0-"/> + + <rule ref="WordPress-Core"> + <exclude name="Squiz.PHP.DisallowMultipleAssignments.Found" /> + <exclude name="WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar" /> + <exclude name="WordPress.NamingConventions.ValidVariableName.MemberNotSnakeCase" /> + <exclude name="WordPress.NamingConventions.ValidVariableName.NotSnakeCase" /> + </rule> + <rule ref="WordPress.Files.FileName"> + <properties> + <property name="strict_class_file_names" value="false"/> + </properties> + <exclude name="WordPress.Files.FileName.NotHyphenatedLowercase" /> + </rule> +</ruleset> From ea341a4c6571eee315f3ee22a255c3218e2cf160 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 1 Aug 2018 14:11:03 +0530 Subject: [PATCH 42/52] Update creation in test for type=html Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- features/site.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/site.feature b/features/site.feature index 42bb717c..a68401cf 100644 --- a/features/site.feature +++ b/features/site.feature @@ -26,7 +26,7 @@ Feature: Site Command """ Scenario: Create html site successfully - When I run 'sudo bin/ee site create site.test --html' + When I run 'sudo bin/ee site create site.test --type=html' Then The site 'site.test' should have webroot And The site 'site.test' should have WordPress And Request on 'site.test' should contain following headers: From b3fb7fb581e48e0f4aebcd3f007d482c861e86d3 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 1 Aug 2018 14:19:27 +0530 Subject: [PATCH 43/52] Remove wordpress check from tests Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- features/site.feature | 1 - 1 file changed, 1 deletion(-) diff --git a/features/site.feature b/features/site.feature index a68401cf..d38df868 100644 --- a/features/site.feature +++ b/features/site.feature @@ -28,7 +28,6 @@ Feature: Site Command Scenario: Create html site successfully When I run 'sudo bin/ee site create site.test --type=html' Then The site 'site.test' should have webroot - And The site 'site.test' should have WordPress And Request on 'site.test' should contain following headers: | header | | HTTP/1.1 200 OK | From ba2ed5f81f5b1cc8de74805230615b19d84bc074 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Wed, 1 Aug 2018 19:16:27 +0530 Subject: [PATCH 44/52] Removing ssl redirection tests temporarily Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- features/redirect.feature | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/features/redirect.feature b/features/redirect.feature index ad37dcad..422fb226 100644 --- a/features/redirect.feature +++ b/features/redirect.feature @@ -14,24 +14,3 @@ Feature: Site Redirection | HTTP/1.1 301 Moved Permanently | | Location: http://www.example1.test/ | - Scenario: no_www-ssl redirection works properly - When I run 'sudo bin/ee site create example2.test --le --le-mail=test@test.com --skip-status-check' - Then Request on 'localhost' with header 'Host: www.example2.test' should contain following headers: - | header | - | HTTP/1.1 301 Moved Permanently | - | Location: https://example2.test/ | - And Request on 'https://www.example2.test' with resolve option 'www.example2.test:443:127.0.0.1' should contain following headers: - | header | - | HTTP/1.1 301 Moved Permanently | - | Location: https://example2.test/ | - - Scenario: www-ssl redirection works properly - When I run 'sudo bin/ee site create www.example3.test --le --le-mail=test@test.com --skip-status-check' - Then Request on 'localhost' with header 'Host: example3.test' should contain following headers: - | header | - | HTTP/1.1 301 Moved Permanently | - | Location: https://www.example3.test/ | - And Request on 'https://example3.test/' with resolve option 'example3.test:443:127.0.0.1' should contain following headers: - | header | - | HTTP/1.1 301 Moved Permanently | - | Location: https://www.example3.test/ | From 595257f6c233611936d9bf6c5d02fea878808129 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Thu, 2 Aug 2018 14:08:01 +0530 Subject: [PATCH 45/52] Update tests for EE::launch changes in core Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- features/bootstrap/FeatureContext.php | 35 +++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 50ea7f57..598ca413 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -1,10 +1,41 @@ <?php -include_once(__DIR__ . '/../../php/class-ee.php'); -include_once(__DIR__ . '/../../php/utils.php'); +define('EE_ROOT',__DIR__ . '/../..'); +include_once(EE_ROOT . '/php/class-ee.php'); +include_once(EE_ROOT . '/php/EE/Runner.php'); +include_once(EE_ROOT . '/php/utils.php'); + +define( 'EE', true ); +define( 'EE_VERSION', trim( file_get_contents( EE_ROOT . '/VERSION' ) ) ); define( 'EE_CONF_ROOT', '/opt/easyengine' ); +require_once EE_ROOT . '/php/bootstrap.php'; + +if ( ! class_exists( 'EE\Runner' ) ) { + require_once EE_ROOT . '/php/EE/Runner.php'; +} + +if ( ! class_exists( 'EE\Configurator' ) ) { + require_once EE_ROOT . '/php/EE/Configurator.php'; +} + +$logger_dir = EE_ROOT . '/php/EE/Loggers'; +$iterator = new \DirectoryIterator( $logger_dir ); + +// Make sure the base class is declared first. +include_once "$logger_dir/Base.php"; + +foreach ( $iterator as $filename ) { + if ( '.php' !== substr( $filename, - 4 ) ) { + continue; + } + + include_once "$logger_dir/$filename"; +} +$runner = \EE::get_runner(); +$runner->init_logger(); + use Behat\Behat\Context\Context; use Behat\Behat\Hook\Scope\AfterFeatureScope; use Behat\Behat\Hook\Scope\AfterScenarioScope; From 02afccad1478c74a9336e514311e21d1605feb3f Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Thu, 2 Aug 2018 15:53:34 +0530 Subject: [PATCH 46/52] Give sudo permission to create log file Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0629e94a..2d954556 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,7 @@ before_script: script: - cd "$TRAVIS_BUILD_DIR/../easyengine" - - ./vendor/bin/behat + - sudo ./vendor/bin/behat after_script: - cat /opt/easyengine/ee.log From 6bc0e5fbe3176126e1d41444d7ced28f1d4c01dd Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Thu, 2 Aug 2018 17:09:15 +0530 Subject: [PATCH 47/52] Remove sudo test and sudo Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- features/redirect.feature | 4 ++-- features/site.feature | 18 +++++------------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/features/redirect.feature b/features/redirect.feature index 422fb226..9f06e09d 100644 --- a/features/redirect.feature +++ b/features/redirect.feature @@ -1,14 +1,14 @@ Feature: Site Redirection Scenario: no_www-no_ssl redirection works properly - When I run 'sudo bin/ee site create example.test' + When I run 'bin/ee site create example.test' Then Request on 'localhost' with header 'Host: www.example.test' should contain following headers: | header | | HTTP/1.1 301 Moved Permanently | | Location: http://example.test/ | Scenario: www-no_ssl redirection works properly - When I run 'sudo bin/ee site create www.example1.test' + When I run 'bin/ee site create www.example1.test' Then Request on 'localhost' with header 'Host: example1.test' should contain following headers: | header | | HTTP/1.1 301 Moved Permanently | diff --git a/features/site.feature b/features/site.feature index d38df868..827f6ed8 100644 --- a/features/site.feature +++ b/features/site.feature @@ -1,16 +1,8 @@ Feature: Site Command - Scenario: ee throws error when run without root - Given 'bin/ee' is installed - When I run 'bin/ee' - Then STDERR should return exactly - """ - Error: Please run `ee` with root privileges. - """ - Scenario: ee executable is command working correctly Given 'bin/ee' is installed - When I run 'sudo bin/ee' + When I run 'bin/ee' Then STDOUT should return something like """ NAME @@ -19,28 +11,28 @@ Feature: Site Command """ Scenario: Check site command is present - When I run 'sudo bin/ee site' + When I run 'bin/ee site' Then STDOUT should return something like """ usage: ee site """ Scenario: Create html site successfully - When I run 'sudo bin/ee site create site.test --type=html' + When I run 'bin/ee site create site.test --type=html' Then The site 'site.test' should have webroot And Request on 'site.test' should contain following headers: | header | | HTTP/1.1 200 OK | Scenario: List the sites - When I run 'sudo bin/ee site list --format=text' + When I run 'bin/ee site list --format=text' Then STDOUT should return exactly """ site.test """ Scenario: Delete the sites - When I run 'sudo bin/ee site delete site.test --yes' + When I run 'bin/ee site delete site.test --yes' Then STDOUT should return something like """ Site site.test deleted. From f07c8161fa3703ad79f3dd71fd2b0aece0ba2921 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Thu, 2 Aug 2018 20:06:33 +0530 Subject: [PATCH 48/52] Update comments Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- features/bootstrap/FeatureContext.php | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 598ca413..f8f62e31 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -1,10 +1,16 @@ <?php +/** + * Behat tests. + * + * @package ee-cli + */ -define('EE_ROOT',__DIR__ . '/../..'); +/* Start: Loading required files to enable EE::launch() in tests. */ +define( 'EE_ROOT', __DIR__ . '/../..' ); -include_once(EE_ROOT . '/php/class-ee.php'); -include_once(EE_ROOT . '/php/EE/Runner.php'); -include_once(EE_ROOT . '/php/utils.php'); +include_once( EE_ROOT . '/php/class-ee.php' ); +include_once( EE_ROOT . '/php/EE/Runner.php' ); +include_once( EE_ROOT . '/php/utils.php' ); define( 'EE', true ); define( 'EE_VERSION', trim( file_get_contents( EE_ROOT . '/VERSION' ) ) ); @@ -27,7 +33,7 @@ include_once "$logger_dir/Base.php"; foreach ( $iterator as $filename ) { - if ( '.php' !== substr( $filename, - 4 ) ) { + if ( '.php' !== pathinfo( $filename, PATHINFO_EXTENSION ) ) { continue; } @@ -35,6 +41,7 @@ } $runner = \EE::get_runner(); $runner->init_logger(); +/* End. Loading required files to enable EE::launch() in tests. */ use Behat\Behat\Context\Context; use Behat\Behat\Hook\Scope\AfterFeatureScope; From 04638ae2a87b237459df7ec8e9020a51ff5e0f59 Mon Sep 17 00:00:00 2001 From: Kirtan Gajjar <kirtangajjar95@gmail.com> Date: Mon, 6 Aug 2018 10:39:10 +0530 Subject: [PATCH 49/52] Add redirect tests Signed-off-by: Kirtan Gajjar <kirtangajjar95@gmail.com> --- features/redirect.feature | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/features/redirect.feature b/features/redirect.feature index 9f06e09d..66222c40 100644 --- a/features/redirect.feature +++ b/features/redirect.feature @@ -14,3 +14,24 @@ Feature: Site Redirection | HTTP/1.1 301 Moved Permanently | | Location: http://www.example1.test/ | + Scenario: no_www-ssl redirection works properly + When I run 'sudo bin/ee site create example2.test --le --le-mail=test@test.com --skip-status-check' + Then Request on 'localhost' with header 'Host: www.example2.test' should contain following headers: + | header | + | HTTP/1.1 301 Moved Permanently | + | Location: https://example2.test/ | + And Request on 'https://www.example2.test' with resolve option 'www.example2.test:443:127.0.0.1' should contain following headers: + | header | + | HTTP/1.1 301 Moved Permanently | + | Location: https://example2.test/ | + + Scenario: www-ssl redirection works properly + When I run 'sudo bin/ee site create www.example3.test --le --le-mail=test@test.com --skip-status-check' + Then Request on 'localhost' with header 'Host: example3.test' should contain following headers: + | header | + | HTTP/1.1 301 Moved Permanently | + | Location: https://www.example3.test/ | + And Request on 'https://example3.test/' with resolve option 'example3.test:443:127.0.0.1' should contain following headers: + | header | + | HTTP/1.1 301 Moved Permanently | + | Location: https://www.example3.test/ | From efd8072b9df1d4af418173c50d4d91e6dc20aa84 Mon Sep 17 00:00:00 2001 From: Kirtan Gajjar <kirtangajjar95@gmail.com> Date: Mon, 6 Aug 2018 12:56:16 +0530 Subject: [PATCH 50/52] Add delay in tests to stop random test failing Signed-off-by: Kirtan Gajjar <kirtangajjar95@gmail.com> --- features/redirect.feature | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/features/redirect.feature b/features/redirect.feature index 66222c40..273e3dbb 100644 --- a/features/redirect.feature +++ b/features/redirect.feature @@ -2,6 +2,7 @@ Feature: Site Redirection Scenario: no_www-no_ssl redirection works properly When I run 'bin/ee site create example.test' + Then After delay of 5 seconds Then Request on 'localhost' with header 'Host: www.example.test' should contain following headers: | header | | HTTP/1.1 301 Moved Permanently | @@ -9,6 +10,7 @@ Feature: Site Redirection Scenario: www-no_ssl redirection works properly When I run 'bin/ee site create www.example1.test' + Then After delay of 5 seconds Then Request on 'localhost' with header 'Host: example1.test' should contain following headers: | header | | HTTP/1.1 301 Moved Permanently | @@ -16,6 +18,7 @@ Feature: Site Redirection Scenario: no_www-ssl redirection works properly When I run 'sudo bin/ee site create example2.test --le --le-mail=test@test.com --skip-status-check' + Then After delay of 5 seconds Then Request on 'localhost' with header 'Host: www.example2.test' should contain following headers: | header | | HTTP/1.1 301 Moved Permanently | @@ -27,6 +30,7 @@ Feature: Site Redirection Scenario: www-ssl redirection works properly When I run 'sudo bin/ee site create www.example3.test --le --le-mail=test@test.com --skip-status-check' + Then After delay of 5 seconds Then Request on 'localhost' with header 'Host: example3.test' should contain following headers: | header | | HTTP/1.1 301 Moved Permanently | From 7f83728202b223e22509dd42e02df42eda03d15c Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Mon, 6 Aug 2018 22:42:01 +0530 Subject: [PATCH 51/52] Remove mailhog container Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- src/Site_Command.php | 1 - src/Site_Docker.php | 20 -------------------- 2 files changed, 21 deletions(-) diff --git a/src/Site_Command.php b/src/Site_Command.php index afa0311d..a78f2976 100644 --- a/src/Site_Command.php +++ b/src/Site_Command.php @@ -139,7 +139,6 @@ public function info( $args, $assoc_args ) { $prefix = ( $this->le ) ? 'https://' : 'http://'; $info = [ [ 'Site', $prefix . $this->site['name'] ], - [ 'Access mailhog', $prefix . $this->site['name'] . '/ee-admin/mailhog/' ], [ 'Site Root', $this->site['root'] ], [ 'SSL', $ssl ], ]; diff --git a/src/Site_Docker.php b/src/Site_Docker.php index 8a2cd269..d025914c 100644 --- a/src/Site_Docker.php +++ b/src/Site_Docker.php @@ -46,27 +46,7 @@ public function generate_docker_compose_yml( array $filters = [] ) { ]; $nginx['networks'] = $network_default; - // mailhog configuration. - $mailhog['service_name'] = [ 'name' => 'mailhog' ]; - $mailhog['image'] = [ 'name' => 'easyengine/mailhog:v' . EE_VERSION ]; - $mailhog['restart'] = $restart_default; - $mailhog['command'] = [ 'name' => '["-invite-jim=false"]' ]; - $mailhog['environment'] = [ - 'env' => [ - [ 'name' => $v_host ], - [ 'name' => 'VIRTUAL_PATH=/ee-admin/mailhog/' ], - [ 'name' => 'VIRTUAL_PORT=8025' ], - ], - ]; - $mailhog['labels'] = [ - 'label' => [ - 'name' => 'io.easyengine.site=${VIRTUAL_HOST}', - ], - ]; - $mailhog['networks'] = $network_default; - $base[] = $nginx; - $base[] = $mailhog; $binding = [ 'services' => $base, From 73c16198714d80fb009611353c9b70c842405636 Mon Sep 17 00:00:00 2001 From: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> Date: Mon, 6 Aug 2018 23:10:33 +0530 Subject: [PATCH 52/52] Fix labels test Signed-off-by: Riddhesh Sanghvi <riddheshsanghvi96@gmail.com> --- features/bootstrap/FeatureContext.php | 2 +- features/labels.feature | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index f8f62e31..bec661c4 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -382,7 +382,7 @@ public function thereShouldBeContainersWithLabel($expected_running_containers, P $labels = $pyStringNode->getStrings(); $label_string = implode($labels, ' -f label='); - $result = EE::launch( "docker ps -aqf label=$label_string | wc -l", false, true ); + $result = EE::launch( "docker ps -qf label=$label_string | wc -l", false, true ); $running_containers = (int) trim($result->stdout); if($expected_running_containers === $running_containers) { diff --git a/features/labels.feature b/features/labels.feature index acef3ce3..25ff2184 100644 --- a/features/labels.feature +++ b/features/labels.feature @@ -3,7 +3,7 @@ Feature: Container Labels Scenario: All easyengine containers are tagged Given I run "bin/ee site create labels.test" - Then There should be 2 containers with labels + Then There should be 1 containers with labels """ io.easyengine.site=labels.test """