Skip to content

Commit 1d934e6

Browse files
author
Denys Gonchar
authored
Merge pull request #197 from esl/adding-scope-for-amoc-settings
Introducing setting scope (local/global)
2 parents 97fb8ca + 890a7c5 commit 1d934e6

19 files changed

Lines changed: 334 additions & 111 deletions

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ integration_test:
4545
./integration_test/test_amoc_cluster.sh
4646
./integration_test/test_distribute_scenario.sh
4747
./integration_test/test_run_scenario.sh
48+
./integration_test/test_update_settings.sh
4849
./integration_test/test_add_new_node.sh
4950

5051
rerun_integration_test:
@@ -53,6 +54,7 @@ rerun_integration_test:
5354
./integration_test/test_amoc_cluster.sh
5455
./integration_test/test_distribute_scenario.sh
5556
./integration_test/test_run_scenario.sh
57+
./integration_test/test_update_settings.sh
5658
./integration_test/test_add_new_node.sh
5759

5860
dialyzer:

integration_test/build_docker_image.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ source "$(dirname "$0")/helper.sh"
44
enable_strict_mode
55
cd "$git_root"
66

7-
otp_vsn="${OTP_RELEASE:-25.3}"
7+
otp_vsn="${OTP_RELEASE:-28}"
88
echo "ERLANG/OTP '${otp_vsn}'"
99

1010
docker build \

integration_test/extra_code_paths/path1/dummy_helper.erl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,8 @@ test_amoc_dist() ->
3333
?assertEqual(N2, N1 + 20, ?comment(Users2)),
3434
%% remove 10 users
3535
remove_and_wait(Master, 10),
36-
{N3, Max3, Nodes3, _Ids3, Users3} = get_users_info(Slaves),
36+
{N3, _Max3, Nodes3, _Ids3, Users3} = get_users_info(Slaves),
3737
?assertEqual(N2 - 10, N3, ?comment(Users3)),
38-
?assertEqual(Max2, Max3, ?comment(Users3)),
3938
?assertEqual(Nodes2, Nodes3, ?comment(Users3)),
4039
%% try to remove N3 users
4140
Ret = remove_and_wait(Master, N3),
@@ -67,6 +66,7 @@ get_users_info(SlaveNodes) ->
6766
Nodes = lists:usort([Node || {Node, Users} <- Distrib, [] =/= Users]),
6867
N = length(Ids),
6968
MaxId = lists:max(Ids),
69+
%% logger:error(#{n => N, max_id => MaxId, nodes => Nodes, ids => Ids, distrib => Distrib}),
7070
{N, MaxId, Nodes, Ids, Distrib}.
7171

7272
add_and_wait(Master, Num) ->

integration_test/extra_code_paths/path2/dummy_scenario.erl

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,15 @@
2929
#{name => var6, description => "description6"},
3030
#{name => nodes, description => "this variable is set for docker "
3131
"container via AMOC_NODES env"},
32-
#{name => test, description => "this one to be set via REST API"}]).
32+
#{name => test1, description => "this variable is to be set via initial settings"},
33+
#{name => test2, update => none, description => "this one to be updated"}]).
34+
35+
36+
-required_variable([
37+
#{name => global_test1, scope => global,
38+
description => "this variable is to be set via initial settings"},
39+
#{name => global_test2, scope => global, update => none,
40+
description => "this one to be updated"}]).
3341

3442
%% parameter verification method
3543
-export([test_verification_function/1]).
@@ -63,8 +71,9 @@ init() ->
6371
%% results in exception.
6472
{invalid_setting, undeclared_variable} =
6573
(catch amoc_config:get(undeclared_variable)),
66-
%% this variable is set via REST API
67-
<<"test_value">> = amoc_config:get(test),
74+
%% this variable is set via settings
75+
<<"test_value2">> = amoc_config:get(test1),
76+
6877
%% dummy_var variable is defined in the dummy_helper module.
6978
%% if dummy_helper is not propagated, then this call crashes
7079
default_value = amoc_config:get(dummy_var),

