Skip to content

Commit a763aae

Browse files
committed
AstarteExport: Add Cassandra host/port and update README
- Modified export_realm_data/3 to accept db_host_and_port as an argument. - Set Cassandra host and port as env variables - Updated the run/1 function to reflect the new parameters for exporting. - Enhanced documentation to include the new db_host_and_port argument. - Updated README to reflect the changes in function usage and parameters. Signed-off-by: Jusuf <jusuf.avdic@secomind.com>
1 parent 5926acc commit a763aae

File tree

6 files changed

+98
-34
lines changed

6 files changed

+98
-34
lines changed

tools/astarte_export/README.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Astarte Export is an easy to use tool that allows to exporting all the devices and data from an existing Astarte realm to XML format.
44

55
```iex
6-
iex(astarte_export@127.0.0.1)6> Astarte.Export.export_realm_data("test", "test.xml")
6+
iex(astarte_export@127.0.0.1)6> Astarte.Export.export_realm_data("test", "test.xml", [{:device_id, "ogmcilZpRDe"}, {:db_host_and_port, "localhost:9042"}])
77
level=info ts=2020-02-03T03:57:21.412+00:00 msg="Export started." module=Astarte.Export function=generate_xml/2 realm=test tag=export_started
88
level=info ts=2020-02-03T03:57:21.413+00:00 msg="Connecting to \"172.23.0.3\":\"9042\" cassandra database." module=Astarte.Export.FetchData.Queries function=get_connection/0
99
level=info ts=2020-02-03T03:57:21.414+00:00 msg="Connected to database." module=Astarte.Export.FetchData.Queries function=get_connection/0
@@ -40,12 +40,26 @@ To export data for all devices in a realm:
4040
To export data for a single device in a realm:
4141

4242
```bash
43-
mix astarte.export <REALM> <FILE_XML> <DEVICE_ID>
43+
mix astarte.export <REALM> <FILE_XML> --device_id <DEVICE_ID>
4444
```
4545

4646
- `<REALM>`: The name of the Astarte realm.
4747
- `<FILE_XML>`: The output file path where the exported data will be saved.
48-
- `<DEVICE_ID>`: The unique identifier of the device (e.g., "ogmcilZpRDeDWwuNfJr0yA").
48+
- `--device_id <DEVICE_ID>`(optional): The unique identifier of the device (e.g., "ogmcilZpRDeDWwuNfJr0yA").
49+
50+
## Export Data for a Realm with a Custom Database Host and Port
51+
52+
To export data from a specific Astarte realm with a custom database host and port:
53+
54+
```bash
55+
mix astarte.export <REALM> <FILE_XML> --device_id <DEVICE_ID> --db_host_and_port <DB_HOST_AND_PORT>
56+
```
57+
58+
- `<REALM>`: The name of the Astarte realm.
59+
- `<FILE_XML>`: The output file path where the exported data will be saved.
60+
- `--device_id <DEVICE_ID>` (optional): The unique identifier of the device (e.g., "ogmcilZpRDeDWwuNfJr0yA").
61+
- `--db_host_and_port <DB_HOST_AND_PORT>` (optional):
62+
The host and port of the database in the format host:port (e.g., "localhost:9042"").
4963

5064
## Example Commands
5165

tools/astarte_export/lib/astarte/export.ex

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,14 @@ defmodule Astarte.Export do
3737
- options -> options to export the realm data.
3838
"""
3939

40-
@spec export_realm_data(String.t(), String.t(), keyword()) ::
40+
@spec export_realm_data(
41+
String.t(),
42+
String.t(),
43+
[{:db_host_and_port, String.t()} | {:device_id, String.t()}] | []
44+
) ::
45+
:ok | {:error, :invalid_parameters} | {:error, any()}
46+
47+
@spec export_realm_data(String.t(), String.t()) ::
4148
:ok | {:error, :invalid_parameters} | {:error, any()}
4249

4350
def export_realm_data(realm, file, opts \\ []) do
@@ -54,7 +61,7 @@ defmodule Astarte.Export do
5461
with {:ok, state} <- XMLGenerate.xml_write_default_header(fd),
5562
{:ok, state} <- XMLGenerate.xml_write_start_tag(fd, {"astarte", []}, state),
5663
{:ok, state} <- XMLGenerate.xml_write_start_tag(fd, {"devices", []}, state),
57-
{:ok, conn} <- FetchData.db_connection_identifier(),
64+
{:ok, conn} <- FetchData.db_connection_identifier(opts),
5865
{:ok, state} <- process_devices(conn, realm, fd, state, opts),
5966
{:ok, state} <- XMLGenerate.xml_write_end_tag(fd, state),
6067
{:ok, _state} <- XMLGenerate.xml_write_end_tag(fd, state),

tools/astarte_export/lib/astarte/fetchdata/fetchdata.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ defmodule Astarte.Export.FetchData do
1313
booleanarray: :boolean
1414
}
1515

16-
def db_connection_identifier() do
17-
with {:ok, conn_ref} <- Queries.get_connection() do
16+
def db_connection_identifier(opts \\ []) do
17+
with {:ok, conn_ref} <- Queries.get_connection(opts) do
1818
{:ok, conn_ref}
1919
else
2020
_ -> {:error, :connection_setup_failed}

tools/astarte_export/lib/astarte/fetchdata/queries/queries.ex

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,22 @@ defmodule Astarte.Export.FetchData.Queries do
66

77
require Logger
88

9-
def get_connection() do
10-
host = System.get_env("CASSANDRA_DB_HOST")
11-
port = System.get_env("CASSANDRA_DB_PORT")
12-
Logger.info("Connecting to #{inspect(host)}:#{inspect(port)} cassandra database.")
9+
def get_connection(opts \\ []) do
10+
db_host_and_port = Keyword.get(opts, :db_host_and_port)
1311

14-
with {:ok, xandra_conn} <- Xandra.start_link(nodes: ["#{host}:#{port}"], atom_keys: true) do
12+
[db_host, db_port] =
13+
case db_host_and_port do
14+
nil ->
15+
[System.get_env("CASSANDRA_DB_HOST"), System.get_env("CASSANDRA_DB_PORT")]
16+
17+
_ ->
18+
String.split(db_host_and_port, ":")
19+
end
20+
21+
Logger.info("Connecting to #{inspect(db_host)}:#{inspect(db_port)} cassandra database.")
22+
23+
with {:ok, xandra_conn} <-
24+
Xandra.start_link(nodes: ["#{db_host}:#{db_port}"], atom_keys: true) do
1525
Logger.info("Connected to database.")
1626
{:ok, xandra_conn}
1727
else

tools/astarte_export/lib/mix/tasks/astarte_export.ex

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,43 @@ defmodule Mix.Tasks.Astarte.Export do
55
require Logger
66

77
@impl Mix.Task
8-
@shortdoc "export data from an existing Astarte realm"
8+
@shortdoc "Export data from an existing Astarte realm"
99
def run(args) do
10-
case args do
11-
[realm, file_name] ->
12-
Logger.info("Exporting data from realm #{realm} to file #{file_name}")
10+
{realm, file_name, device_id, db_host_and_port} = parse_args(args)
1311

14-
case Application.ensure_all_started(:astarte_export) do
15-
{:ok, _} ->
16-
Export.export_realm_data(realm, file_name)
12+
Logger.info("Exporting data from realm #{realm} to file #{file_name}")
1713

18-
{:error, reason} ->
19-
Logger.error("Cannot start applications: #{inspect(reason)}")
20-
end
14+
options =
15+
case {db_host_and_port, device_id} do
16+
{nil, nil} -> []
17+
{nil, _} -> [device_id: device_id]
18+
{_, nil} -> [db_host_and_port: db_host_and_port]
19+
{_, _} -> [db_host_and_port: db_host_and_port, device_id: device_id]
20+
end
2121

22-
[realm, file_name, device_id] ->
23-
Logger.info(
24-
"Exporting data for device #{device_id} from realm #{realm} to file #{file_name}"
25-
)
22+
case Application.ensure_all_started(:astarte_export) do
23+
{:ok, _} ->
24+
Export.export_realm_data(realm, file_name, options)
2625

27-
options = [device_id: device_id]
26+
{:error, reason} ->
27+
Logger.error("Cannot start applications: #{inspect(reason)}")
28+
end
29+
end
2830

29-
case Application.ensure_all_started(:astarte_export) do
30-
{:ok, _} ->
31-
Export.export_realm_data(realm, file_name, options)
31+
defp parse_args([realm, file_name | opts]) do
32+
{device_id, db_host_and_port} = parse_optional_args(opts)
33+
{realm, file_name, device_id, db_host_and_port}
34+
end
3235

33-
{:error, reason} ->
34-
Logger.error("Cannot start applications: #{inspect(reason)}")
35-
end
36-
end
36+
defp parse_optional_args([]), do: {nil, nil}
37+
38+
defp parse_optional_args(["--device_id", device_id | rest]) do
39+
{device_id, parse_optional_args(rest) |> elem(1)}
40+
end
41+
42+
defp parse_optional_args(["--db_host_and_port", db_host_and_port | rest]) do
43+
{parse_optional_args(rest) |> elem(0), db_host_and_port}
3744
end
45+
46+
defp parse_optional_args([_ | rest]), do: parse_optional_args(rest)
3847
end

tools/astarte_export/test/astarte_export_test.exs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ defmodule Astarte.ExportTest do
55
alias Astarte.Export.FetchData
66
alias Astarte.DatabaseTestdata
77
@realm "test"
8+
@db_host_and_port "localhost:9042"
89

910
@expected_xml """
1011
<?xml version="1.0" encoding="UTF-8"?>
@@ -77,12 +78,35 @@ defmodule Astarte.ExportTest do
7778
assert @expected_xml == File.read!(file)
7879
end
7980

81+
test "export realm data to xml file with db_host_and_port" do
82+
DatabaseTestdata.initialize_database()
83+
assert {:ok, :export_completed} ==
84+
Export.export_realm_data(@realm, "test.xml", [db_host_and_port: @db_host_and_port])
85+
file = Path.expand("test.xml") |> Path.absname()
86+
assert @expected_xml == File.read!(file)
87+
end
88+
8089
test "export realm data to xmlfile in a absolute path " do
8190
file = File.cwd!() <> "/test.xml"
8291
assert {:ok, :export_completed} == Export.export_realm_data(@realm, file)
8392
assert @expected_xml == File.read!(file)
8493
end
8594

95+
test "export realm data to xml file with db_host_and_port in absolute path" do
96+
file = File.cwd!() <> "/test.xml"
97+
assert {:ok, :export_completed} == Export.export_realm_data(@realm, file, [db_host_and_port: @db_host_and_port])
98+
assert @expected_xml == File.read!(file)
99+
end
100+
101+
test "export fails with invalid realm" do
102+
assert {:error, :database_error} == Export.export_realm_data("invalid_realm", "test.xml")
103+
end
104+
105+
test "export fails with database connection error" do
106+
assert {:error, :database_connection_error} ==
107+
Export.export_realm_data(@realm, "test.xml", [db_host_and_port: "invalid_host:0000"])
108+
end
109+
86110
test "test to export xml data " do
87111
{:ok, stdio} = read_stdio_output_on_port()
88112
{:ok, state} = XMLGenerate.xml_write_default_header(:standard_error)

0 commit comments

Comments
 (0)