From 4be6bb62cf58656ff87bebea6c38286d9f455c9b Mon Sep 17 00:00:00 2001 From: sagar Date: Tue, 4 Sep 2018 22:19:36 +0530 Subject: [PATCH 01/11] Add site type php --- .distignore | 16 + .editorconfig | 25 + .gitignore | 12 + .travis.yml | 41 ++ ci/add-test-certs.sh | 106 ++++ ci/prepare.sh | 32 ++ composer.json | 24 + features/bootstrap/FeatureContext.php | 426 +++++++++++++++ features/bootstrap/support.php | 207 ++++++++ features/labels.feature | 9 + features/redirect.feature | 17 + features/site.feature | 77 +++ phpcs.xml.dist | 43 ++ site-type-php.php | 19 + src/PHP.php | 513 +++++++++++++++++++ src/Site_PHP_Docker.php | 190 +++++++ templates/config/.env.mustache | 10 + templates/config/nginx/default.conf.mustache | 144 ++++++ templates/config/php-fpm/php.ini.mustache | 7 + templates/docker-compose.mustache | 59 +++ templates/index.php.mustache | 3 + 21 files changed, 1980 insertions(+) create mode 100644 .distignore create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100755 ci/add-test-certs.sh create mode 100755 ci/prepare.sh create mode 100644 composer.json create mode 100644 features/bootstrap/FeatureContext.php create mode 100644 features/bootstrap/support.php create mode 100644 features/labels.feature create mode 100644 features/redirect.feature create mode 100644 features/site.feature create mode 100644 phpcs.xml.dist create mode 100644 site-type-php.php create mode 100644 src/PHP.php create mode 100644 src/Site_PHP_Docker.php create mode 100644 templates/config/.env.mustache create mode 100644 templates/config/nginx/default.conf.mustache create mode 100644 templates/config/php-fpm/php.ini.mustache create mode 100644 templates/docker-compose.mustache create mode 100644 templates/index.php.mustache diff --git a/.distignore b/.distignore new file mode 100644 index 0000000..acbaa32 --- /dev/null +++ b/.distignore @@ -0,0 +1,16 @@ +.DS_Store +.git +.gitignore +.gitlab-ci.yml +.editorconfig +.travis.yml +behat.yml +circle.yml +bin/ +features/ +utils/ +*.zip +*.tar.gz +*.swp +*.txt +*.log diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..fa483b1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,25 @@ +# This file is for unifying the coding style for different editors and IDEs +# editorconfig.org + +# WordPress Coding Standards +# https://make.wordpress.org/core/handbook/coding-standards/ + +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = tab + +[{.jshintrc,*.json,*.yml,*.feature}] +indent_style = space +indent_size = 2 + +[{*.txt,wp-config-sample.php}] +end_of_line = crlf + +[composer.json] +indent_style = space +indent_size = 4 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..92b69bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +.DS_Store +wp-cli.local.yml +node_modules/ +vendor/ +*.zip +*.tar.gz +*.swp +*.txt +*.log +composer.lock +.idea +*.db diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..e944a4e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,41 @@ +sudo: required + +language: php +php: 7.0 + +env: + global: + - TEST_COMMAND=$(echo $TRAVIS_REPO_SLUG | cut -d/ -f 2) # Get command name to be tested + +before_script: + - sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose + - | + # Remove Xdebug for a huge performance increase: + if [ -f ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini ]; then + phpenv config-rm xdebug.ini + else + echo "xdebug.ini does not exist" + fi + - ./ci/prepare.sh + - ./ci/add-test-certs.sh + +script: + - cd "$TRAVIS_BUILD_DIR/../easyengine" + - sudo ./vendor/bin/behat + +after_script: + - cat /opt/easyengine/ee.log + +cache: + directories: + - $HOME/.composer/cache + +notifications: + email: + on_success: never + on_failure: change + +addons: + apt: + packages: + - docker-ce diff --git a/ci/add-test-certs.sh b/ci/add-test-certs.sh new file mode 100755 index 0000000..54c4bd0 --- /dev/null +++ b/ci/add-test-certs.sh @@ -0,0 +1,106 @@ +#!/usr/bin/env bash +sudo mkdir -p /opt/easyengine/nginx/certs + +cat < /dev/null +sudo php easyengine.phar cli info \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..bb11c9d --- /dev/null +++ b/composer.json @@ -0,0 +1,24 @@ +{ + "name": "easyengine/site-wp-command", + "description": "EasyEngine package for WordPress site creation.", + "type": "ee-cli-package", + "homepage": "https://github.com/easyengine/site-wp-command", + "license": "MIT", + "authors": [], + "minimum-stability": "dev", + "prefer-stable": true, + "autoload": { + "psr-4": { + "": "src/" + } + }, + "require-dev": { + "wp-cli/mustangostang-spyc": "^0.6.3" + }, + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + }, + "bundled": true + } +} diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php new file mode 100644 index 0000000..b955316 --- /dev/null +++ b/features/bootstrap/FeatureContext.php @@ -0,0 +1,426 @@ +init_logger(); +/* End. Loading required files to enable EE::launch() in tests. */ + +use Behat\Behat\Context\Context; +use Behat\Behat\Hook\Scope\AfterFeatureScope; +use Behat\Behat\Hook\Scope\AfterScenarioScope; + +use Behat\Gherkin\Node\PyStringNode, + Behat\Gherkin\Node\TableNode; + +define( 'EE_SITE_ROOT', getenv('HOME') . '/ee-sites/' ); + +class FeatureContext implements Context +{ + public $command; + public $webroot_path; + public $ee_path; + + /** + * Initializes context. + */ + public function __construct() + { + $this->commands = []; + $this->ee_path = getcwd(); + $config_contents = \Mustangostang\Spyc::YAMLDump(['le-mail' => 'abc@example.com']); + file_put_contents( EE_CONF_ROOT . '/config.yml', $config_contents ); + } + + /** + * @Given ee phar is generated + */ + public function eePharIsPresent() + { + // Checks if phar already exists, replaces it + if(file_exists('ee-old.phar')) { + // Below exec call is required as currenly `ee cli update` is ran with root + // which updates ee.phar with root privileges. + exec("sudo rm ee.phar"); + copy('ee-old.phar','ee.phar'); + return 0; + } + exec("php -dphar.readonly=0 utils/make-phar.php ee.phar", $output, $return_status); + if (0 !== $return_status) { + throw new Exception("Unable to generate phar" . $return_status); + } + + // Cache generaed phar as it is expensive to generate one + copy('ee.phar','ee-old.phar'); + } + + /** + * @Given :command is installed + */ + public function isInstalled($command) + { + exec("type " . $command, $output, $return_status); + if (0 !== $return_status) { + throw new Exception($command . " is not installed! Exit code is:" . $return_status); + } + } + + /** + * @When I run :command + */ + public function iRun($command) + { + $this->commands[] = EE::launch($command, false, true); + } + + /** + * @When I create subsite :subsite in :site + */ + public function iCreateSubsiteInOfType($subsite, $site ) + { + $php_container = implode( explode( '.', $subsite ) ) . '_php_1'; + + EE::launch( "docker exec -it --user='www-data' $php_container sh -c 'wp site create --slug=$site'", false, true ); + } + + /** + * @Then return value should be 0 + */ + public function returnValueShouldBe0() + { + if ( 0 !== $this->commands[0]->return_code ) { + throw new Exception("Actual return code is not zero: \n" . $this->command); + } + } + + /** + * @Then return value of command :index should be 0 + */ + public function returnValueOfCommandShouldBe0($index) + { + if ( 0 !== $this->commands[ $index - 1 ]->return_code ) { + throw new Exception("Actual return code is not zero: \n" . $this->command); + } + } + + /** + * @Then After delay of :time seconds + */ + public function afterDelayOfSeconds( $time ) + { + sleep( $time ); + } + + /** + * @Then /(STDOUT|STDERR) should return exactly/ + */ + public function stdoutShouldReturnExactly($output_stream, PyStringNode $expected_output) + { + $command_output = $output_stream === "STDOUT" ? $this->commands[0]->stdout : $this->commands[0]->stderr; + + $command_output = str_replace(["\033[1;31m","\033[0m"],'',$command_output); + + if ( $expected_output->getRaw() !== trim($command_output)) { + throw new Exception("Actual output is:\n" . $command_output); + } + } + + /** + * @Then /(STDOUT|STDERR) of command :index should return exactly/ + */ + public function stdoutOfCommandShouldReturnExactly($output_stream, $index, PyStringNode $expected_output) + { + $command_output = $output_stream === "STDOUT" ? $this->commands[ $index - 1 ]->stdout : $this->commands[ $index - 1 ]->stderr; + + $command_output = str_replace(["\033[1;31m","\033[0m"],'',$command_output); + + $expected_out = isset($expected_output->getStrings()[0]) ? $expected_output->getStrings()[0] : ''; + if ( $expected_out !== trim($command_output)) { + throw new Exception("Actual output is:\n" . $command_output); + } + } + + /** + * @Then /(STDOUT|STDERR) should return something like/ + */ + public function stdoutShouldReturnSomethingLike($output_stream, PyStringNode $expected_output) + { + $command_output = $output_stream === "STDOUT" ? $this->commands[0]->stdout : $this->commands[0]->stderr; + + $expected_out = isset($expected_output->getStrings()[0]) ? $expected_output->getStrings()[0] : ''; + if (strpos($command_output, $expected_out) === false) { + throw new Exception("Actual output is:\n" . $command_output); + } + } + + + /** + * @Then /(STDOUT|STDERR) of command :index should return something like/ + */ + public function stdoutOfCommandShouldReturnSomethingLike($output_stream, $index, PyStringNode $expected_output) + { + $command_output = $output_stream === "STDOUT" ? $this->commands[ $index - 1 ]->stdout : $this->commands[ $index - 1 ]->stderr; + + $expected_out = isset($expected_output->getStrings()[0]) ? $expected_output->getStrings()[0] : ''; + if (strpos($command_output, $expected_out) === false) { + throw new Exception("Actual output is:\n" . $command_output); + } + } + + /** + * @Then The site :site should be :type multisite + */ + public function theSiteShouldBeMultisite( $site, $type ) + { + $result = EE::launch("cd " . EE_SITE_ROOT . "$site && docker-compose exec --user='www-data' php sh -c 'wp config get SUBDOMAIN_INSTALL'", false, true ); + + if( $result->stderr ) { + throw new Exception("Found error while executing command: $result->stderr"); + } + + if($type === 'subdomain' && trim($result->stdout) !== '1') { + throw new Exception("Expecting SUBDOMAIN_INSTALL to be 1. Got: $result->stdout"); + } + else if($type === 'subdir' && trim($result->stdout) !== '') { + throw new Exception("Expecting SUBDOMAIN_INSTALL to be empty. Got: $result->stdout"); + } + else if($type !== 'subdomain' && $type !== 'subdir') { + throw new Exception("Found unknown site type: $type"); + } + } + + /** + * @Then The :site db entry should be removed + */ + public function theDbEntryShouldBeRemoved($site) + { + $out = shell_exec("sudo bin/ee site list"); + if (strpos($out, $site) !== false) { + throw new Exception("$site db entry not been removed!"); + } + + } + + /** + * @Then The :site webroot should be removed + */ + public function theWebrootShouldBeRemoved($site) + { + if (file_exists(EE_SITE_ROOT . $site)) { + throw new Exception("Webroot has not been removed!"); + } + } + + /** + * @Then Following containers of site :site should be removed: + */ + public function followingContainersOfSiteShouldBeRemoved($site, TableNode $table) + { + $containers = $table->getHash(); + $site_name = implode(explode('.', $site)); + + foreach ($containers as $container) { + + $sevice = $container['container']; + $container_name = $site_name . '_' . $sevice . '_1'; + + exec("docker inspect -f '{{.State.Running}}' $container_name > /dev/null 2>&1", $exec_out, $return); + if (!$return) { + throw new Exception("$container_name has not been removed!"); + } + } + } + + /** + * @Then The site :site should have webroot + */ + public function theSiteShouldHaveWebroot($site) + { + if (!file_exists(EE_SITE_ROOT . $site)) { + throw new Exception("Webroot has not been created!"); + } + } + + /** + * @Then The site :site should have WordPress + */ + public function theSiteShouldHaveWordpress($site) + { + if (!file_exists(EE_SITE_ROOT . $site . "/app/src/wp-config.php")) { + throw new Exception("WordPress data not found!"); + } + } + + /** + * @Then Request on :site should contain following headers: + */ + public function requestOnShouldContainFollowingHeaders($site, TableNode $table) + { + $url = 'http://' . $site; + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HEADER, true); + curl_setopt($ch, CURLOPT_NOBODY, true); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_VERBOSE, true); + $headers = curl_exec($ch); + + curl_close($ch); + + $rows = $table->getHash(); + + foreach ($rows as $row) { + if (strpos($headers, $row['header']) === false) { + throw new Exception("Unable to find " . $row['header'] . "\nActual output is : " . $headers); + } + } + } + + /** + * @Then Request on :host with header :header should contain following headers: + */ + public function requestOnWithHeaderShouldContainFollowingHeaders($host, $header, TableNode $table) + { + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $host); + curl_setopt($ch, CURLOPT_HEADER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ $header ]); + curl_setopt($ch, CURLOPT_NOBODY, true); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_VERBOSE, true); + $headers = curl_exec($ch); + + curl_close($ch); + + $rows = $table->getHash(); + + foreach ($rows as $row) { + if (strpos($headers, $row['header']) === false) { + throw new Exception("Unable to find " . $row['header'] . "\nActual output is : " . $headers); + } + } + } + + /** + * @Then Request on :host with resolve option :resolve should contain following headers: + */ + public function requestOnWithResolveOptionShouldContainFollowingHeaders($host, $resolve, TableNode $table) + { + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $host); + curl_setopt($ch, CURLOPT_HEADER, true); + curl_setopt($ch, CURLOPT_NOBODY, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_RESOLVE, [ $resolve ]); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_VERBOSE, true); + $headers = curl_exec($ch); + curl_close($ch); + + $rows = $table->getHash(); + + foreach ($rows as $row) { + if (strpos($headers, $row['header']) === false) { + throw new Exception("Unable to find " . $row['header'] . "\nActual output is : " . $headers); + } + } + } + + /** + * @AfterScenario + */ + public function cleanupScenario(AfterScenarioScope $scope) + { + $this->commands = []; + chdir($this->ee_path); + } + + /** + * @Then There should be :expected_running_containers containers with labels + */ + public function thereShouldBeContainersWithLabel($expected_running_containers, PyStringNode $pyStringNode) + { + $labels = $pyStringNode->getStrings(); + $label_string = implode($labels, ' -f label='); + + $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) { + throw new Exception("Expected $expected_running_containers running containers. Found: $running_containers"); + } + } + + /** + * @AfterFeature + */ + public static function cleanup(AfterFeatureScope $scope) + { + $test_sites = [ + 'wp.test', + 'wpsubdom.test', + 'wpsubdir.test', + 'example.test', + 'www.example1.test', + 'example2.test', + 'www.example3.test', + 'labels.test' + ]; + + $result = EE::launch( 'sudo bin/ee site list --format=text',false, true ); + $running_sites = explode( "\n", $result->stdout ); + $sites_to_delete = array_intersect( $test_sites, $running_sites ); + + foreach ( $sites_to_delete as $site ) { + exec("sudo bin/ee site delete $site --yes" ); + } + + if(file_exists('ee.phar')) { + unlink('ee.phar'); + } + if(file_exists('ee-old.phar')) { + unlink('ee-old.phar'); + } + } +} diff --git a/features/bootstrap/support.php b/features/bootstrap/support.php new file mode 100644 index 0000000..ed9a5b5 --- /dev/null +++ b/features/bootstrap/support.php @@ -0,0 +1,207 @@ + $value ) { + if ( ! compareContents( $value, $actual->$name ) ) { + return false; + } + } + } else if ( is_array( $expected ) ) { + foreach ( $expected as $key => $value ) { + if ( ! compareContents( $value, $actual[$key] ) ) { + return false; + } + } + } else { + return $expected === $actual; + } + + return true; +} + +/** + * Compare two strings containing JSON to ensure that @a $actualJson contains at + * least what the JSON string @a $expectedJson contains. + * + * @return whether or not @a $actualJson contains @a $expectedJson + * @retval true @a $actualJson contains @a $expectedJson + * @retval false @a $actualJson does not contain @a $expectedJson + * + * @param [in] $actualJson the JSON string to be tested + * @param [in] $expectedJson the expected JSON string + * + * Examples: + * expected: {'a':1,'array':[1,3,5]} + * + * 1 ) + * actual: {'a':1,'b':2,'c':3,'array':[1,2,3,4,5]} + * return: true + * + * 2 ) + * actual: {'b':2,'c':3,'array':[1,2,3,4,5]} + * return: false + * element 'a' is missing from the root object + * + * 3 ) + * actual: {'a':0,'b':2,'c':3,'array':[1,2,3,4,5]} + * return: false + * the value of element 'a' is not 1 + * + * 4 ) + * actual: {'a':1,'b':2,'c':3,'array':[1,2,4,5]} + * return: false + * the contents of 'array' does not include 3 + */ +function checkThatJsonStringContainsJsonString( $actualJson, $expectedJson ) { + $actualValue = json_decode( $actualJson ); + $expectedValue = json_decode( $expectedJson ); + + if ( ! $actualValue ) { + return false; + } + + return compareContents( $expectedValue, $actualValue ); +} + +/** + * Compare two strings to confirm $actualCSV contains $expectedCSV + * Both strings are expected to have headers for their CSVs. + * $actualCSV must match all data rows in $expectedCSV + * + * @param string A CSV string + * @param array A nested array of values + * + * @return bool Whether $actualCSV contains $expectedCSV + */ +function checkThatCsvStringContainsValues( $actualCSV, $expectedCSV ) { + $actualCSV = array_map( 'str_getcsv', explode( PHP_EOL, $actualCSV ) ); + + if ( empty( $actualCSV ) ) { + return false; + } + + // Each sample must have headers + $actualHeaders = array_values( array_shift( $actualCSV ) ); + $expectedHeaders = array_values( array_shift( $expectedCSV ) ); + + // Each expectedCSV must exist somewhere in actualCSV in the proper column + $expectedResult = 0; + foreach ( $expectedCSV as $expected_row ) { + $expected_row = array_combine( $expectedHeaders, $expected_row ); + foreach ( $actualCSV as $actual_row ) { + + if ( count( $actualHeaders ) != count( $actual_row ) ) { + continue; + } + + $actual_row = array_intersect_key( array_combine( $actualHeaders, $actual_row ), $expected_row ); + if ( $actual_row == $expected_row ) { + $expectedResult ++; + } + } + } + + return $expectedResult >= count( $expectedCSV ); +} + +/** + * Compare two strings containing YAML to ensure that @a $actualYaml contains at + * least what the YAML string @a $expectedYaml contains. + * + * @return whether or not @a $actualYaml contains @a $expectedJson + * @retval true @a $actualYaml contains @a $expectedJson + * @retval false @a $actualYaml does not contain @a $expectedJson + * + * @param [in] $actualYaml the YAML string to be tested + * @param [in] $expectedYaml the expected YAML string + */ +function checkThatYamlStringContainsYamlString( $actualYaml, $expectedYaml ) { + $actualValue = Mustangostang\Spyc::YAMLLoad( $actualYaml ); + $expectedValue = Mustangostang\Spyc::YAMLLoad( $expectedYaml ); + + if ( ! $actualValue ) { + return false; + } + + return compareContents( $expectedValue, $actualValue ); +} + diff --git a/features/labels.feature b/features/labels.feature new file mode 100644 index 0000000..f4cacf9 --- /dev/null +++ b/features/labels.feature @@ -0,0 +1,9 @@ +Feature: Container Labels + + + Scenario: All easyengine containers are tagged + Given I run "bin/ee site create labels.test --type=wp" + Then There should be 5 containers with labels + """ + io.easyengine.site=labels.test + """ diff --git a/features/redirect.feature b/features/redirect.feature new file mode 100644 index 0000000..6353505 --- /dev/null +++ b/features/redirect.feature @@ -0,0 +1,17 @@ +Feature: Site Redirection + + Scenario: no_www-no_ssl redirection works properly + When I run 'bin/ee site create example.test --type=wp' + Then After delay of 5 seconds + And 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 'bin/ee site create www.example1.test --type=wp' + Then After delay of 5 seconds + And Request on 'localhost' with header 'Host: example1.test' should contain following headers: + | header | + | HTTP/1.1 301 Moved Permanently | + | Location: http://www.example1.test/ | diff --git a/features/site.feature b/features/site.feature new file mode 100644 index 0000000..b81e413 --- /dev/null +++ b/features/site.feature @@ -0,0 +1,77 @@ +Feature: Site Command + + Scenario: ee executable is command working correctly + Given 'bin/ee' is installed + When I run 'bin/ee' + Then STDOUT should return something like + """ + NAME + + ee + """ + + Scenario: Check site command is present + When I run 'bin/ee site' + Then STDOUT should return something like + """ + usage: ee site + """ + + Scenario: Create wp site successfully + When I run 'bin/ee site create wp.test --type=wp' + Then After delay of 5 seconds + And 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 'bin/ee site create wpsubdir.test --type=wp --mu=subdir' + And I create subsite '1' in 'wpsubdir.test' + Then After delay of 5 seconds + And 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 'bin/ee site create wpsubdom.test --type=wp --mu=subdom' + And I create subsite '1' in 'wpsubdom.test' + Then After delay of 5 seconds + And 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: + | header | + | HTTP/1.1 200 OK | + + Scenario: List the sites + When I run 'bin/ee site list --format=text' + Then STDOUT should return exactly + """ + wp.test + wpsubdir.test + wpsubdom.test + """ + + Scenario: Delete the sites + When I run 'bin/ee site delete wp.test --yes' + Then STDOUT should return something like + """ + Site wp.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: + | container | + | nginx | + | php | + | db | + | redis | + | phpmyadmin | diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000..34d6045 --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,43 @@ + + + WordPress Coding Standards for EE + + + + + + + + + + + . + */ci/* + */features/* + */packages/* + */tests/* + */utils/* + */vendor/* + + + + + + + + + + + + + + + + + + + + + + + diff --git a/site-type-php.php b/site-type-php.php new file mode 100644 index 0000000..3dd1fe2 --- /dev/null +++ b/site-type-php.php @@ -0,0 +1,19 @@ +level = 0; + $this->docker = \EE::docker(); + $this->logger = \EE::get_file_logger()->withName( 'site_php_command' ); + $this->fs = new Filesystem(); + + $this->site_data['site_type'] = 'php'; + } + + /** + * Runs the standard PHP Site installation. + * + * ## OPTIONS + * + * + * : Name of website. + * + * [--cache] + * : Use redis cache for PHP. + * + * [--admin-email=] + * : E-Mail of the administrator. + * + * [--db] + * : Create database for php site. + * + * [--dbname=] + * : Set the database name. + * --- + * default: php + * --- + * + * [--dbuser=] + * : Set the database user. + * + * [--dbpass=] + * : Set the database password. + * + * [--dbhost=] + * : Set the database host. Pass value only when remote dbhost is required. + * --- + * default: db + * --- + * + * [--skip-check] + * : If set, the database connection is not checked. + * + * [--skip-status-check] + * : Skips site status check. + * + * [--ssl=] + * : Enables ssl on site. + * + * [--wildcard] + * : Gets wildcard SSL . + * + * [--force] + * : Resets the remote database if it is not empty. + */ + public function create( $args, $assoc_args ) { + + \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_data['site_url'] = strtolower( \EE\Utils\remove_trailing_slash( $args[0] ) ); + + if ( Site::find( $this->site_data['site_url'] ) ) { + \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_data['site_url'] ) ); + } + + $this->cache_type = \EE\Utils\get_flag_value( $assoc_args, 'cache' ); + $this->site_data['site_ssl'] = \EE\Utils\get_flag_value( $assoc_args, 'ssl' ); + $this->site_data['site_ssl_wildcard'] = \EE\Utils\get_flag_value( $assoc_args, 'wildcard' ); + + if ( ! empty( $assoc_args['db'] ) ) { + $this->site_data['db_name'] = str_replace( [ '.', '-' ], '_', $this->site_data['site_url'] ); + $this->site_data['db_host'] = \EE\Utils\get_flag_value( $assoc_args, 'dbhost' ); + $this->site_data['db_port'] = '3306'; + $this->site_data['db_user'] = \EE\Utils\get_flag_value( $assoc_args, 'dbuser', $this->create_site_db_user( $this->site_data['site_url'] ) ); + $this->site_data['db_password'] = \EE\Utils\get_flag_value( $assoc_args, 'dbpass', \EE\Utils\random_password() ); + $this->site_data['db_root_password'] = \EE\Utils\random_password(); + + // If user wants to connect to remote database. + if ( 'db' !== $this->site_data['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->site_data['db_host'] ); + $this->site_data['db_host'] = $arg_host_port[0]; + $this->site_data['db_port'] = empty( $arg_host_port[1] ) ? '3306' : $arg_host_port[1]; + } + } + + + $this->skip_status_check = \EE\Utils\get_flag_value( $assoc_args, 'skip-status-check' ); + $this->force = \EE\Utils\get_flag_value( $assoc_args, 'force' ); + + \EE\Site\Utils\init_checks(); + + \EE::log( 'Configuring project.' ); + + $this->create_site( $assoc_args ); + \EE\Utils\delem_log( 'site create end' ); + } + + /** + * Creates database user for a site + * + * @param string $site_url URL of site. + * + * @return string Generated db user. + */ + private function create_site_db_user( string $site_url ): string { + if ( strlen( $site_url ) > 53 ) { + $site_url = substr( $site_url, 0, 53 ); + } + + return $site_url . '-' . \EE\Utils\random_password( 6 ); + } + + /** + * Display all the relevant site information, credentials and useful links. + * + * [] + * : Name of the website whose info is required. + */ + public function info( $args, $assoc_args ) { + + \EE\Utils\delem_log( 'site info start' ); + if ( ! isset( $this->site_data['site_url'] ) ) { + $args = auto_site_name( $args, 'php', __FUNCTION__ ); + $this->site_data = get_site_info( $args, false ); + $this->cache_type = $this->site_data['cache_nginx_fullpage']; + } + $ssl = $this->site_data['site_ssl'] ? 'Enabled' : 'Not Enabled'; + $prefix = ( $this->site_data['site_ssl'] ) ? 'https://' : 'http://'; + $info = [ [ 'Site', $prefix . $this->site_data['site_url'] ] ]; + if ( ! empty( $this->site_data['admin_tools'] ) ) { + $info[] = [ 'Access admin-tools', $prefix . $this->site_data['site_url'] . '/ee-admin/' ]; + } + + if ( ! empty( $this->site_data['db_host'] ) ) { + $info[] = [ 'DB Root Password', $this->site_data['db_root_password'] ]; + $info[] = [ 'DB Name', $this->site_data['db_name'] ]; + $info[] = [ 'DB User', $this->site_data['db_user'] ]; + $info[] = [ 'DB Password', $this->site_data['db_password'] ]; + } + + $info[] = [ 'E-Mail', '' ]; + $info[] = [ 'SSL', $ssl ]; + + if ( $this->site_data['site_ssl'] ) { + $info[] = [ 'SSL Wildcard', $this->site_data['site_ssl_wildcard'] ? 'Yes' : 'No' ]; + } + $info[] = [ 'Cache', $this->cache_type ? 'Enabled' : 'None' ]; + + \EE\Utils\format_table( $info ); + + \EE\Utils\delem_log( 'site info end' ); + } + + /** + * Function to configure site and copy all the required files. + */ + private function configure_site_files() { + + $site_conf_dir = $this->site_data['site_fs_path'] . '/config'; + $site_docker_yml = $this->site_data['site_fs_path'] . '/docker-compose.yml'; + $site_conf_env = $this->site_data['site_fs_path'] . '/.env'; + $site_nginx_default_conf = $site_conf_dir . '/nginx/default.conf'; + $site_php_ini = $site_conf_dir . '/php-fpm/php.ini'; + $site_src_dir = $this->site_data['site_fs_path'] . '/app/src'; + $server_name = $this->site_data['site_url']; + $process_user = posix_getpwuid( posix_geteuid() ); + + \EE::log( 'Creating PHP site ' . $this->site_data['site_url'] ); + \EE::log( 'Copying configuration files.' ); + + $filter = []; + $filter[] = $this->cache_type ? 'redis' : 'none'; + + $env_data = [ + 'virtual_host' => $this->site_data['site_url'], + 'user_id' => $process_user['uid'], + 'group_id' => $process_user['gid'], + ]; + + if ( ! empty( $this->site_data['db_host'] ) ) { + $filter[] = $this->site_data['db_host']; + $local = ( 'db' === $this->site_data['db_host'] ) ? true : false; + $db_host = $local ? $this->site_data['db_host'] : $this->site_data['db_host'] . ':' . $this->site_data['db_port']; + + $env_data['local'] = $local; + $env_data['root_password'] = $this->site_data['db_root_password']; + $env_data['database_name'] = $this->site_data['db_name']; + $env_data['database_user'] = $this->site_data['db_user']; + $env_data['user_password'] = $this->site_data['db_password']; + } + + $site_docker = new Site_PHP_Docker(); + $docker_compose_content = $site_docker->generate_docker_compose_yml( $filter ); + $default_conf_content = $this->generate_default_conf( $this->cache_type, $server_name ); + + + $php_ini_data = [ + // @todo: add email flag in create. + 'admin_email' => 'example@example.com', + ]; + + $env_content = \EE\Utils\mustache_render( SITE_PHP_TEMPLATE_ROOT . '/config/.env.mustache', $env_data ); + $php_ini_content = \EE\Utils\mustache_render( SITE_PHP_TEMPLATE_ROOT . '/config/php-fpm/php.ini.mustache', $php_ini_data ); + + try { + $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 ); + $this->fs->mkdir( $site_conf_dir . '/php-fpm' ); + $this->fs->dumpFile( $site_php_ini, $php_ini_content ); + + \EE\Site\Utils\set_postfix_files( $this->site_data['site_url'], $site_conf_dir ); + + $index_data = [ + 'version' => 'v' . EE_VERSION, + 'site_src_root' => $this->site_data['site_fs_path'] . '/app/src', + ]; + $index_html = \EE\Utils\mustache_render( SITE_PHP_TEMPLATE_ROOT . '/index.php.mustache', $index_data ); + $this->fs->mkdir( $site_src_dir ); + $this->fs->dumpFile( $site_src_dir . '/index.html', $index_html ); + + \EE::success( 'Configuration files copied.' ); + } catch ( \Exception $e ) { + $this->catch_clean( $e ); + } + } + + + /** + * Function to generate default.conf from mustache templates. + * + * @param boolean $cache_type Cache enabled or not. + * @param string $server_name Name of server to use in virtual_host. + * + * @return string Parsed mustache template string output. + */ + private function generate_default_conf( $cache_type, $server_name ) { + + $default_conf_data['server_name'] = $server_name; + $default_conf_data['include_php_conf'] = ! $cache_type; + $default_conf_data['include_redis_conf'] = $cache_type; + + return \EE\Utils\mustache_render( SITE_PHP_TEMPLATE_ROOT . '/config/nginx/default.conf.mustache', $default_conf_data ); + } + + private function maybe_verify_remote_db_connection() { + + if ( 'db' === $this->site_data['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->site_data['db_host'] === '127.0.0.1' || $this->site_data['db_host'] === 'localhost' ) { + $launch = \EE::exec( sprintf( "docker network inspect %s --format='{{ (index .IPAM.Config 0).Gateway }}'", $this->site_data['site_url'] ), false, true ); + + if ( ! $launch->return_code ) { + $this->site_data['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::exec( sprintf( "docker run -it --rm --network='%s' mysql sh -c \"mysql --host='%s' --port='%s' --user='%s' --password='%s' --execute='EXIT'\"", $this->site_data['site_url'], $this->site_data['db_host'], $this->site_data['db_port'], $this->site_data['db_user'], $this->site_data['db_password'] ) ) ) { + throw new \Exception( 'Unable to connect to remote db' ); + } + + \EE::success( 'Connection to remote db verified' ); + } + + /** + * Function to create the site. + */ + private function create_site( $assoc_args ) { + + $this->site_data['site_fs_path'] = WEBROOT . $this->site_data['site_url']; + $this->level = 1; + try { + \EE\Site\Utils\create_site_root( $this->site_data['site_fs_path'], $this->site_data['site_url'] ); + $this->level = 2; + + $containers = ['nginx', 'postfix']; + + if ( ! empty( $assoc_args['db'] ) ) { + $this->maybe_verify_remote_db_connection(); + $containers[]= 'db'; + } + $this->level = 3; + $this->configure_site_files(); + + \EE\Site\Utils\start_site_containers( $this->site_data['site_fs_path'], $containers ); + \EE\Site\Utils\configure_postfix( $this->site_data['site_url'], $this->site_data['site_fs_path'] ); + + \EE\Site\Utils\create_etc_hosts_entry( $this->site_data['site_url'] ); + if ( ! $this->skip_status_check ) { + $this->level = 4; + \EE\Site\Utils\site_status_check( $this->site_data['site_url'] ); + } + + \EE\Site\Utils\add_site_redirects( $this->site_data['site_url'], false, 'inherit' === $this->site_data['site_ssl'] ); + \EE\Site\Utils\reload_proxy_configuration(); + + if ( $this->site_data['site_ssl'] ) { + $wildcard = $this->site_data['site_ssl_wildcard']; + \EE::debug( 'Wildcard in site wp command: ' . $this->site_data['site_ssl_wildcard'] ); + $this->init_ssl( $this->site_data['site_url'], $this->site_data['site_fs_path'], $this->site_data['site_ssl'], $wildcard ); + + \EE\Site\Utils\add_site_redirects( $this->site_data['site_url'], true, 'inherit' === $this->site_data['site_ssl'] ); + \EE\Site\Utils\reload_proxy_configuration(); + } + } catch ( \Exception $e ) { + $this->catch_clean( $e ); + } + + $this->info( [ $this->site_data['site_url'] ], [] ); + $this->create_site_db_entry(); + } + + /** + * Function to save the site configuration entry into database. + */ + private function create_site_db_entry() { + $ssl = null; + + if ( $this->site_data['site_ssl'] ) { + $ssl = 'letsencrypt'; + } + + $data = [ + 'site_url' => $this->site_data['site_url'], + 'site_type' => $this->site_data['site_type'], + 'cache_nginx_browser' => (int) $this->cache_type, + 'cache_nginx_fullpage' => (int) $this->cache_type, + 'cache_mysql_query' => (int) $this->cache_type, + 'site_fs_path' => $this->site_data['site_fs_path'], + 'site_ssl' => $ssl, + 'site_ssl_wildcard' => $this->site_data['site_ssl_wildcard'] ? 1 : 0, + 'php_version' => '7.2', + 'created_on' => date( 'Y-m-d H:i:s', time() ), + ]; + + if ( ! empty( $this->site_data['db_host'] ) ) { + $data['db_name'] = $this->site_data['db_name']; + $data['db_user'] = $this->site_data['db_user']; + $data['db_host'] = $this->site_data['db_host']; + $data['db_port'] = isset( $this->site_data['db_port'] ) ? $this->site_data['db_port'] : ''; + $data['db_password'] = $this->site_data['db_password']; + $data['db_root_password'] = $this->site_data['db_root_password']; + } + + try { + if ( Site::create( $data ) ) { + \EE::log( 'Site entry created.' ); + } else { + throw new \Exception( 'Error creating site entry in database.' ); + } + } catch ( \Exception $e ) { + $this->catch_clean( $e ); + } + } + + /** + * Restarts containers associated with site. + * When no service(--nginx etc.) is specified, all site containers will be restarted. + * + * [] + * : Name of the site. + * + * [--all] + * : Restart all containers of site. + * + * [--nginx] + * : Restart nginx container of site. + * + * [--php] + * : Restart php container of site. + * + * [--db] + * : Restart db container of site. + */ + public function restart( $args, $assoc_args, $whitelisted_containers = [] ) { + $whitelisted_containers = [ 'nginx', 'php', 'db' ]; + parent::restart( $args, $assoc_args, $whitelisted_containers ); + } + + /** + * Reload services in containers without restarting container(s) associated with site. + * When no service(--nginx etc.) is specified, all services will be reloaded. + * + * [] + * : Name of the site. + * + * [--all] + * : Reload all services of site(which are supported). + * + * [--nginx] + * : Reload nginx service in container. + * + * [--php] + * : Reload php container of site. + */ + public function reload( $args, $assoc_args, $whitelisted_containers = [], $reload_commands = [] ) { + $whitelisted_containers = [ 'nginx', 'php' ]; + $reload_commands['php'] = 'kill -USR2 1'; + parent::reload( $args, $assoc_args, $whitelisted_containers, $reload_commands ); + } + + + /** + * Catch and clean exceptions. + * + * @param \Exception $e + */ + 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_data['site_url'], $this->site_data['site_fs_path'] ); + \EE\Utils\delem_log( 'site cleanup end' ); + exit; + } + + /** + * Roll back on interrupt. + */ + protected 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_data['site_url'], $this->site_data['site_fs_path'] ); + } + \EE::success( 'Rollback complete. Exiting now.' ); + exit; + } + +} diff --git a/src/Site_PHP_Docker.php b/src/Site_PHP_Docker.php new file mode 100644 index 0000000..df564a0 --- /dev/null +++ b/src/Site_PHP_Docker.php @@ -0,0 +1,190 @@ + Generates default WordPress docker-compose.yml + * ['le'] -> Enables letsencrypt in the generation. + * + * @return String docker-compose.yml content string. + */ + public function generate_docker_compose_yml( array $filters = [] ) { + $img_versions = \EE\Utils\get_image_versions(); + $base = []; + + $restart_default = [ 'name' => 'always' ]; + $network_default = [ + 'net' => [ + [ 'name' => 'site-network' ] + ] + ]; + + // db configuration. + $db['service_name'] = [ 'name' => 'db' ]; + $db['image'] = [ 'name' => 'easyengine/mariadb:' . $img_versions['easyengine/mariadb'] ]; + $db['restart'] = $restart_default; + $db['labels'] = [ + 'label' => [ + 'name' => 'io.easyengine.site=${VIRTUAL_HOST}', + ], + ]; + $db['volumes'] = [ + [ + 'vol' => [ + 'name' => './app/db:/var/lib/mysql', + ], + ], + ]; + $db['environment'] = [ + 'env' => [ + [ 'name' => 'MYSQL_ROOT_PASSWORD' ], + [ 'name' => 'MYSQL_DATABASE' ], + [ 'name' => 'MYSQL_USER' ], + [ 'name' => 'MYSQL_PASSWORD' ], + ], + ]; + $db['networks'] = $network_default; + // PHP configuration. + $php['service_name'] = [ 'name' => 'php' ]; + $php['image'] = [ 'name' => 'easyengine/php:' . $img_versions['easyengine/php'] ]; + $php['restart'] = $restart_default; + $php['labels'] = [ + 'label' => [ + 'name' => 'io.easyengine.site=${VIRTUAL_HOST}', + ], + ]; + $php['volumes'] = [ + [ + 'vol' => [ + [ 'name' => './app/src:/var/www/htdocs' ], + [ 'name' => './config/php-fpm/php.ini:/usr/local/etc/php/php.ini' ], + ], + ], + ]; + $php['environment'] = [ + 'env' => [ + [ 'name' => 'USER_ID' ], + [ 'name' => 'GROUP_ID' ], + [ 'name' => 'VIRTUAL_HOST' ], + ], + ]; + $php['networks'] = $network_default; + + // nginx configuration. + $nginx['service_name'] = [ 'name' => 'nginx' ]; + $nginx['image'] = [ 'name' => 'easyengine/nginx:' . $img_versions['easyengine/nginx'] ]; + $nginx['depends_on'] = [ 'name' => 'php' ]; + $nginx['restart'] = $restart_default; + + $v_host = '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'] = [ + 'net' => [ + [ 'name' => 'site-network' ], + [ 'name' => 'global-network' ], + ] + ]; + + // mailhog configuration. + $mailhog['service_name'] = [ 'name' => 'mailhog' ]; + $mailhog['image'] = [ 'name' => 'easyengine/mailhog:' . $img_versions['easyengine/mailhog'] ]; + $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'] = [ + 'net' => [ + [ 'name' => 'site-network' ], + [ 'name' => 'global-network' ], + ] + ]; + + // postfix configuration. + $postfix['service_name'] = [ 'name' => 'postfix' ]; + $postfix['image'] = [ 'name' => 'easyengine/postfix:' . $img_versions['easyengine/postfix'] ]; + $postfix['hostname'] = [ 'name' => '${VIRTUAL_HOST}' ]; + $postfix['restart'] = $restart_default; + $postfix['labels'] = [ + 'label' => [ + 'name' => 'io.easyengine.site=${VIRTUAL_HOST}', + ], + ]; + $postfix['volumes'] = [ + 'vol' => [ + [ 'name' => '/dev/log:/dev/log' ], + [ 'name' => './config/postfix/ssl:/etc/ssl/postfix' ], + [ 'name' => './app/postfix/spool:/var/spool/postfix' ], + ], + ]; + $postfix['networks'] = $network_default; + + + // redis configuration. + $redis['service_name'] = [ 'name' => 'redis' ]; + $redis['image'] = [ 'name' => 'easyengine/redis:' . $img_versions['easyengine/redis'] ]; + $redis['labels'] = [ + 'label' => [ + '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[] = $postfix; + + if ( in_array( 'redis', $filters, true ) ) { + $base[] = $redis; + } + + $binding = [ + 'services' => $base, + 'network' => true, + ]; + + $docker_compose_yml = mustache_render( SITE_WP_TEMPLATE_ROOT . '/docker-compose.mustache', $binding ); + + return $docker_compose_yml; + } +} diff --git a/templates/config/.env.mustache b/templates/config/.env.mustache new file mode 100644 index 0000000..76ffd9c --- /dev/null +++ b/templates/config/.env.mustache @@ -0,0 +1,10 @@ +{{#local}} +MYSQL_ROOT_PASSWORD={{root_password}} +MYSQL_DATABASE={{database_name}} +MYSQL_USER={{database_user}} +MYSQL_PASSWORD={{user_password}} +{{/local}} +VIRTUAL_HOST={{virtual_host}} +VIRTUAL_HOST_EMAIL=example@{{virtual_host}} +USER_ID={{user_id}} +GROUP_ID={{group_id}} diff --git a/templates/config/nginx/default.conf.mustache b/templates/config/nginx/default.conf.mustache new file mode 100644 index 0000000..54e6a58 --- /dev/null +++ b/templates/config/nginx/default.conf.mustache @@ -0,0 +1,144 @@ +# Add your custom config in custom.conf +# ALL CHANGES IN THIS FILE WILL BE LOST AFTER EasyEngine Update + +server { + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + + root /var/www/htdocs; + + 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; + } + # 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_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}} + + {{! locations.conf }} + # NGINX CONFIGURATION FOR COMMON LOCATION + # Basic locations files + location = /favicon.ico { + access_log off; + log_not_found off; + 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" "*"; + access_log off; + log_not_found off; + expires max; + } + # Security settings for better privacy + # Allow LetsEncrypt HTTP challenge URL + location ^~ /.well-known/acme-challenge/ { + auth_basic off; + allow all; + try_files $uri =404; + break; + } + # Deny hidden files + location ~ /\. { + deny all; + access_log off; + log_not_found off; + } + + # Deny backup extensions & log files + location ~* ^.+\.(bak|log|old|orig|original|php#|php~|php_bak|save|swo|swp|sql)$ { + deny all; + access_log off; + log_not_found off; + } + # Return 403 forbidden for readme.(txt|html) or license.(txt|html) or example.(txt|html) + if ($uri ~* "^.+(readme|license|example)\.(txt|html)$") { + return 403; + } + # Status pages + location /nginx_status { + 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"; + } + + {{! /locations.conf }} + + client_max_body_size 100m; +} diff --git a/templates/config/php-fpm/php.ini.mustache b/templates/config/php-fpm/php.ini.mustache new file mode 100644 index 0000000..73e1728 --- /dev/null +++ b/templates/config/php-fpm/php.ini.mustache @@ -0,0 +1,7 @@ +# Custom PHP settings + +upload_max_filesize = 100M +post_max_size = 100M + +[mail function] +sendmail_path = /usr/sbin/sendmail -t -i -f {{admin_email}} diff --git a/templates/docker-compose.mustache b/templates/docker-compose.mustache new file mode 100644 index 0000000..956a559 --- /dev/null +++ b/templates/docker-compose.mustache @@ -0,0 +1,59 @@ +version: '3.5' + +services: + +{{#services}} + {{#service_name}} + {{name}}: + {{/service_name}} + {{#image}} + image: {{name}} + {{/image}} + {{#hostname}} + hostname: {{name}} + {{/hostname}} + {{#depends_on}} + depends_on: + - {{name}} + {{/depends_on}} + {{#restart}} + restart: {{name}} + {{/restart}} + {{#command}} + command: {{name}} + {{/command}} + {{#labels}} + labels: + {{#label}} + - "{{name}}" + {{/label}} + {{/labels}} + {{#volumes}} + volumes: + {{#vol}} + - "{{name}}" + {{/vol}} + {{/volumes}} + {{#environment}} + environment: + {{#env}} + - {{name}} + {{/env}} + {{/environment}} + {{#networks}} + networks: + {{#net}} + - {{name}} + {{/net}} + {{/networks}} + +{{/services}} + +{{#network}} +networks: + site-network: + name: ${VIRTUAL_HOST} + global-network: + external: + name: ee-global-network +{{/network}} diff --git a/templates/index.php.mustache b/templates/index.php.mustache new file mode 100644 index 0000000..cd3f59a --- /dev/null +++ b/templates/index.php.mustache @@ -0,0 +1,3 @@ +