integration_test/test_add_new_node.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ enable_strict_mode
66
docker_compose up --wait --wait-timeout 100 amoc-worker-3
77

88
amoc_eval amoc-worker-3 "amoc_controller:get_status()." | contains_all dummy_scenario running
9-
amoc_eval amoc-worker-3 "binary_to_list(amoc_config:get(test))." | contains_all "test_value"
9+
10+
11+
amoc_eval amoc-worker-3 "binary_to_list(amoc_config:get(global_test1))." | contains_all "test_value1"
12+
amoc_eval amoc-worker-3 "binary_to_list(amoc_config:get(global_test2))." | contains_all "test_value3"
13+
amoc_eval amoc-worker-3 "binary_to_list(amoc_config:get(test1))." | contains_all "test_value2"
14+
amoc_eval amoc-worker-3 "atom_to_list(amoc_config:get(test2))." | contains_all "undefined"
15+
1016
amoc_eval amoc-worker-3 "dummy_helper:test_amoc_dist()." | contains_all 'amoc_dist_works_as_expected'
1117
echo "amoc_dist_works_as_expected"

integration_test/test_run_scenario.sh

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
source "$(dirname "$0")/helper.sh"
44
enable_strict_mode
55

6-
#############################
7-
## amoc REST API functions ##
8-
#############################
6+
####################
7+
## amoc functions ##
8+
####################
99
run_scenario() {
10-
amoc_eval "$1" "amoc_dist:do(${2}, ${3}, [{test, <<\"test_value\">>}])."
10+
amoc_eval "$1" "amoc_dist:do(${2}, ${3}, [{global_test1, <<\"test_value1\">>},
11+
{test1, <<\"test_value2\">>}])."
1112
}
1213

1314
result="$(run_scenario amoc-master dummy_scenario 10)"
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/bin/bash
2+
3+
source "$(dirname "$0")/helper.sh"
4+
enable_strict_mode
5+
6+
####################
7+
## amoc functions ##
8+
####################
9+
update_settings() {
10+
amoc_eval "$1" "amoc_dist:update_settings(${2}, ${3})."
11+
}
12+
13+
amoc_eval amoc-worker-1 "binary_to_list(amoc_config:get(global_test1))." | contains_all "test_value1"
14+
amoc_eval amoc-worker-1 "atom_to_list(amoc_config:get(global_test2))." | contains_all "undefined"
15+
amoc_eval amoc-worker-1 "binary_to_list(amoc_config:get(test1))." | contains_all "test_value2"
16+
amoc_eval amoc-worker-1 "atom_to_list(amoc_config:get(test2))." | contains_all "undefined"
17+
18+
amoc_eval amoc-worker-2 "binary_to_list(amoc_config:get(global_test1))." | contains_all "test_value1"
19+
amoc_eval amoc-worker-2 "atom_to_list(amoc_config:get(global_test2))." | contains_all "undefined"
20+
amoc_eval amoc-worker-2 "binary_to_list(amoc_config:get(test1))." | contains_all "test_value2"
21+
amoc_eval amoc-worker-2 "atom_to_list(amoc_config:get(test2))." | contains_all "undefined"
22+
23+
amoc_eval amoc-master "binary_to_list(amoc_config:get(global_test1))." | contains_all "test_value1"
24+
amoc_eval amoc-master "atom_to_list(amoc_config:get(global_test2))." | contains_all "undefined"
25+
amoc_eval amoc-master "binary_to_list(amoc_config:get(test1))." | contains_all "test_value2"
26+
amoc_eval amoc-master "atom_to_list(amoc_config:get(test2))." | contains_all "undefined"
27+
28+
update_settings amoc-master "[{global_test2, <<\"test_value3\">>}, {test2, <<\"test_value4\">>}]" "[node()]"
29+
30+
amoc_eval amoc-master "binary_to_list(amoc_config:get(global_test2))." | contains_all "test_value3"
31+
amoc_eval amoc-master "binary_to_list(amoc_config:get(test2))." | contains_all "test_value4"
32+
33+
amoc_eval amoc-worker-1 "binary_to_list(amoc_config:get(global_test2))." | contains_all "test_value3"
34+
amoc_eval amoc-worker-1 "atom_to_list(amoc_config:get(test2))." | contains_all "undefined"
35+
36+
amoc_eval amoc-worker-2 "binary_to_list(amoc_config:get(global_test2))." | contains_all "test_value3"
37+
amoc_eval amoc-worker-2 "atom_to_list(amoc_config:get(test2))." | contains_all "undefined"
38+
39+
update_settings amoc-master "[{test2, <<\"test_value5\">>}]" "nodes()"
40+
41+
amoc_eval amoc-worker-1 "binary_to_list(amoc_config:get(test2))." | contains_all "test_value5"
42+
amoc_eval amoc-worker-2 "binary_to_list(amoc_config:get(test2))." | contains_all "test_value5"
43+
44+
update_settings amoc-master "[{global_test2, <<\"test_value6\">>}]" "nodes()" | \
45+
contains_all "changing_global_parameters_on_a_slave_node" "error"
46+
47+
amoc_eval amoc-master "binary_to_list(amoc_config:get(global_test2))." | contains_all "test_value3"
48+
amoc_eval amoc-worker-1 "binary_to_list(amoc_config:get(global_test2))." | contains_all "test_value3"
49+
amoc_eval amoc-worker-2 "binary_to_list(amoc_config:get(global_test2))." | contains_all "test_value3"

src/amoc_controller.erl

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
-define(DEFAULT_USER_RATE, 1200).
1212

1313
-required_variable(#{name => user_rate, default_value => ?DEFAULT_USER_RATE,
14-
verification => {?MODULE, verify_user_rate, 1},
14+
verification => {?MODULE, verify_user_rate, 1}, scope => global,
1515
description => "Throttle rate for the Scenario:start/1,2 callback",
1616
update => {?MODULE, update_user_rate, 2}}).
1717

