Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add user and group support #15

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 24 additions & 7 deletions apps/htoad/include/stdlib.hrl
Expand Up @@ -15,26 +15,43 @@
}). }).


%% %%
-record(user,
{
id,
name
}).

-record(group,
{
id,
name
}).


-record(file, -record(file,
{ {
type = file :: file | dir, type = file :: file | dir,
path :: undefined | string(), path :: undefined | string(),
ensure = present :: present | absent, user :: #user{} | string() | integer(),
group :: #group{} | string() | integer(),
mode, mode,
content = "", content = ""
%% special flag denoting file request
producer :: undefined | fs
}). }).


-record(package, -record(package,
{ {
name, name,
version, version
ensure = present :: present | absent
}). }).


-record(shell, -record(shell,
{ {
cmd cmd,
run_as :: undefined | superuser | term()
}).

-record(error_report,
{
rule :: {module(), atom()},
fact :: tuple(),
reason :: term()
}). }).
4 changes: 3 additions & 1 deletion apps/htoad/src/htoad.app.src
Expand Up @@ -25,10 +25,12 @@
htoad_lfs, htoad_lfs,
htoad_deps, htoad_deps,
htoad_pkg, htoad_pkg,
htoad_pkg_yum,
htoad_pkg_brew, htoad_pkg_brew,
htoad_pkg_apt, htoad_pkg_apt,
htoad_io, htoad_io,
htoad_shell htoad_shell,
htoad_error
]} ]}
]} ]}


Expand Down
6 changes: 3 additions & 3 deletions apps/htoad/src/htoad.erl
Expand Up @@ -15,7 +15,7 @@ start(App) ->
end. end.


add_rules(Rules) -> add_rules(Rules) ->
seresye:add_rules(?ENGINE, Rules), htoad_engine:add_rules(?ENGINE, Rules),
case Rules of case Rules of
Module when is_atom(Module) -> Module when is_atom(Module) ->
ok; ok;
Expand All @@ -26,13 +26,13 @@ add_rules(Rules) ->
assert([{file_request, F} || F <- FReqs]). assert([{file_request, F} || F <- FReqs]).


assert(Fact) when is_list(Fact); is_tuple(Fact) -> assert(Fact) when is_list(Fact); is_tuple(Fact) ->
seresye:assert(?ENGINE, Fact). htoad_engine:assert(?ENGINE, Fact).


assert(Engine, Fact) when is_list(Fact); is_tuple(Fact) -> assert(Engine, Fact) when is_list(Fact); is_tuple(Fact) ->
seresye_engine:assert(Engine, Fact). seresye_engine:assert(Engine, Fact).


retract(Fact) when is_list(Fact); is_tuple(Fact) -> retract(Fact) when is_list(Fact); is_tuple(Fact) ->
seresye:assert(?ENGINE, Fact). htoad_engine:assert(?ENGINE, Fact).


retract(Engine, Fact) when is_list(Fact); is_tuple(Fact) -> retract(Engine, Fact) when is_list(Fact); is_tuple(Fact) ->
seresye_engine:retract(Engine, Fact). seresye_engine:retract(Engine, Fact).
209 changes: 209 additions & 0 deletions apps/htoad/src/htoad_engine.erl
@@ -0,0 +1,209 @@
%%% Extracted from:
%%%
%%% SERESYE, a Swarm oriented ERlang Expert SYstem Engine
%%%
%%% Copyright (c) 2005-2010, Francesca Gangemi, Corrado Santoro
%%% All rights reserved.
%%%
%%% You may use this file under the terms of the BSD License. See the
%%% license distributed with this project or
%%% http://www.opensource.org/licenses/bsd-license.php
-module(htoad_engine).

%%====================================================================
%% External exports
%%====================================================================

-export([start/0, start/1, start/2, stop/1, get_engine/1,
add_rules/2, add_rule/2, add_rule/3, assert/2, get_kb/1,
get_rules_fired/1, get_client_state/1,
set_client_state/2, query_kb/2, remove_rule/2, retract/2]).

%% gen_server callbacks
-export([start_link/0, start_link/1, start_link/2, init/1, handle_call/3,
handle_cast/2, handle_info/2, terminate/2, code_change/3]).

