From d19297adda810822894ebffaaf43ff70de184d88 Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Thu, 22 Oct 2015 19:09:53 +0100 Subject: [PATCH 01/27] Support for configuration per node and multiple nodes per server --- .gitignore | 1 + .kitchen.yml | 10 + README.md | 100 +++-- defaults/main.yml | 3 + elasticsearch.iml | 9 + meta/main.yml | 3 +- tasks/checkParameters.yml | 10 + tasks/elasticsearch-Debian.yml | 22 +- tasks/elasticsearch-RedHat.yml | 22 +- tasks/elasticsearch-config.yml | 117 ++++++ tasks/elasticsearch.yml | 22 +- tasks/java.yml | 4 +- tasks/main.yml | 4 + templates/elasticsearch.yml.j2 | 390 ++++++++++++++++++ test/integration/config.yml | 12 + test/integration/config/config.yml | 2 + .../config/serverspec/default_spec.rb | 42 ++ .../config/serverspec/spec_helper.rb | 2 + test/integration/multi.yml | 8 + test/integration/multi/multi.yml | 2 + .../multi/serverspec/default_spec.rb | 81 ++++ .../multi/serverspec/spec_helper.rb | 2 + test/integration/package.yml | 4 +- .../package/serverspec/default_spec.rb | 2 +- test/integration/standard.yml | 2 +- .../standard/serverspec/default_spec.rb | 2 +- vars/Debian.yml | 11 + vars/Linux.yml | 1 - vars/RedHat.yml | 6 + vars/main.yml | 10 +- 30 files changed, 818 insertions(+), 88 deletions(-) create mode 100644 elasticsearch.iml create mode 100644 tasks/checkParameters.yml create mode 100644 tasks/elasticsearch-config.yml create mode 100644 templates/elasticsearch.yml.j2 create mode 100644 test/integration/config.yml create mode 100644 test/integration/config/config.yml create mode 100644 test/integration/config/serverspec/default_spec.rb create mode 100644 test/integration/config/serverspec/spec_helper.rb create mode 100644 test/integration/multi.yml create mode 100644 test/integration/multi/multi.yml create mode 100644 test/integration/multi/serverspec/default_spec.rb create mode 100644 test/integration/multi/serverspec/spec_helper.rb create mode 100644 vars/Debian.yml delete mode 100644 vars/Linux.yml create mode 100644 vars/RedHat.yml diff --git a/.gitignore b/.gitignore index 625f5a1..0155da6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ .vendor .bundle Converging +TODO diff --git a/.kitchen.yml b/.kitchen.yml index 488db67..1122b95 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -64,4 +64,14 @@ suites: attributes: provisioner: playbook: test/integration/package.yml + - name: config + run_list: + attributes: + provisioner: + playbook: test/integration/config.yml + - name: multi + run_list: + attributes: + provisioner: + playbook: test/integration/multi.yml diff --git a/README.md b/README.md index 063700d..f8b5517 100644 --- a/README.md +++ b/README.md @@ -24,44 +24,88 @@ Then create your playbook yaml adding the role elasticsearch and overriding any --- hosts: my_host roles: - - elasticsearch + - { role: elasticsearch, es_multicast_enabled: true} tasks: - .... your tasks ... ``` -or more complex.. +By default es_multicast_enabled is false. If this is not to true, the user is required to specify the following additional parameters: +1. es_http_port - the http port for the node +2. es_transport_tcp_port - the transport port for the node +3. es_unicast_hosts - the unicast discovery list, in the comma separated format ":,:" (typically the clusters dedicated masters) + + +If set to true, the ports will be auto defined and node discovery will be performed using multicast. + +A more complex example: ``` --- -hosts: my_host - roles: - - elasticsearch - vars: - java_packages: - - "oracle-java7-installer" - es_major_version: 1.4 - es_version: 1.4.4 - es_start_service: false - es_plugins_reinstall: false - es_plugins: - - plugin: elasticsearch/elasticsearch-cloud-aws - version: 2.5.0 - - plugin: elasticsearch/marvel - version: latest - - plugin: elasticsearch/license - version: latest - - plugin: elasticsearch/shield - version: latest - - plugin: elasticsearch/elasticsearch-support-diagnostics - version: latest - - plugin: lmenezes/elasticsearch-kopf - version: master - tasks: - - .... your tasks ... +hosts: localhost +roles: + - { role: elasticsearch, es_unicast_hosts: "localhost:9301", es_http_port: "9201", es_transport_tcp_port: "9301", es_data_node: false, es_master_node: true, es_m_lock_enabled: true, es_multicast_enabled: false, es_node_name_prefix: "node1_", es_cluster_name: "custom-cluster" } +vars: + es_scripts: false + es_templates: false + es_version_lock: false + es_m_lock_enabled: true + es_start_service: false + es_plugins_reinstall: false + es_plugins: + - plugin: elasticsearch/elasticsearch-cloud-aws + version: 2.5.0 + - plugin: elasticsearch/marvel + version: latest + - plugin: elasticsearch/license + version: latest + - plugin: elasticsearch/shield + version: latest + - plugin: elasticsearch/elasticsearch-support-diagnostics + version: latest + - plugin: lmenezes/elasticsearch-kopf + version: master +tasks: + - .... your tasks ... ``` -Make sure your hosts are defined in your ```hosts``` file with the appropriate ```ansible_ssh_host```, ```ansible_ssh_user``` and ```ansible_ssh_private_key_file``` values. +The above example illustrates the ability to control the configuration. + +The application of a role results in the installation of a node on a host. Multiple roles equates to multiple nodes for a single host. If specifying multiple roles for a host, and thus multiple nodes, the user must: + +1. Provide a es_node_name_prefix. This is used to ensure seperation of data, log, config and init scripts. +2. Ensure those playbooks responsible for installing and starting master eligble roles are specified first. These are required for cluster initalization. + +An example of a two server deployment, each with 1 node on one server and 2 nodes on another. The first server holds the master and is thus declared first. + +``` +--- +hosts: masters +roles: + - { role: elasticsearch, es_node_name_prefix: "node1_", es_unicast_hosts: "localhost:9300", es_http_port: "9201", es_transport_tcp_port: "9301", es_data_node: true, es_master_node: false, es_m_lock_enabled: true, es_multicast_enabled: false } +vars: + es_scripts: false + es_templates: false + es_version_lock: false + es_cluster_name: example-cluster + m_lock_enabled: false + +- hosts: data_nodes + roles: + - { role: elasticsearch, es_data_node: true, es_master_node: false, es_m_lock_enabled: true, es_multicast_enabled: false, es_node_name_prefix: "node1_" } + - { role: elasticsearch, es_data_node: true, es_master_node: false, es_m_lock_enabled: true, es_multicast_enabled: false, es_node_name_prefix: "node2_" } + vars: + es_scripts: false + es_templates: false + es_version_lock: false + es_cluster_name: example-cluster + m_lock_enabled: true + es_plugins: +``` + +Parameters can additionally be assigned to hosts using the inventory file if desired. + +Make sure your hosts are defined in your ```inventory``` file with the appropriate ```ansible_ssh_host```, ```ansible_ssh_user``` and ```ansible_ssh_private_key_file``` values. Then run it: diff --git a/defaults/main.yml b/defaults/main.yml index 6b00692..ff4abc0 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -9,3 +9,6 @@ es_scripts: false es_templates: false es_user: elasticsearch es_group: elasticsearch +es_cluster_name: elasticsearch +es_multicast_enabled: false +es_node_name_prefix: "" \ No newline at end of file diff --git a/elasticsearch.iml b/elasticsearch.iml new file mode 100644 index 0000000..af03825 --- /dev/null +++ b/elasticsearch.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/meta/main.yml b/meta/main.yml index 357f0fe..4f961d5 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,5 +1,6 @@ --- -dependencies: [] + +allow_duplicates: yes galaxy_info: author: Robin Clarke diff --git a/tasks/checkParameters.yml b/tasks/checkParameters.yml new file mode 100644 index 0000000..242c6a6 --- /dev/null +++ b/tasks/checkParameters.yml @@ -0,0 +1,10 @@ +# Check for mandatory parameters + +- fail: msg="Parameter 'es_http_port' must be defined when multicast is disabled" + when: es_multicast_enabled == false and es_http_port is not defined + +- fail: msg="Parameter 'es_transport_tcp_port' must be defined when multicast is disabled" + when: es_multicast_enabled == false and es_transport_tcp_port is not defined + +- fail: msg="Parameter 'es_unicast_hosts' must be defined when multicast is disabled" + when: es_multicast_enabled == false and es_unicast_hosts is not defined \ No newline at end of file diff --git a/tasks/elasticsearch-Debian.yml b/tasks/elasticsearch-Debian.yml index ea10dc8..15e697f 100644 --- a/tasks/elasticsearch-Debian.yml +++ b/tasks/elasticsearch-Debian.yml @@ -19,24 +19,4 @@ - name: Debian - Ensure elasticsearch is installed from downloaded package apt: deb=/tmp/elasticsearch-{{ es_version }}.deb when: not es_use_repository - register: elasticsearch_install - -- name: Debian - configure memory - lineinfile: dest=/etc/default/elasticsearch regexp="^ES_HEAP_SIZE" insertafter="^#ES_HEAP_SIZE" line="ES_HEAP_SIZE={{ es_heap_size }}" - when: es_heap_size is defined - register: elasticsearch_configure -- name: Debian - configure data store - lineinfile: dest=/etc/default/elasticsearch regexp="^DATA_DIR" insertafter="^#DATA_DIR" line="DATA_DIR={{ es_data_dir }}" - when: es_data_dir is defined - register: elasticsearch_configure -- name: Debian - configure elasticsearch user - lineinfile: dest=/etc/default/elasticsearch regexp="^ES_USER" insertafter="^#ES_USER" line="ES_USER={{ es_user }}" - when: es_user is defined - register: elasticsearch_configure -- name: Debian - configure elasticsearch group - lineinfile: dest=/etc/default/elasticsearch regexp="^ES_GROUP" insertafter="^#ES_GROUP" line="ES_GROUP={{ es_group }}" - when: es_group is defined - register: elasticsearch_configure -- name: Debian - create data dir - file: state=directory path={{ es_data_dir }} owner={{ es_user }} group={{ es_group }} - when: es_data_dir is defined + register: elasticsearch_install \ No newline at end of file diff --git a/tasks/elasticsearch-RedHat.yml b/tasks/elasticsearch-RedHat.yml index e256293..d01163d 100644 --- a/tasks/elasticsearch-RedHat.yml +++ b/tasks/elasticsearch-RedHat.yml @@ -19,24 +19,4 @@ - name: RedHat - Install Elasticsearch from url yum: name={% if es_custom_package_url is defined %}{{ es_custom_package_url }}{% else %}{{ es_package_url }}-{{ es_version }}.noarch.rpm{% endif %} state=present when: not es_use_repository - register: elasticsearch_install - -- name: RedHat - configure memory - lineinfile: dest=/etc/sysconfig/elasticsearch regexp="^ES_HEAP_SIZE" insertafter="^#ES_HEAP_SIZE" line="ES_HEAP_SIZE={{ es_heap_size }}" - when: es_heap_size is defined - register: elasticsearch_configure -- name: RedHat - configure data store - lineinfile: dest=/etc/sysconfig/elasticsearch regexp="^DATA_DIR" insertafter="^#DATA_DIR" line="DATA_DIR={{ es_data_dir }}" - when: es_data_dir is defined - register: elasticsearch_configure -- name: RedHat - configure elasticsearch user - lineinfile: dest=/etc/sysconfig/elasticsearch regexp="^ES_USER" insertafter="^#ES_USER" line="ES_USER={{ es_user }}" - when: es_user is defined - register: elasticsearch_configure -- name: RedHat - configure elasticsearch group - lineinfile: dest=/etc/sysconfig/elasticsearch regexp="^ES_GROUP" insertafter="^#ES_GROUP" line="ES_GROUP={{ es_group }}" - when: es_group is defined - register: elasticsearch_configure -- name: RedHat - create data dir - file: state=directory path={{ es_data_dir }} owner={{ es_user }} group={{ es_group }} - when: es_data_dir is defined + register: elasticsearch_install \ No newline at end of file diff --git a/tasks/elasticsearch-config.yml b/tasks/elasticsearch-config.yml new file mode 100644 index 0000000..98f7a68 --- /dev/null +++ b/tasks/elasticsearch-config.yml @@ -0,0 +1,117 @@ +--- + +# Configure Elasticsearch Node + +# Create an instance specific default file +- name: Copy Default File for Instance + command: creates={{instance_default_file}} cp "{{default_file}}" "{{instance_default_file}}" + when: instance_default_file != default_file + +- debug: msg="DEBUG {{ hostvars[inventory_hostname] }}" + +# Create an instance specific init file +- name: Copy Init File for Instance + command: creates={{instance_init_script}} cp "{{init_script}}" "{{instance_init_script}}" + when: instance_init_script != init_script + + +#Create Config directory +- name: Create Config Directory + file: path={{ instance_config_directory }} state=directory owner={{ es_user }} group={{ es_group }} + +#Copy the config template +- name: Copy configuration file + template: src=elasticsearch.yml.j2 dest={{instance_config_directory}}/elasticsearch.yml owner={{ es_user }} group={{ es_group }} mode=0644 force=yes + +# Apply changes to the default file for this instance +- name: Configure config directory + lineinfile: dest={{instance_default_file}} regexp="^CONF_DIR" insertafter="^#CONF_DIR" line="CONF_DIR={{ instance_config_directory }}" + register: elasticsearch_configure + +- name: Configure config file + lineinfile: dest={{instance_default_file}} regexp="^CONF_FILE" insertafter="^#CONF_FILE" line="CONF_FILE={{ instance_config_directory }}/elasticsearch.yml" + register: elasticsearch_configure + +- name: Configure memory in defaults + lineinfile: dest={{instance_default_file}} regexp="^ES_HEAP_SIZE" insertafter="^#ES_HEAP_SIZE" line="ES_HEAP_SIZE={{ es_heap_size }}" + when: es_heap_size is defined + register: elasticsearch_configure + +#We only have to set these if they are specified. The start scripts will by default use the NAME set later on constructing directory names to avoid collisions. + +- name: Configure max open files + lineinfile: dest={{instance_default_file}} regexp="^MAX_OPEN_FILES" insertafter="^#MAX_OPEN_FILES" line="MAX_OPEN_FILES={{ es_max_open_files }}" + when: es_max_open_files is defined + register: elasticsearch_configure + +#For directories we also use the {{ es_node_name_prefix }}{{inventory_hostname}} - this helps if we have a shared SAN. {{es_node_name_prefix}}{{default_file | basename} could potentially be used - +#init script effectively means this is the default. + +#Create PID directory +- name: Create PID Directory + file: path={{pid_dir}}/{{ es_node_name_prefix }}{{inventory_hostname}} state=directory owner={{ es_user }} group={{ es_group }} + +- name: Configure PID directory + lineinfile: dest={{instance_default_file}} regexp="^PID_DIR" insertafter="^#PID_DIR" line="PID_DIR={{pid_dir}}/{{ es_node_name_prefix }}{{inventory_hostname}}" + register: elasticsearch_configure + +- set_fact: es_data_dir={{default_data_dir}} + when: es_data_dir is undefined + +#include the host name as potentially shared SAN +- name: Create data dir + file: state=directory path={{ es_data_dir }}/{{ es_node_name_prefix }}{{inventory_hostname}} owner={{ es_user }} group={{ es_group }} + +- name: Configure data store + lineinfile: dest={{instance_default_file}} regexp="^DATA_DIR" insertafter="^#DATA_DIR" line="DATA_DIR={{ es_data_dir }}/{{ es_node_name_prefix }}{{inventory_hostname}}" + register: elasticsearch_configure + +- set_fact: es_work_dir={{default_work_dir}} + when: es_work_dir is undefined + +- name: Create work dir + file: state=directory path={{ es_work_dir }}/{{ es_node_name_prefix }}{{inventory_hostname}} owner={{ es_user }} group={{ es_group }} + +- name: Configure work directory + lineinfile: dest={{instance_default_file}} regexp="^WORK_DIR" insertafter="^#WORK_DIR" line="WORK_DIR={{ es_work_dir }}/{{ es_node_name_prefix }}{{inventory_hostname}}" + register: elasticsearch_configure + +- set_fact: es_log_dir={{default_log_dir}} + when: es_log_dir is undefined + +- name: Create log dir + file: state=directory path={{ es_log_dir }}/{{ es_node_name_prefix }}{{inventory_hostname}} owner={{ es_user }} group={{ es_group }} + +- name: Configure log directory + lineinfile: dest={{instance_default_file}} regexp="^LOG_DIR" insertafter="^#LOG_DIR" line="LOG_DIR={{ es_log_dir }}/{{ es_node_name_prefix }}{{inventory_hostname}}" + register: elasticsearch_configure + +#required so that the ES_HOME does not change between instances + +- name: Configure elasticsearch home + lineinfile: dest={{instance_default_file}} regexp="^ES_HOME" insertafter="^#ES_HOME" line="ES_HOME={{es_home}}" + register: elasticsearch_configure + +- name: Configure elasticsearch user + lineinfile: dest={{instance_default_file}} regexp="^ES_USER" insertafter="^#ES_USER" line="ES_USER={{ es_user }}" + when: es_user is defined + register: elasticsearch_configure + +- name: Configure elasticsearch group + lineinfile: dest={{instance_default_file}} regexp="^ES_GROUP" insertafter="^#ES_GROUP" line="ES_GROUP={{ es_group }}" + when: es_group is defined + register: elasticsearch_configure + +#Apply changes to init script - NAME can be changed in Debian start script +- name: Name Node in Init Script + lineinfile: dest={{instance_init_script}} regexp="^NAME" line="NAME={{es_node_name_prefix}}{{default_file | basename}}" + register: elasticsearch_configure + when: ansible_os_family == 'Debian' + +- debug: msg="For {{ instance_init_script }} using default {{ instance_default_file }}" + +- name: Environment in Init Script + lineinfile: dest={{instance_init_script}} regexp="^ES_ENV_FILE" line="ES_ENV_FILE={{instance_default_file}}" + register: elasticsearch_configure + when: ansible_os_family == 'RedHat' + diff --git a/tasks/elasticsearch.yml b/tasks/elasticsearch.yml index 1d4073c..aca22c7 100644 --- a/tasks/elasticsearch.yml +++ b/tasks/elasticsearch.yml @@ -1,21 +1,31 @@ --- -# Trigger Debian section -- name: Include Debian specific Elasticsearch +- set_fact: instance_default_file={{default_file | dirname}}/{{es_node_name_prefix}}{{default_file | basename}} +- set_fact: instance_init_script={{init_script | dirname }}/{{es_node_name_prefix}}{{init_script | basename}} +- set_fact: instance_config_directory={{ es_conf_dir }}/{{es_node_name_prefix}}elasticsearch + + + +# Install OS specific elasticsearch - this can be abbreviated in version 2.0.0 +- name: Include specific Elasticsearch include: elasticsearch-Debian.yml when: ansible_os_family == 'Debian' -# Trigger Redhat section -- name: Include RedHat specific Elasticsearch +- name: Include specific Elasticsearch include: elasticsearch-RedHat.yml when: ansible_os_family == 'RedHat' +#Configuration file for elasticsearch +- name: Elasticsearch configuration + include: elasticsearch-config.yml + # Make sure the service is started, and restart if necessary - name: Start elasticsearch service - service: name=elasticsearch state=started + service: name={{instance_init_script | basename}} state=started when: es_start_service register: elasticsearch_started + - name: Restart elasticsearch service if new version installed - service: name=elasticsearch state=restarted + service: name={{instance_init_script | basename}} state=restarted when: es_start_service and ( elasticsearch_install.changed or elasticsearch_configure.changed ) and not elasticsearch_started.changed diff --git a/tasks/java.yml b/tasks/java.yml index 7b042b0..05fb5e7 100644 --- a/tasks/java.yml +++ b/tasks/java.yml @@ -1,8 +1,8 @@ --- - name: RedHat - Ensure Java is installed - yum: name={{ java_rhel }} state=latest + yum: name={{ java }} state=latest when: ansible_os_family == 'RedHat' - name: Debian - Ensure Java is installed - apt: name={{ java_debian }} state=present update_cache=yes + apt: name={{ java }} state=present update_cache=yes force=yes when: ansible_os_family == 'Debian' \ No newline at end of file diff --git a/tasks/main.yml b/tasks/main.yml index b492c29..5791593 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,4 +1,8 @@ --- +- name: check-parameters + include: checkParameters.yml +- name: os-specific vars + include_vars: "{{ansible_os_family}}.yml" - include: java.yml - include: elasticsearch.yml - include: elasticsearch-plugins.yml diff --git a/templates/elasticsearch.yml.j2 b/templates/elasticsearch.yml.j2 new file mode 100644 index 0000000..16237f6 --- /dev/null +++ b/templates/elasticsearch.yml.j2 @@ -0,0 +1,390 @@ +##################### Elasticsearch Configuration Example ##################### + +# This file contains an overview of various configuration settings, +# targeted at operations staff. Application developers should +# consult the guide at . +# +# The installation procedure is covered at +# . +# +# Elasticsearch comes with reasonable defaults for most settings, +# so you can try it out without bothering with configuration. +# +# Most of the time, these defaults are just fine for running a production +# cluster. If you're fine-tuning your cluster, or wondering about the +# effect of certain configuration option, please _do ask_ on the +# mailing list or IRC channel [http://elasticsearch.org/community]. + +# Any element in the configuration can be replaced with environment variables +# by placing them in ${...} notation. For example: +# +#node.rack: ${RACK_ENV_VAR} + +# For information on supported formats and syntax for the config file, see +# + + +################################### Cluster ################################### + +# Cluster name identifies your cluster for auto-discovery. If you're running +# multiple clusters on the same network, make sure you're using unique names. +# +cluster.name: {{ es_cluster_name }} + +#################################### Node ##################################### + +# Node names are generated dynamically on startup, so you're relieved +# from configuring them manually. You can tie this node to a specific name: +# +node.name: {{es_node_name_prefix}}{{inventory_hostname}} + +# Every node can be configured to allow or deny being eligible as the master, +# and to allow or deny to store the data. +# +# Allow this node to be eligible as a master node (enabled by default): +# +{% if es_master_node is defined %} +node.master: {{es_master_node | lower}} +{% endif %} + +# +# Allow this node to store data (enabled by default): +# +{% if es_data_node is defined %} +node.data: {{es_data_node | lower}} +{% endif %} + +# Use the Cluster Health API [http://localhost:9200/_cluster/health], the +# Node Info API [http://localhost:9200/_nodes] or GUI tools +# such as , +# , +# and +# to inspect the cluster state. + +# A node can have generic attributes associated with it, which can later be used +# for customized shard allocation filtering, or allocation awareness. An attribute +# is a simple key value pair, similar to node.key: value, here is an example: +# +{% if es_node_rack is defined %} +node.rack: {{ es_node_rack }} +{% endif %} + +# By default, multiple nodes are allowed to start from the same installation location +# to disable it, set the following: +#node.max_local_storage_nodes: 1 + + +#################################### Index #################################### + +# You can set a number of options (such as shard/replica options, mapping +# or analyzer definitions, translog settings, ...) for indices globally, +# in this file. +# +# Note, that it makes more sense to configure index settings specifically for +# a certain index, either when creating it or by using the index templates API. +# +# See and +# +# for more information. + +# Set the number of shards (splits) of an index (5 by default) if provided: + +{% if es_index_number_of_shards is defined %} +index.number_of_shards: {{ es_index_number_of_shards }} +{% endif %} + +# Set the number of replicas (additional copies) of an index (1 by default) if provided: +{% if es_index_number_of_replicas is defined %} +index.number_of_replicas: {{ es_index_number_of_replicas }} +{% endif %} + + +# These settings directly affect the performance of index and search operations +# in your cluster. Assuming you have enough machines to hold shards and +# replicas, the rule of thumb is: +# +# 1. Having more *shards* enhances the _indexing_ performance and allows to +# _distribute_ a big index across machines. +# 2. Having more *replicas* enhances the _search_ performance and improves the +# cluster _availability_. +# +# The "number_of_shards" is a one-time setting for an index. +# +# The "number_of_replicas" can be increased or decreased anytime, +# by using the Index Update Settings API. +# +# Elasticsearch takes care about load balancing, relocating, gathering the +# results from nodes, etc. Experiment with different settings to fine-tune +# your setup. + +# Use the Index Status API () to inspect +# the index status. + + +#################################### Paths #################################### + +# Path to directory containing configuration (this file and logging.yml): +# +{% if es_conf_dir is defined %} +path.conf: {{ es_conf_dir }} +{% endif %} + + +# Path to directory where to store index data allocated for this node. +# +# Can optionally include more than one location, causing data to be striped across +# the locations (a la RAID 0) on a file level, favouring locations with most free +# space on creation. For example: +# +{% if es_data_dir is defined %} +path.data: {{ es_data_dir }} +{% endif %} + +# Path to temporary files: +{% if es_work_dir is defined %} +path.work: {{ es_work_dir }} +{% endif %} + +# Path to log files: +{% if es_log_dir is defined %} +path.logs: {{ es_log_dir }} +{% endif %} + +# Path to where plugins are installed: +# +#path.plugins: /path/to/plugins + + +#################################### Plugin ################################### + +# If a plugin listed here is not installed for current node, the node will not start. +# +#plugin.mandatory: mapper-attachments,lang-groovy + + +################################### Memory #################################### + +# Elasticsearch performs poorly when JVM starts swapping: you should ensure that +# it _never_ swaps. +# +# Set this property to true to lock the memory: +# +{% if es_m_lock_enabled is defined %} +bootstrap.mlockall: {{es_m_lock_enabled | lower}} +{% endif %} + + +# Make sure that the ES_MIN_MEM and ES_MAX_MEM environment variables are set +# to the same value, and that the machine has enough memory to allocate +# for Elasticsearch, leaving enough memory for the operating system itself. +# +# You should also make sure that the Elasticsearch process is allowed to lock +# the memory, eg. by using `ulimit -l unlimited`. + + +############################## Network And HTTP ############################### + +# Elasticsearch, by default, binds itself to the 0.0.0.0 address, and listens +# on port [9200-9300] for HTTP traffic and on port [9300-9400] for node-to-node +# communication. (the range means that if the port is busy, it will automatically +# try the next port). + +# Set the bind address specifically (IPv4 or IPv6): +# +#network.bind_host: 192.168.0.1 + +# Set the address other nodes will use to communicate with this node. If not +# set, it is automatically derived. It must point to an actual IP address. +# +#network.publish_host: 192.168.0.1 + +# Set both 'bind_host' and 'publish_host': +# +{% if es_network_host is defined %} +network.host: {{ es_network_host }} +{% endif %} + + +# Set a custom port for the node to node communication (9300 by default): +# +{% if es_transport_tcp_port is defined %} +transport.tcp.port: {{ es_transport_tcp_port }} +{% endif %} + +# Enable compression for all communication between nodes (disabled by default): +# +#transport.tcp.compress: true + +# Set a custom port to listen for HTTP traffic (9200 by default): +# +{% if es_http_port is defined %} +http.port: {{ es_http_port }} +{% endif %} + +# Set a custom allowed content length: +# +#http.max_content_length: 100mb + +# Disable HTTP completely: +# +#http.enabled: false + + +################################### Gateway ################################### + +# The gateway allows for persisting the cluster state between full cluster +# restarts. Every change to the state (such as adding an index) will be stored +# in the gateway, and when the cluster starts up for the first time, +# it will read its state from the gateway. + +# There are several types of gateway implementations. For more information, see +# . + +# The default gateway type is the "local" gateway (recommended): +# +#gateway.type: local + +# Settings below control how and when to start the initial recovery process on +# a full cluster restart (to reuse as much local data as possible when using shared +# gateway). + +# Allow recovery process after N nodes in a cluster are up: +# +#gateway.recover_after_nodes: 1 + +# Set the timeout to initiate the recovery process, once the N nodes +# from previous setting are up (accepts time value): +# +#gateway.recover_after_time: 5m + +# Set how many nodes are expected in this cluster. Once these N nodes +# are up (and recover_after_nodes is met), begin recovery process immediately +# (without waiting for recover_after_time to expire): +# +#gateway.expected_nodes: 2 + + +############################# Recovery Throttling ############################# + +# These settings allow to control the process of shards allocation between +# nodes during initial recovery, replica allocation, rebalancing, +# or when adding and removing nodes. + +# Set the number of concurrent recoveries happening on a node: +# +# 1. During the initial recovery +# +#cluster.routing.allocation.node_initial_primaries_recoveries: 4 +# +# 2. During adding/removing nodes, rebalancing, etc +# +#cluster.routing.allocation.node_concurrent_recoveries: 2 + +# Set to throttle throughput when recovering (eg. 100mb, by default 20mb): +# +#indices.recovery.max_bytes_per_sec: 20mb + +# Set to limit the number of open concurrent streams when +# recovering a shard from a peer: +# +#indices.recovery.concurrent_streams: 5 + + +################################## Discovery ################################## + +# Discovery infrastructure ensures nodes can be found within a cluster +# and master node is elected. Multicast discovery is the default. + +# Set to ensure a node sees N other master eligible nodes to be considered +# operational within the cluster. This should be set to a quorum/majority of +# the master-eligible nodes in the cluster. +# +#discovery.zen.minimum_master_nodes: 1 + +# Set the time to wait for ping responses from other nodes when discovering. +# Set this option to a higher value on a slow or congested network +# to minimize discovery failures: +# +#discovery.zen.ping.timeout: 3s + +# For more information, see +# + +# Unicast discovery allows to explicitly control which nodes will be used +# to discover the cluster. It can be used when multicast is not present, +# or to restrict the cluster communication-wise. +# +# 1. Disable multicast discovery (enabled by default): +# +discovery.zen.ping.multicast.enabled: {{es_multicast_enabled | lower }} + +# +# 2. Configure an initial list of master nodes in the cluster +# to perform discovery when new nodes (master or data) are started: +# + +#We put all the current eligible masters in here. If not specified, we assumes its a master + +{% if es_multicast_enabled is defined and not es_multicast_enabled %} +discovery.zen.ping.unicast.hosts: {{es_unicast_hosts}} +{% endif %} + + +# EC2 discovery allows to use AWS EC2 API in order to perform discovery. +# +# You have to install the cloud-aws plugin for enabling the EC2 discovery. +# +# For more information, see +# +# +# See +# for a step-by-step tutorial. + +# GCE discovery allows to use Google Compute Engine API in order to perform discovery. +# +# You have to install the cloud-gce plugin for enabling the GCE discovery. +# +# For more information, see . + +# Azure discovery allows to use Azure API in order to perform discovery. +# +# You have to install the cloud-azure plugin for enabling the Azure discovery. +# +# For more information, see . + +################################## Slow Log ################################## + +# Shard level query and fetch threshold logging. + +index.search.slowlog.threshold.query.warn: 2s +index.search.slowlog.threshold.query.info: 2s +index.search.slowlog.threshold.query.debug: 1s +index.search.slowlog.threshold.query.trace: 500ms + +#index.search.slowlog.threshold.fetch.warn: 1s +#index.search.slowlog.threshold.fetch.info: 800ms +#index.search.slowlog.threshold.fetch.debug: 500ms +#index.search.slowlog.threshold.fetch.trace: 200ms + +#index.indexing.slowlog.threshold.index.warn: 10s +#index.indexing.slowlog.threshold.index.info: 5s +#index.indexing.slowlog.threshold.index.debug: 2s +#index.indexing.slowlog.threshold.index.trace: 500ms + +################################## GC Logging ################################ + +#monitor.jvm.gc.young.warn: 1000ms +#monitor.jvm.gc.young.info: 700ms +#monitor.jvm.gc.young.debug: 400ms + +#monitor.jvm.gc.old.warn: 10s +#monitor.jvm.gc.old.info: 5s +#monitor.jvm.gc.old.debug: 2s + +################################## Security ################################ + +# Uncomment if you want to enable JSONP as a valid return transport on the +# http server. With this enabled, it may pose a security risk, so disabling +# it unless you need it is recommended (it is disabled by default). +# +#http.jsonp.enable: true diff --git a/test/integration/config.yml b/test/integration/config.yml new file mode 100644 index 0000000..da421b5 --- /dev/null +++ b/test/integration/config.yml @@ -0,0 +1,12 @@ +--- +#Test explicit setting of parameters and variables +- name: Elasticsearch Package tests + hosts: localhost + roles: + #expand to all available parameters + - { role: elasticsearch, es_unicast_hosts: "localhost:9301", es_http_port: "9201", es_transport_tcp_port: "9301", es_data_node: false, es_master_node: true, es_m_lock_enabled: true, es_multicast_enabled: false, es_node_name_prefix: "node1_", es_cluster_name: "custom-cluster" } + vars: + es_scripts: false + es_templates: false + es_version_lock: false + es_m_lock_enabled: true \ No newline at end of file diff --git a/test/integration/config/config.yml b/test/integration/config/config.yml new file mode 100644 index 0000000..a3c37e1 --- /dev/null +++ b/test/integration/config/config.yml @@ -0,0 +1,2 @@ +--- +- host: test-kitchen diff --git a/test/integration/config/serverspec/default_spec.rb b/test/integration/config/serverspec/default_spec.rb new file mode 100644 index 0000000..9a616bd --- /dev/null +++ b/test/integration/config/serverspec/default_spec.rb @@ -0,0 +1,42 @@ +require 'spec_helper' + +context "basic tests" do + + describe user('elasticsearch') do + it { should exist } + end + + describe service('node1_elasticsearch') do + it { should be_running } + end + + describe package('elasticsearch') do + it { should be_installed } + end + + describe file('/etc/elasticsearch/node1_elasticsearch/elasticsearch.yml') do + it { should be_file } + end + + #test configuration parameters have been set - test all appropriately set in config file + describe file('/etc/elasticsearch/node1_elasticsearch/elasticsearch.yml') do + it { should contain 'http.port: 9201' } + it { should contain 'transport.tcp.port: 9301' } + it { should contain 'node.data: false' } + it { should contain 'node.master: true' } + it { should contain 'discovery.zen.ping.multicast.enabled: false' } + it { should contain 'cluster.name: custom-cluster' } + it { should contain 'node.name: node1_localhost' } + it { should contain 'discovery.zen.ping.unicast.hosts: localhost:9301' } + end + + #test we started on the correct port was used + describe command('curl "localhost:9201" | grep status') do + #TODO: This is returning an empty string + #its(:stdout) { should match /\"status\" : 200/ } + its(:exit_status) { should eq 0 } + end + + +end + diff --git a/test/integration/config/serverspec/spec_helper.rb b/test/integration/config/serverspec/spec_helper.rb new file mode 100644 index 0000000..590c2fa --- /dev/null +++ b/test/integration/config/serverspec/spec_helper.rb @@ -0,0 +1,2 @@ +require 'serverspec' +set :backend, :exec diff --git a/test/integration/multi.yml b/test/integration/multi.yml new file mode 100644 index 0000000..2a1447c --- /dev/null +++ b/test/integration/multi.yml @@ -0,0 +1,8 @@ +--- +#Test ability to deploy multiple instances to a machine +- name: Elasticsearch Config tests + hosts: localhost + roles: + - { role: elasticsearch, es_node_name_prefix: "node1_", es_unicast_hosts: "localhost:9300", es_http_port: "9201", es_transport_tcp_port: "9301", es_data_node: true, es_master_node: false, es_m_lock_enabled: true, es_multicast_enabled: false } + - { role: elasticsearch, es_node_name_prefix: "master_", es_unicast_hosts: "localhost:9300", es_http_port: "9200", es_transport_tcp_port: "9300", es_data_node: false, es_master_node: true, es_m_lock_enabled: true, es_multicast_enabled: false } + vars: diff --git a/test/integration/multi/multi.yml b/test/integration/multi/multi.yml new file mode 100644 index 0000000..a3c37e1 --- /dev/null +++ b/test/integration/multi/multi.yml @@ -0,0 +1,2 @@ +--- +- host: test-kitchen diff --git a/test/integration/multi/serverspec/default_spec.rb b/test/integration/multi/serverspec/default_spec.rb new file mode 100644 index 0000000..5269486 --- /dev/null +++ b/test/integration/multi/serverspec/default_spec.rb @@ -0,0 +1,81 @@ +require 'spec_helper' + +context "basic tests" do + + describe user('elasticsearch') do + it { should exist } + end + + describe service('node1_elasticsearch') do + it { should be_running } + end + + describe service('master_elasticsearch') do + it { should be_running } + end + + describe package('elasticsearch') do + it { should be_installed } + end + + describe file('/etc/elasticsearch/node1_elasticsearch/elasticsearch.yml') do + it { should be_file } + end + + describe file('/etc/elasticsearch/master_elasticsearch/elasticsearch.yml') do + it { should be_file } + end + + #test configuration parameters have been set - test all appropriately set in config file + describe file('/etc/elasticsearch/node1_elasticsearch/elasticsearch.yml') do + it { should contain 'http.port: 9201' } + it { should contain 'transport.tcp.port: 9301' } + it { should contain 'node.data: true' } + it { should contain 'node.master: false' } + it { should contain 'discovery.zen.ping.multicast.enabled: false' } + it { should contain 'node.name: node1_localhost' } + end + + + #test configuration parameters have been set for master - test all appropriately set in config file + describe file('/etc/elasticsearch/master_elasticsearch/elasticsearch.yml') do + it { should contain 'http.port: 9200' } + it { should contain 'transport.tcp.port: 9300' } + it { should contain 'node.data: false' } + it { should contain 'node.master: true' } + it { should contain 'discovery.zen.ping.multicast.enabled: false' } + it { should contain 'node.name: master_localhost' } + end + + describe 'Master listening' do + it 'listening in port 9200' do + expect(port 9200).to be_listening + end + end + + describe 'Node listening' do + it 'node should be listening in port 9201' do + expect(port 9201).to be_listening + end + end + + #test we started on the correct port was used for master + describe 'master started' do + it 'master node should be running', :retry => 3, :retry_wait => 10 do + command = command('curl "localhost:9200" | grep name') + #expect(command.stdout).should match '/*master_localhost*/' + expect(command.exit_status).to eq(0) + end + end + + #test we started on the correct port was used for node 1 + describe 'node1 started' do + it 'node should be running', :retry => 3, :retry_wait => 10 do + command = command('curl "localhost:9201" | grep name') + #expect(command.stdout).should match '/*node1_localhost*/' + expect(command.exit_status).to eq(0) + end + end + +end + diff --git a/test/integration/multi/serverspec/spec_helper.rb b/test/integration/multi/serverspec/spec_helper.rb new file mode 100644 index 0000000..590c2fa --- /dev/null +++ b/test/integration/multi/serverspec/spec_helper.rb @@ -0,0 +1,2 @@ +require 'serverspec' +set :backend, :exec diff --git a/test/integration/package.yml b/test/integration/package.yml index 6b0c7e2..23fd197 100644 --- a/test/integration/package.yml +++ b/test/integration/package.yml @@ -2,5 +2,5 @@ - name: Elasticsearch Package tests hosts: localhost roles: - - elasticsearch - vars: + - { role: elasticsearch, es_multicast_enabled: true} + vars: \ No newline at end of file diff --git a/test/integration/package/serverspec/default_spec.rb b/test/integration/package/serverspec/default_spec.rb index 10a66d3..31d025a 100644 --- a/test/integration/package/serverspec/default_spec.rb +++ b/test/integration/package/serverspec/default_spec.rb @@ -14,7 +14,7 @@ context "basic tests" do it { should be_installed } end - describe file('/etc/elasticsearch/elasticsearch.yml') do + describe file('/etc/elasticsearch/elasticsearch/elasticsearch.yml') do it { should be_file } end diff --git a/test/integration/standard.yml b/test/integration/standard.yml index da56a19..c12deb7 100644 --- a/test/integration/standard.yml +++ b/test/integration/standard.yml @@ -2,7 +2,7 @@ - name: wrapper playbook for kitchen testing "elasticsearch" hosts: localhost roles: - - elasticsearch + - { role: elasticsearch, es_multicast_enabled: true} vars: es_use_repository: "true" es_plugins: diff --git a/test/integration/standard/serverspec/default_spec.rb b/test/integration/standard/serverspec/default_spec.rb index 115a81a..d7471a3 100644 --- a/test/integration/standard/serverspec/default_spec.rb +++ b/test/integration/standard/serverspec/default_spec.rb @@ -14,7 +14,7 @@ context "basic tests" do it { should be_installed } end - describe file('/etc/elasticsearch/elasticsearch.yml') do + describe file('/etc/elasticsearch/elasticsearch/elasticsearch.yml') do it { should be_file } end diff --git a/vars/Debian.yml b/vars/Debian.yml new file mode 100644 index 0000000..5c07034 --- /dev/null +++ b/vars/Debian.yml @@ -0,0 +1,11 @@ +--- +java: "openjdk-7-jre-headless" +default_file: "/etc/default/elasticsearch" +init_script: "/etc/init.d/elasticsearch" +es_conf_dir: "/etc/elasticsearch" +es_home: "/usr/share/elasticsearch" + +default_data_dir: "/var/lib/elasticsearch" +default_log_dir: "/var/log/elasticsearch" +default_work_dir: "/tmp/elasticsearch" +default_pid_dir: "/var/run/elasticsearch" \ No newline at end of file diff --git a/vars/Linux.yml b/vars/Linux.yml deleted file mode 100644 index ed97d53..0000000 --- a/vars/Linux.yml +++ /dev/null @@ -1 +0,0 @@ ---- diff --git a/vars/RedHat.yml b/vars/RedHat.yml new file mode 100644 index 0000000..c7be31d --- /dev/null +++ b/vars/RedHat.yml @@ -0,0 +1,6 @@ +--- +java: "java-1.8.0-openjdk.x86_64" +default_file: "/etc/sysconfig/elasticsearch" +init_script: "/etc/init.d/elasticsearch" +es_conf_dir: "/etc/elasticsearch/" +es_home: "/usr/share/elasticsearch" \ No newline at end of file diff --git a/vars/main.yml b/vars/main.yml index 7a6e693..d5bd5cf 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -1,4 +1,8 @@ --- -java_debian: "openjdk-7-jre-headless" -java_rhel: "java-1.8.0-openjdk.x86_64" -es_package_url: "https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch" \ No newline at end of file +es_package_url: "https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch" +pid_dir: "/var/run/elasticsearch" + +#Needed to provide default directories +default_data_dir: "/var/lib/elasticsearch" +default_log_dir: "/var/log/elasticsearch" +default_work_dir: "/tmp/elasticsearch" From 4689922ad682c64c58e681d37af17206284c9891 Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Thu, 22 Oct 2015 19:10:14 +0100 Subject: [PATCH 02/27] Ignore IntelliJ files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0155da6..cf4e5c2 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ .bundle Converging TODO +.idea/ \ No newline at end of file From d34d5e6103ab77d46c6072254df457a0f8ced7b5 Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Tue, 24 Nov 2015 17:32:36 +0000 Subject: [PATCH 03/27] Changes to support Hash Map for Config --- .kitchen.yml | 7 ++++- README.md | 2 +- ansible.cfg | 2 +- defaults/main.yml | 9 ++++-- tasks/checkParameters.yml | 6 ++-- tasks/elasticsearch-config.yml | 20 ++++++------- tasks/elasticsearch-plugins.yml | 2 +- tasks/elasticsearch.yml | 7 +++-- templates/elasticsearch.yml.j2 | 51 ++++++++++++++++----------------- test/integration/config.yml | 4 +-- test/integration/multi.yml | 4 +-- test/integration/package.yml | 2 +- test/integration/standard.yml | 4 +-- vars/Debian.yml | 7 +---- vars/main.yml | 2 +- 15 files changed, 65 insertions(+), 64 deletions(-) diff --git a/.kitchen.yml b/.kitchen.yml index 1122b95..68bdc44 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -18,6 +18,7 @@ platforms: - apt-get update && apt-get install -y software-properties-common && add-apt-repository -y ppa:ansible/ansible - apt-get update && apt-get -y -q install ansible python-apt python-pycurl use_sudo: false + #run_command: "-e ENV ANSIBLE_HASH_BEHAVIOUR=merge" - name: debian-7 driver_config: image: electrical/debian:7.3 @@ -26,12 +27,16 @@ platforms: - echo 'deb http://http.debian.net/debian/ wheezy-backports main' >> /etc/apt/sources.list - apt-get update - apt-get install -y -q ansible + - apt-get install -y -q net-tools use_sudo: false - name: debian-8 driver_config: image: electrical/debian:8 privileged: true - provision_command: apt-get -y -q install ansible + provision_command: + - apt-get update + - apt-get install -y -q ansible + - apt-get install -y -q net-tools use_sudo: false - name: centos-6 driver_config: diff --git a/README.md b/README.md index f8b5517..77801fd 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ hosts: my_host - .... your tasks ... ``` -By default es_multicast_enabled is false. If this is not to true, the user is required to specify the following additional parameters: +By default es_multicast_enabled is false and the user is required to specify the following additional parameters: 1. es_http_port - the http port for the node 2. es_transport_tcp_port - the transport port for the node diff --git a/ansible.cfg b/ansible.cfg index 613d83b..d7649f6 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -1,2 +1,2 @@ [defaults] -roles_path = ../ +hash_behaviour = merge \ No newline at end of file diff --git a/defaults/main.yml b/defaults/main.yml index ff4abc0..745fa7b 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -9,6 +9,9 @@ es_scripts: false es_templates: false es_user: elasticsearch es_group: elasticsearch -es_cluster_name: elasticsearch -es_multicast_enabled: false -es_node_name_prefix: "" \ No newline at end of file + +es_config: { + "cluster_name": elasticsearch, + "multicast_enabled": false, + "node_name_prefix": "" +} \ No newline at end of file diff --git a/tasks/checkParameters.yml b/tasks/checkParameters.yml index 242c6a6..892ce03 100644 --- a/tasks/checkParameters.yml +++ b/tasks/checkParameters.yml @@ -1,10 +1,10 @@ # Check for mandatory parameters - fail: msg="Parameter 'es_http_port' must be defined when multicast is disabled" - when: es_multicast_enabled == false and es_http_port is not defined + when: es_config['multicast_enabled'] == false and es_config['http_port'] is not defined - fail: msg="Parameter 'es_transport_tcp_port' must be defined when multicast is disabled" - when: es_multicast_enabled == false and es_transport_tcp_port is not defined + when: es_config['multicast_enabled'] == false and es_config['transport_tcp_port'] is not defined - fail: msg="Parameter 'es_unicast_hosts' must be defined when multicast is disabled" - when: es_multicast_enabled == false and es_unicast_hosts is not defined \ No newline at end of file + when: es_config['multicast_enabled'] == false and es_config['unicast_hosts'] is not defined \ No newline at end of file diff --git a/tasks/elasticsearch-config.yml b/tasks/elasticsearch-config.yml index 98f7a68..c5fad45 100644 --- a/tasks/elasticsearch-config.yml +++ b/tasks/elasticsearch-config.yml @@ -44,15 +44,15 @@ when: es_max_open_files is defined register: elasticsearch_configure -#For directories we also use the {{ es_node_name_prefix }}{{inventory_hostname}} - this helps if we have a shared SAN. {{es_node_name_prefix}}{{default_file | basename} could potentially be used - +#For directories we also use the {{ es_config['node_name_prefix'] }}{{inventory_hostname}} - this helps if we have a shared SAN. {{es_config['node_name_prefix']}}{{default_file | basename} could potentially be used - #init script effectively means this is the default. #Create PID directory - name: Create PID Directory - file: path={{pid_dir}}/{{ es_node_name_prefix }}{{inventory_hostname}} state=directory owner={{ es_user }} group={{ es_group }} + file: path={{pid_dir}}/{{ es_config['node_name_prefix'] }}{{inventory_hostname}} state=directory owner={{ es_user }} group={{ es_group }} - name: Configure PID directory - lineinfile: dest={{instance_default_file}} regexp="^PID_DIR" insertafter="^#PID_DIR" line="PID_DIR={{pid_dir}}/{{ es_node_name_prefix }}{{inventory_hostname}}" + lineinfile: dest={{instance_default_file}} regexp="^PID_DIR" insertafter="^#PID_DIR" line="PID_DIR={{pid_dir}}/{{ es_config['node_name_prefix'] }}{{inventory_hostname}}" register: elasticsearch_configure - set_fact: es_data_dir={{default_data_dir}} @@ -60,30 +60,30 @@ #include the host name as potentially shared SAN - name: Create data dir - file: state=directory path={{ es_data_dir }}/{{ es_node_name_prefix }}{{inventory_hostname}} owner={{ es_user }} group={{ es_group }} + file: state=directory path={{ es_data_dir }}/{{ es_config['node_name_prefix'] }}{{inventory_hostname}} owner={{ es_user }} group={{ es_group }} - name: Configure data store - lineinfile: dest={{instance_default_file}} regexp="^DATA_DIR" insertafter="^#DATA_DIR" line="DATA_DIR={{ es_data_dir }}/{{ es_node_name_prefix }}{{inventory_hostname}}" + lineinfile: dest={{instance_default_file}} regexp="^DATA_DIR" insertafter="^#DATA_DIR" line="DATA_DIR={{ es_data_dir }}/{{ es_config['node_name_prefix'] }}{{inventory_hostname}}" register: elasticsearch_configure - set_fact: es_work_dir={{default_work_dir}} when: es_work_dir is undefined - name: Create work dir - file: state=directory path={{ es_work_dir }}/{{ es_node_name_prefix }}{{inventory_hostname}} owner={{ es_user }} group={{ es_group }} + file: state=directory path={{ es_work_dir }}/{{ es_config['node_name_prefix'] }}{{inventory_hostname}} owner={{ es_user }} group={{ es_group }} - name: Configure work directory - lineinfile: dest={{instance_default_file}} regexp="^WORK_DIR" insertafter="^#WORK_DIR" line="WORK_DIR={{ es_work_dir }}/{{ es_node_name_prefix }}{{inventory_hostname}}" + lineinfile: dest={{instance_default_file}} regexp="^WORK_DIR" insertafter="^#WORK_DIR" line="WORK_DIR={{ es_work_dir }}/{{ es_config['node_name_prefix'] }}{{inventory_hostname}}" register: elasticsearch_configure - set_fact: es_log_dir={{default_log_dir}} when: es_log_dir is undefined - name: Create log dir - file: state=directory path={{ es_log_dir }}/{{ es_node_name_prefix }}{{inventory_hostname}} owner={{ es_user }} group={{ es_group }} + file: state=directory path={{ es_log_dir }}/{{ es_config['node_name_prefix'] }}{{inventory_hostname}} owner={{ es_user }} group={{ es_group }} - name: Configure log directory - lineinfile: dest={{instance_default_file}} regexp="^LOG_DIR" insertafter="^#LOG_DIR" line="LOG_DIR={{ es_log_dir }}/{{ es_node_name_prefix }}{{inventory_hostname}}" + lineinfile: dest={{instance_default_file}} regexp="^LOG_DIR" insertafter="^#LOG_DIR" line="LOG_DIR={{ es_log_dir }}/{{ es_config['node_name_prefix'] }}{{inventory_hostname}}" register: elasticsearch_configure #required so that the ES_HOME does not change between instances @@ -104,7 +104,7 @@ #Apply changes to init script - NAME can be changed in Debian start script - name: Name Node in Init Script - lineinfile: dest={{instance_init_script}} regexp="^NAME" line="NAME={{es_node_name_prefix}}{{default_file | basename}}" + lineinfile: dest={{instance_init_script}} regexp="^NAME" line="NAME={{es_config['node_name_prefix']}}{{default_file | basename}}" register: elasticsearch_configure when: ansible_os_family == 'Debian' diff --git a/tasks/elasticsearch-plugins.yml b/tasks/elasticsearch-plugins.yml index 6da7dea..15bdf91 100644 --- a/tasks/elasticsearch-plugins.yml +++ b/tasks/elasticsearch-plugins.yml @@ -12,4 +12,4 @@ failed_when: "'Failed to install' in command_result.stderr" changed_when: command_result.rc == 0 with_items: es_plugins - when: ( ansible_os_family == 'RedHat' or ansible_os_family == 'Debian' ) + when: ( ansible_os_family == 'RedHat' or ansible_os_family == 'Debian' ) \ No newline at end of file diff --git a/tasks/elasticsearch.yml b/tasks/elasticsearch.yml index aca22c7..ca67ccd 100644 --- a/tasks/elasticsearch.yml +++ b/tasks/elasticsearch.yml @@ -1,7 +1,8 @@ --- -- set_fact: instance_default_file={{default_file | dirname}}/{{es_node_name_prefix}}{{default_file | basename}} -- set_fact: instance_init_script={{init_script | dirname }}/{{es_node_name_prefix}}{{init_script | basename}} -- set_fact: instance_config_directory={{ es_conf_dir }}/{{es_node_name_prefix}}elasticsearch +- debug: msg="Node configuration {{ es_config }} " +- set_fact: instance_default_file={{default_file | dirname}}/{{es_config["node_name_prefix"]}}{{default_file | basename}} +- set_fact: instance_init_script={{init_script | dirname }}/{{es_config['node_name_prefix']}}{{init_script | basename}} +- set_fact: instance_config_directory={{ es_conf_dir }}/{{es_config['node_name_prefix']}}elasticsearch diff --git a/templates/elasticsearch.yml.j2 b/templates/elasticsearch.yml.j2 index 16237f6..8633a78 100644 --- a/templates/elasticsearch.yml.j2 +++ b/templates/elasticsearch.yml.j2 @@ -29,29 +29,29 @@ # Cluster name identifies your cluster for auto-discovery. If you're running # multiple clusters on the same network, make sure you're using unique names. # -cluster.name: {{ es_cluster_name }} +cluster.name: {{ es_config['cluster_name'] }} #################################### Node ##################################### # Node names are generated dynamically on startup, so you're relieved # from configuring them manually. You can tie this node to a specific name: # -node.name: {{es_node_name_prefix}}{{inventory_hostname}} +node.name: {{ es_config['node_name_prefix'] }}{{inventory_hostname}} # Every node can be configured to allow or deny being eligible as the master, # and to allow or deny to store the data. # # Allow this node to be eligible as a master node (enabled by default): # -{% if es_master_node is defined %} -node.master: {{es_master_node | lower}} +{% if es_config['master_node'] is defined %} +node.master: {{ es_config['master_node'] | lower}} {% endif %} # # Allow this node to store data (enabled by default): # -{% if es_data_node is defined %} -node.data: {{es_data_node | lower}} +{% if es_config['data_node'] is defined %} +node.data: {{ es_config['data_node'] | lower}} {% endif %} # Use the Cluster Health API [http://localhost:9200/_cluster/health], the @@ -65,8 +65,8 @@ node.data: {{es_data_node | lower}} # for customized shard allocation filtering, or allocation awareness. An attribute # is a simple key value pair, similar to node.key: value, here is an example: # -{% if es_node_rack is defined %} -node.rack: {{ es_node_rack }} +{% if es_config['node_rack'] is defined %} +node.rack: {{ es_config['node_rack'] }} {% endif %} # By default, multiple nodes are allowed to start from the same installation location @@ -89,13 +89,13 @@ node.rack: {{ es_node_rack }} # Set the number of shards (splits) of an index (5 by default) if provided: -{% if es_index_number_of_shards is defined %} -index.number_of_shards: {{ es_index_number_of_shards }} +{% if es_config['index_number_of_shards'] is defined %} +index.number_of_shards: {{ es_config['index_number_of_shards'] }} {% endif %} # Set the number of replicas (additional copies) of an index (1 by default) if provided: -{% if es_index_number_of_replicas is defined %} -index.number_of_replicas: {{ es_index_number_of_replicas }} +{% if es_config['index_number_of_replicas'] is defined %} +index.number_of_replicas: {{ es_config['index_number_of_replicas'] }} {% endif %} @@ -124,10 +124,7 @@ index.number_of_replicas: {{ es_index_number_of_replicas }} #################################### Paths #################################### # Path to directory containing configuration (this file and logging.yml): -# -{% if es_conf_dir is defined %} -path.conf: {{ es_conf_dir }} -{% endif %} +path.conf: {{ instance_config_directory }} # Path to directory where to store index data allocated for this node. @@ -169,8 +166,8 @@ path.logs: {{ es_log_dir }} # # Set this property to true to lock the memory: # -{% if es_m_lock_enabled is defined %} -bootstrap.mlockall: {{es_m_lock_enabled | lower}} +{% if es_config['m_lock_enabled'] is defined %} +bootstrap.mlockall: {{ es_config['m_lock_enabled'] | lower}} {% endif %} @@ -200,15 +197,15 @@ bootstrap.mlockall: {{es_m_lock_enabled | lower}} # Set both 'bind_host' and 'publish_host': # -{% if es_network_host is defined %} -network.host: {{ es_network_host }} +{% if es_config['network_host'] is defined %} +network.host: {{ es_config['network_host'] }} {% endif %} # Set a custom port for the node to node communication (9300 by default): # -{% if es_transport_tcp_port is defined %} -transport.tcp.port: {{ es_transport_tcp_port }} +{% if es_config['transport_tcp_port'] is defined %} +transport.tcp.port: {{ es_config['transport_tcp_port'] }} {% endif %} # Enable compression for all communication between nodes (disabled by default): @@ -217,8 +214,8 @@ transport.tcp.port: {{ es_transport_tcp_port }} # Set a custom port to listen for HTTP traffic (9200 by default): # -{% if es_http_port is defined %} -http.port: {{ es_http_port }} +{% if es_config['http_port'] is defined %} +http.port: {{ es_config['http_port'] }} {% endif %} # Set a custom allowed content length: @@ -316,7 +313,7 @@ http.port: {{ es_http_port }} # # 1. Disable multicast discovery (enabled by default): # -discovery.zen.ping.multicast.enabled: {{es_multicast_enabled | lower }} +discovery.zen.ping.multicast.enabled: {{ es_config['multicast_enabled'] | lower }} # # 2. Configure an initial list of master nodes in the cluster @@ -325,8 +322,8 @@ discovery.zen.ping.multicast.enabled: {{es_multicast_enabled | lower }} #We put all the current eligible masters in here. If not specified, we assumes its a master -{% if es_multicast_enabled is defined and not es_multicast_enabled %} -discovery.zen.ping.unicast.hosts: {{es_unicast_hosts}} +{% if es_config['multicast_enabled'] is defined and not es_config['multicast_enabled'] %} +discovery.zen.ping.unicast.hosts: {{ es_config['unicast_hosts'] }} {% endif %} diff --git a/test/integration/config.yml b/test/integration/config.yml index da421b5..c5f8b4c 100644 --- a/test/integration/config.yml +++ b/test/integration/config.yml @@ -4,9 +4,9 @@ hosts: localhost roles: #expand to all available parameters - - { role: elasticsearch, es_unicast_hosts: "localhost:9301", es_http_port: "9201", es_transport_tcp_port: "9301", es_data_node: false, es_master_node: true, es_m_lock_enabled: true, es_multicast_enabled: false, es_node_name_prefix: "node1_", es_cluster_name: "custom-cluster" } + - { role: elasticsearch, es_config: { node_name_prefix: "node1_", cluster_name: "custom-cluster", unicast_hosts: "localhost:9301", http_port: "9201", transport_tcp_port: "9301", data_node: false, master_node: true, m_lock_enabled: true, multicast_enabled: false } } vars: es_scripts: false es_templates: false es_version_lock: false - es_m_lock_enabled: true \ No newline at end of file + es_config: { "m_lock_enabled": true } \ No newline at end of file diff --git a/test/integration/multi.yml b/test/integration/multi.yml index 2a1447c..99d957c 100644 --- a/test/integration/multi.yml +++ b/test/integration/multi.yml @@ -3,6 +3,6 @@ - name: Elasticsearch Config tests hosts: localhost roles: - - { role: elasticsearch, es_node_name_prefix: "node1_", es_unicast_hosts: "localhost:9300", es_http_port: "9201", es_transport_tcp_port: "9301", es_data_node: true, es_master_node: false, es_m_lock_enabled: true, es_multicast_enabled: false } - - { role: elasticsearch, es_node_name_prefix: "master_", es_unicast_hosts: "localhost:9300", es_http_port: "9200", es_transport_tcp_port: "9300", es_data_node: false, es_master_node: true, es_m_lock_enabled: true, es_multicast_enabled: false } + - { role: elasticsearch, es_config: { "multicast_enabled": false, node_name_prefix: "master_", unicast_hosts: "localhost:9300", http_port: "9200", transport_tcp_port: "9300", data_node: false, master_node: true, m_lock_enabled: true,multicast_enabled: false } } + - { role: elasticsearch, es_config: { "multicast_enabled": false, node_name_prefix: "node1_", unicast_hosts: "localhost:9300", http_port: "9201", transport_tcp_port: "9301", data_node: true, master_node: false, m_lock_enabled: true,multicast_enabled: false } } vars: diff --git a/test/integration/package.yml b/test/integration/package.yml index 23fd197..cccc9c8 100644 --- a/test/integration/package.yml +++ b/test/integration/package.yml @@ -2,5 +2,5 @@ - name: Elasticsearch Package tests hosts: localhost roles: - - { role: elasticsearch, es_multicast_enabled: true} + - { role: elasticsearch, es_config: { "multicast_enabled": true } } vars: \ No newline at end of file diff --git a/test/integration/standard.yml b/test/integration/standard.yml index c12deb7..dab13e3 100644 --- a/test/integration/standard.yml +++ b/test/integration/standard.yml @@ -2,9 +2,9 @@ - name: wrapper playbook for kitchen testing "elasticsearch" hosts: localhost roles: - - { role: elasticsearch, es_multicast_enabled: true} + - { role: elasticsearch, es_config: { "multicast_enabled": true } } vars: es_use_repository: "true" es_plugins: - plugin: lmenezes/elasticsearch-kopf - version: master + version: master \ No newline at end of file diff --git a/vars/Debian.yml b/vars/Debian.yml index 5c07034..7ad3450 100644 --- a/vars/Debian.yml +++ b/vars/Debian.yml @@ -3,9 +3,4 @@ java: "openjdk-7-jre-headless" default_file: "/etc/default/elasticsearch" init_script: "/etc/init.d/elasticsearch" es_conf_dir: "/etc/elasticsearch" -es_home: "/usr/share/elasticsearch" - -default_data_dir: "/var/lib/elasticsearch" -default_log_dir: "/var/log/elasticsearch" -default_work_dir: "/tmp/elasticsearch" -default_pid_dir: "/var/run/elasticsearch" \ No newline at end of file +es_home: "/usr/share/elasticsearch" \ No newline at end of file diff --git a/vars/main.yml b/vars/main.yml index d5bd5cf..0cd1e77 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -5,4 +5,4 @@ pid_dir: "/var/run/elasticsearch" #Needed to provide default directories default_data_dir: "/var/lib/elasticsearch" default_log_dir: "/var/log/elasticsearch" -default_work_dir: "/tmp/elasticsearch" +default_work_dir: "/tmp/elasticsearch" \ No newline at end of file From d25fc792b69889ddc23a864afe0525043ef7b630 Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Wed, 25 Nov 2015 15:28:09 +0000 Subject: [PATCH 04/27] Correct handling of map in template --- .kitchen.yml | 3 - ansible.cfg | 3 +- defaults/main.yml | 10 +- tasks/checkParameters.yml | 18 +- tasks/elasticsearch-config.yml | 40 +- tasks/elasticsearch-templates.yml | 1 + tasks/elasticsearch.yml | 13 +- tasks/main.yml | 8 +- templates/elasticsearch.yml.j2 | 383 +----------------- test/integration/config.yml | 4 +- .../config/serverspec/default_spec.rb | 11 +- test/integration/multi.yml | 6 +- .../multi/serverspec/default_spec.rb | 22 +- test/integration/package.yml | 2 +- .../package/serverspec/default_spec.rb | 10 +- test/integration/standard.yml | 2 +- .../standard/serverspec/default_spec.rb | 19 +- vars/RedHat.yml | 2 +- vars/main.yml | 6 - 19 files changed, 116 insertions(+), 447 deletions(-) diff --git a/.kitchen.yml b/.kitchen.yml index 68bdc44..a1f05b6 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -18,7 +18,6 @@ platforms: - apt-get update && apt-get install -y software-properties-common && add-apt-repository -y ppa:ansible/ansible - apt-get update && apt-get -y -q install ansible python-apt python-pycurl use_sudo: false - #run_command: "-e ENV ANSIBLE_HASH_BEHAVIOUR=merge" - name: debian-7 driver_config: image: electrical/debian:7.3 @@ -51,8 +50,6 @@ platforms: - sed -ri 's/^#?PasswordAuthentication .*/PasswordAuthentication yes/' /etc/ssh/sshd_config - sed -ri 's/^#?UsePAM .*/UsePAM no/' /etc/ssh/sshd_config - yum -y install initscripts - # - BUSSER_ROOT="/tmp/verifier" GEM_HOME="/tmp/verifier/gems" GEM_PATH="/tmp/verifier/gems" GEM_CACHE="/tmp/verifier/gems/cache" gem install --no-rdoc --no-ri rake - # - chown kitchen:kitchen /tmp/verifier -R - yum clean all run_command: "/usr/sbin/init" privileged: true diff --git a/ansible.cfg b/ansible.cfg index d7649f6..d9a8c50 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -1,2 +1 @@ -[defaults] -hash_behaviour = merge \ No newline at end of file +[defaults] \ No newline at end of file diff --git a/defaults/main.yml b/defaults/main.yml index 745fa7b..c403691 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -10,8 +10,8 @@ es_templates: false es_user: elasticsearch es_group: elasticsearch -es_config: { - "cluster_name": elasticsearch, - "multicast_enabled": false, - "node_name_prefix": "" -} \ No newline at end of file +#Need to provide default directories +es_pid_dir: "/var/run/elasticsearch" +es_data_dir: "/var/lib/elasticsearch" +es_log_dir: "/var/log/elasticsearch" +es_work_dir: "/tmp/elasticsearch" diff --git a/tasks/checkParameters.yml b/tasks/checkParameters.yml index 892ce03..e0b4ac8 100644 --- a/tasks/checkParameters.yml +++ b/tasks/checkParameters.yml @@ -1,10 +1,16 @@ # Check for mandatory parameters -- fail: msg="Parameter 'es_http_port' must be defined when multicast is disabled" - when: es_config['multicast_enabled'] == false and es_config['http_port'] is not defined +- fail: msg="es_instance_name must be specified" + when: es_instance_name is not defined -- fail: msg="Parameter 'es_transport_tcp_port' must be defined when multicast is disabled" - when: es_config['multicast_enabled'] == false and es_config['transport_tcp_port'] is not defined +- fail: msg="Parameter 'http.port' must be defined when multicast is disabled" + when: es_config['discovery.zen.ping.multicast.enabled'] == false and es_config['http.port'] is not defined -- fail: msg="Parameter 'es_unicast_hosts' must be defined when multicast is disabled" - when: es_config['multicast_enabled'] == false and es_config['unicast_hosts'] is not defined \ No newline at end of file +- fail: msg="Parameter 'transport.tcp.port' must be defined when multicast is disabled" + when: es_config['discovery.zen.ping.multicast.enabled'] == false and es_config['transport.tcp.port'] is not defined + +- fail: msg="Parameter 'discovery.zen.ping.unicast.hosts' must be defined when multicast is disabled" + when: es_config['discovery.zen.ping.multicast.enabled'] == false and es_config['discovery.zen.ping.unicast.hosts'] is not defined + + +# If multicast is false OR if > 2.0 AND not defined as true (or explictly false) \ No newline at end of file diff --git a/tasks/elasticsearch-config.yml b/tasks/elasticsearch-config.yml index c5fad45..128c9ae 100644 --- a/tasks/elasticsearch-config.yml +++ b/tasks/elasticsearch-config.yml @@ -2,6 +2,15 @@ # Configure Elasticsearch Node +- set_fact: pid_dir={{es_pid_dir}}/{{inventory_hostname}}-{{ es_instance_name }} + +- set_fact: data_dir={{ es_data_dir }}/{{inventory_hostname}}-{{ es_instance_name }} + +- set_fact: log_dir={{ es_log_dir }}/{{inventory_hostname}}-{{ es_instance_name }} + +- set_fact: work_dir={{ es_work_dir }}/{{inventory_hostname}}-{{ es_instance_name }} + + # Create an instance specific default file - name: Copy Default File for Instance command: creates={{instance_default_file}} cp "{{default_file}}" "{{instance_default_file}}" @@ -44,46 +53,37 @@ when: es_max_open_files is defined register: elasticsearch_configure -#For directories we also use the {{ es_config['node_name_prefix'] }}{{inventory_hostname}} - this helps if we have a shared SAN. {{es_config['node_name_prefix']}}{{default_file | basename} could potentially be used - -#init script effectively means this is the default. + +#For directories we also use the {{inventory_hostname}}-{{ es_instance_name }} - this helps if we have a shared SAN. #Create PID directory - name: Create PID Directory - file: path={{pid_dir}}/{{ es_config['node_name_prefix'] }}{{inventory_hostname}} state=directory owner={{ es_user }} group={{ es_group }} + file: path={{ pid_dir }} state=directory owner={{ es_user }} group={{ es_group }} - name: Configure PID directory - lineinfile: dest={{instance_default_file}} regexp="^PID_DIR" insertafter="^#PID_DIR" line="PID_DIR={{pid_dir}}/{{ es_config['node_name_prefix'] }}{{inventory_hostname}}" + lineinfile: dest={{instance_default_file}} regexp="^PID_DIR" insertafter="^#PID_DIR" line="PID_DIR={{ pid_dir }}" register: elasticsearch_configure -- set_fact: es_data_dir={{default_data_dir}} - when: es_data_dir is undefined - #include the host name as potentially shared SAN - name: Create data dir - file: state=directory path={{ es_data_dir }}/{{ es_config['node_name_prefix'] }}{{inventory_hostname}} owner={{ es_user }} group={{ es_group }} + file: state=directory path={{ data_dir }} owner={{ es_user }} group={{ es_group }} - name: Configure data store - lineinfile: dest={{instance_default_file}} regexp="^DATA_DIR" insertafter="^#DATA_DIR" line="DATA_DIR={{ es_data_dir }}/{{ es_config['node_name_prefix'] }}{{inventory_hostname}}" + lineinfile: dest={{instance_default_file}} regexp="^DATA_DIR" insertafter="^#DATA_DIR" line="DATA_DIR={{ data_dir }}" register: elasticsearch_configure -- set_fact: es_work_dir={{default_work_dir}} - when: es_work_dir is undefined - - name: Create work dir - file: state=directory path={{ es_work_dir }}/{{ es_config['node_name_prefix'] }}{{inventory_hostname}} owner={{ es_user }} group={{ es_group }} + file: state=directory path={{ work_dir }} owner={{ es_user }} group={{ es_group }} - name: Configure work directory - lineinfile: dest={{instance_default_file}} regexp="^WORK_DIR" insertafter="^#WORK_DIR" line="WORK_DIR={{ es_work_dir }}/{{ es_config['node_name_prefix'] }}{{inventory_hostname}}" + lineinfile: dest={{instance_default_file}} regexp="^WORK_DIR" insertafter="^#WORK_DIR" line="WORK_DIR={{ work_dir }}" register: elasticsearch_configure -- set_fact: es_log_dir={{default_log_dir}} - when: es_log_dir is undefined - - name: Create log dir - file: state=directory path={{ es_log_dir }}/{{ es_config['node_name_prefix'] }}{{inventory_hostname}} owner={{ es_user }} group={{ es_group }} + file: state=directory path={{ log_dir }} owner={{ es_user }} group={{ es_group }} - name: Configure log directory - lineinfile: dest={{instance_default_file}} regexp="^LOG_DIR" insertafter="^#LOG_DIR" line="LOG_DIR={{ es_log_dir }}/{{ es_config['node_name_prefix'] }}{{inventory_hostname}}" + lineinfile: dest={{instance_default_file}} regexp="^LOG_DIR" insertafter="^#LOG_DIR" line="LOG_DIR={{ log_dir }}" register: elasticsearch_configure #required so that the ES_HOME does not change between instances @@ -104,7 +104,7 @@ #Apply changes to init script - NAME can be changed in Debian start script - name: Name Node in Init Script - lineinfile: dest={{instance_init_script}} regexp="^NAME" line="NAME={{es_config['node_name_prefix']}}{{default_file | basename}}" + lineinfile: dest={{instance_init_script}} regexp="^NAME" line="NAME={{es_instance_name}}_{{default_file | basename}}" register: elasticsearch_configure when: ansible_os_family == 'Debian' diff --git a/tasks/elasticsearch-templates.yml b/tasks/elasticsearch-templates.yml index 26e345b..73f016f 100644 --- a/tasks/elasticsearch-templates.yml +++ b/tasks/elasticsearch-templates.yml @@ -1,4 +1,5 @@ --- +#TODO: How to handle in multi node - name: Copy templates to elasticsearch copy: src=templates dest=/etc/elasticsearch/ diff --git a/tasks/elasticsearch.yml b/tasks/elasticsearch.yml index ca67ccd..d161cac 100644 --- a/tasks/elasticsearch.yml +++ b/tasks/elasticsearch.yml @@ -1,10 +1,10 @@ --- + +- set_fact: instance_default_file={{default_file | dirname}}/{{es_instance_name}}_{{default_file | basename}} +- set_fact: instance_init_script={{init_script | dirname }}/{{es_instance_name}}_{{init_script | basename}} +- set_fact: instance_config_directory={{ es_conf_dir }}/{{es_instance_name}} + - debug: msg="Node configuration {{ es_config }} " -- set_fact: instance_default_file={{default_file | dirname}}/{{es_config["node_name_prefix"]}}{{default_file | basename}} -- set_fact: instance_init_script={{init_script | dirname }}/{{es_config['node_name_prefix']}}{{init_script | basename}} -- set_fact: instance_config_directory={{ es_conf_dir }}/{{es_config['node_name_prefix']}}elasticsearch - - # Install OS specific elasticsearch - this can be abbreviated in version 2.0.0 - name: Include specific Elasticsearch @@ -19,6 +19,9 @@ - name: Elasticsearch configuration include: elasticsearch-config.yml +#We remove the node.name key as it may be set by another node on the same server + + # Make sure the service is started, and restart if necessary - name: Start elasticsearch service service: name={{instance_init_script | basename}} state=started diff --git a/tasks/main.yml b/tasks/main.yml index 5791593..ca640cc 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -7,8 +7,8 @@ - include: elasticsearch.yml - include: elasticsearch-plugins.yml when: es_plugins is defined -- include: elasticsearch-scripts.yml - when: es_scripts -- include: elasticsearch-templates.yml - when: es_templates +#- include: elasticsearch-scripts.yml +# when: es_scripts +#- include: elasticsearch-templates.yml +# when: es_templates diff --git a/templates/elasticsearch.yml.j2 b/templates/elasticsearch.yml.j2 index 8633a78..275c93c 100644 --- a/templates/elasticsearch.yml.j2 +++ b/templates/elasticsearch.yml.j2 @@ -1,387 +1,20 @@ -##################### Elasticsearch Configuration Example ##################### +{{ es_config | to_nice_yaml }} -# This file contains an overview of various configuration settings, -# targeted at operations staff. Application developers should -# consult the guide at . -# -# The installation procedure is covered at -# . -# -# Elasticsearch comes with reasonable defaults for most settings, -# so you can try it out without bothering with configuration. -# -# Most of the time, these defaults are just fine for running a production -# cluster. If you're fine-tuning your cluster, or wondering about the -# effect of certain configuration option, please _do ask_ on the -# mailing list or IRC channel [http://elasticsearch.org/community]. - -# Any element in the configuration can be replaced with environment variables -# by placing them in ${...} notation. For example: -# -#node.rack: ${RACK_ENV_VAR} - -# For information on supported formats and syntax for the config file, see -# - - -################################### Cluster ################################### - -# Cluster name identifies your cluster for auto-discovery. If you're running -# multiple clusters on the same network, make sure you're using unique names. -# -cluster.name: {{ es_config['cluster_name'] }} - -#################################### Node ##################################### - -# Node names are generated dynamically on startup, so you're relieved -# from configuring them manually. You can tie this node to a specific name: -# -node.name: {{ es_config['node_name_prefix'] }}{{inventory_hostname}} - -# Every node can be configured to allow or deny being eligible as the master, -# and to allow or deny to store the data. -# -# Allow this node to be eligible as a master node (enabled by default): -# -{% if es_config['master_node'] is defined %} -node.master: {{ es_config['master_node'] | lower}} +{% if es_config['cluster.name'] is not defined %} +cluster.name: elasticsearch {% endif %} -# -# Allow this node to store data (enabled by default): -# -{% if es_config['data_node'] is defined %} -node.data: {{ es_config['data_node'] | lower}} +{% if es_config['node.name'] is not defined %} +node.name: {{inventory_hostname}}-{{es_instance_name}} {% endif %} -# Use the Cluster Health API [http://localhost:9200/_cluster/health], the -# Node Info API [http://localhost:9200/_nodes] or GUI tools -# such as , -# , -# and -# to inspect the cluster state. - -# A node can have generic attributes associated with it, which can later be used -# for customized shard allocation filtering, or allocation awareness. An attribute -# is a simple key value pair, similar to node.key: value, here is an example: -# -{% if es_config['node_rack'] is defined %} -node.rack: {{ es_config['node_rack'] }} -{% endif %} - -# By default, multiple nodes are allowed to start from the same installation location -# to disable it, set the following: -#node.max_local_storage_nodes: 1 - - -#################################### Index #################################### - -# You can set a number of options (such as shard/replica options, mapping -# or analyzer definitions, translog settings, ...) for indices globally, -# in this file. -# -# Note, that it makes more sense to configure index settings specifically for -# a certain index, either when creating it or by using the index templates API. -# -# See and -# -# for more information. - -# Set the number of shards (splits) of an index (5 by default) if provided: - -{% if es_config['index_number_of_shards'] is defined %} -index.number_of_shards: {{ es_config['index_number_of_shards'] }} -{% endif %} - -# Set the number of replicas (additional copies) of an index (1 by default) if provided: -{% if es_config['index_number_of_replicas'] is defined %} -index.number_of_replicas: {{ es_config['index_number_of_replicas'] }} -{% endif %} - - -# These settings directly affect the performance of index and search operations -# in your cluster. Assuming you have enough machines to hold shards and -# replicas, the rule of thumb is: -# -# 1. Having more *shards* enhances the _indexing_ performance and allows to -# _distribute_ a big index across machines. -# 2. Having more *replicas* enhances the _search_ performance and improves the -# cluster _availability_. -# -# The "number_of_shards" is a one-time setting for an index. -# -# The "number_of_replicas" can be increased or decreased anytime, -# by using the Index Update Settings API. -# -# Elasticsearch takes care about load balancing, relocating, gathering the -# results from nodes, etc. Experiment with different settings to fine-tune -# your setup. - -# Use the Index Status API () to inspect -# the index status. - - #################################### Paths #################################### # Path to directory containing configuration (this file and logging.yml): path.conf: {{ instance_config_directory }} +path.data: {{ data_dir }} -# Path to directory where to store index data allocated for this node. -# -# Can optionally include more than one location, causing data to be striped across -# the locations (a la RAID 0) on a file level, favouring locations with most free -# space on creation. For example: -# -{% if es_data_dir is defined %} -path.data: {{ es_data_dir }} -{% endif %} +path.work: {{ work_dir }} -# Path to temporary files: -{% if es_work_dir is defined %} -path.work: {{ es_work_dir }} -{% endif %} - -# Path to log files: -{% if es_log_dir is defined %} -path.logs: {{ es_log_dir }} -{% endif %} - -# Path to where plugins are installed: -# -#path.plugins: /path/to/plugins - - -#################################### Plugin ################################### - -# If a plugin listed here is not installed for current node, the node will not start. -# -#plugin.mandatory: mapper-attachments,lang-groovy - - -################################### Memory #################################### - -# Elasticsearch performs poorly when JVM starts swapping: you should ensure that -# it _never_ swaps. -# -# Set this property to true to lock the memory: -# -{% if es_config['m_lock_enabled'] is defined %} -bootstrap.mlockall: {{ es_config['m_lock_enabled'] | lower}} -{% endif %} - - -# Make sure that the ES_MIN_MEM and ES_MAX_MEM environment variables are set -# to the same value, and that the machine has enough memory to allocate -# for Elasticsearch, leaving enough memory for the operating system itself. -# -# You should also make sure that the Elasticsearch process is allowed to lock -# the memory, eg. by using `ulimit -l unlimited`. - - -############################## Network And HTTP ############################### - -# Elasticsearch, by default, binds itself to the 0.0.0.0 address, and listens -# on port [9200-9300] for HTTP traffic and on port [9300-9400] for node-to-node -# communication. (the range means that if the port is busy, it will automatically -# try the next port). - -# Set the bind address specifically (IPv4 or IPv6): -# -#network.bind_host: 192.168.0.1 - -# Set the address other nodes will use to communicate with this node. If not -# set, it is automatically derived. It must point to an actual IP address. -# -#network.publish_host: 192.168.0.1 - -# Set both 'bind_host' and 'publish_host': -# -{% if es_config['network_host'] is defined %} -network.host: {{ es_config['network_host'] }} -{% endif %} - - -# Set a custom port for the node to node communication (9300 by default): -# -{% if es_config['transport_tcp_port'] is defined %} -transport.tcp.port: {{ es_config['transport_tcp_port'] }} -{% endif %} - -# Enable compression for all communication between nodes (disabled by default): -# -#transport.tcp.compress: true - -# Set a custom port to listen for HTTP traffic (9200 by default): -# -{% if es_config['http_port'] is defined %} -http.port: {{ es_config['http_port'] }} -{% endif %} - -# Set a custom allowed content length: -# -#http.max_content_length: 100mb - -# Disable HTTP completely: -# -#http.enabled: false - - -################################### Gateway ################################### - -# The gateway allows for persisting the cluster state between full cluster -# restarts. Every change to the state (such as adding an index) will be stored -# in the gateway, and when the cluster starts up for the first time, -# it will read its state from the gateway. - -# There are several types of gateway implementations. For more information, see -# . - -# The default gateway type is the "local" gateway (recommended): -# -#gateway.type: local - -# Settings below control how and when to start the initial recovery process on -# a full cluster restart (to reuse as much local data as possible when using shared -# gateway). - -# Allow recovery process after N nodes in a cluster are up: -# -#gateway.recover_after_nodes: 1 - -# Set the timeout to initiate the recovery process, once the N nodes -# from previous setting are up (accepts time value): -# -#gateway.recover_after_time: 5m - -# Set how many nodes are expected in this cluster. Once these N nodes -# are up (and recover_after_nodes is met), begin recovery process immediately -# (without waiting for recover_after_time to expire): -# -#gateway.expected_nodes: 2 - - -############################# Recovery Throttling ############################# - -# These settings allow to control the process of shards allocation between -# nodes during initial recovery, replica allocation, rebalancing, -# or when adding and removing nodes. - -# Set the number of concurrent recoveries happening on a node: -# -# 1. During the initial recovery -# -#cluster.routing.allocation.node_initial_primaries_recoveries: 4 -# -# 2. During adding/removing nodes, rebalancing, etc -# -#cluster.routing.allocation.node_concurrent_recoveries: 2 - -# Set to throttle throughput when recovering (eg. 100mb, by default 20mb): -# -#indices.recovery.max_bytes_per_sec: 20mb - -# Set to limit the number of open concurrent streams when -# recovering a shard from a peer: -# -#indices.recovery.concurrent_streams: 5 - - -################################## Discovery ################################## - -# Discovery infrastructure ensures nodes can be found within a cluster -# and master node is elected. Multicast discovery is the default. - -# Set to ensure a node sees N other master eligible nodes to be considered -# operational within the cluster. This should be set to a quorum/majority of -# the master-eligible nodes in the cluster. -# -#discovery.zen.minimum_master_nodes: 1 - -# Set the time to wait for ping responses from other nodes when discovering. -# Set this option to a higher value on a slow or congested network -# to minimize discovery failures: -# -#discovery.zen.ping.timeout: 3s - -# For more information, see -# - -# Unicast discovery allows to explicitly control which nodes will be used -# to discover the cluster. It can be used when multicast is not present, -# or to restrict the cluster communication-wise. -# -# 1. Disable multicast discovery (enabled by default): -# -discovery.zen.ping.multicast.enabled: {{ es_config['multicast_enabled'] | lower }} - -# -# 2. Configure an initial list of master nodes in the cluster -# to perform discovery when new nodes (master or data) are started: -# - -#We put all the current eligible masters in here. If not specified, we assumes its a master - -{% if es_config['multicast_enabled'] is defined and not es_config['multicast_enabled'] %} -discovery.zen.ping.unicast.hosts: {{ es_config['unicast_hosts'] }} -{% endif %} - - -# EC2 discovery allows to use AWS EC2 API in order to perform discovery. -# -# You have to install the cloud-aws plugin for enabling the EC2 discovery. -# -# For more information, see -# -# -# See -# for a step-by-step tutorial. - -# GCE discovery allows to use Google Compute Engine API in order to perform discovery. -# -# You have to install the cloud-gce plugin for enabling the GCE discovery. -# -# For more information, see . - -# Azure discovery allows to use Azure API in order to perform discovery. -# -# You have to install the cloud-azure plugin for enabling the Azure discovery. -# -# For more information, see . - -################################## Slow Log ################################## - -# Shard level query and fetch threshold logging. - -index.search.slowlog.threshold.query.warn: 2s -index.search.slowlog.threshold.query.info: 2s -index.search.slowlog.threshold.query.debug: 1s -index.search.slowlog.threshold.query.trace: 500ms - -#index.search.slowlog.threshold.fetch.warn: 1s -#index.search.slowlog.threshold.fetch.info: 800ms -#index.search.slowlog.threshold.fetch.debug: 500ms -#index.search.slowlog.threshold.fetch.trace: 200ms - -#index.indexing.slowlog.threshold.index.warn: 10s -#index.indexing.slowlog.threshold.index.info: 5s -#index.indexing.slowlog.threshold.index.debug: 2s -#index.indexing.slowlog.threshold.index.trace: 500ms - -################################## GC Logging ################################ - -#monitor.jvm.gc.young.warn: 1000ms -#monitor.jvm.gc.young.info: 700ms -#monitor.jvm.gc.young.debug: 400ms - -#monitor.jvm.gc.old.warn: 10s -#monitor.jvm.gc.old.info: 5s -#monitor.jvm.gc.old.debug: 2s - -################################## Security ################################ - -# Uncomment if you want to enable JSONP as a valid return transport on the -# http server. With this enabled, it may pose a security risk, so disabling -# it unless you need it is recommended (it is disabled by default). -# -#http.jsonp.enable: true +path.logs: {{ log_dir }} \ No newline at end of file diff --git a/test/integration/config.yml b/test/integration/config.yml index c5f8b4c..98bbd75 100644 --- a/test/integration/config.yml +++ b/test/integration/config.yml @@ -4,9 +4,9 @@ hosts: localhost roles: #expand to all available parameters - - { role: elasticsearch, es_config: { node_name_prefix: "node1_", cluster_name: "custom-cluster", unicast_hosts: "localhost:9301", http_port: "9201", transport_tcp_port: "9301", data_node: false, master_node: true, m_lock_enabled: true, multicast_enabled: false } } + - { role: elasticsearch, es_instance_name: "node1", es_config: {node.name: "node1", cluster.name: "custom-cluster", discovery.zen.ping.unicast.hosts: "localhost:9301", http.port: 9201, transport.tcp.port: 9301, node.data: false, node.master: true, bootstrap.mlockall: true, discovery.zen.ping.multicast.enabled: false } } vars: es_scripts: false es_templates: false es_version_lock: false - es_config: { "m_lock_enabled": true } \ No newline at end of file + es_config: { "discovery.zen.ping.multicast.enabled": true } \ No newline at end of file diff --git a/test/integration/config/serverspec/default_spec.rb b/test/integration/config/serverspec/default_spec.rb index 9a616bd..0248fe1 100644 --- a/test/integration/config/serverspec/default_spec.rb +++ b/test/integration/config/serverspec/default_spec.rb @@ -14,20 +14,25 @@ context "basic tests" do it { should be_installed } end - describe file('/etc/elasticsearch/node1_elasticsearch/elasticsearch.yml') do + describe file('/etc/elasticsearch/node1/elasticsearch.yml') do it { should be_file } end #test configuration parameters have been set - test all appropriately set in config file - describe file('/etc/elasticsearch/node1_elasticsearch/elasticsearch.yml') do + describe file('/etc/elasticsearch/node1/elasticsearch.yml') do it { should contain 'http.port: 9201' } it { should contain 'transport.tcp.port: 9301' } it { should contain 'node.data: false' } it { should contain 'node.master: true' } it { should contain 'discovery.zen.ping.multicast.enabled: false' } it { should contain 'cluster.name: custom-cluster' } - it { should contain 'node.name: node1_localhost' } + it { should contain 'node.name: node1' } + it { should contain 'bootstrap.mlockall: true' } it { should contain 'discovery.zen.ping.unicast.hosts: localhost:9301' } + it { should contain 'path.conf: /etc/elasticsearch/node1' } + it { should contain 'path.data: /var/lib/elasticsearch/localhost-node1' } + it { should contain 'path.work: /tmp/elasticsearch/localhost-node1' } + it { should contain 'path.logs: /var/log/elasticsearch/localhost-node1' } end #test we started on the correct port was used diff --git a/test/integration/multi.yml b/test/integration/multi.yml index 99d957c..cec17ea 100644 --- a/test/integration/multi.yml +++ b/test/integration/multi.yml @@ -3,6 +3,6 @@ - name: Elasticsearch Config tests hosts: localhost roles: - - { role: elasticsearch, es_config: { "multicast_enabled": false, node_name_prefix: "master_", unicast_hosts: "localhost:9300", http_port: "9200", transport_tcp_port: "9300", data_node: false, master_node: true, m_lock_enabled: true,multicast_enabled: false } } - - { role: elasticsearch, es_config: { "multicast_enabled": false, node_name_prefix: "node1_", unicast_hosts: "localhost:9300", http_port: "9201", transport_tcp_port: "9301", data_node: true, master_node: false, m_lock_enabled: true,multicast_enabled: false } } - vars: + - { role: elasticsearch, es_instance_name: "master", es_config: { "discovery.zen.ping.multicast.enabled": false, discovery.zen.ping.unicast.hosts: "localhost:9300", http.port: 9200, transport.tcp.port: 9300, node.data: false, node.master: true, bootstrap.mlockall: true, discovery.zen.ping.multicast.enabled: false } } + - { role: elasticsearch, es_instance_name: "node1", es_config: { "discovery.zen.ping.multicast.enabled": false, discovery.zen.ping.unicast.hosts: "localhost:9300", http.port: 9201, transport.tcp.port: 9301, node.data: true, node.master: false, discovery.zen.ping.multicast.enabled: false } } + vars: \ No newline at end of file diff --git a/test/integration/multi/serverspec/default_spec.rb b/test/integration/multi/serverspec/default_spec.rb index 5269486..9ce6b7b 100644 --- a/test/integration/multi/serverspec/default_spec.rb +++ b/test/integration/multi/serverspec/default_spec.rb @@ -18,33 +18,43 @@ context "basic tests" do it { should be_installed } end - describe file('/etc/elasticsearch/node1_elasticsearch/elasticsearch.yml') do + describe file('/etc/elasticsearch/node1/elasticsearch.yml') do it { should be_file } end - describe file('/etc/elasticsearch/master_elasticsearch/elasticsearch.yml') do + describe file('/etc/elasticsearch/master/elasticsearch.yml') do it { should be_file } end #test configuration parameters have been set - test all appropriately set in config file - describe file('/etc/elasticsearch/node1_elasticsearch/elasticsearch.yml') do + describe file('/etc/elasticsearch/node1/elasticsearch.yml') do it { should contain 'http.port: 9201' } it { should contain 'transport.tcp.port: 9301' } it { should contain 'node.data: true' } it { should contain 'node.master: false' } it { should contain 'discovery.zen.ping.multicast.enabled: false' } - it { should contain 'node.name: node1_localhost' } + it { should contain 'node.name: localhost-node1' } + it { should_not contain 'bootstrap.mlockall: true' } + it { should contain 'path.conf: /etc/elasticsearch/node1' } + it { should contain 'path.data: /var/lib/elasticsearch/localhost-node1' } + it { should contain 'path.work: /tmp/elasticsearch/localhost-node1' } + it { should contain 'path.logs: /var/log/elasticsearch/localhost-node1' } end #test configuration parameters have been set for master - test all appropriately set in config file - describe file('/etc/elasticsearch/master_elasticsearch/elasticsearch.yml') do + describe file('/etc/elasticsearch/master/elasticsearch.yml') do it { should contain 'http.port: 9200' } it { should contain 'transport.tcp.port: 9300' } it { should contain 'node.data: false' } it { should contain 'node.master: true' } it { should contain 'discovery.zen.ping.multicast.enabled: false' } - it { should contain 'node.name: master_localhost' } + it { should contain 'node.name: localhost-master' } + it { should contain 'bootstrap.mlockall: true' } + it { should contain 'path.conf: /etc/elasticsearch/master' } + it { should contain 'path.data: /var/lib/elasticsearch/localhost-master' } + it { should contain 'path.work: /tmp/elasticsearch/localhost-master' } + it { should contain 'path.logs: /var/log/elasticsearch/localhost-master' } end describe 'Master listening' do diff --git a/test/integration/package.yml b/test/integration/package.yml index cccc9c8..5142f93 100644 --- a/test/integration/package.yml +++ b/test/integration/package.yml @@ -2,5 +2,5 @@ - name: Elasticsearch Package tests hosts: localhost roles: - - { role: elasticsearch, es_config: { "multicast_enabled": true } } + - { role: elasticsearch, es_config: { "discovery.zen.ping.multicast.enabled": true }, es_instance_name: "node1" } vars: \ No newline at end of file diff --git a/test/integration/package/serverspec/default_spec.rb b/test/integration/package/serverspec/default_spec.rb index 31d025a..6dc47a3 100644 --- a/test/integration/package/serverspec/default_spec.rb +++ b/test/integration/package/serverspec/default_spec.rb @@ -6,7 +6,7 @@ context "basic tests" do it { should exist } end - describe service('elasticsearch') do + describe service('node1_elasticsearch') do it { should be_running } end @@ -14,9 +14,15 @@ context "basic tests" do it { should be_installed } end - describe file('/etc/elasticsearch/elasticsearch/elasticsearch.yml') do + describe file('/etc/elasticsearch/node1/elasticsearch.yml') do it { should be_file } end + describe 'Node listening' do + it 'listening in port 9200' do + expect(port 9200).to be_listening + end + end + end diff --git a/test/integration/standard.yml b/test/integration/standard.yml index dab13e3..89236d7 100644 --- a/test/integration/standard.yml +++ b/test/integration/standard.yml @@ -2,7 +2,7 @@ - name: wrapper playbook for kitchen testing "elasticsearch" hosts: localhost roles: - - { role: elasticsearch, es_config: { "multicast_enabled": true } } + - { role: elasticsearch, es_config: { "discovery.zen.ping.multicast.enabled": true }, es_instance_name: "node1" } vars: es_use_repository: "true" es_plugins: diff --git a/test/integration/standard/serverspec/default_spec.rb b/test/integration/standard/serverspec/default_spec.rb index d7471a3..09e8742 100644 --- a/test/integration/standard/serverspec/default_spec.rb +++ b/test/integration/standard/serverspec/default_spec.rb @@ -6,7 +6,7 @@ context "basic tests" do it { should exist } end - describe service('elasticsearch') do + describe service('node1_elasticsearch') do it { should be_running } end @@ -14,10 +14,25 @@ context "basic tests" do it { should be_installed } end - describe file('/etc/elasticsearch/elasticsearch/elasticsearch.yml') do + describe file('/etc/elasticsearch/node1/elasticsearch.yml') do it { should be_file } end + describe file('/etc/elasticsearch/node1/elasticsearch.yml') do + it { should contain 'node.name: localhost-node1' } + it { should contain 'cluster.name: "elasticsearch"' } + it { should contain 'path.conf: /etc/elasticsearch/node1' } + it { should contain 'path.data: /var/lib/elasticsearch/localhost-node1' } + it { should contain 'path.work: /tmp/elasticsearch/localhost-node1' } + it { should contain 'path.logs: /var/log/elasticsearch/localhost-node1' } + end + + describe 'Node listening' do + it 'listening in port 9200' do + expect(port 9200).to be_listening + end + end + describe 'plugin' do it 'should be reported as existing', :retry => 3, :retry_wait => 10 do diff --git a/vars/RedHat.yml b/vars/RedHat.yml index c7be31d..f2f2f89 100644 --- a/vars/RedHat.yml +++ b/vars/RedHat.yml @@ -2,5 +2,5 @@ java: "java-1.8.0-openjdk.x86_64" default_file: "/etc/sysconfig/elasticsearch" init_script: "/etc/init.d/elasticsearch" -es_conf_dir: "/etc/elasticsearch/" +es_conf_dir: "/etc/elasticsearch" es_home: "/usr/share/elasticsearch" \ No newline at end of file diff --git a/vars/main.yml b/vars/main.yml index 0cd1e77..f4531d4 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -1,8 +1,2 @@ --- es_package_url: "https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch" -pid_dir: "/var/run/elasticsearch" - -#Needed to provide default directories -default_data_dir: "/var/lib/elasticsearch" -default_log_dir: "/var/log/elasticsearch" -default_work_dir: "/tmp/elasticsearch" \ No newline at end of file From bdb9ee6a4a727363fc8727c7100557d99972e8c2 Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Wed, 25 Nov 2015 17:13:45 +0000 Subject: [PATCH 05/27] Support for scripts --- defaults/main.yml | 2 +- tasks/checkParameters.yml | 2 +- tasks/elasticsearch-scripts.yml | 11 ++++++- tasks/main.yml | 4 +-- templates/elasticsearch.yml.j2 | 6 +++- test/integration/config.yml | 2 +- .../config/serverspec/default_spec.rb | 31 +++++++++++++++++-- test/integration/package.yml | 3 +- .../package/scripts/calculate-score.groovy | 1 + .../standard/serverspec/default_spec.rb | 2 +- vars/Debian.yml | 1 - vars/RedHat.yml | 1 - vars/main.yml | 1 + 13 files changed, 53 insertions(+), 14 deletions(-) create mode 100644 test/integration/package/scripts/calculate-score.groovy diff --git a/defaults/main.yml b/defaults/main.yml index c403691..2906571 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -14,4 +14,4 @@ es_group: elasticsearch es_pid_dir: "/var/run/elasticsearch" es_data_dir: "/var/lib/elasticsearch" es_log_dir: "/var/log/elasticsearch" -es_work_dir: "/tmp/elasticsearch" +es_work_dir: "/tmp/elasticsearch" \ No newline at end of file diff --git a/tasks/checkParameters.yml b/tasks/checkParameters.yml index e0b4ac8..11fe3d8 100644 --- a/tasks/checkParameters.yml +++ b/tasks/checkParameters.yml @@ -13,4 +13,4 @@ when: es_config['discovery.zen.ping.multicast.enabled'] == false and es_config['discovery.zen.ping.unicast.hosts'] is not defined -# If multicast is false OR if > 2.0 AND not defined as true (or explictly false) \ No newline at end of file +# If multicast is false OR if > 2.0 AND not defined as true (or explicitly false) \ No newline at end of file diff --git a/tasks/elasticsearch-scripts.yml b/tasks/elasticsearch-scripts.yml index 82655ab..eb55422 100644 --- a/tasks/elasticsearch-scripts.yml +++ b/tasks/elasticsearch-scripts.yml @@ -1,3 +1,12 @@ --- + +- set_fact: es_script_dir={{ es_log_dir }}/{{inventory_hostname}}-{{ es_instance_name }} + +- set_fact: es_script_dir={{es_config['path.scripts']}} + when: es_config['path.scripts'] is not defined + +- name: Create script dir + file: state=directory path={{ es_script_dir }} owner={{ es_user }} group={{ es_group }} + - name: Copy scripts to elasticsearch - copy: src=scripts dest=/etc/elasticsearch/ + copy: src=scripts dest={{ es_scripts_dir }} diff --git a/tasks/main.yml b/tasks/main.yml index ca640cc..2df9bd1 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -7,8 +7,8 @@ - include: elasticsearch.yml - include: elasticsearch-plugins.yml when: es_plugins is defined -#- include: elasticsearch-scripts.yml -# when: es_scripts +- include: elasticsearch-scripts.yml + when: es_scripts #- include: elasticsearch-templates.yml # when: es_templates diff --git a/templates/elasticsearch.yml.j2 b/templates/elasticsearch.yml.j2 index 275c93c..29c970d 100644 --- a/templates/elasticsearch.yml.j2 +++ b/templates/elasticsearch.yml.j2 @@ -17,4 +17,8 @@ path.data: {{ data_dir }} path.work: {{ work_dir }} -path.logs: {{ log_dir }} \ No newline at end of file +path.logs: {{ log_dir }} + +{% if es_scripts and es_config['path.scripts'] is not defined %} +path.scripts: {{ es_conf_dir }}/{{es_instance_name}}/scripts +{% endif %} \ No newline at end of file diff --git a/test/integration/config.yml b/test/integration/config.yml index 98bbd75..71b02b5 100644 --- a/test/integration/config.yml +++ b/test/integration/config.yml @@ -4,7 +4,7 @@ hosts: localhost roles: #expand to all available parameters - - { role: elasticsearch, es_instance_name: "node1", es_config: {node.name: "node1", cluster.name: "custom-cluster", discovery.zen.ping.unicast.hosts: "localhost:9301", http.port: 9201, transport.tcp.port: 9301, node.data: false, node.master: true, bootstrap.mlockall: true, discovery.zen.ping.multicast.enabled: false } } + - { role: elasticsearch, es_instance_name: "node1", es_data_dir: "/opt/elasticsearch/data", es_log_dir: "/opt/elasticsearch/logs", es_work_dir: "/opt/elasticsearch/temp", es_config: {node.name: "node1", cluster.name: "custom-cluster", discovery.zen.ping.unicast.hosts: "localhost:9301", http.port: 9201, transport.tcp.port: 9301, node.data: false, node.master: true, bootstrap.mlockall: true, discovery.zen.ping.multicast.enabled: false } } vars: es_scripts: false es_templates: false diff --git a/test/integration/config/serverspec/default_spec.rb b/test/integration/config/serverspec/default_spec.rb index 0248fe1..627a75f 100644 --- a/test/integration/config/serverspec/default_spec.rb +++ b/test/integration/config/serverspec/default_spec.rb @@ -30,9 +30,34 @@ context "basic tests" do it { should contain 'bootstrap.mlockall: true' } it { should contain 'discovery.zen.ping.unicast.hosts: localhost:9301' } it { should contain 'path.conf: /etc/elasticsearch/node1' } - it { should contain 'path.data: /var/lib/elasticsearch/localhost-node1' } - it { should contain 'path.work: /tmp/elasticsearch/localhost-node1' } - it { should contain 'path.logs: /var/log/elasticsearch/localhost-node1' } + it { should contain 'path.data: /opt/elasticsearch/data/localhost-node1' } + it { should contain 'path.work: /opt/elasticsearch/temp/localhost-node1' } + it { should contain 'path.logs: /opt/elasticsearch/logs/localhost-node1' } + end + + #test directories exist + describe file('/etc/elasticsearch/node1') do + it { should be_directory } + it { should be_owned_by 'elasticsearch' } + end + + describe file('/opt/elasticsearch/data/localhost-node1') do + it { should be_directory } + it { should be_owned_by 'elasticsearch' } + end + + describe file('/opt/elasticsearch/logs/localhost-node1') do + it { should be_directory } + it { should be_owned_by 'elasticsearch' } + end + + describe file('/opt/elasticsearch/temp/localhost-node1') do + it { should be_directory } + it { should be_owned_by 'elasticsearch' } + end + + describe file('/etc/init.d/node1_elasticsearch') do + it { should be_file } end #test we started on the correct port was used diff --git a/test/integration/package.yml b/test/integration/package.yml index 5142f93..9c7db94 100644 --- a/test/integration/package.yml +++ b/test/integration/package.yml @@ -3,4 +3,5 @@ hosts: localhost roles: - { role: elasticsearch, es_config: { "discovery.zen.ping.multicast.enabled": true }, es_instance_name: "node1" } - vars: \ No newline at end of file + vars: + es_scripts: true \ No newline at end of file diff --git a/test/integration/package/scripts/calculate-score.groovy b/test/integration/package/scripts/calculate-score.groovy new file mode 100644 index 0000000..442c25c --- /dev/null +++ b/test/integration/package/scripts/calculate-score.groovy @@ -0,0 +1 @@ +log(_score * 2) + my_modifier \ No newline at end of file diff --git a/test/integration/standard/serverspec/default_spec.rb b/test/integration/standard/serverspec/default_spec.rb index 09e8742..fa19d45 100644 --- a/test/integration/standard/serverspec/default_spec.rb +++ b/test/integration/standard/serverspec/default_spec.rb @@ -20,7 +20,7 @@ context "basic tests" do describe file('/etc/elasticsearch/node1/elasticsearch.yml') do it { should contain 'node.name: localhost-node1' } - it { should contain 'cluster.name: "elasticsearch"' } + it { should contain 'cluster.name: elasticsearch' } it { should contain 'path.conf: /etc/elasticsearch/node1' } it { should contain 'path.data: /var/lib/elasticsearch/localhost-node1' } it { should contain 'path.work: /tmp/elasticsearch/localhost-node1' } diff --git a/vars/Debian.yml b/vars/Debian.yml index 7ad3450..d0d3da3 100644 --- a/vars/Debian.yml +++ b/vars/Debian.yml @@ -2,5 +2,4 @@ java: "openjdk-7-jre-headless" default_file: "/etc/default/elasticsearch" init_script: "/etc/init.d/elasticsearch" -es_conf_dir: "/etc/elasticsearch" es_home: "/usr/share/elasticsearch" \ No newline at end of file diff --git a/vars/RedHat.yml b/vars/RedHat.yml index f2f2f89..0d8dbbe 100644 --- a/vars/RedHat.yml +++ b/vars/RedHat.yml @@ -2,5 +2,4 @@ java: "java-1.8.0-openjdk.x86_64" default_file: "/etc/sysconfig/elasticsearch" init_script: "/etc/init.d/elasticsearch" -es_conf_dir: "/etc/elasticsearch" es_home: "/usr/share/elasticsearch" \ No newline at end of file diff --git a/vars/main.yml b/vars/main.yml index f4531d4..1c232fa 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -1,2 +1,3 @@ --- es_package_url: "https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch" +es_conf_dir: "/etc/elasticsearch" \ No newline at end of file From 1daf8eb379cc0c588c8e87db060a74af671fd6cb Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Wed, 25 Nov 2015 17:40:14 +0000 Subject: [PATCH 06/27] Script tests --- .../package/scripts => scripts}/calculate-score.groovy | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {test/integration/package/scripts => scripts}/calculate-score.groovy (100%) diff --git a/test/integration/package/scripts/calculate-score.groovy b/scripts/calculate-score.groovy similarity index 100% rename from test/integration/package/scripts/calculate-score.groovy rename to scripts/calculate-score.groovy From 1739cc8595271e8727110f262d621422b1c64dca Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Wed, 25 Nov 2015 17:40:28 +0000 Subject: [PATCH 07/27] Script tests --- defaults/main.yml | 1 + tasks/elasticsearch-scripts.yml | 6 +++--- test/integration/package.yml | 3 ++- test/integration/package/serverspec/default_spec.rb | 5 +++++ 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 2906571..40b88e0 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -6,6 +6,7 @@ es_use_repository: true es_start_service: true es_plugins_reinstall: false es_scripts: false +es_scripts_src: scripts es_templates: false es_user: elasticsearch es_group: elasticsearch diff --git a/tasks/elasticsearch-scripts.yml b/tasks/elasticsearch-scripts.yml index eb55422..554bf8e 100644 --- a/tasks/elasticsearch-scripts.yml +++ b/tasks/elasticsearch-scripts.yml @@ -1,12 +1,12 @@ --- -- set_fact: es_script_dir={{ es_log_dir }}/{{inventory_hostname}}-{{ es_instance_name }} +- set_fact: es_script_dir={{ es_conf_dir }}/{{es_instance_name}}/scripts - set_fact: es_script_dir={{es_config['path.scripts']}} - when: es_config['path.scripts'] is not defined + when: es_config['path.scripts'] is defined - name: Create script dir file: state=directory path={{ es_script_dir }} owner={{ es_user }} group={{ es_group }} - name: Copy scripts to elasticsearch - copy: src=scripts dest={{ es_scripts_dir }} + copy: src={{es_scripts_src}} dest={{ es_script_dir }} \ No newline at end of file diff --git a/test/integration/package.yml b/test/integration/package.yml index 9c7db94..9adbfcc 100644 --- a/test/integration/package.yml +++ b/test/integration/package.yml @@ -4,4 +4,5 @@ roles: - { role: elasticsearch, es_config: { "discovery.zen.ping.multicast.enabled": true }, es_instance_name: "node1" } vars: - es_scripts: true \ No newline at end of file + es_scripts: true + es_scripts_src: "./test/package/scripts/" \ No newline at end of file diff --git a/test/integration/package/serverspec/default_spec.rb b/test/integration/package/serverspec/default_spec.rb index 6dc47a3..b01bc1c 100644 --- a/test/integration/package/serverspec/default_spec.rb +++ b/test/integration/package/serverspec/default_spec.rb @@ -18,6 +18,11 @@ context "basic tests" do it { should be_file } end + describe file('/etc/elasticsearch/node1/scripts') do + it { should be_directory } + it { should be_owned_by 'elasticsearch' } + end + describe 'Node listening' do it 'listening in port 9200' do expect(port 9200).to be_listening From 4ef743614334cbd8c35f30f0a8f3449b57f64575 Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Wed, 25 Nov 2015 18:31:03 +0000 Subject: [PATCH 08/27] script fixes --- defaults/main.yml | 1 - {scripts => files/scripts}/calculate-score.groovy | 0 tasks/elasticsearch-scripts.yml | 5 +++-- tasks/elasticsearch-templates.yml | 1 + templates/elasticsearch.yml.j2 | 6 +----- test/integration/package.yml | 3 +-- test/integration/package/serverspec/default_spec.rb | 5 +++++ 7 files changed, 11 insertions(+), 10 deletions(-) rename {scripts => files/scripts}/calculate-score.groovy (100%) diff --git a/defaults/main.yml b/defaults/main.yml index 40b88e0..2906571 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -6,7 +6,6 @@ es_use_repository: true es_start_service: true es_plugins_reinstall: false es_scripts: false -es_scripts_src: scripts es_templates: false es_user: elasticsearch es_group: elasticsearch diff --git a/scripts/calculate-score.groovy b/files/scripts/calculate-score.groovy similarity index 100% rename from scripts/calculate-score.groovy rename to files/scripts/calculate-score.groovy diff --git a/tasks/elasticsearch-scripts.yml b/tasks/elasticsearch-scripts.yml index 554bf8e..546ed19 100644 --- a/tasks/elasticsearch-scripts.yml +++ b/tasks/elasticsearch-scripts.yml @@ -1,12 +1,13 @@ --- -- set_fact: es_script_dir={{ es_conf_dir }}/{{es_instance_name}}/scripts +- set_fact: es_script_dir={{ es_conf_dir }}/{{es_instance_name}} - set_fact: es_script_dir={{es_config['path.scripts']}} when: es_config['path.scripts'] is defined - name: Create script dir file: state=directory path={{ es_script_dir }} owner={{ es_user }} group={{ es_group }} + when: es_config['path.scripts'] is defined - name: Copy scripts to elasticsearch - copy: src={{es_scripts_src}} dest={{ es_script_dir }} \ No newline at end of file + copy: src=scripts dest={{ es_script_dir }} owner={{ es_user }} group={{ es_group }} \ No newline at end of file diff --git a/tasks/elasticsearch-templates.yml b/tasks/elasticsearch-templates.yml index 73f016f..b6fa7c6 100644 --- a/tasks/elasticsearch-templates.yml +++ b/tasks/elasticsearch-templates.yml @@ -1,5 +1,6 @@ --- #TODO: How to handle in multi node +# 1. Template directory needs to be specifiable. 2. Port needs to based on configuration - name: Copy templates to elasticsearch copy: src=templates dest=/etc/elasticsearch/ diff --git a/templates/elasticsearch.yml.j2 b/templates/elasticsearch.yml.j2 index 29c970d..275c93c 100644 --- a/templates/elasticsearch.yml.j2 +++ b/templates/elasticsearch.yml.j2 @@ -17,8 +17,4 @@ path.data: {{ data_dir }} path.work: {{ work_dir }} -path.logs: {{ log_dir }} - -{% if es_scripts and es_config['path.scripts'] is not defined %} -path.scripts: {{ es_conf_dir }}/{{es_instance_name}}/scripts -{% endif %} \ No newline at end of file +path.logs: {{ log_dir }} \ No newline at end of file diff --git a/test/integration/package.yml b/test/integration/package.yml index 9adbfcc..9c7db94 100644 --- a/test/integration/package.yml +++ b/test/integration/package.yml @@ -4,5 +4,4 @@ roles: - { role: elasticsearch, es_config: { "discovery.zen.ping.multicast.enabled": true }, es_instance_name: "node1" } vars: - es_scripts: true - es_scripts_src: "./test/package/scripts/" \ No newline at end of file + es_scripts: true \ No newline at end of file diff --git a/test/integration/package/serverspec/default_spec.rb b/test/integration/package/serverspec/default_spec.rb index b01bc1c..5670024 100644 --- a/test/integration/package/serverspec/default_spec.rb +++ b/test/integration/package/serverspec/default_spec.rb @@ -23,6 +23,11 @@ context "basic tests" do it { should be_owned_by 'elasticsearch' } end + describe file('/etc/elasticsearch/node1/scripts/calculate-score.groovy') do + it { should be_file } + it { should be_owned_by 'elasticsearch' } + end + describe 'Node listening' do it 'listening in port 9200' do expect(port 9200).to be_listening From 23c8bdb7de11272cc7177b8b1260f72e29e7557c Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Wed, 25 Nov 2015 23:43:01 +0000 Subject: [PATCH 09/27] Fixes for scripts, Logging.yml moved --- defaults/main.yml | 2 +- files/templates/basic.json | 0 tasks/elasticsearch-config.yml | 10 ++++++---- tasks/elasticsearch-templates.yml | 11 ++++++++--- tasks/main.yml | 4 ++-- test/integration/standard/serverspec/default_spec.rb | 4 ++++ 6 files changed, 21 insertions(+), 10 deletions(-) create mode 100644 files/templates/basic.json diff --git a/defaults/main.yml b/defaults/main.yml index 2906571..96f0e88 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,6 +1,6 @@ --- es_major_version: "1.7" -es_version: "1.7.1" +es_version: "1.7.3" es_version_lock: false es_use_repository: true es_start_service: true diff --git a/files/templates/basic.json b/files/templates/basic.json new file mode 100644 index 0000000..e69de29 diff --git a/tasks/elasticsearch-config.yml b/tasks/elasticsearch-config.yml index 128c9ae..c8decc6 100644 --- a/tasks/elasticsearch-config.yml +++ b/tasks/elasticsearch-config.yml @@ -16,14 +16,11 @@ command: creates={{instance_default_file}} cp "{{default_file}}" "{{instance_default_file}}" when: instance_default_file != default_file -- debug: msg="DEBUG {{ hostvars[inventory_hostname] }}" - # Create an instance specific init file - name: Copy Init File for Instance command: creates={{instance_init_script}} cp "{{init_script}}" "{{instance_init_script}}" when: instance_init_script != init_script - #Create Config directory - name: Create Config Directory file: path={{ instance_config_directory }} state=directory owner={{ es_user }} group={{ es_group }} @@ -47,7 +44,6 @@ register: elasticsearch_configure #We only have to set these if they are specified. The start scripts will by default use the NAME set later on constructing directory names to avoid collisions. - - name: Configure max open files lineinfile: dest={{instance_default_file}} regexp="^MAX_OPEN_FILES" insertafter="^#MAX_OPEN_FILES" line="MAX_OPEN_FILES={{ es_max_open_files }}" when: es_max_open_files is defined @@ -115,3 +111,9 @@ register: elasticsearch_configure when: ansible_os_family == 'RedHat' +#Copy the logging.yml - TODO: i.e we may template this. +- name: Copy Logging.yml for Instance + command: creates={{instance_config_directory}}/logging.yml cp "{{ es_conf_dir }}/logging.yml" "{{instance_config_directory}}/logging.yml" + when: instance_init_script != init_script + +- file: path={{instance_config_directory}}/logging.yml state=touch owner={{ es_user }} group={{ es_group }} \ No newline at end of file diff --git a/tasks/elasticsearch-templates.yml b/tasks/elasticsearch-templates.yml index b6fa7c6..e524c0c 100644 --- a/tasks/elasticsearch-templates.yml +++ b/tasks/elasticsearch-templates.yml @@ -1,16 +1,21 @@ --- #TODO: How to handle in multi node -# 1. Template directory needs to be specifiable. 2. Port needs to based on configuration +# 1. Template directory needs to be specifiable - name: Copy templates to elasticsearch copy: src=templates dest=/etc/elasticsearch/ +- set_fact: http_port=9200 + +- set_fact: http_port={{es_config['http.port']}} + when: es_config['http.port'] is defined + - name: Wait for elasticsearch to startup - wait_for: port=9200 delay=10 + wait_for: port={{http_port}} delay=10 - name: Get template files shell: find . -maxdepth 1 -type f | sed "s#\./##" | sed "s/.json//" chdir=/etc/elasticsearch/templates register: resultstemplate - name: Install template(s) - command: 'curl -sL -XPUT http://localhost:9200/_template/{{item}} -d @/etc/elasticsearch/templates/{{item}}.json' + command: "curl -sL -XPUT http://localhost:{{http_port}}/_template/{{item}} -d @/etc/elasticsearch/templates/{{item}}.json" with_items: resultstemplate.stdout_lines diff --git a/tasks/main.yml b/tasks/main.yml index 2df9bd1..5791593 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -9,6 +9,6 @@ when: es_plugins is defined - include: elasticsearch-scripts.yml when: es_scripts -#- include: elasticsearch-templates.yml -# when: es_templates +- include: elasticsearch-templates.yml + when: es_templates diff --git a/test/integration/standard/serverspec/default_spec.rb b/test/integration/standard/serverspec/default_spec.rb index fa19d45..d378831 100644 --- a/test/integration/standard/serverspec/default_spec.rb +++ b/test/integration/standard/serverspec/default_spec.rb @@ -18,6 +18,10 @@ context "basic tests" do it { should be_file } end + describe file('/etc/elasticsearch/node1/logging.yml') do + it { should be_file } + end + describe file('/etc/elasticsearch/node1/elasticsearch.yml') do it { should contain 'node.name: localhost-node1' } it { should contain 'cluster.name: elasticsearch' } From 61fa65d16133d151b5a3ccdc8c78249ce9221860 Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Thu, 26 Nov 2015 10:20:58 +0000 Subject: [PATCH 10/27] Tests for templates --- files/templates/basic.json | 11 +++++++++++ tasks/elasticsearch-templates.yml | 4 ++-- test/integration/package.yml | 3 ++- .../package/serverspec/default_spec.rb | 18 ++++++++++++++++++ .../standard/serverspec/default_spec.rb | 4 ++-- 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/files/templates/basic.json b/files/templates/basic.json index e69de29..3a3871d 100644 --- a/files/templates/basic.json +++ b/files/templates/basic.json @@ -0,0 +1,11 @@ +{ + "template" : "te*", + "settings" : { + "number_of_shards" : 1 + }, + "mappings" : { + "type1" : { + "_source" : { "enabled" : false } + } + } +} \ No newline at end of file diff --git a/tasks/elasticsearch-templates.yml b/tasks/elasticsearch-templates.yml index e524c0c..3033e73 100644 --- a/tasks/elasticsearch-templates.yml +++ b/tasks/elasticsearch-templates.yml @@ -2,7 +2,7 @@ #TODO: How to handle in multi node # 1. Template directory needs to be specifiable - name: Copy templates to elasticsearch - copy: src=templates dest=/etc/elasticsearch/ + copy: src=templates dest=/etc/elasticsearch/ owner={{ es_user }} group={{ es_group }} - set_fact: http_port=9200 @@ -18,4 +18,4 @@ - name: Install template(s) command: "curl -sL -XPUT http://localhost:{{http_port}}/_template/{{item}} -d @/etc/elasticsearch/templates/{{item}}.json" - with_items: resultstemplate.stdout_lines + with_items: resultstemplate.stdout_lines \ No newline at end of file diff --git a/test/integration/package.yml b/test/integration/package.yml index 9c7db94..13710e7 100644 --- a/test/integration/package.yml +++ b/test/integration/package.yml @@ -4,4 +4,5 @@ roles: - { role: elasticsearch, es_config: { "discovery.zen.ping.multicast.enabled": true }, es_instance_name: "node1" } vars: - es_scripts: true \ No newline at end of file + es_scripts: true + es_templates: true \ No newline at end of file diff --git a/test/integration/package/serverspec/default_spec.rb b/test/integration/package/serverspec/default_spec.rb index 5670024..4751760 100644 --- a/test/integration/package/serverspec/default_spec.rb +++ b/test/integration/package/serverspec/default_spec.rb @@ -34,5 +34,23 @@ context "basic tests" do end end + describe file('/etc/elasticsearch/templates') do + it { should be_directory } + it { should be_owned_by 'elasticsearch' } + end + + describe file('/etc/elasticsearch/templates/basic.json') do + it { should be_file } + it { should be_owned_by 'elasticsearch' } + end + + describe 'Template Installed' do + it 'should be reported as being installed', :retry => 3, :retry_wait => 10 do + command = command('curl localhost:9200/_template/basic') + expect(command.stdout).to match(/basic/) + expect(command.exit_status).to eq(0) + end + end + end diff --git a/test/integration/standard/serverspec/default_spec.rb b/test/integration/standard/serverspec/default_spec.rb index d378831..78c7823 100644 --- a/test/integration/standard/serverspec/default_spec.rb +++ b/test/integration/standard/serverspec/default_spec.rb @@ -16,10 +16,12 @@ context "basic tests" do describe file('/etc/elasticsearch/node1/elasticsearch.yml') do it { should be_file } + it { should be_owned_by 'elasticsearch' } end describe file('/etc/elasticsearch/node1/logging.yml') do it { should be_file } + it { should be_owned_by 'elasticsearch' } end describe file('/etc/elasticsearch/node1/elasticsearch.yml') do @@ -38,13 +40,11 @@ context "basic tests" do end describe 'plugin' do - it 'should be reported as existing', :retry => 3, :retry_wait => 10 do command = command('curl localhost:9200/_nodes/?plugin | grep kopf') expect(command.stdout).to match(/kopf/) expect(command.exit_status).to eq(0) end - end end From f2621c4af9055d5befcc586ef0f8e13c5da29f1e Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Thu, 26 Nov 2015 10:56:35 +0000 Subject: [PATCH 11/27] Require ports and unicast to be specified for 2.0 --- tasks/checkParameters.yml | 7 +++---- test/integration/config.yml | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/tasks/checkParameters.yml b/tasks/checkParameters.yml index 11fe3d8..8e2cc88 100644 --- a/tasks/checkParameters.yml +++ b/tasks/checkParameters.yml @@ -4,13 +4,12 @@ when: es_instance_name is not defined - fail: msg="Parameter 'http.port' must be defined when multicast is disabled" - when: es_config['discovery.zen.ping.multicast.enabled'] == false and es_config['http.port'] is not defined + when: es_config['discovery.zen.ping.multicast.enabled'] == false or (es_version | version_compare('2.0', '>=') and es_config['discovery.zen.ping.multicast.enabled'] is not defined) and es_config['http.port'] is not defined - fail: msg="Parameter 'transport.tcp.port' must be defined when multicast is disabled" - when: es_config['discovery.zen.ping.multicast.enabled'] == false and es_config['transport.tcp.port'] is not defined + when: es_config['discovery.zen.ping.multicast.enabled'] == false or (es_version | version_compare('2.0', '>=') and es_config['discovery.zen.ping.multicast.enabled'] is not defined) and es_config['transport.tcp.port'] is not defined - fail: msg="Parameter 'discovery.zen.ping.unicast.hosts' must be defined when multicast is disabled" - when: es_config['discovery.zen.ping.multicast.enabled'] == false and es_config['discovery.zen.ping.unicast.hosts'] is not defined - + when: es_config['discovery.zen.ping.multicast.enabled'] == false or (es_version | version_compare('2.0', '>=') and es_config['discovery.zen.ping.multicast.enabled'] is not defined) and es_config['discovery.zen.ping.unicast.hosts'] is not defined # If multicast is false OR if > 2.0 AND not defined as true (or explicitly false) \ No newline at end of file diff --git a/test/integration/config.yml b/test/integration/config.yml index 71b02b5..bcb8925 100644 --- a/test/integration/config.yml +++ b/test/integration/config.yml @@ -8,5 +8,4 @@ vars: es_scripts: false es_templates: false - es_version_lock: false - es_config: { "discovery.zen.ping.multicast.enabled": true } \ No newline at end of file + es_version_lock: false \ No newline at end of file From dc9b2dd53c1cf4859bcbf3f97528a00f4e82e17a Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Thu, 26 Nov 2015 14:19:25 +0000 Subject: [PATCH 12/27] Support for mlock with tests --- meta/main.yml | 2 +- tasks/checkParameters.yml | 10 ++++++---- tasks/elasticsearch-config.yml | 20 +++++++++++++++++-- tasks/elasticsearch.yml | 4 ++-- test/integration/config.yml | 3 ++- .../config/serverspec/default_spec.rb | 5 +++++ 6 files changed, 34 insertions(+), 10 deletions(-) diff --git a/meta/main.yml b/meta/main.yml index 4f961d5..bc95109 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -3,7 +3,7 @@ allow_duplicates: yes galaxy_info: - author: Robin Clarke + author: Robin Clarke, Jakob Reiter, Dale McDiarmid description: Elasticsearch for Linux company: "Elastic.co" license: "license (Apache)" diff --git a/tasks/checkParameters.yml b/tasks/checkParameters.yml index 8e2cc88..3fbf5d9 100644 --- a/tasks/checkParameters.yml +++ b/tasks/checkParameters.yml @@ -4,12 +4,14 @@ when: es_instance_name is not defined - fail: msg="Parameter 'http.port' must be defined when multicast is disabled" - when: es_config['discovery.zen.ping.multicast.enabled'] == false or (es_version | version_compare('2.0', '>=') and es_config['discovery.zen.ping.multicast.enabled'] is not defined) and es_config['http.port'] is not defined + when: (es_config['discovery.zen.ping.multicast.enabled'] == False or (es_version | version_compare('2.0', '>=') and es_config['discovery.zen.ping.multicast.enabled'] is not defined)) and es_config['http.port'] is not defined - fail: msg="Parameter 'transport.tcp.port' must be defined when multicast is disabled" - when: es_config['discovery.zen.ping.multicast.enabled'] == false or (es_version | version_compare('2.0', '>=') and es_config['discovery.zen.ping.multicast.enabled'] is not defined) and es_config['transport.tcp.port'] is not defined + when: (es_config['discovery.zen.ping.multicast.enabled'] == False or (es_version | version_compare('2.0', '>=') and es_config['discovery.zen.ping.multicast.enabled'] is not defined)) and es_config['transport.tcp.port'] is not defined - fail: msg="Parameter 'discovery.zen.ping.unicast.hosts' must be defined when multicast is disabled" - when: es_config['discovery.zen.ping.multicast.enabled'] == false or (es_version | version_compare('2.0', '>=') and es_config['discovery.zen.ping.multicast.enabled'] is not defined) and es_config['discovery.zen.ping.unicast.hosts'] is not defined + when: (es_config['discovery.zen.ping.multicast.enabled'] == False or (es_version | version_compare('2.0', '>=') and es_config['discovery.zen.ping.multicast.enabled'] is not defined)) and es_config['discovery.zen.ping.unicast.hosts'] is not defined -# If multicast is false OR if > 2.0 AND not defined as true (or explicitly false) \ No newline at end of file +#If the user attempts to lock memory they must specify a heap size +- fail: msg="If locking memory with bootstrap.mlockall a heap size must be specified" + when: es_config['bootstrap.mlockall'] == True and es_heap_size is not defined \ No newline at end of file diff --git a/tasks/elasticsearch-config.yml b/tasks/elasticsearch-config.yml index c8decc6..a26ef55 100644 --- a/tasks/elasticsearch-config.yml +++ b/tasks/elasticsearch-config.yml @@ -111,9 +111,25 @@ register: elasticsearch_configure when: ansible_os_family == 'RedHat' -#Copy the logging.yml - TODO: i.e we may template this. +#Copy the logging.yml - name: Copy Logging.yml for Instance command: creates={{instance_config_directory}}/logging.yml cp "{{ es_conf_dir }}/logging.yml" "{{instance_config_directory}}/logging.yml" when: instance_init_script != init_script -- file: path={{instance_config_directory}}/logging.yml state=touch owner={{ es_user }} group={{ es_group }} \ No newline at end of file +- file: path={{instance_config_directory}}/logging.yml state=touch owner={{ es_user }} group={{ es_group }} + +#Configure mlock if enabled +- name: Configure mlock + lineinfile: dest={{instance_default_file}} regexp="^MAX_LOCKED_MEMORY" insertafter="^#MAX_LOCKED_MEMORY" line="MAX_LOCKED_MEMORY=unlimited" + when: es_config['bootstrap.mlockall'] is defined and es_config['bootstrap.mlockall'] == True + register: elasticsearch_configure + +#Change for systemd setting to ensure mlock is achieved + +- stat: path=/usr/lib/systemd/system/elasticsearch.service + register: systemd_service + +- name: Configure systemd + lineinfile: dest=/usr/lib/systemd/system/elasticsearch.service regexp="^LimitMEMLOCK" insertafter="^#LimitMEMLOCK" line="LimitMEMLOCK=infinity" + when: es_config['bootstrap.mlockall'] is defined and es_config['bootstrap.mlockall'] == True and systemd_service.stat.exists == True + register: elasticsearch_configure diff --git a/tasks/elasticsearch.yml b/tasks/elasticsearch.yml index d161cac..4b0ebbf 100644 --- a/tasks/elasticsearch.yml +++ b/tasks/elasticsearch.yml @@ -24,12 +24,12 @@ # Make sure the service is started, and restart if necessary - name: Start elasticsearch service - service: name={{instance_init_script | basename}} state=started + service: name={{instance_init_script | basename}} state=started enabled=yes when: es_start_service register: elasticsearch_started - name: Restart elasticsearch service if new version installed - service: name={{instance_init_script | basename}} state=restarted + service: name={{instance_init_script | basename}} state=restarted enabled=yes when: es_start_service and ( elasticsearch_install.changed or elasticsearch_configure.changed ) and not elasticsearch_started.changed diff --git a/test/integration/config.yml b/test/integration/config.yml index bcb8925..357752d 100644 --- a/test/integration/config.yml +++ b/test/integration/config.yml @@ -8,4 +8,5 @@ vars: es_scripts: false es_templates: false - es_version_lock: false \ No newline at end of file + es_version_lock: false + es_heap_size: 1g \ No newline at end of file diff --git a/test/integration/config/serverspec/default_spec.rb b/test/integration/config/serverspec/default_spec.rb index 627a75f..4d42eeb 100644 --- a/test/integration/config/serverspec/default_spec.rb +++ b/test/integration/config/serverspec/default_spec.rb @@ -67,6 +67,11 @@ context "basic tests" do its(:exit_status) { should eq 0 } end + #test to make sure mlock was applied + describe command('curl "localhost:9201/_nodes/process?pretty" | grep mlockall') do + its(:stdout) { should match /\"mlockall\" : true/ } + its(:exit_status) { should eq 0 } + end end From bddb7ee20bde7711e4fea992b94f7a40e6f4111c Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Thu, 26 Nov 2015 14:45:00 +0000 Subject: [PATCH 13/27] Tests for scripts, templates and mlock all on multi node installs --- tasks/checkParameters.yml | 2 +- test/integration/multi.yml | 6 +- .../multi/serverspec/default_spec.rb | 59 +++++++++++++++++++ 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/tasks/checkParameters.yml b/tasks/checkParameters.yml index 3fbf5d9..34d52d3 100644 --- a/tasks/checkParameters.yml +++ b/tasks/checkParameters.yml @@ -14,4 +14,4 @@ #If the user attempts to lock memory they must specify a heap size - fail: msg="If locking memory with bootstrap.mlockall a heap size must be specified" - when: es_config['bootstrap.mlockall'] == True and es_heap_size is not defined \ No newline at end of file + when: es_config['bootstrap.mlockall'] is defined and es_config['bootstrap.mlockall'] == True and es_heap_size is not defined \ No newline at end of file diff --git a/test/integration/multi.yml b/test/integration/multi.yml index cec17ea..7943b44 100644 --- a/test/integration/multi.yml +++ b/test/integration/multi.yml @@ -3,6 +3,8 @@ - name: Elasticsearch Config tests hosts: localhost roles: - - { role: elasticsearch, es_instance_name: "master", es_config: { "discovery.zen.ping.multicast.enabled": false, discovery.zen.ping.unicast.hosts: "localhost:9300", http.port: 9200, transport.tcp.port: 9300, node.data: false, node.master: true, bootstrap.mlockall: true, discovery.zen.ping.multicast.enabled: false } } + - { role: elasticsearch, es_heap_size: "1g", es_instance_name: "master", es_config: { "discovery.zen.ping.multicast.enabled": false, discovery.zen.ping.unicast.hosts: "localhost:9300", http.port: 9200, transport.tcp.port: 9300, node.data: false, node.master: true, bootstrap.mlockall: true, discovery.zen.ping.multicast.enabled: false } } - { role: elasticsearch, es_instance_name: "node1", es_config: { "discovery.zen.ping.multicast.enabled": false, discovery.zen.ping.unicast.hosts: "localhost:9300", http.port: 9201, transport.tcp.port: 9301, node.data: true, node.master: false, discovery.zen.ping.multicast.enabled: false } } - vars: \ No newline at end of file + vars: + es_scripts: true + es_templates: true \ No newline at end of file diff --git a/test/integration/multi/serverspec/default_spec.rb b/test/integration/multi/serverspec/default_spec.rb index 9ce6b7b..6d09358 100644 --- a/test/integration/multi/serverspec/default_spec.rb +++ b/test/integration/multi/serverspec/default_spec.rb @@ -87,5 +87,64 @@ context "basic tests" do end end + #test to make sure mlock was applied + describe command('curl "localhost:9200/_nodes/process?pretty" | grep mlockall') do + its(:stdout) { should match /\"mlockall\" : true/ } + its(:exit_status) { should eq 0 } + end + + #test to make sure mlock was not applied + describe command('curl "localhost:9201/_nodes/process?pretty" | grep mlockall') do + its(:stdout) { should match /\"mlockall\" : false/ } + its(:exit_status) { should eq 0 } + end + + describe file('/etc/elasticsearch/templates') do + it { should be_directory } + it { should be_owned_by 'elasticsearch' } + end + + describe file('/etc/elasticsearch/templates/basic.json') do + it { should be_file } + it { should be_owned_by 'elasticsearch' } + end + + describe 'Template Installed' do + it 'should be reported as being installed', :retry => 3, :retry_wait => 10 do + command = command('curl localhost:9200/_template/basic') + expect(command.stdout).to match(/basic/) + expect(command.exit_status).to eq(0) + end + end + + describe 'Template Installed' do + it 'should be reported as being installed', :retry => 3, :retry_wait => 10 do + command = command('curl localhost:9201/_template/basic') + expect(command.stdout).to match(/basic/) + expect(command.exit_status).to eq(0) + end + end + + #Confirm scripts are on both nodes + describe file('/etc/elasticsearch/node1/scripts') do + it { should be_directory } + it { should be_owned_by 'elasticsearch' } + end + + describe file('/etc/elasticsearch/node1/scripts/calculate-score.groovy') do + it { should be_file } + it { should be_owned_by 'elasticsearch' } + end + + describe file('/etc/elasticsearch/master/scripts') do + it { should be_directory } + it { should be_owned_by 'elasticsearch' } + end + + describe file('/etc/elasticsearch/master/scripts/calculate-score.groovy') do + it { should be_file } + it { should be_owned_by 'elasticsearch' } + end + end From e98b74ab28374d8fc575c308b9851a465a4a77ac Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Thu, 26 Nov 2015 15:58:48 +0000 Subject: [PATCH 14/27] Data directory checks and inheritence variable test --- test/integration/multi.yml | 2 +- .../integration/multi/serverspec/default_spec.rb | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/test/integration/multi.yml b/test/integration/multi.yml index 7943b44..e138f7b 100644 --- a/test/integration/multi.yml +++ b/test/integration/multi.yml @@ -3,7 +3,7 @@ - name: Elasticsearch Config tests hosts: localhost roles: - - { role: elasticsearch, es_heap_size: "1g", es_instance_name: "master", es_config: { "discovery.zen.ping.multicast.enabled": false, discovery.zen.ping.unicast.hosts: "localhost:9300", http.port: 9200, transport.tcp.port: 9300, node.data: false, node.master: true, bootstrap.mlockall: true, discovery.zen.ping.multicast.enabled: false } } + - { role: elasticsearch, es_instance_name: "master", es_data_dir: "/opt/elasticsearch", es_heap_size: "1g", es_config: { "discovery.zen.ping.multicast.enabled": false, discovery.zen.ping.unicast.hosts: "localhost:9300", http.port: 9200, transport.tcp.port: 9300, node.data: false, node.master: true, bootstrap.mlockall: true, discovery.zen.ping.multicast.enabled: false } } - { role: elasticsearch, es_instance_name: "node1", es_config: { "discovery.zen.ping.multicast.enabled": false, discovery.zen.ping.unicast.hosts: "localhost:9300", http.port: 9201, transport.tcp.port: 9301, node.data: true, node.master: false, discovery.zen.ping.multicast.enabled: false } } vars: es_scripts: true diff --git a/test/integration/multi/serverspec/default_spec.rb b/test/integration/multi/serverspec/default_spec.rb index 6d09358..3447f4a 100644 --- a/test/integration/multi/serverspec/default_spec.rb +++ b/test/integration/multi/serverspec/default_spec.rb @@ -52,7 +52,7 @@ context "basic tests" do it { should contain 'node.name: localhost-master' } it { should contain 'bootstrap.mlockall: true' } it { should contain 'path.conf: /etc/elasticsearch/master' } - it { should contain 'path.data: /var/lib/elasticsearch/localhost-master' } + it { should contain 'path.data: /opt/elasticsearch/localhost-master' } it { should contain 'path.work: /tmp/elasticsearch/localhost-master' } it { should contain 'path.logs: /var/log/elasticsearch/localhost-master' } end @@ -146,5 +146,19 @@ context "basic tests" do it { should be_owned_by 'elasticsearch' } end + #Confirm that the data directory has only been set for the first node + describe file('/opt/elasticsearch/localhost-master') do + it { should be_directory } + it { should be_owned_by 'elasticsearch' } + end + + describe file('/opt/elasticsearch/localhost-node1') do + it { should_not exist } + end + + describe file('/var/lib/elasticsearch/localhost-node1') do + it { should be_directory } + it { should be_owned_by 'elasticsearch' } + end end From b2997cc0bcca40f2f84a5fae1aa1c9b5db325800 Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Thu, 26 Nov 2015 17:26:28 +0000 Subject: [PATCH 15/27] Additional tests + support for empty es_config + documentation --- README.md | 140 +++++++++++------- defaults/main.yml | 2 +- tasks/checkParameters.yml | 8 +- tasks/elasticsearch-config.yml | 1 + templates/elasticsearch.yml.j2 | 3 + test/integration/config.yml | 2 +- test/integration/multi.yml | 2 +- .../multi/serverspec/default_spec.rb | 4 +- test/integration/standard.yml | 2 +- 9 files changed, 101 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index 77801fd..e26197b 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,7 @@ Ansible playbook / roles / tasks for Elasticsearch. Currently it will work on D ## Usage -Create your ansible playbook with your own tasks, and include the role elasticsearch. -You will have to have this repository accessible within the context of playbook, e.g. +Create your Ansible playbook with your own tasks, and include the role elasticsearch. You will have to have this repository accessible within the context of playbook, e.g. e.g. @@ -17,23 +16,46 @@ mkdir -p roles ln -s /my/repos/ansible-elasticsearch ./roles/elasticsearch ``` -Then create your playbook yaml adding the role elasticsearch and overriding any variables you wish. It can be as simple as this to take all the defaults: +Then create your playbook yaml adding the role elasticsearch. By default, the user is only required to specify a unique es_instance_name per role application. +The simplest configuration therefore consists of: ``` --- -hosts: my_host +- name: Simple Example + hosts: localhost roles: - - { role: elasticsearch, es_multicast_enabled: true} - tasks: - - .... your tasks ... + - { role: elasticsearch, es_instance_name: "node1" } + vars: ``` -By default es_multicast_enabled is false and the user is required to specify the following additional parameters: +All Elasticsearch configuration parameters are supported. This is achieved using a configuration map parameter 'es_config' which is serialized into the elasticsearch.yml file. +The use of a map ensures the Ansible playbook does not need to be updated to reflect new/deprecated/plugin configuration parameters. -1. es_http_port - the http port for the node -2. es_transport_tcp_port - the transport port for the node -3. es_unicast_hosts - the unicast discovery list, in the comma separated format ":,:" (typically the clusters dedicated masters) +In addition to the es_config map, several other parameters are supported for additional functions e.g. script installation. These can be found in the role's defaults/main.yml file. + +The following illustrates applying configuration parameters to an Elasticsearch instance. + +``` +- name: Elasticsearch with custom configuration + hosts: localhost + roles: + #expand to all available parameters + - { role: elasticsearch, es_instance_name: "node1", es_data_dir: "/opt/elasticsearch/data", es_log_dir: "/opt/elasticsearch/logs", es_work_dir: "/opt/elasticsearch/temp", es_config: {node.name: "node1", cluster.name: "custom-cluster", discovery.zen.ping.unicast.hosts: "localhost:9301", http.port: 9201, transport.tcp.port: 9301, node.data: false, node.master: true, bootstrap.mlockall: true, discovery.zen.ping.multicast.enabled: false } } + vars: + es_scripts: false + es_templates: false + es_version_lock: false + es_heap_size: 1g +``` + + + +The playbook utilises Elasticsearch version defaults. By default, therefore, multicast is enabled for 1.x. If disabled, the user user is required to specify the following additional parameters: + +1. es_config['http.port'] - the http port for the node +2. es_config['transport.tcp.port'] - the transport port for the node +3. es_config['discovery.zen.ping.unicast.hosts'] - the unicast discovery list, in the comma separated format ":,:" (typically the clusters dedicated masters) If set to true, the ports will be auto defined and node discovery will be performed using multicast. @@ -42,65 +64,75 @@ A more complex example: ``` --- -hosts: localhost -roles: - - { role: elasticsearch, es_unicast_hosts: "localhost:9301", es_http_port: "9201", es_transport_tcp_port: "9301", es_data_node: false, es_master_node: true, es_m_lock_enabled: true, es_multicast_enabled: false, es_node_name_prefix: "node1_", es_cluster_name: "custom-cluster" } -vars: - es_scripts: false - es_templates: false - es_version_lock: false - es_m_lock_enabled: true - es_start_service: false - es_plugins_reinstall: false - es_plugins: - - plugin: elasticsearch/elasticsearch-cloud-aws - version: 2.5.0 - - plugin: elasticsearch/marvel - version: latest - - plugin: elasticsearch/license - version: latest - - plugin: elasticsearch/shield - version: latest - - plugin: elasticsearch/elasticsearch-support-diagnostics - version: latest - - plugin: lmenezes/elasticsearch-kopf - version: master -tasks: - - .... your tasks ... +- name: Elasticsearch with custom configuration + hosts: localhost + roles: + #expand to all available parameters + - { role: elasticsearch, es_instance_name: "node1", es_data_dir: "/opt/elasticsearch/data", es_log_dir: "/opt/elasticsearch/logs", es_work_dir: "/opt/elasticsearch/temp", es_config: {node.name: "node1", cluster.name: "custom-cluster", discovery.zen.ping.unicast.hosts: "localhost:9301", http.port: 9201, transport.tcp.port: 9301, node.data: false, node.master: true, bootstrap.mlockall: true, discovery.zen.ping.multicast.enabled: false } } + vars: + es_scripts: false + es_templates: false + es_version_lock: false + es_heap_size: 1g + es_scripts: false + es_templates: false + es_version_lock: false + es_start_service: false + es_plugins_reinstall: false + es_plugins: + - plugin: elasticsearch/elasticsearch-cloud-aws + version: 2.5.0 + - plugin: elasticsearch/marvel + version: latest + - plugin: elasticsearch/license + version: latest + - plugin: elasticsearch/shield + version: latest + - plugin: elasticsearch/elasticsearch-support-diagnostics + version: latest + - plugin: lmenezes/elasticsearch-kopf + version: master ``` -The above example illustrates the ability to control the configuration. +The application of a role results in the installation of a node on a host. Multiple roles equates to multiple nodes for a single host. -The application of a role results in the installation of a node on a host. Multiple roles equates to multiple nodes for a single host. If specifying multiple roles for a host, and thus multiple nodes, the user must: - -1. Provide a es_node_name_prefix. This is used to ensure seperation of data, log, config and init scripts. -2. Ensure those playbooks responsible for installing and starting master eligble roles are specified first. These are required for cluster initalization. +In any multi node cluster configuration it is recommened the user list the master eligble roles first - especially if these are used a unicast hosts off which other nodes are 'booted' An example of a two server deployment, each with 1 node on one server and 2 nodes on another. The first server holds the master and is thus declared first. ``` --- -hosts: masters -roles: - - { role: elasticsearch, es_node_name_prefix: "node1_", es_unicast_hosts: "localhost:9300", es_http_port: "9201", es_transport_tcp_port: "9301", es_data_node: true, es_master_node: false, es_m_lock_enabled: true, es_multicast_enabled: false } -vars: - es_scripts: false - es_templates: false - es_version_lock: false - es_cluster_name: example-cluster - m_lock_enabled: false -- hosts: data_nodes +- hosts: master_nodes roles: - - { role: elasticsearch, es_data_node: true, es_master_node: false, es_m_lock_enabled: true, es_multicast_enabled: false, es_node_name_prefix: "node1_" } - - { role: elasticsearch, es_data_node: true, es_master_node: false, es_m_lock_enabled: true, es_multicast_enabled: false, es_node_name_prefix: "node2_" } + # one master per host + - { role: elasticsearch, es_instance_name: "node1", es_heap_size: "1g", es_config: { "discovery.zen.ping.multicast.enabled": false, discovery.zen.ping.unicast.hosts: "elastic02:9300", http.port: 9200, transport.tcp.port: 9300, node.data: false, node.master: true, bootstrap.mlockall: false, discovery.zen.ping.multicast.enabled: false } } vars: es_scripts: false es_templates: false es_version_lock: false - es_cluster_name: example-cluster + es_cluster_name: test-cluster m_lock_enabled: true + ansible_user: ansible es_plugins: + - plugin: elasticsearch/license + version: latest + +- hosts: data_nodes + roles: + # two nodes per host + - { role: elasticsearch, es_instance_name: "node1", es_data_dir: "/opt/elasticsearch", es_config: { "discovery.zen.ping.multicast.enabled": false, discovery.zen.ping.unicast.hosts: "elastic02:9300", http.port: 9200, transport.tcp.port: 9300, node.data: true, node.master: false, bootstrap.mlockall: false, discovery.zen.ping.multicast.enabled: false } } + - { role: elasticsearch, es_instance_name: "node2", es_config: { "discovery.zen.ping.multicast.enabled": false, discovery.zen.ping.unicast.hosts: "elastic02:9300", http.port: 9201, transport.tcp.port: 9301, node.data: true, node.master: false, bootstrap.mlockall: false, discovery.zen.ping.multicast.enabled: false } } + vars: + es_scripts: false + es_templates: false + es_version_lock: false + es_cluster_name: test-cluster + m_lock_enabled: false + ansible_user: ansible + es_plugins: + - plugin: elasticsearch/license + version: latest ``` Parameters can additionally be assigned to hosts using the inventory file if desired. diff --git a/defaults/main.yml b/defaults/main.yml index 96f0e88..86ac56d 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -9,7 +9,7 @@ es_scripts: false es_templates: false es_user: elasticsearch es_group: elasticsearch - +es_config: {} #Need to provide default directories es_pid_dir: "/var/run/elasticsearch" es_data_dir: "/var/lib/elasticsearch" diff --git a/tasks/checkParameters.yml b/tasks/checkParameters.yml index 34d52d3..d2a03a4 100644 --- a/tasks/checkParameters.yml +++ b/tasks/checkParameters.yml @@ -3,14 +3,16 @@ - fail: msg="es_instance_name must be specified" when: es_instance_name is not defined +- set_fact: multi_cast={{ (es_version | version_compare('2.0', '<') and es_config['discovery.zen.ping.multicast.enabled'] is not defined) or es_config['discovery.zen.ping.multicast.enabled']}} + - fail: msg="Parameter 'http.port' must be defined when multicast is disabled" - when: (es_config['discovery.zen.ping.multicast.enabled'] == False or (es_version | version_compare('2.0', '>=') and es_config['discovery.zen.ping.multicast.enabled'] is not defined)) and es_config['http.port'] is not defined + when: not multi_cast and es_config['http.port'] is not defined - fail: msg="Parameter 'transport.tcp.port' must be defined when multicast is disabled" - when: (es_config['discovery.zen.ping.multicast.enabled'] == False or (es_version | version_compare('2.0', '>=') and es_config['discovery.zen.ping.multicast.enabled'] is not defined)) and es_config['transport.tcp.port'] is not defined + when: not multi_cast and es_config['transport.tcp.port'] is not defined - fail: msg="Parameter 'discovery.zen.ping.unicast.hosts' must be defined when multicast is disabled" - when: (es_config['discovery.zen.ping.multicast.enabled'] == False or (es_version | version_compare('2.0', '>=') and es_config['discovery.zen.ping.multicast.enabled'] is not defined)) and es_config['discovery.zen.ping.unicast.hosts'] is not defined + when: not multi_cast and es_config['discovery.zen.ping.unicast.hosts'] is not defined #If the user attempts to lock memory they must specify a heap size - fail: msg="If locking memory with bootstrap.mlockall a heap size must be specified" diff --git a/tasks/elasticsearch-config.yml b/tasks/elasticsearch-config.yml index a26ef55..ebceb25 100644 --- a/tasks/elasticsearch-config.yml +++ b/tasks/elasticsearch-config.yml @@ -128,6 +128,7 @@ - stat: path=/usr/lib/systemd/system/elasticsearch.service register: systemd_service + when: es_config['bootstrap.mlockall'] is defined and es_config['bootstrap.mlockall'] == True - name: Configure systemd lineinfile: dest=/usr/lib/systemd/system/elasticsearch.service regexp="^LimitMEMLOCK" insertafter="^#LimitMEMLOCK" line="LimitMEMLOCK=infinity" diff --git a/templates/elasticsearch.yml.j2 b/templates/elasticsearch.yml.j2 index 275c93c..c31d7da 100644 --- a/templates/elasticsearch.yml.j2 +++ b/templates/elasticsearch.yml.j2 @@ -1,4 +1,7 @@ + +{% if es_config %} {{ es_config | to_nice_yaml }} +{% endif %} {% if es_config['cluster.name'] is not defined %} cluster.name: elasticsearch diff --git a/test/integration/config.yml b/test/integration/config.yml index 357752d..9bd8936 100644 --- a/test/integration/config.yml +++ b/test/integration/config.yml @@ -1,6 +1,6 @@ --- #Test explicit setting of parameters and variables -- name: Elasticsearch Package tests +- name: Elasticsearch Config tests hosts: localhost roles: #expand to all available parameters diff --git a/test/integration/multi.yml b/test/integration/multi.yml index e138f7b..34652b6 100644 --- a/test/integration/multi.yml +++ b/test/integration/multi.yml @@ -1,6 +1,6 @@ --- #Test ability to deploy multiple instances to a machine -- name: Elasticsearch Config tests +- name: Elasticsearch Multi tests hosts: localhost roles: - { role: elasticsearch, es_instance_name: "master", es_data_dir: "/opt/elasticsearch", es_heap_size: "1g", es_config: { "discovery.zen.ping.multicast.enabled": false, discovery.zen.ping.unicast.hosts: "localhost:9300", http.port: 9200, transport.tcp.port: 9300, node.data: false, node.master: true, bootstrap.mlockall: true, discovery.zen.ping.multicast.enabled: false } } diff --git a/test/integration/multi/serverspec/default_spec.rb b/test/integration/multi/serverspec/default_spec.rb index 3447f4a..38f8334 100644 --- a/test/integration/multi/serverspec/default_spec.rb +++ b/test/integration/multi/serverspec/default_spec.rb @@ -88,13 +88,13 @@ context "basic tests" do end #test to make sure mlock was applied - describe command('curl "localhost:9200/_nodes/process?pretty" | grep mlockall') do + describe command('curl "localhost:9200/_nodes/localhost-master/process?pretty" | grep mlockall') do its(:stdout) { should match /\"mlockall\" : true/ } its(:exit_status) { should eq 0 } end #test to make sure mlock was not applied - describe command('curl "localhost:9201/_nodes/process?pretty" | grep mlockall') do + describe command('curl "localhost:9201/_nodes/localhost-node1/process?pretty" | grep mlockall') do its(:stdout) { should match /\"mlockall\" : false/ } its(:exit_status) { should eq 0 } end diff --git a/test/integration/standard.yml b/test/integration/standard.yml index 89236d7..66fd90e 100644 --- a/test/integration/standard.yml +++ b/test/integration/standard.yml @@ -2,7 +2,7 @@ - name: wrapper playbook for kitchen testing "elasticsearch" hosts: localhost roles: - - { role: elasticsearch, es_config: { "discovery.zen.ping.multicast.enabled": true }, es_instance_name: "node1" } + - { role: elasticsearch, es_instance_name: "node1" } vars: es_use_repository: "true" es_plugins: From d7d144b6388d14050d73c5feee30848f26ca6c41 Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Fri, 27 Nov 2015 13:17:09 +0000 Subject: [PATCH 16/27] Support for removing mlock + max open files + fix to documentation error --- README.md | 2 -- tasks/elasticsearch-config.yml | 34 +++++++++++++++++++++++++++++----- tasks/elasticsearch.yml | 2 -- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index e26197b..02b565b 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,6 @@ An example of a two server deployment, each with 1 node on one server and 2 node es_templates: false es_version_lock: false es_cluster_name: test-cluster - m_lock_enabled: true ansible_user: ansible es_plugins: - plugin: elasticsearch/license @@ -128,7 +127,6 @@ An example of a two server deployment, each with 1 node on one server and 2 node es_templates: false es_version_lock: false es_cluster_name: test-cluster - m_lock_enabled: false ansible_user: ansible es_plugins: - plugin: elasticsearch/license diff --git a/tasks/elasticsearch-config.yml b/tasks/elasticsearch-config.yml index ebceb25..b214b93 100644 --- a/tasks/elasticsearch-config.yml +++ b/tasks/elasticsearch-config.yml @@ -43,12 +43,19 @@ when: es_heap_size is defined register: elasticsearch_configure -#We only have to set these if they are specified. The start scripts will by default use the NAME set later on constructing directory names to avoid collisions. +- debug: msg="{{elasticsearch_configure}}" + +#We only have to set these if they are specified. The start scripts will by default set this value. - name: Configure max open files lineinfile: dest={{instance_default_file}} regexp="^MAX_OPEN_FILES" insertafter="^#MAX_OPEN_FILES" line="MAX_OPEN_FILES={{ es_max_open_files }}" when: es_max_open_files is defined register: elasticsearch_configure +#If the setting is not specified we remove it if its present. This will mean it reverts to the value in the init script. +- name: Remove max open files + lineinfile: dest={{instance_default_file}} regexp="^MAX_OPEN_FILES" line="MAX_OPEN_FILES=" state=absent + when: es_max_open_files is not defined + register: elasticsearch_configure #For directories we also use the {{inventory_hostname}}-{{ es_instance_name }} - this helps if we have a shared SAN. @@ -117,20 +124,37 @@ when: instance_init_script != init_script - file: path={{instance_config_directory}}/logging.yml state=touch owner={{ es_user }} group={{ es_group }} + changed_when: false + +- set_fact: m_lock_enabled={{ es_config['bootstrap.mlockall'] is defined and es_config['bootstrap.mlockall'] == True }} #Configure mlock if enabled - name: Configure mlock lineinfile: dest={{instance_default_file}} regexp="^MAX_LOCKED_MEMORY" insertafter="^#MAX_LOCKED_MEMORY" line="MAX_LOCKED_MEMORY=unlimited" - when: es_config['bootstrap.mlockall'] is defined and es_config['bootstrap.mlockall'] == True + when: m_lock_enabled register: elasticsearch_configure -#Change for systemd setting to ensure mlock is achieved +#Removed mlock if not enabled and present +- name: Remove mlock + lineinfile: dest={{instance_default_file}} regexp="^MAX_LOCKED_MEMORY" line="MAX_LOCKED_MEMORY=unlimited" state=absent + when: not m_lock_enabled - stat: path=/usr/lib/systemd/system/elasticsearch.service register: systemd_service - when: es_config['bootstrap.mlockall'] is defined and es_config['bootstrap.mlockall'] == True + when: m_lock_enabled +#Change for systemd setting to ensure mlock is achieved - name: Configure systemd lineinfile: dest=/usr/lib/systemd/system/elasticsearch.service regexp="^LimitMEMLOCK" insertafter="^#LimitMEMLOCK" line="LimitMEMLOCK=infinity" - when: es_config['bootstrap.mlockall'] is defined and es_config['bootstrap.mlockall'] == True and systemd_service.stat.exists == True + when: m_lock_enabled and systemd_service.stat.exists == True register: elasticsearch_configure + +#Remove setting if mlock is disabled +- name: Remove systemd + lineinfile: dest=/usr/lib/systemd/system/elasticsearch.service regexp="^LimitMEMLOCK" line="LimitMEMLOCK=infinity" state=absent + when: not m_lock_enabled + +- debug: msg="{{m_lock_enabled}}" + + +- debug: msg="{{elasticsearch_configure}}" \ No newline at end of file diff --git a/tasks/elasticsearch.yml b/tasks/elasticsearch.yml index 4b0ebbf..8e54a8a 100644 --- a/tasks/elasticsearch.yml +++ b/tasks/elasticsearch.yml @@ -19,8 +19,6 @@ - name: Elasticsearch configuration include: elasticsearch-config.yml -#We remove the node.name key as it may be set by another node on the same server - # Make sure the service is started, and restart if necessary - name: Start elasticsearch service From fe336c3767ef4bfbafacfa7837449eb9ad7bfaf0 Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Fri, 27 Nov 2015 13:42:03 +0000 Subject: [PATCH 17/27] Support for removing memory settings --- tasks/elasticsearch-config.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tasks/elasticsearch-config.yml b/tasks/elasticsearch-config.yml index b214b93..67a37d1 100644 --- a/tasks/elasticsearch-config.yml +++ b/tasks/elasticsearch-config.yml @@ -43,6 +43,11 @@ when: es_heap_size is defined register: elasticsearch_configure +- name: Remove memory in defaults + lineinfile: dest={{instance_default_file}} regexp="^ES_HEAP_SIZE" line="ES_HEAP_SIZE=" state=absent + when: es_heap_size is not defined + register: elasticsearch_configure + - debug: msg="{{elasticsearch_configure}}" #We only have to set these if they are specified. The start scripts will by default set this value. From 3d7d6deef045d645ca01741103762d2b69721762 Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Fri, 27 Nov 2015 13:47:23 +0000 Subject: [PATCH 18/27] Debug statements removed --- tasks/elasticsearch-config.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tasks/elasticsearch-config.yml b/tasks/elasticsearch-config.yml index 67a37d1..b525771 100644 --- a/tasks/elasticsearch-config.yml +++ b/tasks/elasticsearch-config.yml @@ -157,9 +157,4 @@ #Remove setting if mlock is disabled - name: Remove systemd lineinfile: dest=/usr/lib/systemd/system/elasticsearch.service regexp="^LimitMEMLOCK" line="LimitMEMLOCK=infinity" state=absent - when: not m_lock_enabled - -- debug: msg="{{m_lock_enabled}}" - - -- debug: msg="{{elasticsearch_configure}}" \ No newline at end of file + when: not m_lock_enabled \ No newline at end of file From 37447d1618b85b36f4ac40b3e56249cb5cd233ea Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Fri, 27 Nov 2015 18:12:59 +0000 Subject: [PATCH 19/27] Templates everything + Systemd improvements+fixes + Notifications for restart + Idempotent checks for multiple runs --- handlers/main.yml | 4 + tasks/elasticsearch-config.yml | 155 +++------------- tasks/elasticsearch.yml | 9 +- templates/elasticsearch.j2 | 84 +++++++++ templates/init/debian/elasticsearch.j2 | 237 +++++++++++++++++++++++++ templates/init/redhat/elasticsearch.j2 | 185 +++++++++++++++++++ templates/logging.yml.j2 | 68 +++++++ templates/systemd/elasticsearch.j2 | 50 ++++++ vars/main.yml | 3 +- 9 files changed, 663 insertions(+), 132 deletions(-) create mode 100644 handlers/main.yml create mode 100644 templates/elasticsearch.j2 create mode 100755 templates/init/debian/elasticsearch.j2 create mode 100755 templates/init/redhat/elasticsearch.j2 create mode 100644 templates/logging.yml.j2 create mode 100644 templates/systemd/elasticsearch.j2 diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..3501e12 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,4 @@ + +- name: restart elasticsearch + service: name={{instance_init_script | basename}} state=restarted enabled=yes + when: es_start_service and not elasticsearch_started.changed \ No newline at end of file diff --git a/tasks/elasticsearch-config.yml b/tasks/elasticsearch-config.yml index b525771..9f9d117 100644 --- a/tasks/elasticsearch-config.yml +++ b/tasks/elasticsearch-config.yml @@ -1,6 +1,7 @@ --- # Configure Elasticsearch Node +#For directories we also use the {{inventory_hostname}}-{{ es_instance_name }} - this helps if we have a shared SAN. - set_fact: pid_dir={{es_pid_dir}}/{{inventory_hostname}}-{{ es_instance_name }} @@ -10,151 +11,49 @@ - set_fact: work_dir={{ es_work_dir }}/{{inventory_hostname}}-{{ es_instance_name }} - -# Create an instance specific default file -- name: Copy Default File for Instance - command: creates={{instance_default_file}} cp "{{default_file}}" "{{instance_default_file}}" - when: instance_default_file != default_file - -# Create an instance specific init file -- name: Copy Init File for Instance - command: creates={{instance_init_script}} cp "{{init_script}}" "{{instance_init_script}}" - when: instance_init_script != init_script - -#Create Config directory -- name: Create Config Directory - file: path={{ instance_config_directory }} state=directory owner={{ es_user }} group={{ es_group }} - -#Copy the config template -- name: Copy configuration file - template: src=elasticsearch.yml.j2 dest={{instance_config_directory}}/elasticsearch.yml owner={{ es_user }} group={{ es_group }} mode=0644 force=yes - -# Apply changes to the default file for this instance -- name: Configure config directory - lineinfile: dest={{instance_default_file}} regexp="^CONF_DIR" insertafter="^#CONF_DIR" line="CONF_DIR={{ instance_config_directory }}" - register: elasticsearch_configure - -- name: Configure config file - lineinfile: dest={{instance_default_file}} regexp="^CONF_FILE" insertafter="^#CONF_FILE" line="CONF_FILE={{ instance_config_directory }}/elasticsearch.yml" - register: elasticsearch_configure - -- name: Configure memory in defaults - lineinfile: dest={{instance_default_file}} regexp="^ES_HEAP_SIZE" insertafter="^#ES_HEAP_SIZE" line="ES_HEAP_SIZE={{ es_heap_size }}" - when: es_heap_size is defined - register: elasticsearch_configure - -- name: Remove memory in defaults - lineinfile: dest={{instance_default_file}} regexp="^ES_HEAP_SIZE" line="ES_HEAP_SIZE=" state=absent - when: es_heap_size is not defined - register: elasticsearch_configure - -- debug: msg="{{elasticsearch_configure}}" - -#We only have to set these if they are specified. The start scripts will by default set this value. -- name: Configure max open files - lineinfile: dest={{instance_default_file}} regexp="^MAX_OPEN_FILES" insertafter="^#MAX_OPEN_FILES" line="MAX_OPEN_FILES={{ es_max_open_files }}" - when: es_max_open_files is defined - register: elasticsearch_configure - -#If the setting is not specified we remove it if its present. This will mean it reverts to the value in the init script. -- name: Remove max open files - lineinfile: dest={{instance_default_file}} regexp="^MAX_OPEN_FILES" line="MAX_OPEN_FILES=" state=absent - when: es_max_open_files is not defined - register: elasticsearch_configure - -#For directories we also use the {{inventory_hostname}}-{{ es_instance_name }} - this helps if we have a shared SAN. - -#Create PID directory +#Create required directories - name: Create PID Directory file: path={{ pid_dir }} state=directory owner={{ es_user }} group={{ es_group }} -- name: Configure PID directory - lineinfile: dest={{instance_default_file}} regexp="^PID_DIR" insertafter="^#PID_DIR" line="PID_DIR={{ pid_dir }}" - register: elasticsearch_configure - -#include the host name as potentially shared SAN - name: Create data dir file: state=directory path={{ data_dir }} owner={{ es_user }} group={{ es_group }} -- name: Configure data store - lineinfile: dest={{instance_default_file}} regexp="^DATA_DIR" insertafter="^#DATA_DIR" line="DATA_DIR={{ data_dir }}" - register: elasticsearch_configure - - name: Create work dir file: state=directory path={{ work_dir }} owner={{ es_user }} group={{ es_group }} -- name: Configure work directory - lineinfile: dest={{instance_default_file}} regexp="^WORK_DIR" insertafter="^#WORK_DIR" line="WORK_DIR={{ work_dir }}" - register: elasticsearch_configure - - name: Create log dir file: state=directory path={{ log_dir }} owner={{ es_user }} group={{ es_group }} -- name: Configure log directory - lineinfile: dest={{instance_default_file}} regexp="^LOG_DIR" insertafter="^#LOG_DIR" line="LOG_DIR={{ log_dir }}" - register: elasticsearch_configure +- name: Create Config Directory + file: path={{ instance_config_directory }} state=directory owner={{ es_user }} group={{ es_group }} -#required so that the ES_HOME does not change between instances +#Copy the config template +- name: Copy Configuration File + template: src=elasticsearch.yml.j2 dest={{instance_config_directory}}/elasticsearch.yml owner={{ es_user }} group={{ es_group }} mode=0644 force=yes + notify: restart elasticsearch -- name: Configure elasticsearch home - lineinfile: dest={{instance_default_file}} regexp="^ES_HOME" insertafter="^#ES_HOME" line="ES_HOME={{es_home}}" - register: elasticsearch_configure +#Copy the instance specific default file +- name: Copy Default File for Instance + template: src=elasticsearch.j2 dest={{instance_default_file}} mode=0644 force=yes + notify: restart elasticsearch -- name: Configure elasticsearch user - lineinfile: dest={{instance_default_file}} regexp="^ES_USER" insertafter="^#ES_USER" line="ES_USER={{ es_user }}" - when: es_user is defined - register: elasticsearch_configure - -- name: Configure elasticsearch group - lineinfile: dest={{instance_default_file}} regexp="^ES_GROUP" insertafter="^#ES_GROUP" line="ES_GROUP={{ es_group }}" - when: es_group is defined - register: elasticsearch_configure - -#Apply changes to init script - NAME can be changed in Debian start script -- name: Name Node in Init Script - lineinfile: dest={{instance_init_script}} regexp="^NAME" line="NAME={{es_instance_name}}_{{default_file | basename}}" - register: elasticsearch_configure +#Copy the instance specific init file +- name: Copy Debian Init File for Instance + template: src=init/debian/elasticsearch.j2 dest={{instance_init_script}} mode=0755 force=yes when: ansible_os_family == 'Debian' -- debug: msg="For {{ instance_init_script }} using default {{ instance_default_file }}" +#Copy the instance specific init file +- name: Copy Redhat Init File for Instance + template: src=init/redhat/elasticsearch.j2 dest={{instance_init_script}} mode=0755 force=yes + when: ansible_os_family == 'Redhat' -- name: Environment in Init Script - lineinfile: dest={{instance_init_script}} regexp="^ES_ENV_FILE" line="ES_ENV_FILE={{instance_default_file}}" - register: elasticsearch_configure - when: ansible_os_family == 'RedHat' +#Copy the systemd specific file if systemd is installed +- name: Copy Systemd File for Instance + template: src=systemd/elasticsearch.j2 dest={{instance_sysd_script}} mode=0644 force=yes + when: systemd_service + notify: restart elasticsearch #Copy the logging.yml -- name: Copy Logging.yml for Instance - command: creates={{instance_config_directory}}/logging.yml cp "{{ es_conf_dir }}/logging.yml" "{{instance_config_directory}}/logging.yml" - when: instance_init_script != init_script - -- file: path={{instance_config_directory}}/logging.yml state=touch owner={{ es_user }} group={{ es_group }} - changed_when: false - -- set_fact: m_lock_enabled={{ es_config['bootstrap.mlockall'] is defined and es_config['bootstrap.mlockall'] == True }} - -#Configure mlock if enabled -- name: Configure mlock - lineinfile: dest={{instance_default_file}} regexp="^MAX_LOCKED_MEMORY" insertafter="^#MAX_LOCKED_MEMORY" line="MAX_LOCKED_MEMORY=unlimited" - when: m_lock_enabled - register: elasticsearch_configure - -#Removed mlock if not enabled and present -- name: Remove mlock - lineinfile: dest={{instance_default_file}} regexp="^MAX_LOCKED_MEMORY" line="MAX_LOCKED_MEMORY=unlimited" state=absent - when: not m_lock_enabled - -- stat: path=/usr/lib/systemd/system/elasticsearch.service - register: systemd_service - when: m_lock_enabled - -#Change for systemd setting to ensure mlock is achieved -- name: Configure systemd - lineinfile: dest=/usr/lib/systemd/system/elasticsearch.service regexp="^LimitMEMLOCK" insertafter="^#LimitMEMLOCK" line="LimitMEMLOCK=infinity" - when: m_lock_enabled and systemd_service.stat.exists == True - register: elasticsearch_configure - -#Remove setting if mlock is disabled -- name: Remove systemd - lineinfile: dest=/usr/lib/systemd/system/elasticsearch.service regexp="^LimitMEMLOCK" line="LimitMEMLOCK=infinity" state=absent - when: not m_lock_enabled \ No newline at end of file +- name: Copy Systemd File for Instance + template: src=logging.yml.j2 dest={{instance_config_directory}}/logging.yml owner={{ es_user }} group={{ es_group }} mode=0644 force=yes + notify: restart elasticsearch \ No newline at end of file diff --git a/tasks/elasticsearch.yml b/tasks/elasticsearch.yml index 8e54a8a..e626ddc 100644 --- a/tasks/elasticsearch.yml +++ b/tasks/elasticsearch.yml @@ -3,6 +3,11 @@ - set_fact: instance_default_file={{default_file | dirname}}/{{es_instance_name}}_{{default_file | basename}} - set_fact: instance_init_script={{init_script | dirname }}/{{es_instance_name}}_{{init_script | basename}} - set_fact: instance_config_directory={{ es_conf_dir }}/{{es_instance_name}} +- stat: path={{sysd_script}} + register: systemd_service +- set_fact: instance_sysd_script={{sysd_script | dirname }}/{{es_instance_name}}_{{sysd_script | basename}} + when: systemd_service +- set_fact: m_lock_enabled={{ es_config['bootstrap.mlockall'] is defined and es_config['bootstrap.mlockall'] == True }} - debug: msg="Node configuration {{ es_config }} " @@ -28,6 +33,4 @@ - name: Restart elasticsearch service if new version installed service: name={{instance_init_script | basename}} state=restarted enabled=yes - when: es_start_service and - ( elasticsearch_install.changed or elasticsearch_configure.changed ) - and not elasticsearch_started.changed + when: es_start_service and elasticsearch_install.changed and not elasticsearch_started.changed \ No newline at end of file diff --git a/templates/elasticsearch.j2 b/templates/elasticsearch.j2 new file mode 100644 index 0000000..9c577b5 --- /dev/null +++ b/templates/elasticsearch.j2 @@ -0,0 +1,84 @@ +################################ +# Elasticsearch +################################ + +# Elasticsearch home directory +ES_HOME={{es_home}} + +# Elasticsearch configuration directory +CONF_DIR={{instance_config_directory}} + +# Elasticsearch configuration file +CONF_FILE=$CONF_DIR/elasticsearch.yml + +# Elasticsearch data directory +DATA_DIR={{data_dir}} + +# Elasticsearch logs directory +LOG_DIR={{log_dir}} + +# Elasticsearch work directory +WORK_DIR={{work_dir}} + +# Elasticsearch PID directory +PID_DIR={{pid_dir}} + +# Heap size defaults to 256m min, 1g max +# Set ES_HEAP_SIZE to 50% of available RAM, but no more than 31g +{% if es_heap_size is defined %} +ES_HEAP_SIZE={{es_heap_size}} +{% endif %} + +# Heap new generation +#ES_HEAP_NEWSIZE= + +# Maximum direct memory +#ES_DIRECT_SIZE= + +# Additional Java OPTS +#ES_JAVA_OPTS= + +# Configure restart on package upgrade (true, every other setting will lead to not restarting) +#ES_RESTART_ON_UPGRADE=true + +# Path to the GC log file +#ES_GC_LOG_FILE=/var/log/elasticsearch/gc.log + +################################ +# Elasticsearch service +################################ + +# SysV init.d +# +# When executing the init script, this user will be used to run the elasticsearch service. +# The default value is 'elasticsearch' and is declared in the init.d file. +# Note that this setting is only used by the init script. If changed, make sure that +# the configured user can read and write into the data, work, plugins and log directories. +# For systemd service, the user is usually configured in file /usr/lib/systemd/system/elasticsearch.service +ES_USER={{es_user}} +ES_GROUP={{es_group}} + +################################ +# System properties +################################ + +# Specifies the maximum file descriptor number that can be opened by this process +# When using Systemd, this setting is ignored and the LimitNOFILE defined in +# /usr/lib/systemd/system/elasticsearch.service takes precedence +{% if es_max_open_files is defined %} +MAX_OPEN_FILES={{es_max_open_files}} +{% endif %} + +# The maximum number of bytes of memory that may be locked into RAM +# Set to "unlimited" if you use the 'bootstrap.mlockall: true' option +# in elasticsearch.yml (ES_HEAP_SIZE must also be set). +# When using Systemd, the LimitMEMLOCK property must be set +# in /usr/lib/systemd/system/elasticsearch.service +{% if m_lock_enabled %} +MAX_LOCKED_MEMORY=unlimited +{% endif %} + +# Maximum number of VMA (Virtual Memory Areas) a process can own +# When using Systemd, this setting is ignored and the 'vm.max_map_count' +# property is set at boot time in /usr/lib/sysctl.d/elasticsearch.conf +#MAX_MAP_COUNT=262144 diff --git a/templates/init/debian/elasticsearch.j2 b/templates/init/debian/elasticsearch.j2 new file mode 100755 index 0000000..b9e65c7 --- /dev/null +++ b/templates/init/debian/elasticsearch.j2 @@ -0,0 +1,237 @@ +#!/bin/sh +# +# /etc/init.d/elasticsearch -- startup script for Elasticsearch +# +# Written by Miquel van Smoorenburg . +# Modified for Debian GNU/Linux by Ian Murdock . +# Modified for Tomcat by Stefan Gybas . +# Modified for Tomcat6 by Thierry Carrez . +# Additional improvements by Jason Brittain . +# Modified by Nicolas Huray for Elasticsearch . +# +### BEGIN INIT INFO +# Provides: elasticsearch +# Required-Start: $network $remote_fs $named +# Required-Stop: $network $remote_fs $named +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Starts elasticsearch +# Description: Starts elasticsearch using start-stop-daemon +### END INIT INFO + +PATH=/bin:/usr/bin:/sbin:/usr/sbin +NAME={{es_instance_name}}_{{default_file | basename}} +{% if es_config['node.name'] is defined %} +DESC="Elasticsearch Server - {{es_config['node.name']}}" +{% else %} +DESC="Elasticsearch Server - {{es_instance_name}}" +{% endif %} +DEFAULT=/etc/default/$NAME + +if [ `id -u` -ne 0 ]; then + echo "You need root privileges to run this script" + exit 1 +fi + + +. /lib/lsb/init-functions + +if [ -r /etc/default/rcS ]; then + . /etc/default/rcS +fi + +# The following variables can be overwritten in $DEFAULT + +# Run Elasticsearch as this user ID and group ID +ES_USER=elasticsearch +ES_GROUP=elasticsearch + +# The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT) +JDK_DIRS="/usr/lib/jvm/java-8-oracle/ /usr/lib/jvm/j2sdk1.8-oracle/ /usr/lib/jvm/jdk-7-oracle-x64 /usr/lib/jvm/java-7-oracle /usr/lib/jvm/j2sdk1.7-oracle/ /usr/lib/jvm/java-7-openjdk /usr/lib/jvm/java-7-openjdk-amd64/ /usr/lib/jvm/java-7-openjdk-armhf /usr/lib/jvm/java-7-openjdk-i386/ /usr/lib/jvm/default-java" + +# Look for the right JVM to use +for jdir in $JDK_DIRS; do + if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then + JAVA_HOME="$jdir" + fi +done +export JAVA_HOME + +# Directory where the Elasticsearch binary distribution resides +ES_HOME=/usr/share/$NAME + +# Heap size defaults to 256m min, 1g max +# Set ES_HEAP_SIZE to 50% of available RAM, but no more than 31g +#ES_HEAP_SIZE=2g + +# Heap new generation +#ES_HEAP_NEWSIZE= + +# max direct memory +#ES_DIRECT_SIZE= + +# Additional Java OPTS +#ES_JAVA_OPTS= + +# Maximum number of open files +MAX_OPEN_FILES=65535 + +# Maximum amount of locked memory +#MAX_LOCKED_MEMORY= + +# Elasticsearch log directory +LOG_DIR=/var/log/$NAME + +# Elasticsearch data directory +DATA_DIR=/var/lib/$NAME + +# Elasticsearch work directory +WORK_DIR=/tmp/$NAME + +# Elasticsearch configuration directory +CONF_DIR=/etc/$NAME + +# Elasticsearch configuration file (elasticsearch.yml) +CONF_FILE=$CONF_DIR/elasticsearch.yml + +# Maximum number of VMA (Virtual Memory Areas) a process can own +MAX_MAP_COUNT=262144 + +# Path to the GC log file +#ES_GC_LOG_FILE=/var/log/elasticsearch/gc.log + +# Elasticsearch PID file directory +PID_DIR="/var/run/elasticsearch" + +# End of variables that can be overwritten in $DEFAULT + +# overwrite settings from default file +if [ -f "$DEFAULT" ]; then + . "$DEFAULT" +fi + +# Define other required variables +PID_FILE="$PID_DIR/$NAME.pid" +DAEMON=$ES_HOME/bin/elasticsearch +DAEMON_OPTS="-d -p $PID_FILE --default.config=$CONF_FILE --default.path.home=$ES_HOME --default.path.logs=$LOG_DIR --default.path.data=$DATA_DIR --default.path.work=$WORK_DIR --default.path.conf=$CONF_DIR" + +export ES_HEAP_SIZE +export ES_HEAP_NEWSIZE +export ES_DIRECT_SIZE +export ES_JAVA_OPTS + +# Check DAEMON exists +test -x $DAEMON || exit 0 + +checkJava() { + if [ -x "$JAVA_HOME/bin/java" ]; then + JAVA="$JAVA_HOME/bin/java" + else + JAVA=`which java` + fi + + if [ ! -x "$JAVA" ]; then + echo "Could not find any executable java binary. Please install java in your PATH or set JAVA_HOME" + exit 1 + fi +} + +case "$1" in + start) + checkJava + + if [ -n "$MAX_LOCKED_MEMORY" -a -z "$ES_HEAP_SIZE" ]; then + log_failure_msg "MAX_LOCKED_MEMORY is set - ES_HEAP_SIZE must also be set" + exit 1 + fi + + log_daemon_msg "Starting $DESC" + + pid=`pidofproc -p $PID_FILE elasticsearch` + if [ -n "$pid" ] ; then + log_begin_msg "Already running." + log_end_msg 0 + exit 0 + fi + + # Prepare environment + mkdir -p "$LOG_DIR" "$DATA_DIR" "$WORK_DIR" && chown "$ES_USER":"$ES_GROUP" "$LOG_DIR" "$DATA_DIR" "$WORK_DIR" + + # Ensure that the PID_DIR exists (it is cleaned at OS startup time) + if [ -n "$PID_DIR" ] && [ ! -e "$PID_DIR" ]; then + mkdir -p "$PID_DIR" && chown "$ES_USER":"$ES_GROUP" "$PID_DIR" + fi + if [ -n "$PID_FILE" ] && [ ! -e "$PID_FILE" ]; then + touch "$PID_FILE" && chown "$ES_USER":"$ES_GROUP" "$PID_FILE" + fi + + if [ -n "$MAX_OPEN_FILES" ]; then + ulimit -n $MAX_OPEN_FILES + fi + + if [ -n "$MAX_LOCKED_MEMORY" ]; then + ulimit -l $MAX_LOCKED_MEMORY + fi + + if [ -n "$MAX_MAP_COUNT" -a -f /proc/sys/vm/max_map_count ]; then + sysctl -q -w vm.max_map_count=$MAX_MAP_COUNT + fi + + # Start Daemon + start-stop-daemon --start -b --user "$ES_USER" -c "$ES_USER" --pidfile "$PID_FILE" --exec $DAEMON -- $DAEMON_OPTS + return=$? + if [ $return -eq 0 ] + then + i=0 + timeout=10 + # Wait for the process to be properly started before exiting + until { cat "$PID_FILE" | xargs kill -0; } >/dev/null 2>&1 + do + sleep 1 + i=$(($i + 1)) + if [ $i -gt $timeout ]; then + log_end_msg 1 + exit 1 + fi + done + else + log_end_msg $return + fi + ;; + stop) + log_daemon_msg "Stopping $DESC" + + if [ -f "$PID_FILE" ]; then + start-stop-daemon --stop --pidfile "$PID_FILE" \ + --user "$ES_USER" \ + --retry=TERM/20/KILL/5 >/dev/null + if [ $? -eq 1 ]; then + log_progress_msg "$DESC is not running but pid file exists, cleaning up" + elif [ $? -eq 3 ]; then + PID="`cat $PID_FILE`" + log_failure_msg "Failed to stop $DESC (pid $PID)" + exit 1 + fi + rm -f "$PID_FILE" + else + log_progress_msg "(not running)" + fi + log_end_msg 0 + ;; + status) + status_of_proc -p $PID_FILE elasticsearch elasticsearch && exit 0 || exit $? + ;; + restart|force-reload) + if [ -f "$PID_FILE" ]; then + $0 stop + sleep 1 + fi + $0 start + ;; + *) + log_success_msg "Usage: $0 {start|stop|restart|force-reload|status}" + exit 1 + ;; +esac + +exit 0 diff --git a/templates/init/redhat/elasticsearch.j2 b/templates/init/redhat/elasticsearch.j2 new file mode 100755 index 0000000..fab94b3 --- /dev/null +++ b/templates/init/redhat/elasticsearch.j2 @@ -0,0 +1,185 @@ +#!/bin/sh +# +# elasticsearch +# +# chkconfig: 2345 80 20 +# description: Starts and stops a single elasticsearch instance on this system +# + +### BEGIN INIT INFO +# Provides: Elasticsearch +# Required-Start: $network $named +# Required-Stop: $network $named +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: This service manages the elasticsearch daemon +# Description: Elasticsearch is a very scalable, schema-free and high-performance search solution supporting multi-tenancy and near realtime search. +### END INIT INFO + +# +# init.d / servicectl compatibility (openSUSE) +# +if [ -f /etc/rc.status ]; then + . /etc/rc.status + rc_reset +fi + +# +# Source function library. +# +if [ -f /etc/rc.d/init.d/functions ]; then + . /etc/rc.d/init.d/functions +fi + +# Sets the default values for elasticsearch variables used in this script +ES_USER="elasticsearch" +ES_GROUP="elasticsearch" +ES_HOME="/usr/share/elasticsearch" +MAX_OPEN_FILES=65535 +MAX_MAP_COUNT=262144 +LOG_DIR="/var/log/elasticsearch" +DATA_DIR="/var/lib/elasticsearch" +WORK_DIR="/tmp/elasticsearch" +CONF_DIR="/etc/elasticsearch" +CONF_FILE="/etc/elasticsearch/elasticsearch.yml" +PID_DIR="/var/run/elasticsearch" + +# Source the default env file +ES_ENV_FILE="{{instance_default_file}}" +if [ -f "$ES_ENV_FILE" ]; then + . "$ES_ENV_FILE" +fi + +exec="$ES_HOME/bin/elasticsearch" +prog="elasticsearch" +pidfile="$PID_DIR/${prog}.pid" + +export ES_HEAP_SIZE +export ES_HEAP_NEWSIZE +export ES_DIRECT_SIZE +export ES_JAVA_OPTS +export JAVA_HOME + +lockfile=/var/lock/subsys/$prog + +# backwards compatibility for old config sysconfig files, pre 0.90.1 +if [ -n $USER ] && [ -z $ES_USER ] ; then + ES_USER=$USER +fi + +checkJava() { + if [ -x "$JAVA_HOME/bin/java" ]; then + JAVA="$JAVA_HOME/bin/java" + else + JAVA=`which java` + fi + + if [ ! -x "$JAVA" ]; then + echo "Could not find any executable java binary. Please install java in your PATH or set JAVA_HOME" + exit 1 + fi +} + +start() { + checkJava + [ -x $exec ] || exit 5 + [ -f $CONF_FILE ] || exit 6 + if [ -n "$MAX_LOCKED_MEMORY" -a -z "$ES_HEAP_SIZE" ]; then + echo "MAX_LOCKED_MEMORY is set - ES_HEAP_SIZE must also be set" + return 7 + fi + if [ -n "$MAX_OPEN_FILES" ]; then + ulimit -n $MAX_OPEN_FILES + fi + if [ -n "$MAX_LOCKED_MEMORY" ]; then + ulimit -l $MAX_LOCKED_MEMORY + fi + if [ -n "$MAX_MAP_COUNT" -a -f /proc/sys/vm/max_map_count ]; then + sysctl -q -w vm.max_map_count=$MAX_MAP_COUNT + fi + if [ -n "$WORK_DIR" ]; then + mkdir -p "$WORK_DIR" + chown "$ES_USER":"$ES_GROUP" "$WORK_DIR" + fi + + # Ensure that the PID_DIR exists (it is cleaned at OS startup time) + if [ -n "$PID_DIR" ] && [ ! -e "$PID_DIR" ]; then + mkdir -p "$PID_DIR" && chown "$ES_USER":"$ES_GROUP" "$PID_DIR" + fi + if [ -n "$pidfile" ] && [ ! -e "$pidfile" ]; then + touch "$pidfile" && chown "$ES_USER":"$ES_GROUP" "$pidfile" + fi + + echo -n $"Starting $prog: " + # if not running, start it up here, usually something like "daemon $exec" + daemon --user $ES_USER --pidfile $pidfile $exec -p $pidfile -d -Des.default.path.home=$ES_HOME -Des.default.path.logs=$LOG_DIR -Des.default.path.data=$DATA_DIR -Des.default.path.work=$WORK_DIR -Des.default.path.conf=$CONF_DIR + retval=$? + echo + [ $retval -eq 0 ] && touch $lockfile + return $retval +} + +stop() { + echo -n $"Stopping $prog: " + # stop it here, often "killproc $prog" + killproc -p $pidfile -d 20 $prog + retval=$? + echo + [ $retval -eq 0 ] && rm -f $lockfile + return $retval +} + +restart() { + stop + start +} + +reload() { + restart +} + +force_reload() { + restart +} + +rh_status() { + # run checks to determine if the service is running or use generic status + status -p $pidfile $prog +} + +rh_status_q() { + rh_status >/dev/null 2>&1 +} + + +case "$1" in + start) + rh_status_q && exit 0 + $1 + ;; + stop) + rh_status_q || exit 0 + $1 + ;; + restart) + $1 + ;; + reload) + rh_status_q || exit 7 + $1 + ;; + force-reload) + force_reload + ;; + status) + rh_status + ;; + condrestart|try-restart) + rh_status_q || exit 0 + restart + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}" + exit 2 +esac +exit $? diff --git a/templates/logging.yml.j2 b/templates/logging.yml.j2 new file mode 100644 index 0000000..538c9bd --- /dev/null +++ b/templates/logging.yml.j2 @@ -0,0 +1,68 @@ +# you can override this using by setting a system property, for example -Des.logger.level=DEBUG +es.logger.level: INFO +rootLogger: ${es.logger.level}, console, file +logger: + # log action execution errors for easier debugging + action: DEBUG + # reduce the logging for aws, too much is logged under the default INFO + com.amazonaws: WARN + org.apache.http: INFO + + # gateway + #gateway: DEBUG + #index.gateway: DEBUG + + # peer shard recovery + #indices.recovery: DEBUG + + # discovery + #discovery: TRACE + + index.search.slowlog: TRACE, index_search_slow_log_file + index.indexing.slowlog: TRACE, index_indexing_slow_log_file + +additivity: + index.search.slowlog: false + index.indexing.slowlog: false + +appender: + console: + type: console + layout: + type: consolePattern + conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n" + + file: + type: dailyRollingFile + file: ${path.logs}/${cluster.name}.log + datePattern: "'.'yyyy-MM-dd" + layout: + type: pattern + conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n" + + # Use the following log4j-extras RollingFileAppender to enable gzip compression of log files. + # For more information see https://logging.apache.org/log4j/extras/apidocs/org/apache/log4j/rolling/RollingFileAppender.html + #file: + #type: extrasRollingFile + #file: ${path.logs}/${cluster.name}.log + #rollingPolicy: timeBased + #rollingPolicy.FileNamePattern: ${path.logs}/${cluster.name}.log.%d{yyyy-MM-dd}.gz + #layout: + #type: pattern + #conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n" + + index_search_slow_log_file: + type: dailyRollingFile + file: ${path.logs}/${cluster.name}_index_search_slowlog.log + datePattern: "'.'yyyy-MM-dd" + layout: + type: pattern + conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n" + + index_indexing_slow_log_file: + type: dailyRollingFile + file: ${path.logs}/${cluster.name}_index_indexing_slowlog.log + datePattern: "'.'yyyy-MM-dd" + layout: + type: pattern + conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n" \ No newline at end of file diff --git a/templates/systemd/elasticsearch.j2 b/templates/systemd/elasticsearch.j2 new file mode 100644 index 0000000..5e19d0e --- /dev/null +++ b/templates/systemd/elasticsearch.j2 @@ -0,0 +1,50 @@ +[Unit] +Description=Elasticsearch +Documentation=http://www.elastic.co +Wants=network-online.target +After=network-online.target + +[Service] +Environment=ES_HOME={{es_home}} +Environment=CONF_DIR={{instance_config_directory}} +Environment=CONF_FILE={{instance_config_directory}}/elasticsearch.yml +Environment=DATA_DIR={{data_dir}} +Environment=LOG_DIR={{log_dir}} +Environment=PID_DIR={{pid_dir}} +EnvironmentFile=-{{instance_default_file}} + +User={{es_user}} +Group={{es_group}} + +ExecStart={{es_home}}/bin/elasticsearch \ + -Des.pidfile=$PID_DIR/elasticsearch.pid \ + -Des.default.path.home=$ES_HOME \ + -Des.default.path.logs=$LOG_DIR \ + -Des.default.path.data=$DATA_DIR \ + -Des.default.config=$CONF_FILE \ + -Des.default.path.conf=$CONF_DIR + +# Connects standard output to /dev/null +StandardOutput=null + +# Connects standard error to journal +StandardError=journal + +# When a JVM receives a SIGTERM signal it exits with code 143 +SuccessExitStatus=143 + +# Specifies the maximum file descriptor number that can be opened by this process +LimitNOFILE=65535 + +# Specifies the maximum number of bytes of memory that may be locked into RAM +# Set to "infinity" if you use the 'bootstrap.mlockall: true' option +# in elasticsearch.yml and 'MAX_LOCKED_MEMORY=unlimited' in {{instance_default_file}} +{% if m_lock_enabled %} +LimitMEMLOCK=infinity +{% endif %} + +# Shutdown delay in seconds, before process is tried to be killed with KILL (if configured) +TimeoutStopSec=20 + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/vars/main.yml b/vars/main.yml index 1c232fa..b2f74d9 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -1,3 +1,4 @@ --- es_package_url: "https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch" -es_conf_dir: "/etc/elasticsearch" \ No newline at end of file +es_conf_dir: "/etc/elasticsearch" +sysd_script: "/usr/lib/systemd/system/elasticsearch.service" \ No newline at end of file From 145f345ec1f2f379b9f2d8b01e1eacbf6a03eacc Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Fri, 27 Nov 2015 19:39:47 +0000 Subject: [PATCH 20/27] Fixes for serverspec --- tasks/elasticsearch-config.yml | 12 ++++++++-- tasks/elasticsearch.yml | 4 ---- templates/elasticsearch.j2 | 2 +- templates/systemd/elasticsearch.j2 | 2 +- .../multi/serverspec/default_spec.rb | 24 +++++++++---------- 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/tasks/elasticsearch-config.yml b/tasks/elasticsearch-config.yml index 9f9d117..c98c3b4 100644 --- a/tasks/elasticsearch-config.yml +++ b/tasks/elasticsearch-config.yml @@ -1,6 +1,14 @@ --- # Configure Elasticsearch Node + +#This relies on elasticsearch installing a serviced script to determine whether one should be copied. +- stat: path={{sysd_script}} + register: systemd_service + +- set_fact: instance_sysd_script={{sysd_script | dirname }}/{{es_instance_name}}_{{sysd_script | basename}} + when: systemd_service.stat.exists + #For directories we also use the {{inventory_hostname}}-{{ es_instance_name }} - this helps if we have a shared SAN. - set_fact: pid_dir={{es_pid_dir}}/{{inventory_hostname}}-{{ es_instance_name }} @@ -45,12 +53,12 @@ #Copy the instance specific init file - name: Copy Redhat Init File for Instance template: src=init/redhat/elasticsearch.j2 dest={{instance_init_script}} mode=0755 force=yes - when: ansible_os_family == 'Redhat' + when: ansible_os_family == 'RedHat' #Copy the systemd specific file if systemd is installed - name: Copy Systemd File for Instance template: src=systemd/elasticsearch.j2 dest={{instance_sysd_script}} mode=0644 force=yes - when: systemd_service + when: systemd_service.stat.exists notify: restart elasticsearch #Copy the logging.yml diff --git a/tasks/elasticsearch.yml b/tasks/elasticsearch.yml index e626ddc..b921d8b 100644 --- a/tasks/elasticsearch.yml +++ b/tasks/elasticsearch.yml @@ -3,10 +3,6 @@ - set_fact: instance_default_file={{default_file | dirname}}/{{es_instance_name}}_{{default_file | basename}} - set_fact: instance_init_script={{init_script | dirname }}/{{es_instance_name}}_{{init_script | basename}} - set_fact: instance_config_directory={{ es_conf_dir }}/{{es_instance_name}} -- stat: path={{sysd_script}} - register: systemd_service -- set_fact: instance_sysd_script={{sysd_script | dirname }}/{{es_instance_name}}_{{sysd_script | basename}} - when: systemd_service - set_fact: m_lock_enabled={{ es_config['bootstrap.mlockall'] is defined and es_config['bootstrap.mlockall'] == True }} - debug: msg="Node configuration {{ es_config }} " diff --git a/templates/elasticsearch.j2 b/templates/elasticsearch.j2 index 9c577b5..d940425 100644 --- a/templates/elasticsearch.j2 +++ b/templates/elasticsearch.j2 @@ -9,7 +9,7 @@ ES_HOME={{es_home}} CONF_DIR={{instance_config_directory}} # Elasticsearch configuration file -CONF_FILE=$CONF_DIR/elasticsearch.yml +CONF_FILE={{instance_config_directory}}/elasticsearch.yml # Elasticsearch data directory DATA_DIR={{data_dir}} diff --git a/templates/systemd/elasticsearch.j2 b/templates/systemd/elasticsearch.j2 index 5e19d0e..bedcceb 100644 --- a/templates/systemd/elasticsearch.j2 +++ b/templates/systemd/elasticsearch.j2 @@ -1,5 +1,5 @@ [Unit] -Description=Elasticsearch +Description=Elasticsearch-{{es_instance_name}} Documentation=http://www.elastic.co Wants=network-online.target After=network-online.target diff --git a/test/integration/multi/serverspec/default_spec.rb b/test/integration/multi/serverspec/default_spec.rb index 38f8334..93b03aa 100644 --- a/test/integration/multi/serverspec/default_spec.rb +++ b/test/integration/multi/serverspec/default_spec.rb @@ -87,18 +87,6 @@ context "basic tests" do end end - #test to make sure mlock was applied - describe command('curl "localhost:9200/_nodes/localhost-master/process?pretty" | grep mlockall') do - its(:stdout) { should match /\"mlockall\" : true/ } - its(:exit_status) { should eq 0 } - end - - #test to make sure mlock was not applied - describe command('curl "localhost:9201/_nodes/localhost-node1/process?pretty" | grep mlockall') do - its(:stdout) { should match /\"mlockall\" : false/ } - its(:exit_status) { should eq 0 } - end - describe file('/etc/elasticsearch/templates') do it { should be_directory } it { should be_owned_by 'elasticsearch' } @@ -160,5 +148,17 @@ context "basic tests" do it { should be_directory } it { should be_owned_by 'elasticsearch' } end + + #test to make sure mlock was applied + describe command('curl "localhost:9200/_nodes/localhost-master/process?pretty" | grep mlockall') do + its(:stdout) { should match /true/ } + its(:exit_status) { should eq 0 } + end + + #test to make sure mlock was not applied + describe command('curl "localhost:9201/_nodes/localhost-node1/process?pretty" | grep mlockall') do + its(:stdout) { should match /false/ } + its(:exit_status) { should eq 0 } + end end From 0c7c338d6d49e95a215fc58a8e1718aa109e7208 Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Fri, 27 Nov 2015 19:42:52 +0000 Subject: [PATCH 21/27] Minor change for template --- templates/elasticsearch.j2 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/templates/elasticsearch.j2 b/templates/elasticsearch.j2 index d940425..60e4ccf 100644 --- a/templates/elasticsearch.j2 +++ b/templates/elasticsearch.j2 @@ -66,6 +66,7 @@ ES_GROUP={{es_group}} # When using Systemd, this setting is ignored and the LimitNOFILE defined in # /usr/lib/systemd/system/elasticsearch.service takes precedence {% if es_max_open_files is defined %} +#MAX_OPEN_FILES MAX_OPEN_FILES={{es_max_open_files}} {% endif %} @@ -75,6 +76,7 @@ MAX_OPEN_FILES={{es_max_open_files}} # When using Systemd, the LimitMEMLOCK property must be set # in /usr/lib/systemd/system/elasticsearch.service {% if m_lock_enabled %} +#MAX_LOCKED_MEMORY= MAX_LOCKED_MEMORY=unlimited {% endif %} From 7455b7fe3e1de138fa7e03d53501fb5d6b564990 Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Fri, 27 Nov 2015 19:58:54 +0000 Subject: [PATCH 22/27] systemd tests --- .../config/serverspec/default_spec.rb | 12 ++++++-- .../multi/serverspec/default_spec.rb | 29 ++++++++++++------- .../package/serverspec/default_spec.rb | 2 +- .../standard/serverspec/default_spec.rb | 2 +- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/test/integration/config/serverspec/default_spec.rb b/test/integration/config/serverspec/default_spec.rb index 4d42eeb..56f064a 100644 --- a/test/integration/config/serverspec/default_spec.rb +++ b/test/integration/config/serverspec/default_spec.rb @@ -61,17 +61,23 @@ context "basic tests" do end #test we started on the correct port was used - describe command('curl "localhost:9201" | grep status') do + describe command('curl -s "localhost:9201" | grep status') do #TODO: This is returning an empty string #its(:stdout) { should match /\"status\" : 200/ } its(:exit_status) { should eq 0 } end #test to make sure mlock was applied - describe command('curl "localhost:9201/_nodes/process?pretty" | grep mlockall') do - its(:stdout) { should match /\"mlockall\" : true/ } + describe command('curl -s "localhost:9201/_nodes/process?pretty" | grep mlockall') do + its(:stdout) { should match /true/ } its(:exit_status) { should eq 0 } end + describe file('/usr/lib/systemd/system/node1_elasticsearch.service') do + it { should be_file } + it { should contain 'LimitMEMLOCK=infinity' } + it { should contain 'EnvironmentFile=-/etc/sysconfig/node1_elasticsearch' } + end + end diff --git a/test/integration/multi/serverspec/default_spec.rb b/test/integration/multi/serverspec/default_spec.rb index 93b03aa..ca93b42 100644 --- a/test/integration/multi/serverspec/default_spec.rb +++ b/test/integration/multi/serverspec/default_spec.rb @@ -18,16 +18,9 @@ context "basic tests" do it { should be_installed } end - describe file('/etc/elasticsearch/node1/elasticsearch.yml') do - it { should be_file } - end - - describe file('/etc/elasticsearch/master/elasticsearch.yml') do - it { should be_file } - end - #test configuration parameters have been set - test all appropriately set in config file describe file('/etc/elasticsearch/node1/elasticsearch.yml') do + it { should be_file } it { should contain 'http.port: 9201' } it { should contain 'transport.tcp.port: 9301' } it { should contain 'node.data: true' } @@ -44,6 +37,7 @@ context "basic tests" do #test configuration parameters have been set for master - test all appropriately set in config file describe file('/etc/elasticsearch/master/elasticsearch.yml') do + it { should be_file } it { should contain 'http.port: 9200' } it { should contain 'transport.tcp.port: 9300' } it { should contain 'node.data: false' } @@ -150,15 +144,30 @@ context "basic tests" do end #test to make sure mlock was applied - describe command('curl "localhost:9200/_nodes/localhost-master/process?pretty" | grep mlockall') do + describe command('curl -s "localhost:9200/_nodes/localhost-master/process?pretty=true" | grep mlockall') do its(:stdout) { should match /true/ } its(:exit_status) { should eq 0 } end #test to make sure mlock was not applied - describe command('curl "localhost:9201/_nodes/localhost-node1/process?pretty" | grep mlockall') do + describe command('curl -s "localhost:9201/_nodes/localhost-node1/process?pretty=true" | grep mlockall') do its(:stdout) { should match /false/ } its(:exit_status) { should eq 0 } end + + + #Test server spec file has been created and modified + describe file('/usr/lib/systemd/system/master_elasticsearch.service') do + it { should be_file } + it { should contain 'LimitMEMLOCK=infinity' } + it { should contain 'EnvironmentFile=-/etc/sysconfig/master_elasticsearch' } + end + + describe file('/usr/lib/systemd/system/node1_elasticsearch.service') do + it { should be_file } + it { should_not contain 'LimitMEMLOCK=infinity' } + it { should contain 'EnvironmentFile=-/etc/sysconfig/node1_elasticsearch' } + end + end diff --git a/test/integration/package/serverspec/default_spec.rb b/test/integration/package/serverspec/default_spec.rb index 4751760..29bc14b 100644 --- a/test/integration/package/serverspec/default_spec.rb +++ b/test/integration/package/serverspec/default_spec.rb @@ -46,7 +46,7 @@ context "basic tests" do describe 'Template Installed' do it 'should be reported as being installed', :retry => 3, :retry_wait => 10 do - command = command('curl localhost:9200/_template/basic') + command = command('curl -s "localhost:9200/_template/basic"') expect(command.stdout).to match(/basic/) expect(command.exit_status).to eq(0) end diff --git a/test/integration/standard/serverspec/default_spec.rb b/test/integration/standard/serverspec/default_spec.rb index 78c7823..9e3a51b 100644 --- a/test/integration/standard/serverspec/default_spec.rb +++ b/test/integration/standard/serverspec/default_spec.rb @@ -41,7 +41,7 @@ context "basic tests" do describe 'plugin' do it 'should be reported as existing', :retry => 3, :retry_wait => 10 do - command = command('curl localhost:9200/_nodes/?plugin | grep kopf') + command = command('curl -s localhost:9200/_nodes/?plugin | grep kopf') expect(command.stdout).to match(/kopf/) expect(command.exit_status).to eq(0) end From 70283110d8071bf7cc43628b232ae56d7950d37f Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Fri, 27 Nov 2015 20:10:41 +0000 Subject: [PATCH 23/27] Documentation Improvements --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 02b565b..44f05f5 100644 --- a/README.md +++ b/README.md @@ -162,3 +162,11 @@ Following variables affect the versions installed: * ```java_repos``` (an array of repositories to be added to allow java to be installed) * ```java_packages``` (an array of packages to be installed to get Java installed) + +## Notes + +* The role assumes the user/group exists on the server. The elasticsearch packages create the default elasticsearch user. If this needs to be changed, ensure the user exists. +* The playbook relies on the inventory_name of each host to ensure its directories are unique +* Systemd scripts are by default installed in addition to init scripts. This is pending improvement and currently relies on the user to determine the prefered mechanism. +* Changing an instance_name for a role application will result in the installation of a new component. The previous component will remain. +* KitchenCI has been used for testing. This is used to confirm images reach the correct state after a play is first applied. From 2019d36e10dd21b69db29f1ccb850b51d5d1f70d Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Fri, 27 Nov 2015 20:29:44 +0000 Subject: [PATCH 24/27] Test fix for serverspec --- test/integration/config/serverspec/default_spec.rb | 1 - test/integration/multi/serverspec/default_spec.rb | 2 -- 2 files changed, 3 deletions(-) diff --git a/test/integration/config/serverspec/default_spec.rb b/test/integration/config/serverspec/default_spec.rb index 56f064a..0b07653 100644 --- a/test/integration/config/serverspec/default_spec.rb +++ b/test/integration/config/serverspec/default_spec.rb @@ -76,7 +76,6 @@ context "basic tests" do describe file('/usr/lib/systemd/system/node1_elasticsearch.service') do it { should be_file } it { should contain 'LimitMEMLOCK=infinity' } - it { should contain 'EnvironmentFile=-/etc/sysconfig/node1_elasticsearch' } end end diff --git a/test/integration/multi/serverspec/default_spec.rb b/test/integration/multi/serverspec/default_spec.rb index ca93b42..08a784b 100644 --- a/test/integration/multi/serverspec/default_spec.rb +++ b/test/integration/multi/serverspec/default_spec.rb @@ -160,13 +160,11 @@ context "basic tests" do describe file('/usr/lib/systemd/system/master_elasticsearch.service') do it { should be_file } it { should contain 'LimitMEMLOCK=infinity' } - it { should contain 'EnvironmentFile=-/etc/sysconfig/master_elasticsearch' } end describe file('/usr/lib/systemd/system/node1_elasticsearch.service') do it { should be_file } it { should_not contain 'LimitMEMLOCK=infinity' } - it { should contain 'EnvironmentFile=-/etc/sysconfig/node1_elasticsearch' } end end From b750bb875986c933d6fa728e0a8913e7f928e1f8 Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Fri, 27 Nov 2015 21:09:58 +0000 Subject: [PATCH 25/27] COmment change --- tasks/elasticsearch-config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/elasticsearch-config.yml b/tasks/elasticsearch-config.yml index c98c3b4..5afed39 100644 --- a/tasks/elasticsearch-config.yml +++ b/tasks/elasticsearch-config.yml @@ -62,6 +62,6 @@ notify: restart elasticsearch #Copy the logging.yml -- name: Copy Systemd File for Instance +- name: Copy Logging.yml File for Instance template: src=logging.yml.j2 dest={{instance_config_directory}}/logging.yml owner={{ es_user }} group={{ es_group }} mode=0644 force=yes notify: restart elasticsearch \ No newline at end of file From 6c4289b2df9c620b17fc2b0f525c00c67c8d0a2f Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Fri, 27 Nov 2015 21:43:49 +0000 Subject: [PATCH 26/27] Systemd temp path for Debian 8 --- README.md | 2 +- tasks/elasticsearch-config.yml | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 44f05f5..fdb20f3 100644 --- a/README.md +++ b/README.md @@ -167,6 +167,6 @@ Following variables affect the versions installed: * The role assumes the user/group exists on the server. The elasticsearch packages create the default elasticsearch user. If this needs to be changed, ensure the user exists. * The playbook relies on the inventory_name of each host to ensure its directories are unique -* Systemd scripts are by default installed in addition to init scripts. This is pending improvement and currently relies on the user to determine the prefered mechanism. +* Systemd scripts are by default installed in addition to init scripts - with the exception of Debian 8. This is pending improvement and currently relies on the user to determine the preferred mechanism. * Changing an instance_name for a role application will result in the installation of a new component. The previous component will remain. * KitchenCI has been used for testing. This is used to confirm images reach the correct state after a play is first applied. diff --git a/tasks/elasticsearch-config.yml b/tasks/elasticsearch-config.yml index 5afed39..afbec76 100644 --- a/tasks/elasticsearch-config.yml +++ b/tasks/elasticsearch-config.yml @@ -6,8 +6,10 @@ - stat: path={{sysd_script}} register: systemd_service +- set_fact: use_system_d={{systemd_service.stat.exists and (ansible_os_family == 'RedHat' or ansible_distribution_version | version_compare('8', '<'))}} + - set_fact: instance_sysd_script={{sysd_script | dirname }}/{{es_instance_name}}_{{sysd_script | basename}} - when: systemd_service.stat.exists + when: use_system_d #For directories we also use the {{inventory_hostname}}-{{ es_instance_name }} - this helps if we have a shared SAN. @@ -58,7 +60,7 @@ #Copy the systemd specific file if systemd is installed - name: Copy Systemd File for Instance template: src=systemd/elasticsearch.j2 dest={{instance_sysd_script}} mode=0644 force=yes - when: systemd_service.stat.exists + when: use_system_d notify: restart elasticsearch #Copy the logging.yml From 103499589909f08ec0f7e654473dcd3941308d6a Mon Sep 17 00:00:00 2001 From: Dale McDiarmid Date: Fri, 27 Nov 2015 22:52:36 +0000 Subject: [PATCH 27/27] Fix for server spec debian 8 --- README.md | 9 ++++++++- tasks/elasticsearch-config.yml | 3 +-- test/integration/config/serverspec/default_spec.rb | 5 ----- test/integration/multi/serverspec/default_spec.rb | 11 ----------- 4 files changed, 9 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index fdb20f3..6f21171 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,13 @@ # ansible-elasticsearch -Ansible playbook / roles / tasks for Elasticsearch. Currently it will work on Debian and RedHat based linux systems. +Ansible playbook / roles / tasks for Elasticsearch. Currently it will work on Debian and RedHat based linux systems. Tested platforms are: + +* Ubuntu 1404 +* Debian 7 +* Debian 8 +* Centos 7 +* Centos 8 + ## Usage diff --git a/tasks/elasticsearch-config.yml b/tasks/elasticsearch-config.yml index afbec76..0a827f2 100644 --- a/tasks/elasticsearch-config.yml +++ b/tasks/elasticsearch-config.yml @@ -5,8 +5,7 @@ #This relies on elasticsearch installing a serviced script to determine whether one should be copied. - stat: path={{sysd_script}} register: systemd_service - -- set_fact: use_system_d={{systemd_service.stat.exists and (ansible_os_family == 'RedHat' or ansible_distribution_version | version_compare('8', '<'))}} +- set_fact: use_system_d={{systemd_service.stat.exists and (not ansible_distribution == 'Debian' or ansible_distribution_version | version_compare('8', '<'))}} - set_fact: instance_sysd_script={{sysd_script | dirname }}/{{es_instance_name}}_{{sysd_script | basename}} when: use_system_d diff --git a/test/integration/config/serverspec/default_spec.rb b/test/integration/config/serverspec/default_spec.rb index 0b07653..eb646e4 100644 --- a/test/integration/config/serverspec/default_spec.rb +++ b/test/integration/config/serverspec/default_spec.rb @@ -73,10 +73,5 @@ context "basic tests" do its(:exit_status) { should eq 0 } end - describe file('/usr/lib/systemd/system/node1_elasticsearch.service') do - it { should be_file } - it { should contain 'LimitMEMLOCK=infinity' } - end - end diff --git a/test/integration/multi/serverspec/default_spec.rb b/test/integration/multi/serverspec/default_spec.rb index 08a784b..91e01d1 100644 --- a/test/integration/multi/serverspec/default_spec.rb +++ b/test/integration/multi/serverspec/default_spec.rb @@ -156,16 +156,5 @@ context "basic tests" do end - #Test server spec file has been created and modified - describe file('/usr/lib/systemd/system/master_elasticsearch.service') do - it { should be_file } - it { should contain 'LimitMEMLOCK=infinity' } - end - - describe file('/usr/lib/systemd/system/node1_elasticsearch.service') do - it { should be_file } - it { should_not contain 'LimitMEMLOCK=infinity' } - end - end