@@ -63,10 +63,11 @@
6363
start_scenario/2,
6464
stop_scenario/0,
6565
update_settings/1,
66+
propagate_config/2,
6667
add_users/2,
6768
remove_users/2,
6869
get_status/0,
69-
disable/0]).
70+
disable/2]).
7071

7172
%% ------------------------------------------------------------------
7273
%% Parameters verification functions
@@ -107,6 +108,10 @@ stop_scenario() ->
107108
update_settings(Settings) ->
108109
gen_server:call(?SERVER, {update_settings, Settings}).
109110

111+
-spec propagate_config(node(), amoc_config:config()) -> ok.
112+
propagate_config(Node, Config) ->
113+
gen_server:cast({?SERVER, Node}, {propagate_config, Config}).
114+
110115
-spec add_users(amoc_scenario:user_id(), amoc_scenario:user_id()) ->
111116
ok | {error, term()}.
112117
add_users(StartId, EndId) ->
@@ -123,9 +128,9 @@ get_status() ->
123128
{ok, Status} = gen_server:call(?SERVER, get_status),
124129
Status.
125130

126-
-spec disable() -> ok | {error, term()}.
127-
disable() ->
128-
gen_server:call(?SERVER, disable).
131+
-spec disable(amoc:scenario(), amoc_config:settings()) -> ok | {error, term()}.
132+
disable(Scenario, Settings) ->
133+
gen_server:call(?SERVER, {disable, Scenario, Settings}).
129134