%%====================================================================
%% External functions
%%====================================================================
start() ->
seresye_sup:start_engine().

start(Name) ->
seresye_sup:start_engine(Name).

start(Name, ClientState) ->
seresye_sup:start_engine(Name, ClientState).

set_client_state(Name, NewState) ->
gen_server:cast(Name, {set_client_state, NewState}).

get_client_state(Name) ->
gen_server:call(Name, get_client_state).

stop (EngineName) ->
(catch gen_server:call(EngineName, stop)),
ok.

get_engine(EngineName) ->
gen_server:call(EngineName, get_engine).

%% @doc Insert a fact in the KB.
%% It also checks if the fact verifies any condition,
%% if this is the case the fact is also inserted in the alpha-memory
assert(Name, Facts) ->
gen_server:call(Name, {assert, Facts}, infinity).

%% @doc removes a 'fact' in the Knowledge Base and if something occurs
%% Condition is also deleted from the corresponding alpha-memory
retract(Name, Facts) ->
gen_server:call(Name, {retract, Facts}, infinity).

add_rules(Name, RuleList)
when is_list(RuleList) orelse is_atom(RuleList) ->
gen_server:call(Name, {add_rules, RuleList}).

add_rule(Name, Fun) ->
gen_server:call(Name, {add_rule, Fun}).

add_rule(Name, Rule, Salience) ->
gen_server:call(Name, {add_rule, Rule, Salience}).

remove_rule(Name, Rule) ->
gen_server:call(Name, {remove_rule, Rule}).

get_rules_fired(Name) ->
gen_server:call(Name, get_rules_fired).

get_kb(Name) ->
gen_server:call(Name, get_kb).

query_kb(Name, Pattern) ->
gen_server:call(Name, {query_kb, Pattern}).


%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
start_link() ->
gen_server:start_link(?MODULE, [], []).

start_link(Name) when is_atom(Name) ->
gen_server:start_link({local, Name}, ?MODULE, [], []).

start_link(ClientState, Name) when is_atom(Name) ->
gen_server:start_link({local, Name}, ?MODULE, [ClientState], []).


init([]) ->
{ok, seresye_engine:new()};
init([ClientState]) ->
{ok, seresye_engine:new(ClientState)}.


handle_call(get_client_state, _From, State) ->
Reply =
try
{ok, seresye_engine:get_client_state(State)}
catch
Type:Reason ->
{error, {Type, Reason}}
end,
{reply, Reply, State};
handle_call(stop, _From, State) ->
{stop, normal, State};
handle_call({assert, Facts}, _From, State0) ->
{Reply, State1} =
try
{ok, seresye_engine:assert(State0, Facts)}
catch
Type:Reason ->
{{error, {Type, Reason}}, State0}
end,
{reply, Reply, State1};
handle_call({retract, Facts}, _From, State0) ->
{Reply, State1} =
try
{ok, seresye_engine:retract(State0, Facts)}
catch
Type:Reason ->
{{error, {Type, Reason}}, State0}
end,
{reply, Reply, State1};
handle_call({add_rules, Rules}, _From, State0) ->
{Reply, State1} =
try
{ok, seresye_engine:add_rules(State0, Rules)}
catch
Type:Reason ->
{{error, {Type, Reason}}, State0}
end,
{reply, Reply, State1};
handle_call({add_rule, Rule}, _From, State0) ->
{Reply, State1} =
try
{ok, seresye_engine:add_rule(State0, Rule)}
catch
Type:Reason ->
{{error, {Type, Reason}}, State0}
end,
{reply, Reply, State1};
handle_call({add_rule, Rule, Salience}, _From, State0) ->
{Reply, State1} =
try
{ok, seresye_engine:add_rule(State0, Rule, Salience)}
catch
Type:Reason ->
{{error, {Type, Reason}}, State0}
end,
{reply, Reply, State1};
handle_call({remove_rule, Rule}, _From, State0) ->
{Reply, State1} =
try
{ok, seresye_engine:remove_rule(State0, Rule)}
catch
Type:Reason ->
{{error, {Type, Reason}}, State0}
end,
{reply, Reply, State1};
handle_call(get_rules_fired, _From, State0) ->
Reply =
try
seresye_engine:get_rules_fired(State0)
catch
Type:Reason ->
{error, {Type, Reason}}
end,
{reply, Reply, State0};
handle_call(get_engine, _From, State0) ->
{reply, State0, State0};
handle_call(get_kb, _From, State0) ->
Reply =
try
seresye_engine:get_kb(State0)
catch
Type:Reason ->
{error, {Type, Reason}}
end,
{reply, Reply, State0};
handle_call({query_kb, Pattern}, _From, State0) ->
Reply =
try
seresye_engine:query_kb(State0, Pattern)
catch
Type:Reason ->
{error, {Type, Reason}}
end,
{reply, Reply, State0}.

