File 3922-ssh-Save-info-of-test-machine-s-installed-ssh.patch of Package erlang
From eeafe675b791931e91c6a7121dd5840bc0ba90ec Mon Sep 17 00:00:00 2001
From: Hans Nilsson <hans@erlang.org>
Date: Mon, 20 Dec 2021 11:28:49 +0100
Subject: [PATCH 2/3] ssh: Save info of test machine's installed ssh
The output is saved in <collect_host_info>/ssh_info/<hostname>.data
where <collect_host_info> is a common_test configuration variable.
Examples:
{collect_host_info, "/my/local/dir"}.
{collect_host_info, "hostname:/its/local/dir"}.
{collect_host_info, "user@hostname:/their/local/dir"}.
---
lib/ssh/test/Makefile | 1 +
.../ssh_collect_labmachine_info_SUITE.erl | 250 ++++++++++++++++++
lib/ssh/test/ssh_compat_SUITE.erl | 48 ++++
3 files changed, 299 insertions(+)
create mode 100644 lib/ssh/test/ssh_collect_labmachine_info_SUITE.erl
diff --git a/lib/ssh/test/Makefile b/lib/ssh/test/Makefile
index a3db492f0f..9f31dc92aa 100644
--- a/lib/ssh/test/Makefile
+++ b/lib/ssh/test/Makefile
@@ -32,6 +32,7 @@ MODULES= \
ssh_basic_SUITE \
ssh_bench_SUITE \
ssh_chan_behaviours_SUITE \
+ ssh_collect_labmachine_info_SUITE \
ssh_compat_SUITE \
ssh_connection_SUITE \
ssh_agent_mock_server \
diff --git a/lib/ssh/test/ssh_collect_labmachine_info_SUITE.erl b/lib/ssh/test/ssh_collect_labmachine_info_SUITE.erl
new file mode 100644
index 0000000000..02b11bde1d
--- /dev/null
+++ b/lib/ssh/test/ssh_collect_labmachine_info_SUITE.erl
@@ -0,0 +1,250 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2021. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+
+-module(ssh_collect_labmachine_info_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+
+-export([save_ssh_data/3]).
+
+-export([
+ suite/0,
+ all/0,
+ init_per_suite/1,
+ end_per_suite/1,
+ ssh_info_lib/1
+ ]).
+
+
+-define(DAYS_TO_KEEP, 5).
+
+save_ssh_data(Host, Data, Config0) ->
+ case init_data_transfer(Host, Config0) of
+ Config1 when is_list(Config1) ->
+ Config =
+ case Data of
+ [[_|_]|_] ->
+ lists:foldl(fun save_data/2, Config1, Data);
+ _ ->
+ save_data(Data, Config1)
+ end,
+ end_data_transfer(Config);
+
+ Skip ->
+ Skip
+ end.
+
+%%--------------------------------------------------------------------
+%% Common Test interface functions -----------------------------------
+%%--------------------------------------------------------------------
+
+suite() -> [{timetrap,{seconds,40}}].
+
+all() -> [ssh_info_lib].
+
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ case os:find_executable("ssh") of
+ false ->
+ {skip, "No ssh found"};
+
+ _Path ->
+ init_data_transfer(hostname(), Config)
+ end.
+
+end_per_suite(Config) ->
+ end_data_transfer(Config).
+
+%%--------------------------------------------------------------------
+ssh_info_lib(Config) ->
+ NewEntry = new_entry(),
+ ct:pal("New entry:~n~p",[NewEntry]),
+ save_data(NewEntry, Config).
+
+new_entry() ->
+ [{hostname, hostname()},
+ {type, host},
+ {date, date()},
+ {time, time()},
+ {os_type, os:type()},
+ {os_version, os:version()},
+ {full_ssh_version, ssh_info()}
+ ].
+
+ssh_info() ->
+ try os:cmd("ssh -V") of
+ Version when is_list(Version) -> Version--"\n";
+ _ -> "?"
+ catch
+ _:_ -> "??"
+ end.
+
+%%--------------------------------------------------------------------
+hostname() ->
+ case inet:gethostname() of
+ {ok,Name} -> string:to_lower(Name);
+ _ -> "undefined"
+ end.
+
+priv_dir(Config) -> proplists:get_value(priv_dir, Config).
+
+priv_file(Config, Name) -> filename:join(priv_dir(Config), Name).
+
+remove_drive_letter(FileName) ->
+ ssh_test_lib:winpath_to_linuxpath(FileName).
+
+usable_file(FileName) ->
+ case file:open(FileName, [append]) of
+ {ok,D} ->
+ ok == file:close(D);
+ _ ->
+ false
+ end.
+
+%%%----------------------------------------------------------------
+wsl_ify(Cmnd) ->
+ case os:getenv("WSLENV") of
+ false -> Cmnd;
+ _ -> "wsl " ++ Cmnd
+ end.
+
+%%%================================================================
+save_data(NewEntry, Config) ->
+ LocalFile = proplists:get_value(local_file, Config),
+
+ YoungEntries =
+ case file:consult(LocalFile) of
+ {ok, Consulted} when is_list(Consulted) ->
+ lists:filter(fun(E) -> is_young(E) end,
+ Consulted);
+ Other ->
+ ct:log("Strange result of consult:~n~p", [Other]),
+ ct:fail("Consult failed")
+ end,
+
+ {ok,D} = file:open(LocalFile, [write]),
+ lists:foreach(fun(E) ->
+ io:format(D, '~p.~n', [E])
+ end, lists:usort([NewEntry|YoungEntries])),
+ file:close(D),
+ Config.
+
+
+is_young(E) ->
+ try
+ Days = days_ago(proplists:get_value(date, E)),
+ Days >= 0 andalso Days =< ?DAYS_TO_KEEP
+ catch
+ _:_ -> false % No or illegal date property
+ end.
+
+
+days_ago(D={_,_,_})->
+ calendar:date_to_gregorian_days(date()) - calendar:date_to_gregorian_days(D).
+
+%%%----------------------------------------------------------------
+init_data_transfer(Host, Config) ->
+ case ct:get_config(collect_host_info) of
+ undefined ->
+ {skip, "No 'collect_host_info' path configured"};
+
+ Root when is_list(Root) ->
+ RemoteFile = filename:join([Root, "ssh_info", Host++".data"]),
+ init_data_transfer_cont(Host, Config, RemoteFile)
+ end.
+
+init_data_transfer_cont(Host, Config, RemoteFile) ->
+ LocalFile = priv_file(Config, Host++".sshdata"),
+
+ case usable_file(LocalFile) of
+ false -> ct:fail(no_local_file);
+ true -> ok
+ end,
+
+ TransferType =
+ case {path_type(RemoteFile), os:type()} of
+ {local, {unix,_}} ->
+ case usable_file(RemoteFile) of
+ true -> filesystem;
+ false -> ssh
+ end;
+ _ ->
+ ssh
+ end,
+
+ case TransferType of
+ filesystem ->
+ %% 'filesystem' was concluded since it was possible
+ %% to open the file in append mode
+ {ok,B} = file:read_file(RemoteFile),
+ ok = file:write_file(LocalFile, B);
+ ssh ->
+ SCP = wsl_ify("scp "++RemoteFile++" "++remove_drive_letter(LocalFile)),
+ ct:pal("Run command: \"~s\"", [SCP]),
+ Result = os:cmd(SCP),
+ ct:pal("Command result: \"~s\"",[Result])
+ end,
+
+ [{transfer_type, TransferType},
+ {local_file,LocalFile},
+ {remote_file,RemoteFile} | Config].
+
+%%%----------------------------------------------------------------
+end_data_transfer(Config) ->
+ LocalFile = proplists:get_value(local_file,Config),
+ RemoteFile = proplists:get_value(remote_file,Config),
+ case proplists:get_value(transfer_type,Config) of
+ filesystem ->
+ {ok,B} = file:read_file(LocalFile),
+ ok = file:write_file(RemoteFile, B);
+ ssh ->
+ SCP = wsl_ify("scp "++remove_drive_letter(LocalFile)++" "++RemoteFile),
+ ct:pal("Run command: \"~s\"", [SCP]),
+ Result = os:cmd(SCP),
+ ct:pal("Command result: \"~s\"",[Result])
+ end,
+ file:delete(LocalFile).
+
+path_type(Path) ->
+ case string:lexemes(Path, ":") of
+ [_] ->
+ local;
+ [Host | _] ->
+ case string:find(Host, "/") of
+ nomatch -> remote;
+ _ -> local
+ end
+ end.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/ssh/test/ssh_compat_SUITE.erl b/lib/ssh/test/ssh_compat_SUITE.erl
index bb46653657..a8f6b71488 100644
--- a/lib/ssh/test/ssh_compat_SUITE.erl
+++ b/lib/ssh/test/ssh_compat_SUITE.erl
@@ -98,6 +98,7 @@ init_per_suite(Config) ->
{skip, "No docker"};
_ ->
ssh:start(),
+ log_image_versions(ssh_image_versions(), Config),
ct:log("Crypto info: ~p",[crypto:info_lib()]),
ct:log("ssh image versions: ~p",[ssh_image_versions()]),
Config
@@ -1460,3 +1461,50 @@ renegotiate_test(Kex1, ConnectionRef) ->
%% ct:log("Renegotiate test passed!",[]),
ok
end.
+
+%%%----------------------------------------------------------------
+%% ImageVersions = ['dropbearv2016.72',
+%% 'openssh4.4p1-openssl0.9.8c',
+%% ...
+%% 'openssh8.8p1-openssl1.1.1l']
+
+log_image_versions(ImageVersions, Config) ->
+ case true == (catch
+ lists:member({save_ssh_data,3},
+ ssh_collect_labmachine_info_SUITE:module_info(exports)))
+ of
+ true ->
+ HostPfx = hostname()++"_docker",
+ {_Imax, Entries} = lists:foldl(fix_entry(HostPfx), {0,[]}, ImageVersions),
+ ssh_collect_labmachine_info_SUITE:save_ssh_data(HostPfx, Entries, Config);
+ false ->
+ Config
+ end.
+
+
+fix_entry(HostPfx) ->
+ fun(E, {I,Acc}) ->
+ Entry =
+ [{hostname, lists:flatten(io_lib:format("~s:~2..0w",[HostPfx,I]))},
+ {type, compat_test},
+ {date, date()},
+ {time, time()},
+ {os_type, os:type()},
+ {os_version, os:version()},
+ {full_ssh_version, fix_version(E)}
+ ],
+ {I+1, [Entry|Acc]}
+ end.
+
+fix_version(E) ->
+ case string:tokens(atom_to_list(E), "-") of
+ ["openssh"++Vs, "openssl"++Vc ] -> lists:concat(["OpenSSH_",Vs," OpenSSL ",Vc]);
+ ["openssh"++Vs, "libressl"++Vc] -> lists:concat(["OpenSSH_",Vs," LibreSSL ",Vc]);
+ _ -> atom_to_list(E)
+ end.
+
+hostname() ->
+ case inet:gethostname() of
+ {ok,Name} -> string:to_lower(Name);
+ _ -> "undefined"
+ end.
--
2.35.3