iot_cloud/src/transport/http/container_handler.erl
2026-04-24 15:07:13 +08:00

201 lines
8.3 KiB
Erlang

%%%-------------------------------------------------------------------
%%% @author licheng5
%%% @copyright (C) 2020, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 26. 4月 2020 3:36 下午
%%%-------------------------------------------------------------------
-module(container_handler).
-author("licheng5").
-include("iot.hrl").
-define(REQ_TIMEOUT, 10000).
%% API
-export([handle_request/4]).
handle_request("GET", "/container/get_all", #{<<"uuid">> := UUID}, _) when is_binary(UUID) ->
%% 检查ConfigJson是否是合法的json字符串
case iot_host:get_pid(UUID) of
undefined ->
{ok, 200, iot_util:json_error(-1, <<"host not found">>)};
Pid when is_pid(Pid) ->
case iot_host:get_containers(Pid) of
{ok, Ref} ->
case iot_host:await_reply(Pid, Ref, ?REQ_TIMEOUT) of
{ok, Result} ->
{ok, 200, request_success_response(Result)};
{error, Code, Reason} ->
request_error_http_response(Code, Reason)
end;
{error, Reason} when is_binary(Reason) ->
{ok, 200, iot_util:json_error(-1, Reason)}
end
end;
%% 下发config.json, 微服务接受后,保存服务配置
handle_request("POST", "/container/push_config", _,
#{<<"uuid">> := UUID, <<"container_name">> := ContainerName, <<"config">> := Config, <<"timeout">> := Timeout0})
when is_binary(UUID), is_binary(ContainerName), is_binary(Config), is_integer(Timeout0) ->
%% 检查ConfigJson是否是合法的json字符串
true = iot_util:is_json(Config),
case iot_host:get_pid(UUID) of
undefined ->
{ok, 200, iot_util:json_error(-1, <<"host not found">>)};
Pid when is_pid(Pid) ->
Timeout = Timeout0 * 1000,
case iot_host:config_container(Pid, ContainerName, Config) of
{ok, Ref} ->
case iot_host:await_reply(Pid, Ref, Timeout) of
{ok, Result} ->
{ok, 200, request_success_response(Result)};
{error, Code, Reason} ->
request_error_http_response(Code, Reason)
end;
{error, Reason} when is_binary(Reason) ->
{ok, 200, iot_util:json_error(-1, Reason)}
end
end;
%% 部署微服务
handle_request("POST", "/container/deploy", _, #{<<"uuid">> := UUID, <<"task_id">> := TaskId, <<"config">> := Config})
when is_binary(UUID), is_integer(TaskId), is_map(Config) ->
case iot_host:get_pid(UUID) of
undefined ->
{ok, 200, iot_util:json_error(404, <<"host not found">>)};
Pid when is_pid(Pid) ->
case iot_host:deploy_container(Pid, TaskId, Config) of
{ok, Ref} ->
case iot_host:await_reply(Pid, Ref, ?REQ_TIMEOUT) of
{ok, Result} ->
{ok, 200, request_success_response(Result)};
{error, Code, Reason} ->
request_error_http_response(Code, Reason)
end;
{error, Reason} when is_binary(Reason) ->
{ok, 200, iot_util:json_error(400, Reason)}
end
end;
%% 启动服务
handle_request("POST", "/container/start", _, #{<<"uuid">> := UUID, <<"container_name">> := ContainerName}) when is_binary(UUID), is_binary(ContainerName) ->
case iot_host:get_pid(UUID) of
undefined ->
{ok, 200, iot_util:json_error(404, <<"host not found">>)};
Pid when is_pid(Pid) ->
case iot_host:start_container(Pid, ContainerName) of
{ok, Ref} ->
case iot_host:await_reply(Pid, Ref, ?REQ_TIMEOUT) of
{ok, Result} ->
{ok, 200, request_success_response(Result)};
{error, Code, Reason} ->
request_error_http_response(Code, Reason)
end;
{error, Reason} when is_binary(Reason) ->
{ok, 200, iot_util:json_error(400, Reason)}
end
end;
%% 停止服务
handle_request("POST", "/container/stop", _, #{<<"uuid">> := UUID, <<"container_name">> := ContainerName}) when is_binary(UUID), is_binary(ContainerName) ->
case iot_host:get_pid(UUID) of
undefined ->
{ok, 200, iot_util:json_error(404, <<"host not found">>)};
Pid when is_pid(Pid) ->
case iot_host:stop_container(Pid, ContainerName) of
{ok, Ref} ->
case iot_host:await_reply(Pid, Ref, ?REQ_TIMEOUT) of
{ok, Result} ->
{ok, 200, request_success_response(Result)};
{error, Code, Reason} ->
request_error_http_response(Code, Reason)
end;
{error, Reason} when is_binary(Reason) ->
{ok, 200, iot_util:json_error(400, Reason)}
end
end;
handle_request("POST", "/container/kill", _, #{<<"uuid">> := UUID, <<"container_name">> := ContainerName}) when is_binary(UUID), is_binary(ContainerName) ->
case iot_host:get_pid(UUID) of
undefined ->
{ok, 200, iot_util:json_error(404, <<"host not found">>)};
Pid when is_pid(Pid) ->
case iot_host:kill_container(Pid, ContainerName) of
{ok, Ref} ->
case iot_host:await_reply(Pid, Ref, ?REQ_TIMEOUT) of
{ok, Result} ->
{ok, 200, request_success_response(Result)};
{error, Code, Reason} ->
request_error_http_response(Code, Reason)
end;
{error, Reason} when is_binary(Reason) ->
{ok, 200, iot_util:json_error(400, Reason)}
end
end;
%% 删除容器
handle_request("POST", "/container/remove", _, #{<<"uuid">> := UUID, <<"container_name">> := ContainerName}) when is_binary(UUID), is_binary(ContainerName) ->
case iot_host:get_pid(UUID) of
undefined ->
{ok, 200, iot_util:json_error(404, <<"host not found">>)};
Pid when is_pid(Pid) ->
case iot_host:remove_container(Pid, ContainerName) of
{ok, Ref} ->
case iot_host:await_reply(Pid, Ref, ?REQ_TIMEOUT) of
{ok, Result} ->
{ok, 200, request_success_response(Result)};
{error, Code, Reason} ->
request_error_http_response(Code, Reason)
end;
{error, Reason} when is_binary(Reason) ->
{ok, 200, iot_util:json_error(400, Reason)}
end
end;
handle_request(_, Path, _, _) ->
Path1 = list_to_binary(Path),
{ok, 200, iot_util:json_error(-1, <<"url: ", Path1/binary, " not found">>)}.
request_success_response(Result) when is_binary(Result) ->
case decode_json_bytes(Result) of
{ok, Data} ->
iot_util:json_data(Data);
error ->
iot_util:json_data(Result)
end.
request_error_response(Code, Reason) when is_integer(Code), is_binary(Reason) ->
case decode_json_bytes(Reason) of
{ok, #{<<"message">> := Message}} when is_binary(Message) ->
iot_util:json_error(Code, Message);
{ok, Message} when is_binary(Message) ->
iot_util:json_error(Code, Message);
_ ->
iot_util:json_error(Code, Reason)
end.
-spec request_error_http_response(Code :: integer(), Reason :: binary()) ->
{ok, HttpStatus :: integer(), Body :: iolist()}.
request_error_http_response(Code, Reason) when is_integer(Code), is_binary(Reason) ->
{ok, request_error_status(Code), request_error_response(Code, Reason)}.
-spec request_error_status(Code :: integer()) -> integer().
request_error_status(Code) when is_integer(Code), Code >= 400, Code < 600 ->
Code;
request_error_status(-1) ->
504;
request_error_status(_) ->
400.
decode_json_bytes(Data) when is_binary(Data) ->
case catch json:decode(Data) of
{'EXIT', _} ->
error;
{error, _} ->
error;
Decoded ->
{ok, Decoded}
end.