handle_cast({set_client_state, CS}, State) ->
{noreply, seresye_engine:set_client_state(State, CS)}.

handle_info(_Info, State) ->
{noreply, State}.

terminate(_Reason, _State) ->
ok.

code_change(_OldVsn, State, _Extra) ->
{ok, State}.
10 changes: 10 additions & 0 deletions apps/htoad/src/htoad_error.erl
@@ -0,0 +1,10 @@
-module(htoad_error).
-include_lib("htoad/include/htoad.hrl").
-include_lib("htoad/include/toadie.hrl").
-include_lib("htoad/include/stdlib.hrl").

-rules([report]).

report(Engine, #error_report{ rule = R, fact = F, reason = Reason }) ->
lager:error("Rule ~p failed to process the assertion of ~p with reason: ~p", [R, F, Reason]),
Engine.
12 changes: 5 additions & 7 deletions apps/htoad/src/htoad_host.erl
Expand Up @@ -3,25 +3,23 @@
-include_lib("htoad/include/toadie.hrl"). -include_lib("htoad/include/toadie.hrl").
-include_lib("htoad/include/stdlib.hrl"). -include_lib("htoad/include/stdlib.hrl").


-neg_rule({init, [{htoad_argument, {host, '__IGNORE_UNDERSCORE__'}}]}). -rules([init, init_with_hostname_overriden, linux_lsb, linux_redhat]).

-rules([init, init_with_hostname_overriden, linux_ubuntu, linux_redhat]).


init_with_hostname_overriden(Engine, #init{}, {htoad_argument, {host, Hostname}}) -> init_with_hostname_overriden(Engine, #init{}, {htoad_argument, {host, Hostname}}) ->
initialize(Engine, Hostname). initialize(Engine, Hostname).


init(Engine, #init{}) when not {rule, [{htoad_argument, {host, _}}]} -> init(Engine, #init{}) when not {rule, [{htoad_argument, {host, _}}]} ->
initialize(Engine, hostname()). initialize(Engine, hostname()).


linux_ubuntu(Engine, #file{ path="/etc/lsb-release", producer = fs, content = Content }, {operating_system_name, linux}) -> linux_lsb(Engine, #file{ path="/etc/lsb-release", content = Content }, {operating_system_name, linux}) ->
{match, [Dist]} = re:run(Content,".*DISTRIB_ID=(.*).*",[{capture,[1],list}]), {match, [Dist]} = re:run(Content,".*DISTRIB_ID=(.*).*",[{capture,[1],list}]),
lager:debug("Detected Linux ~s", [Dist]), lager:debug("Linux distribution: ~s", [Dist]),
htoad:assert(Engine, {linux_distribution, Dist}). htoad:assert(Engine, {linux_distribution, Dist}).




linux_redhat(Engine, #file{ path="/etc/redhat-release", producer = fs, content = Content }, {operating_system_name, linux}) -> linux_redhat(Engine, #file{ path="/etc/redhat-release", content = Content }, {operating_system_name, linux}) ->
{match, [Dist]} = re:run(Content,".*(CentOS|RedHat).*",[{capture,[1],list}]), {match, [Dist]} = re:run(Content,".*(CentOS|RedHat).*",[{capture,[1],list}]),
lager:debug("Detected Linux ~s", [Dist]), lager:debug("Linux distribution: ~s", [Dist]),
htoad:assert(Engine, {linux_distribution, Dist}). htoad:assert(Engine, {linux_distribution, Dist}).




Expand Down