Congratulations! Your html site with EasyEngine is working perfectly.

+
+

You can copy your site files to {{site_src_root}}.

From 3b9f47fdb4d8ac5f264d3712d89717df2e002a89 Mon Sep 17 00:00:00 2001 From: sagar Date: Tue, 4 Sep 2018 22:25:08 +0530 Subject: [PATCH 02/11] Update composer.json --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index bb11c9d..9be2ec6 100644 --- a/composer.json +++ b/composer.json @@ -1,8 +1,8 @@ { - "name": "easyengine/site-wp-command", - "description": "EasyEngine package for WordPress site creation.", + "name": "easyengine/site-type-php", + "description": "EasyEngine package for PHP site creation.", "type": "ee-cli-package", - "homepage": "https://github.com/easyengine/site-wp-command", + "homepage": "https://github.com/easyengine/site-type-php", "license": "MIT", "authors": [], "minimum-stability": "dev", From 52e6431b5f6ae0a75fdf3c52c198fdaf3d40fbbf Mon Sep 17 00:00:00 2001 From: sagar Date: Wed, 5 Sep 2018 11:18:37 +0530 Subject: [PATCH 03/11] Fix phpcs in PHP.php --- src/PHP.php | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/PHP.php b/src/PHP.php index 20d5760..35b41ff 100644 --- a/src/PHP.php +++ b/src/PHP.php @@ -134,9 +134,9 @@ public function create( $args, $assoc_args ) { \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_data['site_url'] ) ); } - $this->cache_type = \EE\Utils\get_flag_value( $assoc_args, 'cache' ); - $this->site_data['site_ssl'] = \EE\Utils\get_flag_value( $assoc_args, 'ssl' ); - $this->site_data['site_ssl_wildcard'] = \EE\Utils\get_flag_value( $assoc_args, 'wildcard' ); + $this->cache_type = \EE\Utils\get_flag_value( $assoc_args, 'cache' ); + $this->site_data['site_ssl'] = \EE\Utils\get_flag_value( $assoc_args, 'ssl' ); + $this->site_data['site_ssl_wildcard'] = \EE\Utils\get_flag_value( $assoc_args, 'wildcard' ); if ( ! empty( $assoc_args['db'] ) ) { $this->site_data['db_name'] = str_replace( [ '.', '-' ], '_', $this->site_data['site_url'] ); @@ -157,9 +157,8 @@ public function create( $args, $assoc_args ) { } } - - $this->skip_status_check = \EE\Utils\get_flag_value( $assoc_args, 'skip-status-check' ); - $this->force = \EE\Utils\get_flag_value( $assoc_args, 'force' ); + $this->skip_status_check = \EE\Utils\get_flag_value( $assoc_args, 'skip-status-check' ); + $this->force = \EE\Utils\get_flag_value( $assoc_args, 'force' ); \EE\Site\Utils\init_checks(); @@ -242,13 +241,13 @@ private function configure_site_files() { \EE::log( 'Creating PHP site ' . $this->site_data['site_url'] ); \EE::log( 'Copying configuration files.' ); - $filter = []; - $filter[] = $this->cache_type ? 'redis' : 'none'; + $filter = []; + $filter[] = $this->cache_type ? 'redis' : 'none'; $env_data = [ - 'virtual_host' => $this->site_data['site_url'], - 'user_id' => $process_user['uid'], - 'group_id' => $process_user['gid'], + 'virtual_host' => $this->site_data['site_url'], + 'user_id' => $process_user['uid'], + 'group_id' => $process_user['gid'], ]; if ( ! empty( $this->site_data['db_host'] ) ) { @@ -267,7 +266,6 @@ private function configure_site_files() { $docker_compose_content = $site_docker->generate_docker_compose_yml( $filter ); $default_conf_content = $this->generate_default_conf( $this->cache_type, $server_name ); - $php_ini_data = [ // @todo: add email flag in create. 'admin_email' => 'example@example.com', @@ -312,9 +310,9 @@ private function configure_site_files() { */ private function generate_default_conf( $cache_type, $server_name ) { - $default_conf_data['server_name'] = $server_name; - $default_conf_data['include_php_conf'] = ! $cache_type; - $default_conf_data['include_redis_conf'] = $cache_type; + $default_conf_data['server_name'] = $server_name; + $default_conf_data['include_php_conf'] = ! $cache_type; + $default_conf_data['include_redis_conf'] = $cache_type; return \EE\Utils\mustache_render( SITE_PHP_TEMPLATE_ROOT . '/config/nginx/default.conf.mustache', $default_conf_data ); } @@ -328,7 +326,7 @@ private function maybe_verify_remote_db_connection() { // 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->site_data['db_host'] === '127.0.0.1' || $this->site_data['db_host'] === 'localhost' ) { + if ( '127.0.0.1' === $this->site_data['db_host'] || 'localhost' === $this->site_data['db_host'] ) { $launch = \EE::exec( sprintf( "docker network inspect %s --format='{{ (index .IPAM.Config 0).Gateway }}'", $this->site_data['site_url'] ), false, true ); if ( ! $launch->return_code ) { @@ -357,11 +355,11 @@ private function create_site( $assoc_args ) { \EE\Site\Utils\create_site_root( $this->site_data['site_fs_path'], $this->site_data['site_url'] ); $this->level = 2; - $containers = ['nginx', 'postfix']; + $containers = [ 'nginx', 'postfix' ]; if ( ! empty( $assoc_args['db'] ) ) { $this->maybe_verify_remote_db_connection(); - $containers[]= 'db'; + $containers[] = 'db'; } $this->level = 3; $this->configure_site_files(); From bcd449a729d5edb7a1bf4c1f1bc74afbdde24674 Mon Sep 17 00:00:00 2001 From: sagar Date: Wed, 5 Sep 2018 11:37:08 +0530 Subject: [PATCH 04/11] Remove admin email flag --- src/PHP.php | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/PHP.php b/src/PHP.php index 35b41ff..7b3b28a 100644 --- a/src/PHP.php +++ b/src/PHP.php @@ -83,9 +83,6 @@ public function __construct() { * [--cache] * : Use redis cache for PHP. * - * [--admin-email=] - * : E-Mail of the administrator. - * * [--db] * : Create database for php site. * @@ -211,7 +208,6 @@ public function info( $args, $assoc_args ) { $info[] = [ 'DB Password', $this->site_data['db_password'] ]; } - $info[] = [ 'E-Mail', '' ]; $info[] = [ 'SSL', $ssl ]; if ( $this->site_data['site_ssl'] ) { @@ -266,10 +262,7 @@ private function configure_site_files() { $docker_compose_content = $site_docker->generate_docker_compose_yml( $filter ); $default_conf_content = $this->generate_default_conf( $this->cache_type, $server_name ); - $php_ini_data = [ - // @todo: add email flag in create. - 'admin_email' => 'example@example.com', - ]; + $php_ini_data = []; $env_content = \EE\Utils\mustache_render( SITE_PHP_TEMPLATE_ROOT . '/config/.env.mustache', $env_data ); $php_ini_content = \EE\Utils\mustache_render( SITE_PHP_TEMPLATE_ROOT . '/config/php-fpm/php.ini.mustache', $php_ini_data ); @@ -291,7 +284,7 @@ private function configure_site_files() { ]; $index_html = \EE\Utils\mustache_render( SITE_PHP_TEMPLATE_ROOT . '/index.php.mustache', $index_data ); $this->fs->mkdir( $site_src_dir ); - $this->fs->dumpFile( $site_src_dir . '/index.html', $index_html ); + $this->fs->dumpFile( $site_src_dir . '/index.php', $index_html ); \EE::success( 'Configuration files copied.' ); } catch ( \Exception $e ) { From 9defd607e9d51eb63b1dbc3f5ae9916137419e79 Mon Sep 17 00:00:00 2001 From: Mriyam Tamuli Date: Wed, 5 Sep 2018 12:50:50 +0530 Subject: [PATCH 05/11] Add composer.json Signed-off-by: Mriyam Tamuli --- composer.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 composer.json diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..9be2ec6 --- /dev/null +++ b/composer.json @@ -0,0 +1,24 @@ +{ + "name": "easyengine/site-type-php", + "description": "EasyEngine package for PHP site creation.", + "type": "ee-cli-package", + "homepage": "https://github.com/easyengine/site-type-php", + "license": "MIT", + "authors": [], + "minimum-stability": "dev", + "prefer-stable": true, + "autoload": { + "psr-4": { + "": "src/" + } + }, + "require-dev": { + "wp-cli/mustangostang-spyc": "^0.6.3" + }, + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + }, + "bundled": true + } +} From 25b242bb73aaccbeb39002ec33bb443c9c9f5599 Mon Sep 17 00:00:00 2001 From: sagar Date: Wed, 5 Sep 2018 13:03:48 +0530 Subject: [PATCH 06/11] Remove tests and add check for db in Site_PHP_Docker.php --- .travis.yml | 41 --- ci/add-test-certs.sh | 106 ------- ci/prepare.sh | 32 -- features/bootstrap/FeatureContext.php | 426 -------------------------- features/bootstrap/support.php | 207 ------------- features/labels.feature | 9 - features/redirect.feature | 17 - features/site.feature | 77 ----- src/PHP.php | 23 +- src/Site_PHP_Docker.php | 5 + templates/index.php.mustache | 2 +- 11 files changed, 21 insertions(+), 924 deletions(-) delete mode 100644 .travis.yml delete mode 100755 ci/add-test-certs.sh delete mode 100755 ci/prepare.sh delete mode 100644 features/bootstrap/FeatureContext.php delete mode 100644 features/bootstrap/support.php delete mode 100644 features/labels.feature delete mode 100644 features/redirect.feature delete mode 100644 features/site.feature diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e944a4e..0000000 --- a/.travis.yml +++ /dev/null @@ -1,41 +0,0 @@ -sudo: required - -language: php -php: 7.0 - -env: - global: - - TEST_COMMAND=$(echo $TRAVIS_REPO_SLUG | cut -d/ -f 2) # Get command name to be tested - -before_script: - - sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose - - | - # Remove Xdebug for a huge performance increase: - if [ -f ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini ]; then - phpenv config-rm xdebug.ini - else - echo "xdebug.ini does not exist" - fi - - ./ci/prepare.sh - - ./ci/add-test-certs.sh - -script: - - cd "$TRAVIS_BUILD_DIR/../easyengine" - - sudo ./vendor/bin/behat - -after_script: - - cat /opt/easyengine/ee.log - -cache: - directories: - - $HOME/.composer/cache - -notifications: - email: - on_success: never - on_failure: change - -addons: - apt: - packages: - - docker-ce diff --git a/ci/add-test-certs.sh b/ci/add-test-certs.sh deleted file mode 100755 index 54c4bd0..0000000 --- a/ci/add-test-certs.sh +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env bash -sudo mkdir -p /opt/easyengine/nginx/certs - -cat < /dev/null -sudo php easyengine.phar cli info \ No newline at end of file diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php deleted file mode 100644 index b955316..0000000 --- a/features/bootstrap/FeatureContext.php +++ /dev/null @@ -1,426 +0,0 @@ -init_logger(); -/* End. Loading required files to enable EE::launch() in tests. */ - -use Behat\Behat\Context\Context; -use Behat\Behat\Hook\Scope\AfterFeatureScope; -use Behat\Behat\Hook\Scope\AfterScenarioScope; - -use Behat\Gherkin\Node\PyStringNode, - Behat\Gherkin\Node\TableNode; - -define( 'EE_SITE_ROOT', getenv('HOME') . '/ee-sites/' ); - -class FeatureContext implements Context -{ - public $command; - public $webroot_path; - public $ee_path; - - /** - * Initializes context. - */ - public function __construct() - { - $this->commands = []; - $this->ee_path = getcwd(); - $config_contents = \Mustangostang\Spyc::YAMLDump(['le-mail' => 'abc@example.com']); - file_put_contents( EE_CONF_ROOT . '/config.yml', $config_contents ); - } - - /** - * @Given ee phar is generated - */ - public function eePharIsPresent() - { - // Checks if phar already exists, replaces it - if(file_exists('ee-old.phar')) { - // Below exec call is required as currenly `ee cli update` is ran with root - // which updates ee.phar with root privileges. - exec("sudo rm ee.phar"); - copy('ee-old.phar','ee.phar'); - return 0; - } - exec("php -dphar.readonly=0 utils/make-phar.php ee.phar", $output, $return_status); - if (0 !== $return_status) { - throw new Exception("Unable to generate phar" . $return_status); - } - - // Cache generaed phar as it is expensive to generate one - copy('ee.phar','ee-old.phar'); - } - - /** - * @Given :command is installed - */ - public function isInstalled($command) - { - exec("type " . $command, $output, $return_status); - if (0 !== $return_status) { - throw new Exception($command . " is not installed! Exit code is:" . $return_status); - } - } - - /** - * @When I run :command - */ - public function iRun($command) - { - $this->commands[] = EE::launch($command, false, true); - } - - /** - * @When I create subsite :subsite in :site - */ - public function iCreateSubsiteInOfType($subsite, $site ) - { - $php_container = implode( explode( '.', $subsite ) ) . '_php_1'; - - EE::launch( "docker exec -it --user='www-data' $php_container sh -c 'wp site create --slug=$site'", false, true ); - } - - /** - * @Then return value should be 0 - */ - public function returnValueShouldBe0() - { - if ( 0 !== $this->commands[0]->return_code ) { - throw new Exception("Actual return code is not zero: \n" . $this->command); - } - } - - /** - * @Then return value of command :index should be 0 - */ - public function returnValueOfCommandShouldBe0($index) - { - if ( 0 !== $this->commands[ $index - 1 ]->return_code ) { - throw new Exception("Actual return code is not zero: \n" . $this->command); - } - } - - /** - * @Then After delay of :time seconds - */ - public function afterDelayOfSeconds( $time ) - { - sleep( $time ); - } - - /** - * @Then /(STDOUT|STDERR) should return exactly/ - */ - public function stdoutShouldReturnExactly($output_stream, PyStringNode $expected_output) - { - $command_output = $output_stream === "STDOUT" ? $this->commands[0]->stdout : $this->commands[0]->stderr; - - $command_output = str_replace(["\033[1;31m","\033[0m"],'',$command_output); - - if ( $expected_output->getRaw() !== trim($command_output)) { - throw new Exception("Actual output is:\n" . $command_output); - } - } - - /** - * @Then /(STDOUT|STDERR) of command :index should return exactly/ - */ - public function stdoutOfCommandShouldReturnExactly($output_stream, $index, PyStringNode $expected_output) - { - $command_output = $output_stream === "STDOUT" ? $this->commands[ $index - 1 ]->stdout : $this->commands[ $index - 1 ]->stderr; - - $command_output = str_replace(["\033[1;31m","\033[0m"],'',$command_output); - - $expected_out = isset($expected_output->getStrings()[0]) ? $expected_output->getStrings()[0] : ''; - if ( $expected_out !== trim($command_output)) { - throw new Exception("Actual output is:\n" . $command_output); - } - } - - /** - * @Then /(STDOUT|STDERR) should return something like/ - */ - public function stdoutShouldReturnSomethingLike($output_stream, PyStringNode $expected_output) - { - $command_output = $output_stream === "STDOUT" ? $this->commands[0]->stdout : $this->commands[0]->stderr; - - $expected_out = isset($expected_output->getStrings()[0]) ? $expected_output->getStrings()[0] : ''; - if (strpos($command_output, $expected_out) === false) { - throw new Exception("Actual output is:\n" . $command_output); - } - } - - - /** - * @Then /(STDOUT|STDERR) of command :index should return something like/ - */ - public function stdoutOfCommandShouldReturnSomethingLike($output_stream, $index, PyStringNode $expected_output) - { - $command_output = $output_stream === "STDOUT" ? $this->commands[ $index - 1 ]->stdout : $this->commands[ $index - 1 ]->stderr; - - $expected_out = isset($expected_output->getStrings()[0]) ? $expected_output->getStrings()[0] : ''; - if (strpos($command_output, $expected_out) === false) { - throw new Exception("Actual output is:\n" . $command_output); - } - } - - /** - * @Then The site :site should be :type multisite - */ - public function theSiteShouldBeMultisite( $site, $type ) - { - $result = EE::launch("cd " . EE_SITE_ROOT . "$site && docker-compose exec --user='www-data' php sh -c 'wp config get SUBDOMAIN_INSTALL'", false, true ); - - if( $result->stderr ) { - throw new Exception("Found error while executing command: $result->stderr"); - } - - if($type === 'subdomain' && trim($result->stdout) !== '1') { - throw new Exception("Expecting SUBDOMAIN_INSTALL to be 1. Got: $result->stdout"); - } - else if($type === 'subdir' && trim($result->stdout) !== '') { - throw new Exception("Expecting SUBDOMAIN_INSTALL to be empty. Got: $result->stdout"); - } - else if($type !== 'subdomain' && $type !== 'subdir') { - throw new Exception("Found unknown site type: $type"); - } - } - - /** - * @Then The :site db entry should be removed - */ - public function theDbEntryShouldBeRemoved($site) - { - $out = shell_exec("sudo bin/ee site list"); - if (strpos($out, $site) !== false) { - throw new Exception("$site db entry not been removed!"); - } - - } - - /** - * @Then The :site webroot should be removed - */ - public function theWebrootShouldBeRemoved($site) - { - if (file_exists(EE_SITE_ROOT . $site)) { - throw new Exception("Webroot has not been removed!"); - } - } - - /** - * @Then Following containers of site :site should be removed: - */ - public function followingContainersOfSiteShouldBeRemoved($site, TableNode $table) - { - $containers = $table->getHash(); - $site_name = implode(explode('.', $site)); - - foreach ($containers as $container) { - - $sevice = $container['container']; - $container_name = $site_name . '_' . $sevice . '_1'; - - exec("docker inspect -f '{{.State.Running}}' $container_name > /dev/null 2>&1", $exec_out, $return); - if (!$return) { - throw new Exception("$container_name has not been removed!"); - } - } - } - - /** - * @Then The site :site should have webroot - */ - public function theSiteShouldHaveWebroot($site) - { - if (!file_exists(EE_SITE_ROOT . $site)) { - throw new Exception("Webroot has not been created!"); - } - } - - /** - * @Then The site :site should have WordPress - */ - public function theSiteShouldHaveWordpress($site) - { - if (!file_exists(EE_SITE_ROOT . $site . "/app/src/wp-config.php")) { - throw new Exception("WordPress data not found!"); - } - } - - /** - * @Then Request on :site should contain following headers: - */ - public function requestOnShouldContainFollowingHeaders($site, TableNode $table) - { - $url = 'http://' . $site; - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_HEADER, true); - curl_setopt($ch, CURLOPT_NOBODY, true); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_VERBOSE, true); - $headers = curl_exec($ch); - - curl_close($ch); - - $rows = $table->getHash(); - - foreach ($rows as $row) { - if (strpos($headers, $row['header']) === false) { - throw new Exception("Unable to find " . $row['header'] . "\nActual output is : " . $headers); - } - } - } - - /** - * @Then Request on :host with header :header should contain following headers: - */ - public function requestOnWithHeaderShouldContainFollowingHeaders($host, $header, TableNode $table) - { - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $host); - curl_setopt($ch, CURLOPT_HEADER, true); - curl_setopt($ch, CURLOPT_HTTPHEADER, [ $header ]); - curl_setopt($ch, CURLOPT_NOBODY, true); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_VERBOSE, true); - $headers = curl_exec($ch); - - curl_close($ch); - - $rows = $table->getHash(); - - foreach ($rows as $row) { - if (strpos($headers, $row['header']) === false) { - throw new Exception("Unable to find " . $row['header'] . "\nActual output is : " . $headers); - } - } - } - - /** - * @Then Request on :host with resolve option :resolve should contain following headers: - */ - public function requestOnWithResolveOptionShouldContainFollowingHeaders($host, $resolve, TableNode $table) - { - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $host); - curl_setopt($ch, CURLOPT_HEADER, true); - curl_setopt($ch, CURLOPT_NOBODY, true); - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); - curl_setopt($ch, CURLOPT_RESOLVE, [ $resolve ]); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_VERBOSE, true); - $headers = curl_exec($ch); - curl_close($ch); - - $rows = $table->getHash(); - - foreach ($rows as $row) { - if (strpos($headers, $row['header']) === false) { - throw new Exception("Unable to find " . $row['header'] . "\nActual output is : " . $headers); - } - } - } - - /** - * @AfterScenario - */ - public function cleanupScenario(AfterScenarioScope $scope) - { - $this->commands = []; - chdir($this->ee_path); - } - - /** - * @Then There should be :expected_running_containers containers with labels - */ - public function thereShouldBeContainersWithLabel($expected_running_containers, PyStringNode $pyStringNode) - { - $labels = $pyStringNode->getStrings(); - $label_string = implode($labels, ' -f label='); - - $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) { - throw new Exception("Expected $expected_running_containers running containers. Found: $running_containers"); - } - } - - /** - * @AfterFeature - */ - public static function cleanup(AfterFeatureScope $scope) - { - $test_sites = [ - 'wp.test', - 'wpsubdom.test', - 'wpsubdir.test', - 'example.test', - 'www.example1.test', - 'example2.test', - 'www.example3.test', - 'labels.test' - ]; - - $result = EE::launch( 'sudo bin/ee site list --format=text',false, true ); - $running_sites = explode( "\n", $result->stdout ); - $sites_to_delete = array_intersect( $test_sites, $running_sites ); - - foreach ( $sites_to_delete as $site ) { - exec("sudo bin/ee site delete $site --yes" ); - } - - if(file_exists('ee.phar')) { - unlink('ee.phar'); - } - if(file_exists('ee-old.phar')) { - unlink('ee-old.phar'); - } - } -} diff --git a/features/bootstrap/support.php b/features/bootstrap/support.php deleted file mode 100644 index ed9a5b5..0000000 --- a/features/bootstrap/support.php +++ /dev/null @@ -1,207 +0,0 @@ - $value ) { - if ( ! compareContents( $value, $actual->$name ) ) { - return false; - } - } - } else if ( is_array( $expected ) ) { - foreach ( $expected as $key => $value ) { - if ( ! compareContents( $value, $actual[$key] ) ) { - return false; - } - } - } else { - return $expected === $actual; - } - - return true; -} - -/** - * Compare two strings containing JSON to ensure that @a $actualJson contains at - * least what the JSON string @a $expectedJson contains. - * - * @return whether or not @a $actualJson contains @a $expectedJson - * @retval true @a $actualJson contains @a $expectedJson - * @retval false @a $actualJson does not contain @a $expectedJson - * - * @param [in] $actualJson the JSON string to be tested - * @param [in] $expectedJson the expected JSON string - * - * Examples: - * expected: {'a':1,'array':[1,3,5]} - * - * 1 ) - * actual: {'a':1,'b':2,'c':3,'array':[1,2,3,4,5]} - * return: true - * - * 2 ) - * actual: {'b':2,'c':3,'array':[1,2,3,4,5]} - * return: false - * element 'a' is missing from the root object - * - * 3 ) - * actual: {'a':0,'b':2,'c':3,'array':[1,2,3,4,5]} - * return: false - * the value of element 'a' is not 1 - * - * 4 ) - * actual: {'a':1,'b':2,'c':3,'array':[1,2,4,5]} - * return: false - * the contents of 'array' does not include 3 - */ -function checkThatJsonStringContainsJsonString( $actualJson, $expectedJson ) { - $actualValue = json_decode( $actualJson ); - $expectedValue = json_decode( $expectedJson ); - - if ( ! $actualValue ) { - return false; - } - - return compareContents( $expectedValue, $actualValue ); -} - -/** - * Compare two strings to confirm $actualCSV contains $expectedCSV - * Both strings are expected to have headers for their CSVs. - * $actualCSV must match all data rows in $expectedCSV - * - * @param string A CSV string - * @param array A nested array of values - * - * @return bool Whether $actualCSV contains $expectedCSV - */ -function checkThatCsvStringContainsValues( $actualCSV, $expectedCSV ) { - $actualCSV = array_map( 'str_getcsv', explode( PHP_EOL, $actualCSV ) ); - - if ( empty( $actualCSV ) ) { - return false; - } - - // Each sample must have headers - $actualHeaders = array_values( array_shift( $actualCSV ) ); - $expectedHeaders = array_values( array_shift( $expectedCSV ) ); - - // Each expectedCSV must exist somewhere in actualCSV in the proper column - $expectedResult = 0; - foreach ( $expectedCSV as $expected_row ) { - $expected_row = array_combine( $expectedHeaders, $expected_row ); - foreach ( $actualCSV as $actual_row ) { - - if ( count( $actualHeaders ) != count( $actual_row ) ) { - continue; - } - - $actual_row = array_intersect_key( array_combine( $actualHeaders, $actual_row ), $expected_row ); - if ( $actual_row == $expected_row ) { - $expectedResult ++; - } - } - } - - return $expectedResult >= count( $expectedCSV ); -} - -/** - * Compare two strings containing YAML to ensure that @a $actualYaml contains at - * least what the YAML string @a $expectedYaml contains. - * - * @return whether or not @a $actualYaml contains @a $expectedJson - * @retval true @a $actualYaml contains @a $expectedJson - * @retval false @a $actualYaml does not contain @a $expectedJson - * - * @param [in] $actualYaml the YAML string to be tested - * @param [in] $expectedYaml the expected YAML string - */ -function checkThatYamlStringContainsYamlString( $actualYaml, $expectedYaml ) { - $actualValue = Mustangostang\Spyc::YAMLLoad( $actualYaml ); - $expectedValue = Mustangostang\Spyc::YAMLLoad( $expectedYaml ); - - if ( ! $actualValue ) { - return false; - } - - return compareContents( $expectedValue, $actualValue ); -} - diff --git a/features/labels.feature b/features/labels.feature deleted file mode 100644 index f4cacf9..0000000 --- a/features/labels.feature +++ /dev/null @@ -1,9 +0,0 @@ -Feature: Container Labels - - - Scenario: All easyengine containers are tagged - Given I run "bin/ee site create labels.test --type=wp" - Then There should be 5 containers with labels - """ - io.easyengine.site=labels.test - """ diff --git a/features/redirect.feature b/features/redirect.feature deleted file mode 100644 index 6353505..0000000 --- a/features/redirect.feature +++ /dev/null @@ -1,17 +0,0 @@ -Feature: Site Redirection - - Scenario: no_www-no_ssl redirection works properly - When I run 'bin/ee site create example.test --type=wp' - Then After delay of 5 seconds - And 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 'bin/ee site create www.example1.test --type=wp' - Then After delay of 5 seconds - And Request on 'localhost' with header 'Host: example1.test' should contain following headers: - | header | - | HTTP/1.1 301 Moved Permanently | - | Location: http://www.example1.test/ | diff --git a/features/site.feature b/features/site.feature deleted file mode 100644 index b81e413..0000000 --- a/features/site.feature +++ /dev/null @@ -1,77 +0,0 @@ -Feature: Site Command - - Scenario: ee executable is command working correctly - Given 'bin/ee' is installed - When I run 'bin/ee' - Then STDOUT should return something like - """ - NAME - - ee - """ - - Scenario: Check site command is present - When I run 'bin/ee site' - Then STDOUT should return something like - """ - usage: ee site - """ - - Scenario: Create wp site successfully - When I run 'bin/ee site create wp.test --type=wp' - Then After delay of 5 seconds - And 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 'bin/ee site create wpsubdir.test --type=wp --mu=subdir' - And I create subsite '1' in 'wpsubdir.test' - Then After delay of 5 seconds - And 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 'bin/ee site create wpsubdom.test --type=wp --mu=subdom' - And I create subsite '1' in 'wpsubdom.test' - Then After delay of 5 seconds - And 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: - | header | - | HTTP/1.1 200 OK | - - Scenario: List the sites - When I run 'bin/ee site list --format=text' - Then STDOUT should return exactly - """ - wp.test - wpsubdir.test - wpsubdom.test - """ - - Scenario: Delete the sites - When I run 'bin/ee site delete wp.test --yes' - Then STDOUT should return something like - """ - Site wp.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: - | container | - | nginx | - | php | - | db | - | redis | - | phpmyadmin | diff --git a/src/PHP.php b/src/PHP.php index 7b3b28a..263234f 100644 --- a/src/PHP.php +++ b/src/PHP.php @@ -15,7 +15,7 @@ * ## EXAMPLES * * # Create simple PHP site - * $ ee site create example.com --wp + * $ ee site create example.com --type=php * * @package ee-cli */ @@ -83,7 +83,10 @@ public function __construct() { * [--cache] * : Use redis cache for PHP. * - * [--db] + * [--admin-email=] + * : E-Mail of the administrator. + * + * [--with-db] * : Create database for php site. * * [--dbname=] @@ -135,9 +138,9 @@ public function create( $args, $assoc_args ) { $this->site_data['site_ssl'] = \EE\Utils\get_flag_value( $assoc_args, 'ssl' ); $this->site_data['site_ssl_wildcard'] = \EE\Utils\get_flag_value( $assoc_args, 'wildcard' ); - if ( ! empty( $assoc_args['db'] ) ) { + if ( ! empty( $assoc_args['with-db'] ) ) { $this->site_data['db_name'] = str_replace( [ '.', '-' ], '_', $this->site_data['site_url'] ); - $this->site_data['db_host'] = \EE\Utils\get_flag_value( $assoc_args, 'dbhost' ); + $this->site_data['db_host'] = \EE\Utils\get_flag_value( $assoc_args, 'dbhost', 'db' ); $this->site_data['db_port'] = '3306'; $this->site_data['db_user'] = \EE\Utils\get_flag_value( $assoc_args, 'dbuser', $this->create_site_db_user( $this->site_data['site_url'] ) ); $this->site_data['db_password'] = \EE\Utils\get_flag_value( $assoc_args, 'dbpass', \EE\Utils\random_password() ); @@ -153,7 +156,7 @@ public function create( $args, $assoc_args ) { $this->site_data['db_port'] = empty( $arg_host_port[1] ) ? '3306' : $arg_host_port[1]; } } - + $this->site_data['app_admin_email'] = \EE\Utils\get_flag_value( $assoc_args, 'admin_email', strtolower( 'admin@' . $this->site_data['site_url'] ) ); $this->skip_status_check = \EE\Utils\get_flag_value( $assoc_args, 'skip-status-check' ); $this->force = \EE\Utils\get_flag_value( $assoc_args, 'force' ); @@ -208,6 +211,7 @@ public function info( $args, $assoc_args ) { $info[] = [ 'DB Password', $this->site_data['db_password'] ]; } + $info[] = [ 'E-Mail', $this->site_data['app_admin_email'] ]; $info[] = [ 'SSL', $ssl ]; if ( $this->site_data['site_ssl'] ) { @@ -262,7 +266,9 @@ private function configure_site_files() { $docker_compose_content = $site_docker->generate_docker_compose_yml( $filter ); $default_conf_content = $this->generate_default_conf( $this->cache_type, $server_name ); - $php_ini_data = []; + $php_ini_data = [ + 'admin_email' => $this->site_data['app_admin_email'], + ]; $env_content = \EE\Utils\mustache_render( SITE_PHP_TEMPLATE_ROOT . '/config/.env.mustache', $env_data ); $php_ini_content = \EE\Utils\mustache_render( SITE_PHP_TEMPLATE_ROOT . '/config/php-fpm/php.ini.mustache', $php_ini_data ); @@ -350,7 +356,7 @@ private function create_site( $assoc_args ) { $containers = [ 'nginx', 'postfix' ]; - if ( ! empty( $assoc_args['db'] ) ) { + if ( ! empty( $assoc_args['with-db'] ) && 'db' === $this->site_data['db_host'] ) { $this->maybe_verify_remote_db_connection(); $containers[] = 'db'; } @@ -371,7 +377,7 @@ private function create_site( $assoc_args ) { if ( $this->site_data['site_ssl'] ) { $wildcard = $this->site_data['site_ssl_wildcard']; - \EE::debug( 'Wildcard in site wp command: ' . $this->site_data['site_ssl_wildcard'] ); + \EE::debug( 'Wildcard in site php command: ' . $this->site_data['site_ssl_wildcard'] ); $this->init_ssl( $this->site_data['site_url'], $this->site_data['site_fs_path'], $this->site_data['site_ssl'], $wildcard ); \EE\Site\Utils\add_site_redirects( $this->site_data['site_url'], true, 'inherit' === $this->site_data['site_ssl'] ); @@ -398,6 +404,7 @@ private function create_site_db_entry() { $data = [ 'site_url' => $this->site_data['site_url'], 'site_type' => $this->site_data['site_type'], + 'app_admin_email' => $this->site_data['app_admin_email'], 'cache_nginx_browser' => (int) $this->cache_type, 'cache_nginx_fullpage' => (int) $this->cache_type, 'cache_mysql_query' => (int) $this->cache_type, diff --git a/src/Site_PHP_Docker.php b/src/Site_PHP_Docker.php index df564a0..1216814 100644 --- a/src/Site_PHP_Docker.php +++ b/src/Site_PHP_Docker.php @@ -53,6 +53,11 @@ public function generate_docker_compose_yml( array $filters = [] ) { // PHP configuration. $php['service_name'] = [ 'name' => 'php' ]; $php['image'] = [ 'name' => 'easyengine/php:' . $img_versions['easyengine/php'] ]; + + if ( in_array( 'db', $filters, true ) ) { + $php['depends_on'] = [ 'name' => 'db' ]; + } + $php['restart'] = $restart_default; $php['labels'] = [ 'label' => [ diff --git a/templates/index.php.mustache b/templates/index.php.mustache index cd3f59a..11327b4 100644 --- a/templates/index.php.mustache +++ b/templates/index.php.mustache @@ -1,3 +1,3 @@ -

Congratulations! Your html site with EasyEngine is working perfectly.

+

Congratulations! Your PHP site with EasyEngine is working perfectly.


You can copy your site files to {{site_src_root}}.

From eacfae8808e4b0404f673a71091377cf0350013b Mon Sep 17 00:00:00 2001 From: sagar Date: Wed, 5 Sep 2018 13:07:04 +0530 Subject: [PATCH 07/11] Remove testing includes --- site-type-php.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/site-type-php.php b/site-type-php.php index 3dd1fe2..4dfae41 100644 --- a/site-type-php.php +++ b/site-type-php.php @@ -13,7 +13,4 @@ require_once $autoload; } -include_once __DIR__ . '/src/Site_PHP_Docker.php'; -include_once __DIR__ . '/src/PHP.php'; - Site_Command::add_site_type( 'php', 'EE\Site\Type\PHP' ); From 523cebbb04115fd8be07e2ea91823f3097225c19 Mon Sep 17 00:00:00 2001 From: sagar Date: Wed, 5 Sep 2018 13:30:05 +0530 Subject: [PATCH 08/11] Add db check on restart --- src/PHP.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/PHP.php b/src/PHP.php index 263234f..22ab09f 100644 --- a/src/PHP.php +++ b/src/PHP.php @@ -157,8 +157,8 @@ public function create( $args, $assoc_args ) { } } $this->site_data['app_admin_email'] = \EE\Utils\get_flag_value( $assoc_args, 'admin_email', strtolower( 'admin@' . $this->site_data['site_url'] ) ); - $this->skip_status_check = \EE\Utils\get_flag_value( $assoc_args, 'skip-status-check' ); - $this->force = \EE\Utils\get_flag_value( $assoc_args, 'force' ); + $this->skip_status_check = \EE\Utils\get_flag_value( $assoc_args, 'skip-status-check' ); + $this->force = \EE\Utils\get_flag_value( $assoc_args, 'force' ); \EE\Site\Utils\init_checks(); @@ -455,7 +455,15 @@ private function create_site_db_entry() { * : Restart db container of site. */ public function restart( $args, $assoc_args, $whitelisted_containers = [] ) { - $whitelisted_containers = [ 'nginx', 'php', 'db' ]; + + $args = auto_site_name( $args, 'php', __FUNCTION__ ); + $this->site_data = get_site_info( $args, false ); + + $whitelisted_containers = [ 'nginx', 'php' ]; + + if ( ! empty( $this->site_data['db_host'] ) ) { + $whitelisted_containers[] = 'db'; + } parent::restart( $args, $assoc_args, $whitelisted_containers ); } From 9e9b17caadb51acf6d86ab3a96a79a78cca3ae48 Mon Sep 17 00:00:00 2001 From: sagar Date: Wed, 5 Sep 2018 16:04:24 +0530 Subject: [PATCH 09/11] Use app_sub_type instead of db_host for db checks --- .gitignore | 2 +- src/PHP.php | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 92b69bc..40dc619 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ .DS_Store -wp-cli.local.yml +ee-cli.local.yml node_modules/ vendor/ *.zip diff --git a/src/PHP.php b/src/PHP.php index 22ab09f..05ef33e 100644 --- a/src/PHP.php +++ b/src/PHP.php @@ -137,8 +137,10 @@ public function create( $args, $assoc_args ) { $this->cache_type = \EE\Utils\get_flag_value( $assoc_args, 'cache' ); $this->site_data['site_ssl'] = \EE\Utils\get_flag_value( $assoc_args, 'ssl' ); $this->site_data['site_ssl_wildcard'] = \EE\Utils\get_flag_value( $assoc_args, 'wildcard' ); + $this->site_data['app_sub_type'] = 'php'; if ( ! empty( $assoc_args['with-db'] ) ) { + $this->site_data['app_sub_type'] = 'mysql'; $this->site_data['db_name'] = str_replace( [ '.', '-' ], '_', $this->site_data['site_url'] ); $this->site_data['db_host'] = \EE\Utils\get_flag_value( $assoc_args, 'dbhost', 'db' ); $this->site_data['db_port'] = '3306'; @@ -204,7 +206,7 @@ public function info( $args, $assoc_args ) { $info[] = [ 'Access admin-tools', $prefix . $this->site_data['site_url'] . '/ee-admin/' ]; } - if ( ! empty( $this->site_data['db_host'] ) ) { + if ( 'mysql' === $this->site_data['app_sub_type'] ) { $info[] = [ 'DB Root Password', $this->site_data['db_root_password'] ]; $info[] = [ 'DB Name', $this->site_data['db_name'] ]; $info[] = [ 'DB User', $this->site_data['db_user'] ]; @@ -250,7 +252,7 @@ private function configure_site_files() { 'group_id' => $process_user['gid'], ]; - if ( ! empty( $this->site_data['db_host'] ) ) { + if ( 'mysql' === $this->site_data['app_sub_type'] ) { $filter[] = $this->site_data['db_host']; $local = ( 'db' === $this->site_data['db_host'] ) ? true : false; $db_host = $local ? $this->site_data['db_host'] : $this->site_data['db_host'] . ':' . $this->site_data['db_port']; @@ -413,9 +415,10 @@ private function create_site_db_entry() { 'site_ssl_wildcard' => $this->site_data['site_ssl_wildcard'] ? 1 : 0, 'php_version' => '7.2', 'created_on' => date( 'Y-m-d H:i:s', time() ), + 'app_sub_type' => $this->site_data['app_sub_type'], ]; - if ( ! empty( $this->site_data['db_host'] ) ) { + if ( 'mysql' === $this->site_data['app_sub_type'] ) { $data['db_name'] = $this->site_data['db_name']; $data['db_user'] = $this->site_data['db_user']; $data['db_host'] = $this->site_data['db_host']; @@ -461,7 +464,7 @@ public function restart( $args, $assoc_args, $whitelisted_containers = [] ) { $whitelisted_containers = [ 'nginx', 'php' ]; - if ( ! empty( $this->site_data['db_host'] ) ) { + if ( 'mysql' === $this->site_data['app_sub_type'] ) { $whitelisted_containers[] = 'db'; } parent::restart( $args, $assoc_args, $whitelisted_containers ); From ba15731cdf9af2b2580d47edb024e9075ec56124 Mon Sep 17 00:00:00 2001 From: sagar Date: Wed, 5 Sep 2018 16:51:22 +0530 Subject: [PATCH 10/11] Change .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 40dc619..9e0f1a0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ .DS_Store -ee-cli.local.yml +ee.local.yml node_modules/ vendor/ *.zip From 4e42fce32d1df80923add581459b723dfc3565b8 Mon Sep 17 00:00:00 2001 From: sagar Date: Wed, 5 Sep 2018 20:40:33 +0530 Subject: [PATCH 11/11] Replace reload_proxy_container with reload_global_nginx_proxy --- src/PHP.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PHP.php b/src/PHP.php index 05ef33e..feceeb1 100644 --- a/src/PHP.php +++ b/src/PHP.php @@ -375,7 +375,7 @@ private function create_site( $assoc_args ) { } \EE\Site\Utils\add_site_redirects( $this->site_data['site_url'], false, 'inherit' === $this->site_data['site_ssl'] ); - \EE\Site\Utils\reload_proxy_configuration(); + \EE\Site\Utils\reload_global_nginx_proxy(); if ( $this->site_data['site_ssl'] ) { $wildcard = $this->site_data['site_ssl_wildcard']; @@ -383,7 +383,7 @@ private function create_site( $assoc_args ) { $this->init_ssl( $this->site_data['site_url'], $this->site_data['site_fs_path'], $this->site_data['site_ssl'], $wildcard ); \EE\Site\Utils\add_site_redirects( $this->site_data['site_url'], true, 'inherit' === $this->site_data['site_ssl'] ); - \EE\Site\Utils\reload_proxy_configuration(); + \EE\Site\Utils\reload_global_nginx_proxy(); } } catch ( \Exception $e ) { $this->catch_clean( $e );