1<?php
2
3namespace Elastica\Node;
4
5use Elastica\Exception\ClientException;
6use Elastica\Exception\ConnectionException;
7use Elastica\Exception\ResponseException;
8use Elastica\Node as BaseNode;
9use Elastica\Response;
10use Elasticsearch\Endpoints\Nodes\Info as NodesInfo;
11
12/**
13 * Elastica cluster node object.
14 *
15 * @author Nicolas Ruflin <spam@ruflin.com>
16 *
17 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-status.html
18 */
19class Info
20{
21    /**
22     * Response.
23     *
24     * @var Response Response object
25     */
26    protected $_response;
27
28    /**
29     * Stats data.
30     *
31     * @var array stats data
32     */
33    protected $_data = [];
34
35    /**
36     * Node.
37     *
38     * @var BaseNode Node object
39     */
40    protected $_node;
41
42    /**
43     * Query parameters.
44     *
45     * @var array
46     */
47    protected $_params = [];
48
49    /**
50     * Unique node id.
51     *
52     * @var string
53     */
54    protected $_id;
55
56    /**
57     * Create new info object for node.
58     *
59     * @param BaseNode $node   Node object
60     * @param array    $params List of params to return. Can be: settings, os, process, jvm, thread_pool, network, transport, http
61     */
62    public function __construct(BaseNode $node, array $params = [])
63    {
64        $this->_node = $node;
65        $this->refresh($params);
66    }
67
68    /**
69     * Returns the entry in the data array based on the params.
70     * Several params possible.
71     *
72     * Example 1: get('os', 'mem', 'total') returns total memory of the system the
73     * node is running on
74     * Example 2: get('os', 'mem') returns an array with all mem infos
75     *
76     * @return mixed Data array entry or null if not found
77     */
78    public function get(...$args)
79    {
80        $data = $this->getData();
81
82        foreach ($args as $arg) {
83            if (isset($data[$arg])) {
84                $data = $data[$arg];
85            } else {
86                return null;
87            }
88        }
89
90        return $data;
91    }
92
93    /**
94     * Return port of the node.
95     *
96     * @return string Returns Node port
97     */
98    public function getPort(): string
99    {
100        // Returns string in format: inet[/192.168.1.115:9201]
101        $data = $this->get('http_address');
102        $data = \substr($data, 6, -1);
103        $data = \explode(':', $data);
104
105        return $data[1];
106    }
107
108    /**
109     * Return IP of the node.
110     *
111     * @return string Returns Node ip address
112     */
113    public function getIp(): string
114    {
115        // Returns string in format: inet[/192.168.1.115:9201]
116        $data = $this->get('http_address');
117        $data = \substr($data, 6, -1);
118        $data = \explode(':', $data);
119
120        return $data[0];
121    }
122
123    /**
124     * Return data regarding plugins installed on this node.
125     *
126     * @return array plugin data
127     *
128     * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-nodes-info.html
129     */
130    public function getPlugins(): array
131    {
132        if (!\in_array('plugins', $this->_params, true)) {
133            // Plugin data was not retrieved when refresh() was called last. Get it now.
134            $this->_params[] = 'plugins';
135            $this->refresh($this->_params);
136        }
137
138        return $this->get('plugins');
139    }
140
141    /**
142     * Check if the given plugin is installed on this node.
143     *
144     * @param string $name plugin name
145     *
146     * @return bool true if the plugin is installed, false otherwise
147     */
148    public function hasPlugin($name): bool
149    {
150        foreach ($this->getPlugins() as $plugin) {
151            if ($plugin['name'] === $name) {
152                return true;
153            }
154        }
155
156        return false;
157    }
158
159    /**
160     * Return all info data.
161     *
162     * @return array Data array
163     */
164    public function getData(): array
165    {
166        return $this->_data;
167    }
168
169    /**
170     * Return node object.
171     *
172     * @return BaseNode Node object
173     */
174    public function getNode(): BaseNode
175    {
176        return $this->_node;
177    }
178
179    /**
180     * @return string Unique node id
181     */
182    public function getId(): string
183    {
184        return $this->_id;
185    }
186
187    /**
188     * @return string Node name
189     */
190    public function getName(): string
191    {
192        return $this->_data['name'];
193    }
194
195    /**
196     * Returns response object.
197     *
198     * @return Response Response object
199     */
200    public function getResponse(): Response
201    {
202        return $this->_response;
203    }
204
205    /**
206     * Reloads all nodes information. Has to be called if informations changed.
207     *
208     * @param array $params Params to return (default none). Possible options: settings, os, process, jvm, thread_pool, network, transport, http, plugin
209     *
210     * @throws ClientException
211     * @throws ConnectionException
212     * @throws ResponseException
213     *
214     * @return Response Response object
215     */
216    public function refresh(array $params = []): Response
217    {
218        $this->_params = $params;
219
220        // TODO: Use only NodesInfo when dropping support for elasticsearch/elasticsearch 7.x
221        $endpoint = \class_exists(NodesInfo::class) ? new NodesInfo() : new \Elasticsearch\Endpoints\Cluster\Nodes\Info();
222        $endpoint->setNodeId($this->getNode()->getId());
223
224        if ($params) {
225            $endpoint->setMetric($params);
226        }
227
228        $this->_response = $this->getNode()->getClient()->requestEndpoint($endpoint);
229        $data = $this->getResponse()->getData();
230
231        $this->_data = \reset($data['nodes']);
232        $this->_id = \key($data['nodes']);
233        $this->getNode()->setId($this->getId());
234
235        return $this->_response;
236    }
237}
238