Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Local Server extension for containers #525

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,20 @@
"inc/namespace.php",
"inc/analysis/namespace.php",
"inc/packages/namespace.php"
],
"classmap": [
"inc/"
]
},
"extra": {
"altis": {
"install-overrides": [
"10up/elasticpress",
"humanmade/debug-bar-elasticpress"
]
],
"local-server": {
"compose-extension": "Altis\\Enhanced_Search\\Local_Server_Extension"
}
}
}
}
5 changes: 5 additions & 0 deletions docs/configuration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,8 @@ content.

Depending on the configuration specified for `facets`, if the `match-type` property is set to `any`, it will force the results to
match any selected taxonomy term. If set to `all`, it will match to results with all of the selected terms.


## Local Server

See [the Local Server documentation](docs://local-server/elasticsearch.md) for information on configuring Local Server for ES settings.
246 changes: 246 additions & 0 deletions inc/class-local-server-extension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
<?php
/**
* Local Server Docker Compose file generator.
*/

namespace Altis\Enhanced_Search;

use Altis;
use Altis\Local_Server\Composer\Compose_Extension;
use Altis\Local_Server\Composer\Docker_Compose_Generator;

class Local_Server_Extension implements Compose_Extension {

Check failure on line 12 in inc/class-local-server-extension.php

View check run for this annotation

HM Linter / hmlinter

inc/class-local-server-extension.php#L12

Missing doc comment for class Local_Server_Extension
Raw output
{
  "line": 12,
  "column": 1,
  "severity": "error",
  "message": "Missing doc comment for class Local_Server_Extension",
  "source": "Squiz.Commenting.ClassComment.Missing"
}
protected Docker_Compose_Generator $generator;

Check failure on line 13 in inc/class-local-server-extension.php

View check run for this annotation

HM Linter / hmlinter

inc/class-local-server-extension.php#L13

PHP syntax error: syntax error, unexpected 'Docker_Compose_Generator' (T_STRING), expecting function (T_FUNCTION) or const (T_CONST)
Raw output
{
  "line": 13,
  "column": 1,
  "severity": "error",
  "message": "PHP syntax error: syntax error, unexpected 'Docker_Compose_Generator' (T_STRING), expecting function (T_FUNCTION) or const (T_CONST)",
  "source": "Generic.PHP.Syntax.PHPSyntax"
}

Check failure on line 13 in inc/class-local-server-extension.php

View check run for this annotation

HM Linter / hmlinter

inc/class-local-server-extension.php#L13

Missing member variable doc comment
Raw output
{
  "line": 13,
  "column": 40,
  "severity": "error",
  "message": "Missing member variable doc comment",
  "source": "Squiz.Commenting.VariableComment.Missing"
}

/**
* Configure the extension.
*
* @param Docker_Compose_Generator $generator The root generator.
* @param array $args An optional array of arguments to modify the behaviour of the generator.
*/
public function set_config( Docker_Compose_Generator $generator, array $args ) : void {
$this->generator = $generator;
}

/**
* Filter the docker-compose.yml config.
*
* @param array $config Full docker-compose.yml configuration.
* @return array Altered docker-compose.yml configuration.
*/
public function filter_compose( array $config ) : array {
// Skip entirely if the module is disabled.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like the similarity between the different "config" var names.
Two are the composer config, and one is a docker-compose config. Could they be called full/local_composer_config and docker_config?

$full_config = Altis\get_config()['modules'];
if ( ! ( $full_config['search']['enabled'] ?? true ) ) {
return $config;
}

$local_config = $full_config['search']['local'] ?? [];
if ( ! ( $local_config['enabled'] ?? true ) ) {
return $config;
}

// Handle the main ES service.
$config['volumes']['es-data'] = null;
$config['services'] = array_merge( $config['services'], $this->get_service_elasticsearch() );

foreach ( [ 'php', 'cavalcade' ] as $php_svc ) {
if ( empty( $config['services'][ $php_svc ] ) ) {
continue;
}

$config['services'][ $php_svc ]['external_links'][] = "proxy:elasticsearch-{$this->generator->hostname}";
$config['services'][ $php_svc ]['environment']['ELASTICSEARCH_HOST'] = 'elasticsearch';
$config['services'][ $php_svc ]['environment']['ELASTICSEARCH_PORT'] = 9200;
$config['services'][ $php_svc ]['depends_on']['elasticsearch'] = [
'condition' => 'service_healthy',
];
}

// Enable Kibana. (Defaults to true, but supports new + old style.)

Check failure on line 60 in inc/class-local-server-extension.php

View check run for this annotation

HM Linter / hmlinter

inc/class-local-server-extension.php#L60

Inline comments must end in full-stops, exclamation marks, or question marks
Raw output
{
  "line": 60,
  "column": 9,
  "severity": "error",
  "message": "Inline comments must end in full-stops, exclamation marks, or question marks",
  "source": "Squiz.Commenting.InlineComment.InvalidEndChar"
}
$has_kibana = $local_config['kibana'] ?? $full_config['local-server']['kibana'] ?? true;
if ( $has_kibana ) {
if ( ! empty( $full_config['local-server']['kibana'] ) ) {
trigger_error(
'extra.altis.modules.local-server.kibana is deprecated, use extra.altis.modules.search.kibana instead.',
E_USER_DEPRECATED
);
}

$config['services'] = array_merge( $config['services'], $this->get_service_kibana() );
}

return $config;
}

/**
* Get the Elasticsearch service.
*
* @return array
*/
protected function get_service_elasticsearch() : array {
$mem_limit = getenv( 'ES_MEM_LIMIT' ) ?: '1g';

$version_map = [
'7.10' => 'humanmade/altis-local-server-elasticsearch:4.1.0',
'7' => 'humanmade/altis-local-server-elasticsearch:4.1.0',
'6.8' => 'humanmade/altis-local-server-elasticsearch:3.1.0',
'6' => 'humanmade/altis-local-server-elasticsearch:3.1.0',
'6.3' => 'humanmade/altis-local-server-elasticsearch:3.0.0',
];

$this->check_elasticsearch_version( array_keys( $version_map ) );

$image = $version_map[ $this->get_elasticsearch_version() ];

return [
'elasticsearch' => [
'image' => $image,
'restart' => 'unless-stopped',
'container_name' => "{$this->generator->project_name}-es",
'ulimits' => [
'memlock' => [
'soft' => -1,
'hard' => -1,
],
],
'mem_limit' => $mem_limit,
'volumes' => [
'es-data:/usr/share/elasticsearch/data',
"{$this->generator->root_dir}/content/uploads/es-packages:/usr/share/elasticsearch/config/packages",
],
'ports' => [
'9200',
],
'networks' => [
'proxy',
'default',
],
'healthcheck' => [
'test' => [
'CMD-SHELL',
'curl --silent --fail localhost:9200/_cluster/health || exit 1',
],
'interval' => '5s',
'timeout' => '5s',
'retries' => 25,
],
'labels' => [
'traefik.port=9200',
'traefik.protocol=http',
'traefik.docker.network=proxy',
"traefik.frontend.rule=HostRegexp:elasticsearch-{$this->generator->hostname}",
"traefik.domain=elasticsearch-{$this->generator->hostname}",
],
'environment' => [
'http.max_content_length=10mb',
// Force ES into single-node mode (otherwise defaults to zen discovery as
// network.host is set in the default config).
'discovery.type=single-node',
// Use max container memory limit as the max JVM heap allocation value.
"ES_JAVA_OPTS=-Xms512m -Xmx{$mem_limit}",
],
],
];
}

/**
* Get the Kibana service.
*
* @return array
*/
protected function get_service_kibana() : array {
$version_map = [
'7.10' => 'humanmade/altis-local-server-kibana:1.1.1',
'7' => 'humanmade/altis-local-server-kibana:1.1.1',
'6.8' => 'blacktop/kibana:6.8',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A thought. Why are we still supporting so many old versions? Is this just for clients who haven't upgraded? Or is there a technical reason someone would want to use an old version?

'6' => 'blacktop/kibana:6.8',
'6.3' => 'blacktop/kibana:6.3',
];

$this->check_elasticsearch_version( array_keys( $version_map ) );

$image = $version_map[ $this->get_elasticsearch_version() ];

$yml_file = 'kibana.yml';
if ( version_compare( $this->get_elasticsearch_version(), '7', '>=' ) ) {
$yml_file = 'kibana-7.yml';
}

return [
'kibana' => [
'image' => $image,
'container_name' => "{$this->generator->project_name}-kibana",
'networks' => [
'proxy',
'default',
],
'ports' => [
'5601',
],
'labels' => [
'traefik.port=5601',
'traefik.protocol=http',
'traefik.docker.network=proxy',
"traefik.frontend.rule=Host:{$this->generator->hostname};PathPrefix:/kibana",
],
'depends_on' => [
'elasticsearch' => [
'condition' => 'service_healthy',
],
],
'volumes' => [
"{$this->generator->config_dir}/{$yml_file}:/usr/share/kibana/config/kibana.yml",
],
],
];
}

/**
* Get the configured Elasticsearch version.
*
* @return int
*/
protected function get_elasticsearch_version() : string {
$full_config = Altis\get_config();

// Try new config first.
if ( ! empty( $full_config['modules']['search']['local']['version'] ) ) {
return (string) $full_config['modules']['search']['local']['version'];
}

// Try legacy, and warn if it's still used.
if ( ! empty( $full_config['modules']['local-server']['elasticsearch'] ) ) {
trigger_error(
'extra.altis.modules.local-server.elasticsearch is deprecated, use extra.altis.modules.search.version instead.',
E_USER_DEPRECATED
);
return (string) $full_config['modules']['local-server']['elasticsearch'];
}

return '7';
}

/**
* Check the configured Elasticsearch version in config.
*
* @param array $versions List of available version numbers.
* @return void
*/
protected function check_elasticsearch_version( array $versions ) {
$versions = array_map( 'strval', $versions );
rsort( $versions );
if ( in_array( $this->get_elasticsearch_version(), $versions, true ) ) {
return;
}

echo sprintf(
"The configured elasticsearch version \"%s\" is not supported.\nTry one of the following:\n - %s\n",
// phpcs:ignore HM.Security.EscapeOutput.OutputNotEscaped
$this->get_elasticsearch_version(),
// phpcs:ignore HM.Security.EscapeOutput.OutputNotEscaped
implode( "\n - ", $versions )
);
exit( 1 );
}
}