1111
1212-export ([dispatcher /0 , web_ui /0 ]).
1313-export ([init /2 , to_json /2 , resource_exists /2 , content_types_provided /2 ,
14- is_authorized /2 , allowed_methods /2 , delete_resource /2 ]).
14+ is_authorized /2 , allowed_methods /2 , delete_resource /2 , get_shovel_node / 4 ]).
1515
1616-import (rabbit_misc , [pget /2 ]).
1717
1818-include_lib (" rabbitmq_management_agent/include/rabbit_mgmt_records.hrl" ).
1919-include_lib (" amqp_client/include/amqp_client.hrl" ).
20+ -include_lib (" rabbit_shovel_mgmt.hrl" ).
2021
2122dispatcher () -> [{" /shovels" , ? MODULE , []},
2223 {" /shovels/:vhost" , ? MODULE , []},
@@ -45,11 +46,10 @@ resource_exists(ReqData, Context) ->
4546 none -> true ;
4647 Name ->
4748 % % Deleting or restarting a shovel
48- case rabbit_shovel_status :lookup ({VHost , Name }) of
49- not_found ->
50- rabbit_log :error (" Shovel with the name '~s ' was not found "
51- " on the target node '~s ' and / or virtual host '~s '" ,
52- [Name , node (), VHost ]),
49+ case get_shovel_node (VHost , Name , ReqData , Context ) of
50+ undefined ->
51+ rabbit_log :error (" Shovel with the name '~s ' was not found on virtual host '~s '" ,
52+ [Name , VHost ]),
5353 false ;
5454 _ ->
5555 true
@@ -60,7 +60,7 @@ resource_exists(ReqData, Context) ->
6060
6161to_json (ReqData , Context ) ->
6262 rabbit_mgmt_util :reply_list (
63- filter_vhost_req (status (ReqData , Context ), ReqData ), ReqData , Context ).
63+ filter_vhost_req (rabbit_shovel_mgmt_util : status (ReqData , Context ), ReqData ), ReqData , Context ).
6464
6565is_authorized (ReqData , Context ) ->
6666 rabbit_mgmt_util :is_authorized_monitor (ReqData , Context ).
@@ -71,21 +71,28 @@ delete_resource(ReqData, #context{user = #user{username = Username}}=Context) ->
7171 none ->
7272 false ;
7373 Name ->
74- % % We must distinguish between a delete and restart
75- case is_restart (ReqData ) of
76- true ->
77- case rabbit_shovel_util :restart_shovel (VHost , Name ) of
78- {error , ErrMsg } ->
79- rabbit_log :error (" Error restarting shovel: ~s " , [ErrMsg ]),
80- false ;
81- ok -> true
82- end ;
83- _ ->
84- case rabbit_shovel_util :delete_shovel (VHost , Name , Username ) of
85- {error , ErrMsg } ->
86- rabbit_log :error (" Error deleting shovel: ~s " , [ErrMsg ]),
87- false ;
88- ok -> true
74+ case get_shovel_node (VHost , Name , ReqData , Context ) of
75+ undefined -> rabbit_log :error (" Could not find shovel data for shovel '~s ' in vhost: '~s '" , [Name , VHost ]),
76+ false ;
77+ Node ->
78+ % % We must distinguish between a delete and restart
79+ case is_restart (ReqData ) of
80+ true ->
81+ rabbit_log :info (" Asked to restart shovel '~s ' in vhost '~s ' on node '~s '" , [Name , VHost , Node ]),
82+ case rpc :call (Node , rabbit_shovel_util , restart_shovel , [VHost , Name ], ? SHOVEL_CALLS_TIMEOUT_MS ) of
83+ ok -> true ;
84+ {_ , Msg } -> rabbit_log :error (Msg ),
85+ false
86+ end ;
87+
88+ _ ->
89+ rabbit_log :info (" Asked to delete shovel '~s ' in vhost '~s ' on node '~s '" , [Name , VHost , Node ]),
90+ case rpc :call (Node , rabbit_shovel_util , delete_shovel , [VHost , Name , Username ], ? SHOVEL_CALLS_TIMEOUT_MS ) of
91+ ok -> true ;
92+ {_ , Msg } -> rabbit_log :error (Msg ),
93+ false
94+ end
95+
8996 end
9097 end
9198 end ,
@@ -107,52 +114,29 @@ filter_vhost_req(List, ReqData) ->
107114 pget (vhost , I ) =:= VHost ]
108115 end .
109116
110- % % Allow users to see things in the vhosts they are authorised. But
111- % % static shovels do not have a vhost, so only allow admins (not
112- % % monitors) to see them.
113- filter_vhost_user (List , _ReqData , # context {user = User = # user {tags = Tags }}) ->
114- VHosts = rabbit_mgmt_util :list_login_vhosts_names (User , undefined ),
115- [I || I <- List , case pget (vhost , I ) of
116- undefined -> lists :member (administrator , Tags );
117- VHost -> lists :member (VHost , VHosts )
118- end ].
119-
120- status (ReqData , Context ) ->
121- filter_vhost_user (
122- lists :append ([status (Node ) || Node <- [node () | nodes ()]]),
123- ReqData , Context ).
124-
125- status (Node ) ->
126- case rpc :call (Node , rabbit_shovel_status , status , [], infinity ) of
127- {badrpc , {'EXIT' , _ }} ->
128- [];
129- Status ->
130- [format (Node , I ) || I <- Status ]
117+ get_shovel_node (VHost , Name , ReqData , Context ) ->
118+ Shovels = rabbit_shovel_mgmt_util :status (ReqData , Context ),
119+ Match = find_matching_shovel (VHost , Name , Shovels ),
120+ case Match of
121+ undefined -> undefined ;
122+ Match ->
123+ {_ , Node } = lists :keyfind (node , 1 , Match ),
124+ Node
131125 end .
132126
133- format (Node , {Name , Type , Info , TS }) ->
134- [{node , Node }, {timestamp , format_ts (TS )}] ++
135- format_name (Type , Name ) ++
136- format_info (Info ).
137-
138- format_name (static , Name ) -> [{name , Name },
139- {type , static }];
140- format_name (dynamic , {VHost , Name }) -> [{name , Name },
141- {vhost , VHost },
142- {type , dynamic }].
143-
144- format_info (starting ) ->
145- [{state , starting }];
146-
147- format_info ({running , Props }) ->
148- [{state , running }] ++ Props ;
149-
150- format_info ({terminated , Reason }) ->
151- [{state , terminated },
152- {reason , print (" ~p " , [Reason ])}].
153-
154- format_ts ({{Y , M , D }, {H , Min , S }}) ->
155- print (" ~w -~2.2.0w -~2.2.0w ~w :~2.2.0w :~2.2.0w " , [Y , M , D , H , Min , S ]).
156-
157- print (Fmt , Val ) ->
158- list_to_binary (io_lib :format (Fmt , Val )).
127+ % % This is similar to rabbit_shovel_status:find_matching_shovel/3
128+ % % but operates on a different input (a proplist of Shovel attributes)
129+ -spec find_matching_shovel (VHost :: vhost :name (),
130+ Name :: binary (),
131+ Shovels :: list (list (tuple ()))) -> 'undefined' | list (tuple ()).
132+ find_matching_shovel (VHost , Name , Shovels ) ->
133+ ShovelPred = fun (Attributes ) ->
134+ lists :member ({name , Name }, Attributes ) andalso
135+ lists :member ({vhost , VHost }, Attributes )
136+ end ,
137+ case lists :search (ShovelPred , Shovels ) of
138+ {value , Shovel } ->
139+ Shovel ;
140+ _ ->
141+ undefined
142+ end .
0 commit comments