1%% @author Couchbase <info@couchbase.com>
2%% @copyright 2017-2018 Couchbase, Inc.
3%%
4%% Licensed under the Apache License, Version 2.0 (the "License");
5%% you may not use this file except in compliance with the License.
6%% You may obtain a copy of the License at
7%%
8%%      http://www.apache.org/licenses/LICENSE-2.0
9%%
10%% Unless required by applicable law or agreed to in writing, software
11%% distributed under the License is distributed on an "AS IS" BASIS,
12%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13%% See the License for the specific language governing permissions and
14%% limitations under the License.
15
16%% @doc implementation of alternate_addresses functions that serve
17%% alternate_addresses information stored in ns_config.
18
19-module(alternate_addresses).
20
21-export([map_port/2,
22         service_ports/1,
23         filter_rename_ports/2,
24         get_external/0,
25         get_external/2]).
26
27-include("ns_common.hrl").
28
29-record(port, {config, rest, service}).
30-define(define_port(ConfName, RestName, Service),
31        #port{config  = ConfName,
32              rest    = <<??RestName>>,
33              service = Service}).
34all_ports() ->
35    [%% rest service ports
36     ?define_port(rest_port, mgmt, rest),
37     ?define_port(ssl_rest_port, mgmtSSL, rest),
38     %% kv service ports
39     ?define_port(memcached_port, kv, kv),
40     ?define_port(memcached_ssl_port, kvSSL, kv),
41     ?define_port(capi_port, capi, kv),
42     ?define_port(ssl_capi_port, capiSSL, kv),
43     ?define_port(projector_port, projector, kv),
44     ?define_port(moxi_port, moxi, kv),
45     %% query service ports
46     ?define_port(query_port, n1ql, n1ql),
47     ?define_port(ssl_query_port, n1qlSSL, n1ql),
48     %% index service ports
49     ?define_port(indexer_admin_port, indexAdmin, index),
50     ?define_port(indexer_scan_port, indexScan, index),
51     ?define_port(indexer_http_port, indexHttp, index),
52     ?define_port(indexer_https_port, indexHttps, index),
53     ?define_port(indexer_stinit_port, indexStreamInit, index),
54     ?define_port(indexer_stcatchup_port, indexStreamCatchup, index),
55     ?define_port(indexer_stmaint_port, indexStreamMaint, index),
56     %% fts service ports
57     ?define_port(fts_http_port, fts, fts),
58     ?define_port(fts_ssl_port, ftsSSL, fts),
59     %% eventing service ports
60     ?define_port(eventing_http_port, eventingAdminPort, eventing),
61     ?define_port(eventing_https_port, eventingSSL, eventing),
62     %% cbas service ports
63     ?define_port(cbas_http_port, cbas, cbas),
64     ?define_port(cbas_admin_port, cbasAdmin, cbas),
65     ?define_port(cbas_cc_http_port, cbasCc, cbas),
66     ?define_port(cbas_ssl_port, cbasSSL, cbas),
67     %% miscellaneous cbas ports
68     ?define_port(cbas_cluster_port, cbasCluster, misc),
69     ?define_port(cbas_cc_cluster_port, cbasCcCluster, misc),
70     ?define_port(cbas_cc_client_port, cbasCcClient, misc),
71     ?define_port(cbas_console_port, cbasConsole, misc),
72     ?define_port(cbas_data_port, cbasData, misc),
73     ?define_port(cbas_result_port, cbasResult, misc),
74     ?define_port(cbas_messaging_port, cbasMessaging, misc),
75     ?define_port(cbas_debug_port, cbasDebug, misc),
76     ?define_port(cbas_parent_port, cbasParent, misc),
77     ?define_port(cbas_replication_port, cbasReplication, misc)].
78
79service_ports(Service) ->
80    [P#port.config || P <- all_ports(), P#port.service =:= Service].
81
82map_port(from_rest, Port) ->
83    map_port(Port, #port.rest, #port.config);
84map_port(from_config, Port) ->
85    map_port(Port, #port.config, #port.rest).
86
87map_port(Port, FromField, ToField) ->
88    case lists:keyfind(Port, FromField, all_ports()) of
89        false -> throw({error, [<<"No such port">>]});
90        Tuple -> element(ToField, Tuple)
91    end.
92
93get_external() ->
94    get_external(node(), ns_config:latest()).
95get_external(Node, Config) ->
96    External = ns_config:search_node_prop(Node, Config,
97                                          alternate_addresses, external,
98                                          []),
99    Hostname = proplists:get_value(hostname, External),
100    Ports    = proplists:get_value(ports, External, []),
101    {Hostname, Ports}.
102
103filter_rename_ports([], _WantedPorts) -> [];
104filter_rename_ports(Ports, WantedPorts) ->
105    lists:filtermap(
106      fun (ConfigName) ->
107              case lists:keyfind(ConfigName, 1, Ports) of
108                  false ->
109                      false;
110                  {_ConfigName, Value} ->
111                      RestName = map_port(from_config, ConfigName),
112                      {true, {RestName, Value}}
113              end
114      end, WantedPorts).
115