130135
%% @private
131136
-spec verify_user_rate(any()) -> boolean().
@@ -178,8 +183,8 @@ handle_call({remove, Count, ForceRemove}, _From, State) ->
178183
handle_call(get_status, _From, State) ->
179184
RetValue = handle_status(State),
180185
{reply, {ok, RetValue}, State};
181-
handle_call(disable, _From, State) ->
182-
{RetValue, NewState} = handle_disable(State),
186+
handle_call({disable, Scenario, Settings}, _From, State) ->
187+
{RetValue, NewState} = handle_disable(Scenario, Settings, State),
183188
{reply, RetValue, NewState};
184189
handle_call(_Request, _From, State) ->
185190
{reply, {error, not_implemented}, State}.
@@ -189,6 +194,9 @@ handle_call(_Request, _From, State) ->
189194
handle_cast(zero_users_running, State) ->
190195
NewSate = handle_zero_users_running(State),
191196
{noreply, NewSate};
197+
handle_cast({propagate_config, Config}, State) ->
198+
handle_propagate_config(Config),
199+
{noreply, State};
192200
handle_cast(_Msg, State) ->
193201
{noreply, State}.
194202

@@ -236,14 +244,19 @@ handle_stop_scenario(#state{status = Status} = State) ->
236244
{{error, {invalid_status, Status}}, State}.
237245

238246
-spec handle_update_settings(amoc_config:settings(), state()) -> handle_call_res().
239-
handle_update_settings(Settings, #state{status = running}) ->
247+
handle_update_settings(Settings, #state{status = Status}) when Status =:= disabled;
248+
Status =:= running ->
240249
case amoc_config_scenario:update_settings(Settings) of
241250
ok -> ok;
242251
{error, Type, Reason} -> {error, {Type, Reason}}
243252
end;
244253
handle_update_settings(_Settings, #state{status = Status}) ->
245254
{error, {invalid_status, Status}}.
246255

256+
-spec handle_propagate_config(amoc_config:config()) -> ok.
257+
handle_propagate_config(Config) ->
258+
amoc_config_utils:store_scenario_config(Config).
259+
247260
-spec handle_add(amoc_scenario:user_id(), amoc_scenario:user_id(), state()) ->
248261
{handle_call_res(), state()}.
249262
handle_add(StartId, EndId, #state{status = running,
@@ -281,10 +294,14 @@ handle_status(#state{status = finished, scenario = Scenario}) ->
281294
handle_status(#state{status = Status}) ->
282295
Status. %% idle, disabled or {error, Reason}.
283296

284-
-spec handle_disable(state()) -> {handle_call_res(), state()}.
285-
handle_disable(#state{status = idle} = State) ->
286-
{ok, State#state{status = disabled}};
287-
handle_disable(#state{status = Status} = State) ->
297+
-spec handle_disable(amoc:scenario(), amoc_config:settings(), state()) ->
298+
{handle_call_res(), state()}.
299+
handle_disable(Scenario, Settings, #state{status = idle} = State) ->
300+
case amoc_config_scenario:parse_scenario_settings(Scenario, Settings) of
301+
ok -> {ok, State#state{status = disabled}};
302+
{error, Type, Reason} -> {error, {Type, Reason}}
303+
end;
304+
handle_disable(_Scenario, _Settings, #state{status = Status} = State) ->
288305
{{error, {invalid_status, Status}}, State}.
289306

290307
%% ------------------------------------------------------------------

src/config/amoc_config.erl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55

66
-include("amoc_config.hrl").
77

8+
-type config() :: module_configuration().
89
-export([get/1, get/2]).
9-
-export_type([name/0, value/0, settings/0, maybe_module_config/0]).
10+
-export_type([name/0, value/0, settings/0, config/0, maybe_module_config/0]).
1011

1112
%% ------------------------------------------------------------------
1213
%% API

src/config/amoc_config.hrl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,13 @@
3434
-type maybe_verification_fun() :: verification_fun() | fun((_)-> any()).
3535
-type maybe_update_fun() :: update_fun() | fun((_,_)-> any()).
3636

37+
-type scope() :: local | global.
38+
3739
-record(module_parameter, {name :: name(),
3840
mod :: module(),
3941
value :: value(),
4042
description :: unicode:chardata(),
43+
scope = local :: scope(),
4144
verification_fn :: maybe_verification_fun(),
4245
update_fn = read_only :: maybe_update_fun() | read_only}).
4346

0 commit comments

Comments
 (0)