changed CHANGELOG.md
 
@@ -7,9 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
8
8
## [Unreleased]
9
9
10
+ ## [0.1.1] - 2021-09-24
11
+
12
+ ### Fixed
13
+
14
+ - Validate short and long names properly. This also add better defaults depending
15
+ on which type of nodes PLDS is connecting to.
16
+
17
+ ### Changed
18
+
19
+ - The `--cookie` flag is now optional. By default it will use the one from
20
+ `Node.get_cookie()` when distribution is enabled.
21
+
22
+ ## [0.1.0] - 2021-09-22
23
+
10
24
### Added
11
25
12
26
- Initial release of PLDS.
13
27
14
- [Unreleased]: https://github.com/phoenixframework/plds/compare/v0.1.0...HEAD
28
+ [Unreleased]: https://github.com/phoenixframework/plds/compare/v0.1.1...HEAD
29
+ [0.1.1]: https://github.com/phoenixframework/plds/compare/v0.1.0...v0.1.1
15
30
[0.1.0]: https://github.com/phoenixframework/plds/releases/tag/v0.1.0
changed README.md
 
@@ -1,5 +1,7 @@
1
1
# PLDS - Phoenix LiveDashboard Standalone
2
2
3
+ [![CI](https://github.com/phoenixframework/plds/actions/workflows/ci.yml/badge.svg)](https://github.com/phoenixframework/plds/actions/workflows/ci.yml)
4
+
3
5
<!-- MDOC !-->
4
6
5
7
PLDS is a command line interface for [Phoenix LiveDashboard](https://github.com/phoenixframework/phoenix_live_dashboard)
 
@@ -47,6 +49,12 @@ The only one available today is:
47
49
- Ecto with extras - works for PostgreSQL databases.
48
50
- Broadway Dashboard - to inspect Broadway pipelines.
49
51
52
+ ## Disabled pages
53
+
54
+ Note that some pages will be disabled when using PLDS. "Metrics" page is disabled
55
+ because we can't tell which module is responsible for the data upfront.
56
+ "OS Data" page is enabled only if the node has the `os_mon` application running.
57
+
50
58
<!-- MDOC !-->
51
59
52
60
## Development
changed hex_metadata.config
 
@@ -50,4 +50,4 @@
50
50
{<<"optional">>,false},
51
51
{<<"repository">>,<<"hexpm">>},
52
52
{<<"requirement">>,<<"~> 2.5">>}]]}.
53
- {<<"version">>,<<"0.1.0">>}.
53
+ {<<"version">>,<<"0.1.1">>}.
changed lib/plds/application.ex
 
@@ -10,6 +10,7 @@ defmodule PLDS.Application do
10
10
@impl true
11
11
def start(_type, _args) do
12
12
ensure_distribution!()
13
+ validate_hostname_resolution!()
13
14
connect_to_nodes!()
14
15
15
16
children = [
 
@@ -26,17 +27,37 @@ defmodule PLDS.Application do
26
27
defp ensure_distribution! do
27
28
PLDS.Distribution.ensure_distribution!()
28
29
29
- cookie = Application.fetch_env!(:plds, :cookie)
30
- Node.set_cookie(cookie)
30
+ if cookie = Application.get_env(:plds, :cookie) do
31
+ Node.set_cookie(cookie)
32
+ end
31
33
end
32
34
else
33
35
defp ensure_distribution!, do: :noop
34
36
end
35
37
36
38
defp connect_to_nodes! do
37
- nodes = Application.get_env(:plds, :nodes_to_connect, [])
39
+ PLDS.Distribution.connect_to_nodes!()
40
+ end
38
41
39
- PLDS.Distribution.connect_to_nodes!(nodes)
42
+ # See https://github.com/livebook-dev/livebook/pull/303
43
+ defp validate_hostname_resolution!() do
44
+ unless PLDS.Utils.long_name?() do
45
+ hostname = PLDS.Utils.node_host() |> to_charlist()
46
+
47
+ if hostname != 'nohost' and :inet.gethostbyname(hostname) == {:error, :nxdomain} do
48
+ PLDS.Utils.abort!("""
49
+ your hostname "#{hostname}" does not resolve to any IP address, which indicates something wrong in your OS configuration.
50
+
51
+ Make sure your computer's name resolves locally or start PLDS using a long distribution name:
52
+
53
+ plds server --name [email protected]
54
+
55
+ If you are running it from source, do instead:
56
+
57
+ MIX_ENV=prod elixir --name [email protected] -S mix phx.server
58
+ """)
59
+ end
60
+ end
40
61
end
41
62
42
63
@impl true
changed lib/plds/distribution.ex
 
@@ -41,21 +41,41 @@ defmodule PLDS.Distribution do
41
41
end
42
42
43
43
defp get_node_type_and_name do
44
- Application.get_env(:plds, :node) || {:shortnames, :plds}
44
+ Application.get_env(:plds, :node) || default_node_type_and_name()
45
+ end
46
+
47
+ # Choose for a short or long name based on connections.
48
+ def default_node_type_and_name do
49
+ if Enum.any?(nodes_to_connect(), &PLDS.Utils.long_name?(Atom.to_string(&1))) do
50
+ name = :"[email protected]"
51
+
52
+ print_warning(
53
+ "using long names because one of the nodes is long. Current name is #{inspect(name)}"
54
+ )
55
+
56
+ {:longnames, name}
57
+ else
58
+ {:shortnames, :plds}
59
+ end
60
+ end
61
+
62
+ defp print_warning(message) do
63
+ IO.puts(:stderr, IO.ANSI.format([:yellow, "[PLDS] " <> message]))
64
+ end
65
+
66
+ defp nodes_to_connect do
67
+ Application.get_env(:plds, :nodes_to_connect, [])
45
68
end
46
69
47
70
# Nodes can have long or short names.
48
- def connect_to_nodes!(nodes) do
49
- [_, host] =
50
- node()
51
- |> Atom.to_string()
52
- |> String.split("@")
71
+ def connect_to_nodes!(nodes \\ nodes_to_connect()) do
72
+ host = PLDS.Utils.node_host()
53
73
54
74
# We get the current node host as host for when connect
55
75
# only have shortnames
56
76
for name <- nodes do
57
77
name =
58
- if long_name?(name) do
78
+ if with_host?(name) do
59
79
name
60
80
else
61
81
:"#{name}@#{host}"
 
@@ -67,7 +87,7 @@ defmodule PLDS.Distribution do
67
87
:ok
68
88
end
69
89
70
- defp long_name?(name) do
90
+ defp with_host?(name) do
71
91
name
72
92
|> Atom.to_string()
73
93
|> String.contains?("@")
changed lib/plds/utils.ex
 
@@ -40,4 +40,35 @@ defmodule PLDS.Utils do
40
40
raise "\nERROR!!! [PLDS] " <> message
41
41
end
42
42
end
43
+
44
+ @doc """
45
+ Check if this app is running with long name.
46
+ """
47
+ def long_name? do
48
+ node_host() =~ "."
49
+ end
50
+
51
+ @doc """
52
+ Similar to long_name?/0, but check the given name.
53
+ """
54
+ def long_name?(name) do
55
+ name =~ "@" and name =~ "."
56
+ end
57
+
58
+ @doc """
59
+ Check if the given name is a short name with host.
60
+ """
61
+ def short_name_with_host?(name) do
62
+ String.contains?(name, "@") && not String.contains?(name, ".")
63
+ end
64
+
65
+ @doc """
66
+ Returns the host part of a node.
67
+ """
68
+ @spec node_host() :: binary()
69
+ def node_host do
70
+ [_, host] = node() |> Atom.to_string() |> :binary.split("@")
71
+
72
+ host
73
+ end
43
74
end
changed lib/plds_cli/server.ex
 
@@ -13,8 +13,12 @@ defmodule PLDSCli.Server do
13
13
14
14
-c, --connect One or more node names to connect.
15
15
You can specify more nodes by using this option multiple times.
16
- It accepts both short and long names.
16
+ It accepts both short and long names. For short names you can
17
+ omit the host. If you pass a long name, then PLDS will start
18
+ with a long name with host "127.0.0.1". You cannot use short
19
+ and long names together.
17
20
--cookie Sets a cookie for the app distributed node.
21
+ This is optional and defaults to `Node.get_cookie()`.
18
22
--ip The ip address to start the web application on, defaults to 127.0.0.1
19
23
Must be a valid IPv4 or IPv6 address.
20
24
--name Set a name for the app distributed node.
 
@@ -121,16 +125,55 @@ defmodule PLDSCli.Server do
121
125
c: :connect
122
126
]
123
127
124
- defp args_to_options(args) do
128
+ # TODO: add tests to the name/sname and connect validations
129
+ @doc false
130
+ def args_to_options(args) do
125
131
{opts, _} = OptionParser.parse!(args, strict: @switches, aliases: @aliases)
126
132
validate_options!(opts)
127
133
opts
128
134
end
129
135
130
136
defp validate_options!(opts) do
131
- if Keyword.has_key?(opts, :name) and Keyword.has_key?(opts, :sname) do
132
- raise "the provided --sname and --name options are mutually exclusive, please specify only one of them"
137
+ if Keyword.has_key?(opts, :name) do
138
+ validate_opts_for_name!(opts)
133
139
end
140
+
141
+ if Keyword.has_key?(opts, :sname) do
142
+ validate_opts_for_short_name!(opts)
143
+ end
144
+ end
145
+
146
+ defp validate_opts_for_name!(opts) do
147
+ cond do
148
+ Keyword.has_key?(opts, :sname) ->
149
+ raise "the provided --sname and --name options are mutually exclusive, please specify only one of them"
150
+
151
+ connecting_to_short_names_with_hosts?(opts) ->
152
+ raise "the provided connections should have long names because you specified the --name option"
153
+
154
+ not PLDS.Utils.long_name?(opts[:name]) ->
155
+ raise "the provided --name option should include the full host name"
156
+
157
+ true ->
158
+ :ok
159
+ end
160
+ end
161
+
162
+ defp validate_opts_for_short_name!(opts) do
163
+ has_full_names? =
164
+ opts
165
+ |> Keyword.take([:connect])
166
+ |> Enum.any?(fn {:connect, name} -> PLDS.Utils.long_name?(name) end)
167
+
168
+ if has_full_names? do
169
+ raise "the provided connections should have short names because you specified the --sname option"
170
+ end
171
+ end
172
+
173
+ defp connecting_to_short_names_with_hosts?(opts) do
174
+ opts
175
+ |> Keyword.take([:connect])
176
+ |> Enum.any?(fn {:connect, name} -> PLDS.Utils.short_name_with_host?(name) end)
134
177
end
135
178
136
179
defp opts_to_config([], config), do: config
changed mix.exs
 
@@ -1,7 +1,7 @@
1
1
defmodule PLDS.MixProject do
2
2
use Mix.Project
3
3
4
- @version "0.1.0"
4
+ @version "0.1.1"
5
5
@description "CLI version of Phoenix LiveDashboard"
6
6
7
7
def project do