Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

merge.

  • Loading branch information...
commit ee7179056c477e170c085b9b6b3659037daa7cc7 2 parents 41e8694 + 18195e6
Heinz N. Gies Licenser authored
2  apps/wiggle/src/wiggle.app.src
View
@@ -1,7 +1,7 @@
{application, wiggle,
[
{description, ""},
- {vsn, "0.4.5"},
+ {vsn, "0.4.6"},
{registered, []},
{applications, [
kernel,
5 apps/wiggle/src/wiggle_app.erl
View
@@ -19,6 +19,8 @@ start(_StartType, _StartArgs) ->
{[<<"api">>, '_', <<"groups">>, '...'], wiggle_group_handler, []},
{[<<"api">>, '_', <<"cloud">>, '...'], wiggle_cloud_handler, []},
{[<<"api">>, '_', <<"hypervisors">>, '...'], wiggle_hypervisor_handler, []},
+ {[<<"api">>, '_', <<"dtrace">>, '_', <<"stream">>], wiggle_dtrace_stream, []},
+ {[<<"api">>, '_', <<"dtrace">>, '...'], wiggle_dtrace_handler, []},
{[<<"api">>, '_', <<"vms">>, '_', <<"console">>], wiggle_console_handler, []},
{[<<"api">>, '_', <<"vms">>, '_', <<"vnc">>], wiggle_vnc_handler, []},
{[<<"api">>, '_', <<"vms">>, '...'], wiggle_vm_handler, []},
@@ -27,8 +29,7 @@ start(_StartType, _StartArgs) ->
{[<<"api">>, '_', <<"packages">>, '...'], wiggle_package_handler, []}]}],
{ok, _} = cowboy:start_listener(http, Acceptors,
cowboy_tcp_transport, [{port, Port}],
- cowboy_http_protocol, [{dispatch, Dispatch}]
- ),
+ cowboy_http_protocol, [{dispatch, Dispatch}]),
wiggle_sup:start_link().
16 apps/wiggle/src/wiggle_cloud_handler.erl
View
@@ -18,10 +18,14 @@
is_authorized/2]).
-export([to_json/2,
- from_json/2]).
+ from_json/2,
+ to_msgpack/2,
+ from_msgpack/2]).
-ignore_xref([to_json/2,
from_json/2,
+ from_msgpack/2,
+ to_msgpack/2,
allowed_methods/2,
content_types_accepted/2,
content_types_provided/2,
@@ -66,7 +70,8 @@ options(Req, State) ->
content_types_provided(Req, State) ->
{[
- {<<"application/json">>, to_json}
+ {<<"application/json">>, to_json},
+ {<<"application/x-msgpack">>, to_msgpack}
], Req, State}.
content_types_accepted(Req, State) ->
@@ -122,6 +127,10 @@ to_json(Req, State) ->
{Reply, Req1, State1} = handle_request(Req, State),
{jsx:encode(Reply), Req1, State1}.
+to_msgpack(Req, State) ->
+ {Reply, Req1, State1} = handle_request(Req, State),
+ {msgpack:pack(Reply, [jsx]), Req1, State1}.
+
handle_request(Req, State = #state{path = [<<"connection">>]}) ->
Res = jsxd:thread([{set, <<"sniffle">>, length(libsniffle:servers())},
{set, <<"snarl">>, length(libsnarl:servers())},
@@ -169,6 +178,9 @@ handle_request(Req, State = #state{path = []}) ->
from_json(Req, State) ->
{false, Req, State}.
+from_msgpack(Req, State) ->
+ {false, Req, State}.
+
%%--------------------------------------------------------------------
%% DEETE
%%--------------------------------------------------------------------
56 apps/wiggle/src/wiggle_dataset_handler.erl
View
@@ -13,21 +13,28 @@
delete_resource/2,
forbidden/2,
options/2,
+ post_is_create/2,
+ create_path/2,
service_available/2,
is_authorized/2]).
-export([to_json/2,
- from_json/2]).
-
+ from_json/2,
+ to_msgpack/2,
+ from_msgpack/2]).
-ignore_xref([to_json/2,
from_json/2,
+ from_msgpack/2,
+ to_msgpack/2,
allowed_methods/2,
content_types_accepted/2,
content_types_provided/2,
delete_resource/2,
forbidden/2,
init/3,
+ post_is_create/2,
+ create_path/2,
is_authorized/2,
options/2,
service_available/2,
@@ -60,9 +67,13 @@ options(Req, State) ->
['HEAD', 'OPTIONS' | Methods]), ", "), Req),
{ok, Req1, State}.
+post_is_create(Req, State) ->
+ {true, Req, State}.
+
content_types_provided(Req, State) ->
{[
- {<<"application/json">>, to_json}
+ {<<"application/json">>, to_json},
+ {<<"application/x-msgpack">>, to_msgpack}
], Req, State}.
content_types_accepted(Req, State) ->
@@ -72,10 +83,10 @@ allowed_methods(Req, State) ->
{['HEAD', 'OPTIONS' | allowed_methods(State#state.version, State#state.token, State#state.path)], Req, State}.
allowed_methods(_Version, _Token, []) ->
- ['GET'];
+ ['GET', 'POST'];
allowed_methods(_Version, _Token, [_Dataset]) ->
- ['GET', 'DELETE'];
+ ['GET', 'DELETE', 'PUT'];
allowed_methods(_Version, _Token, [_Dataset, <<"metadata">>|_]) ->
['PUT', 'DELETE'].
@@ -106,12 +117,19 @@ forbidden(Req, State = #state{method = 'OPTIONS'}) ->
forbidden(Req, State = #state{token = undefined}) ->
{true, Req, State};
+forbidden(Req, State = #state{method = 'POST', path = []}) ->
+ {allowed(State#state.token, [<<"cloud">>, <<"datasets">>, <<"create">>]), Req, State};
+
forbidden(Req, State = #state{path = []}) ->
{allowed(State#state.token, [<<"cloud">>, <<"datasets">>, <<"list">>]), Req, State};
+
forbidden(Req, State = #state{method = 'GET', path = [Dataset]}) ->
{allowed(State#state.token, [<<"datasets">>, Dataset, <<"get">>]), Req, State};
+forbidden(Req, State = #state{method = 'PUT', path = [Dataset]}) ->
+ {allowed(State#state.token, [<<"datasets">>, Dataset, <<"edit">>]), Req, State};
+
forbidden(Req, State = #state{method = 'DELETE', path = [Dataset]}) ->
{allowed(State#state.token, [<<"datasets">>, Dataset, <<"delete">>]), Req, State};
@@ -132,6 +150,10 @@ to_json(Req, State) ->
{Reply, Req1, State1} = handle_request(Req, State),
{jsx:encode(Reply), Req1, State1}.
+to_msgpack(Req, State) ->
+ {Reply, Req1, State1} = handle_request(Req, State),
+ {msgpack:pack(Reply, [jsx]), Req1, State1}.
+
handle_request(Req, State = #state{token = Token, path = []}) ->
{ok, Permissions} = libsnarl:user_cache({token, Token}),
{ok, Res} = libsniffle:dataset_list([{must, 'allowed', [<<"datasets">>, {<<"res">>, <<"dataset">>}, <<"get">>], Permissions}]),
@@ -144,6 +166,12 @@ handle_request(Req, State = #state{path = [_Dataset], obj = Obj}) ->
%% PUT
%%--------------------------------------------------------------------
+create_path(Req, State = #state{path = [], version = Version}) ->
+ {ok, Decoded, Req1} = wiggle_handler:decode(Req),
+ {ok, URL} = jsxd:get(<<"url">>, Decoded),
+ {ok, UUID} = libsniffle:dataset_import(URL),
+ {<<"/api/", Version/binary, "/datasets/", UUID/binary>>, Req1, State#state{body = Decoded}}.
+
from_json(Req, State) ->
{ok, Body, Req1} = cowboy_http_req:body(Req),
{Reply, Req2, State1} = case Body of
@@ -155,10 +183,28 @@ from_json(Req, State) ->
end,
{Reply, Req2, State1}.
+from_msgpack(Req, State) ->
+ {ok, Body, Req1} = cowboy_http_req:body(Req),
+ {Reply, Req2, State1} = case Body of
+ <<>> ->
+ handle_write(Req1, State, []);
+ _ ->
+ Decoded = msgpack:unpack(Body, [jsx]),
+ handle_write(Req1, State, Decoded)
+ end,
+ {Reply, Req2, State1}.
+
handle_write(Req, State = #state{path = [Dataset, <<"metadata">> | Path]}, [{K, V}]) ->
libsniffle:dataset_set(Dataset, [<<"metadata">> | Path] ++ [K], jsxd:from_list(V)),
{true, Req, State};
+handle_write(Req, State = #state{path = [Dataset]}, [{K, V}]) ->
+ libsniffle:dataset_set(Dataset, [K], jsxd:from_list(V)),
+ {true, Req, State};
+
+handle_write(Req, State = #state{path = []}, _Body) ->
+ {true, Req, State};
+
handle_write(Req, State, _Body) ->
{false, Req, State}.
246 apps/wiggle/src/wiggle_dtrace_handler.erl
View
@@ -0,0 +1,246 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+%% @doc Hello world handler.
+-module(wiggle_dtrace_handler).
+
+-export([init/3,
+ rest_init/2]).
+
+-export([content_types_provided/2,
+ content_types_accepted/2,
+ allowed_methods/2,
+ resource_exists/2,
+ service_available/2,
+ delete_resource/2,
+ forbidden/2,
+ options/2,
+ create_path/2,
+ post_is_create/2,
+ is_authorized/2]).
+
+-export([to_json/2,
+ from_json/2,
+ to_msgpack/2,
+ from_msgpack/2]).
+
+-ignore_xref([to_json/2,
+ from_json/2,
+ from_msgpack/2,
+ to_msgpack/2,
+ allowed_methods/2,
+ content_types_accepted/2,
+ content_types_provided/2,
+ delete_resource/2,
+ forbidden/2,
+ init/3,
+ is_authorized/2,
+ options/2,
+ service_available/2,
+ resource_exists/2,
+ create_path/2,
+ post_is_create/2,
+ rest_init/2]).
+
+-record(state, {path, method, version, token, content, reply, obj, body}).
+
+init(_Transport, _Req, []) ->
+ {upgrade, protocol, cowboy_http_rest}.
+
+rest_init(Req, _) ->
+ wiggle_handler:initial_state(Req, <<"dtrace">>).
+
+post_is_create(Req, State) ->
+ {true, Req, State}.
+
+service_available(Req, State) ->
+ case {libsniffle:servers(), libsnarl:servers()} of
+ {[], _} ->
+ {false, Req, State};
+ {_, []} ->
+ {false, Req, State};
+ _ ->
+ {true, Req, State}
+ end.
+
+options(Req, State) ->
+ Methods = allowed_methods(Req, State, State#state.path),
+ {ok, Req1} = cowboy_http_req:set_resp_header(
+ <<"Access-Control-Allow-Methods">>,
+ string:join(
+ lists:map(fun erlang:atom_to_list/1,
+ ['HEAD', 'OPTIONS' | Methods]), ", "), Req),
+ {ok, Req1, State}.
+
+content_types_provided(Req, State) ->
+ {[
+ {<<"application/json">>, to_json},
+ {<<"application/x-msgpack">>, to_msgpack}
+ ], Req, State}.
+
+content_types_accepted(Req, State) ->
+ {wiggle_handler:accepted(), Req, State}.
+
+allowed_methods(Req, State) ->
+ {['HEAD', 'OPTIONS' | allowed_methods(State#state.version, State#state.token, State#state.path)], Req, State}.
+
+allowed_methods(_Version, _Token, []) ->
+ ['GET', 'POST'];
+
+allowed_methods(_Version, _Token, [_Dtrace, <<"metadata">>|_]) ->
+ ['PUT', 'DELETE'];
+
+allowed_methods(_Version, _Token, [_Dtrace]) ->
+ ['GET', 'PUT', 'DELETE'].
+
+resource_exists(Req, State = #state{path = []}) ->
+ {true, Req, State};
+
+resource_exists(Req, State = #state{path = [Dtrace | _]}) ->
+ case libsniffle:dtrace_get(Dtrace) of
+ {ok, not_found} ->
+ {false, Req, State};
+ {ok, Obj} ->
+ {true, Req, State#state{obj = Obj}}
+ end.
+
+is_authorized(Req, State = #state{method = 'OPTIONS'}) ->
+ {true, Req, State};
+
+is_authorized(Req, State = #state{token = undefined}) ->
+ {{false, <<"X-Snarl-Token">>}, Req, State};
+
+is_authorized(Req, State) ->
+ {true, Req, State}.
+
+forbidden(Req, State = #state{method = 'OPTIONS'}) ->
+ {false, Req, State};
+
+forbidden(Req, State = #state{token = undefined}) ->
+ {true, Req, State};
+
+forbidden(Req, State = #state{method= 'GET', path = []}) ->
+ {allowed(State#state.token, [<<"cloud">>, <<"dtraces">>, <<"list">>]), Req, State};
+
+forbidden(Req, State = #state{method= 'POST', path = []}) ->
+ {allowed(State#state.token, [<<"cloud">>, <<"dtraces">>, <<"create">>]), Req, State};
+
+forbidden(Req, State = #state{method = 'GET', path = [Dtrace]}) ->
+ {allowed(State#state.token, [<<"dtraces">>, Dtrace, <<"get">>]), Req, State};
+
+forbidden(Req, State = #state{method = 'DELETE', path = [Dtrace]}) ->
+ {allowed(State#state.token, [<<"dtraces">>, Dtrace, <<"delete">>]), Req, State};
+
+forbidden(Req, State = #state{method = 'PUT', path = [Dtrace]}) ->
+ {allowed(State#state.token, [<<"dtraces">>, Dtrace, <<"edit">>]), Req, State};
+
+forbidden(Req, State = #state{method = 'PUT', path = [Dtrace, <<"metadata">> | _]}) ->
+ {allowed(State#state.token, [<<"dtraces">>, Dtrace, <<"edit">>]), Req, State};
+
+forbidden(Req, State = #state{method = 'DELETE', path = [Dtrace, <<"metadata">> | _]}) ->
+ {allowed(State#state.token, [<<"dtraces">>, Dtrace, <<"edit">>]), Req, State};
+
+forbidden(Req, State) ->
+ {true, Req, State}.
+
+%%--------------------------------------------------------------------
+%% GET
+%%--------------------------------------------------------------------
+
+to_json(Req, State) ->
+ {Reply, Req1, State1} = handle_request(Req, State),
+ {jsx:encode(Reply), Req1, State1}.
+
+to_msgpack(Req, State) ->
+ {Reply, Req1, State1} = handle_request(Req, State),
+ {msgpack:pack(Reply, [jsx]), Req1, State1}.
+
+handle_request(Req, State = #state{token = Token, path = []}) ->
+ {ok, Permissions} = libsnarl:user_cache({token, Token}),
+ {ok, Res} = libsniffle:dtrace_list([{must, 'allowed', [<<"dtraces">>, {<<"res">>, <<"uuid">>}, <<"get">>], Permissions}]),
+ {lists:map(fun ({E, _}) -> E end, Res), Req, State};
+
+handle_request(Req, State = #state{path = [_Dtrace], obj = Obj}) ->
+ Obj1 = jsxd:update(<<"script">>, fun (S) ->
+ list_to_binary(S)
+ end, Obj),
+ {Obj1, Req, State}.
+
+
+%%--------------------------------------------------------------------
+%% PUT
+%%--------------------------------------------------------------------
+
+create_path(Req, State = #state{path = [], version = Version}) ->
+ {ok, Data, Req1} = wiggle_handler:decode(Req),
+ {ok, Dtrace} = jsxd:get(<<"name">>, Data),
+ {ok, Script} = jsxd:get(<<"script">>, Data),
+ Script1 = binary_to_list(Script),
+ case libsniffle:dtrace_add(Dtrace, Script1) of
+ {ok, UUID} ->
+ case jsxd:get(<<"config">>, Data) of
+ {ok, Config} ->
+ ok = libsniffle:dtrace_set(UUID, <<"config">>, Config);
+ _ ->
+ ok
+ end,
+ {<<"/api/", Version/binary, "/dtrace/", UUID/binary>>, Req1, State#state{body = Data}};
+ duplicate ->
+ {ok, Req3} = cowboy_http_req:reply(409, Req1),
+ {halt, Req3, State}
+ end.
+
+from_json(Req, State) ->
+ {ok, Body, Req1} = cowboy_http_req:body(Req),
+ {Reply, Req2, State1} = case Body of
+ <<>> ->
+ handle_write(Req1, State, null);
+ _ ->
+ Decoded = jsx:decode(Body),
+ handle_write(Req1, State, Decoded)
+ end,
+ {Reply, Req2, State1}.
+
+from_msgpack(Req, State) ->
+ {ok, Body, Req1} = cowboy_http_req:body(Req),
+ {Reply, Req2, State1} = case Body of
+ <<>> ->
+ handle_write(Req1, State, null);
+ _ ->
+ Decoded = msgpack:unpack(Body, [jsx]),
+ handle_write(Req1, State, Decoded)
+ end,
+ {Reply, Req2, State1}.
+
+%% TODO : This is a icky case it is called after post.
+
+handle_write(Req, State = #state{method = 'POST', path = []}, _) ->
+ {true, Req, State};
+
+handle_write(Req, State = #state{path = [Dtrace, <<"metadata">> | Path]}, [{K, V}]) ->
+ libsniffle:dtrace_set(Dtrace, [<<"metadata">> | Path] ++ [K], jsxd:from_list(V)),
+ {true, Req, State};
+
+handle_write(Req, State, _Body) ->
+ {false, Req, State}.
+
+%%--------------------------------------------------------------------
+%% DEETE
+%%--------------------------------------------------------------------
+
+delete_resource(Req, State = #state{path = [Dtrace, <<"metadata">> | Path]}) ->
+ libsniffle:dtrace_set(Dtrace, [<<"metadata">> | Path], delete),
+ {true, Req, State};
+
+delete_resource(Req, State = #state{path = [Dtrace]}) ->
+ ok = libsniffle:dtrace_delete(Dtrace),
+ {true, Req, State}.
+
+allowed(Token, Perm) ->
+ case libsnarl:allowed({token, Token}, Perm) of
+ not_found ->
+ true;
+ true ->
+ false;
+ false ->
+ true
+ end.
156 apps/wiggle/src/wiggle_dtrace_stream.erl
View
@@ -0,0 +1,156 @@
+-module(wiggle_dtrace_stream).
+
+-behaviour(cowboy_http_handler).
+-behaviour(cowboy_http_websocket_handler).
+
+-export([init/3,
+ handle/2,
+ terminate/2]).
+-export([websocket_init/3,
+ websocket_handle/3,
+ websocket_info/3,
+ websocket_terminate/3]).
+
+init({_Any, http}, Req, []) ->
+ case cowboy_http_req:header('Upgrade', Req) of
+ {undefined, Req2} -> {ok, Req2, undefined};
+ {<<"websocket">>, _Req2} -> {upgrade, protocol, cowboy_http_websocket};
+ {<<"WebSocket">>, _Req2} -> {upgrade, protocol, cowboy_http_websocket}
+ end.
+
+-record(state, {id, socket, config, encoder, decoder, type}).
+
+handle(Req, State) ->
+ {ok, Req1} = cowboy_http_req:reply(200, [], <<"">>, Req),
+ {ok, Req1, State}.
+
+terminate(_Req, _State) ->
+ ok.
+
+websocket_init(_Any, Req, []) ->
+ {_, C, Req0} = cowboy_http_req:parse_header(<<"Sec-Websocket-Protocol">>, Req, <<"json">>),
+ {[<<"api">>, _, <<"dtrace">>, ID, <<"stream">>], Req1} = cowboy_http_req:path(Req0),
+ {ok, Req2} = cowboy_http_req:set_resp_header(
+ <<"Access-Control-Allow-Headers">>,
+ <<"X-Snarl-Token">>, Req1),
+ {ok, Req3} = cowboy_http_req:set_resp_header(
+ <<"Access-Control-Expose-Headers">>,
+ <<"X-Snarl-Token">>, Req2),
+ {ok, Req4} = cowboy_http_req:set_resp_header(
+ <<"Allow-Access-Control-Credentials">>,
+ <<"true">>, Req3),
+ {Encoder, Decoder, Type} = case C of
+ <<"msgpack">> ->
+ {fun(O) ->
+ msgpack:pack(O, [jsx])
+ end,
+ fun(D) ->
+ {ok, O} = msgpack:unpack(D, [jsx]),
+ jsxd:from_list(O)
+ end,
+ binary};
+ <<"json">> ->
+ {fun(O) ->
+ jsx:encode(O)
+ end,
+ fun(D) ->
+ jsxd:from_list(jsx:decode(D))
+ end, text}
+ end,
+
+ {Token, Req5} = case cowboy_http_req:header(<<"X-Snarl-Token">>, Req4) of
+ {undefined, ReqX} ->
+ {TokenX, ReqX1} = cowboy_http_req:cookie(<<"X-Snarl-Token">>, ReqX),
+ {TokenX, ReqX1};
+ {TokenX, ReqX} ->
+ {ok, ReqX1} = cowboy_http_req:set_resp_header(<<"X-Snarl-Token">>, TokenX, ReqX),
+ {TokenX, ReqX1}
+ end,
+ case libsnarl:allowed({token, Token}, [<<"dtrace">>, ID, <<"stream">>]) of
+ true ->
+ case libsniffle:dtrace_get(ID) of
+ {ok, Obj} ->
+ {ok, Req, #state{id = ID, config = jsxd:get(<<"config">>, [], Obj),
+ encoder = Encoder, decoder = Decoder, type = Type}};
+ _ ->
+ {ok, Req6} = cowboy_http_req:reply(404,
+ [{'Content-Type', <<"text/html">>}],
+ <<"not found">>, Req5),
+ {shutdown, Req6}
+ end;
+ false ->
+ {ok, Req6} = cowboy_http_req:reply(401, [{'Content-Type', <<"text/html">>}], <<"">>, Req5),
+ {shutdown, Req6}
+ end.
+
+websocket_handle({Type, <<>>}, Req, State = #state{type = Type}) ->
+ handle(undefined, Req, State);
+
+websocket_handle({Type, M}, Req, State = #state{decoder = Dec, type = Type}) ->
+ handle(Dec(M), Req, State);
+
+websocket_handle(_Any, Req, State) ->
+ {ok, Req, State}.
+
+websocket_info({tcp, _Port, Data}, Req, State = #state{encoder = Enc, type = Type}) ->
+ case binary_to_term(Data) of
+ {dtrace, ok} ->
+ {ok, Req, State, hibernate};
+ {dtrace, JSON} ->
+ {reply, {Type, Enc(JSON)}, Req, State};
+ _ ->
+ {ok, Req, State, hibernate}
+ end;
+
+websocket_info(_Info, Req, State) ->
+ {ok, Req, State, hibernate}.
+
+websocket_terminate(_Reason, _Req, #state{socket = undefined} = _State) ->
+ ok;
+
+websocket_terminate(_Reason, _Req, #state{socket = Port} = _State) ->
+ gen_tcp:close(Port),
+ ok.
+
+handle(null, Req, State = #state{encoder = Enc, type = Type}) ->
+ {ok, Servers} = libsniffle:hypervisor_list(),
+ case libsniffle:dtrace_run(State#state.id, [{<<"servers">>, Servers}]) of
+ {ok, S} ->
+ {reply, {Type, Enc([{<<"config">>, jsxd:merge([{<<"servers">>, Servers}], State#state.config)}])},
+ Req, State#state{socket = S}};
+ E ->
+ {ok, Req1} = cowboy_http_req:reply(505, [{'Content-Type', <<"text/html">>}],
+ list_to_binary(io_lib:format("~p", [E])), Req),
+ {shutdown, Req1}
+ end;
+
+handle(Config, Req, State = #state{encoder = Enc, type = Type}) ->
+ {ok, Servers} = libsniffle:hypervisor_list(),
+ Config1 = case jsxd:get([<<"vms">>], [], Config) of
+ [] ->
+ Config;
+ VMs ->
+ VMs0 = [libsniffle:vm_get(V) || V <- VMs],
+ VMs1 = [jsxd:get([<<"hypervisor">>], V) || {ok, V} <- VMs0],
+ Servers2 = [S || {ok, S} <- VMs1],
+ Filter = [[<<"zonename">>, V] || V <- VMs],
+
+ jsxd:thread([{set, [<<"servers">>], lists:usort(Servers2)},
+ {update, [<<"filter">>],
+ fun (F) ->
+ [{<<"and">>, [Filter | F]}]
+ end, [{<<"and">>, Filter}]}], Config)
+ end,
+ Config2 = jsxd:update([<<"servers">>], fun(S) ->
+ S
+ end, Servers, Config1),
+ io:format("Now we got a config: ~p~n", [Config2]),
+ case libsniffle:dtrace_run(State#state.id, Config2) of
+ {ok, S} ->
+ {reply, {Type, Enc(jsxd:merge(Config1, State#state.config))},
+ Req, State#state{socket = S}};
+ E ->
+ {ok, Req1} = cowboy_http_req:reply(505, [{'Content-Type', <<"text/html">>}],
+ list_to_binary(io_lib:format("~p", [E])), Req),
+ {shutdown, Req1}
+ end.
35 apps/wiggle/src/wiggle_group_handler.erl
View
@@ -22,10 +22,14 @@
is_authorized/2]).
-export([to_json/2,
- from_json/2]).
+ from_json/2,
+ to_msgpack/2,
+ from_msgpack/2]).
-ignore_xref([to_json/2,
from_json/2,
+ from_msgpack/2,
+ to_msgpack/2,
allowed_methods/2,
content_types_accepted/2,
content_types_provided/2,
@@ -71,7 +75,8 @@ options(Req, State) ->
content_types_provided(Req, State) ->
{[
- {<<"application/json">>, to_json}
+ {<<"application/json">>, to_json},
+ {<<"application/x-msgpack">>, to_msgpack}
], Req, State}.
content_types_accepted(Req, State) ->
@@ -182,6 +187,10 @@ to_json(Req, State) ->
{Reply, Req1, State1} = handle_request(Req, State),
{jsx:encode(Reply), Req1, State1}.
+to_msgpack(Req, State) ->
+ {Reply, Req1, State1} = handle_request(Req, State),
+ {msgpack:pack(Reply, [jsx]), Req1, State1}.
+
handle_request(Req, State = #state{path = []}) ->
% {ok, Permissions} = libsnarl:user_cache({token, Token}),
{ok, Res} = libsnarl:group_list(), %{must, 'allowed', [<<"vm">>, {<<"res">>, <<"uuid">>}, <<"get">>], Permissions}),
@@ -202,17 +211,10 @@ handle_request(Req, State = #state{path = [_Group, <<"permissions">>], obj = Gro
%%--------------------------------------------------------------------
create_path(Req, State = #state{path = [], version = Version}) ->
- {ok, Body, Req1} = cowboy_http_req:body(Req),
- {Decoded, Req2} = case Body of
- <<>> ->
- {[], Req1};
- _ ->
- D = jsx:decode(Body),
- {D, Req1}
- end,
+ {ok, Decoded, Req1} = wiggle_handler:decode(Req),
{ok, Group} = jsxd:get(<<"name">>, Decoded),
{ok, UUID} = libsnarl:group_add(Group),
- {<<"/api/", Version/binary, "/groups/", UUID/binary>>, Req2, State}.
+ {<<"/api/", Version/binary, "/groups/", UUID/binary>>, Req1, State#state{body = Decoded}}.
from_json(Req, State) ->
{ok, Body, Req1} = cowboy_http_req:body(Req),
@@ -225,6 +227,17 @@ from_json(Req, State) ->
end,
{Reply, Req2, State1}.
+from_msgpack(Req, State) ->
+ {ok, Body, Req1} = cowboy_http_req:body(Req),
+ {Reply, Req2, State1} = case Body of
+ <<>> ->
+ handle_write(Req1, State, []);
+ _ ->
+ Decoded = msgpack:unpack(Body, [jsx]),
+ handle_write(Req1, State, Decoded)
+ end,
+ {Reply, Req2, State1}.
+
%% TODO : This is a icky case it is called after post.
handle_write(Req, State = #state{method = 'POST', path = []}, _) ->
{true, Req, State};
25 apps/wiggle/src/wiggle_handler.erl
View
@@ -2,7 +2,8 @@
-export([
initial_state/2,
- accepted/0
+ accepted/0,
+ decode/1
]).
-record(state, {path, method, version, token, content, reply, obj, body}).
@@ -37,9 +38,31 @@ initial_state(Req, Component) ->
accepted() ->
[
+ {<<"application/x-msgpack; charset=UTF-8">>, from_msgpack},
+ {<<"application/x-msgpack; charset=utf-8">>, from_msgpack},
+ {<<"application/x-msgpack;charset=utf-8">>, from_msgpack},
+ {<<"application/x-msgpack; charset=UTF-8">>, from_msgpack},
+ {<<"application/x-msgpack">>, from_msgpack},
{<<"application/json; charset=UTF-8">>, from_json},
{<<"application/json; charset=utf-8">>, from_json},
{<<"application/json;charset=UTF-8">>, from_json},
{<<"application/json;charset=utf-8">>, from_json},
{<<"application/json">>, from_json}
].
+
+decode(Req) ->
+ {{G, C, _}, Req0} = cowboy_http_req:parse_header('Content-Type', Req, {<<"application">>, <<"json">>, []}),
+ ContentType = <<G/binary, "/", C/binary>>,
+ {ok, Body, Req1} = cowboy_http_req:body(Req0),
+ Decoded = case Body of
+ <<>> ->
+ [];
+ _ ->
+ case lists:keyfind(ContentType, 1, accepted()) of
+ {_, from_json} ->
+ jsxd:from_list(jsx:decode(Body));
+ {_, from_msgpack} ->
+ jsxd:from_list(msgpack:unpack(Body, [jsx]))
+ end
+ end,
+ {ok, Decoded, Req1}.
24 apps/wiggle/src/wiggle_hypervisor_handler.erl
View
@@ -17,10 +17,14 @@
is_authorized/2]).
-export([to_json/2,
- from_json/2]).
+ from_json/2,
+ to_msgpack/2,
+ from_msgpack/2]).
-ignore_xref([to_json/2,
from_json/2,
+ from_msgpack/2,
+ to_msgpack/2,
allowed_methods/2,
content_types_accepted/2,
content_types_provided/2,
@@ -62,7 +66,8 @@ options(Req, State) ->
content_types_provided(Req, State) ->
{[
- {<<"application/json">>, to_json}
+ {<<"application/json">>, to_json},
+ {<<"application/x-msgpack">>, to_msgpack}
], Req, State}.
content_types_accepted(Req, State) ->
@@ -138,6 +143,10 @@ to_json(Req, State) ->
{Reply, Req1, State1} = handle_request(Req, State),
{jsx:encode(Reply), Req1, State1}.
+to_msgpack(Req, State) ->
+ {Reply, Req1, State1} = handle_request(Req, State),
+ {msgpack:pack(Reply, [jsx]), Req1, State1}.
+
handle_request(Req, State = #state{token = Token, path = []}) ->
{ok, Permissions} = libsnarl:user_cache({token, Token}),
{ok, Res} = libsniffle:hypervisor_list([{must, 'allowed', [<<"hypervisors">>, {<<"res">>, <<"name">>}, <<"get">>], Permissions}]),
@@ -161,6 +170,17 @@ from_json(Req, State) ->
end,
{Reply, Req2, State1}.
+from_msgpack(Req, State) ->
+ {ok, Body, Req1} = cowboy_http_req:body(Req),
+ {Reply, Req2, State1} = case Body of
+ <<>> ->
+ handle_write(Req1, State, []);
+ _ ->
+ Decoded = msgpack:unpack(Body, [jsx]),
+ handle_write(Req1, State, Decoded)
+ end,
+ {Reply, Req2, State1}.
+
handle_write(Req, State = #state{path = [Hypervisor, <<"characteristics">> | Path]}, [{K, V}]) ->
libsniffle:hypervisor_set(Hypervisor, [<<"characteristics">> | Path] ++ [K], jsxd:from_list(V)),
{true, Req, State};
39 apps/wiggle/src/wiggle_iprange_handler.erl
View
@@ -19,10 +19,14 @@
is_authorized/2]).
-export([to_json/2,
- from_json/2]).
+ from_json/2,
+ to_msgpack/2,
+ from_msgpack/2]).
-ignore_xref([to_json/2,
from_json/2,
+ from_msgpack/2,
+ to_msgpack/2,
allowed_methods/2,
content_types_accepted/2,
content_types_provided/2,
@@ -69,7 +73,8 @@ options(Req, State) ->
content_types_provided(Req, State) ->
{[
- {<<"application/json">>, to_json}
+ {<<"application/json">>, to_json},
+ {<<"application/x-msgpack">>, to_msgpack}
], Req, State}.
content_types_accepted(Req, State) ->
@@ -145,6 +150,10 @@ to_json(Req, State) ->
{Reply, Req1, State1} = handle_request(Req, State),
{jsx:encode(Reply), Req1, State1}.
+to_msgpack(Req, State) ->
+ {Reply, Req1, State1} = handle_request(Req, State),
+ {msgpack:pack(Reply, [jsx]), Req1, State1}.
+
handle_request(Req, State = #state{token = Token, path = []}) ->
{ok, Permissions} = libsnarl:user_cache({token, Token}),
{ok, Res} = libsniffle:iprange_list([{must, 'allowed', [<<"ipranges">>, {<<"res">>, <<"uuid">>}, <<"get">>], Permissions}]),
@@ -167,14 +176,7 @@ handle_request(Req, State = #state{path = [_Iprange], obj = Obj}) ->
%%--------------------------------------------------------------------
create_path(Req, State = #state{path = [], version = Version}) ->
- {ok, Body, Req1} = cowboy_http_req:body(Req),
- {Data, Req2} = case Body of
- <<>> ->
- {[], Req1};
- _ ->
- D = jsxd:from_list(jsx:decode(Body)),
- {D, Req1}
- end,
+ {ok, Data, Req1} = wiggle_handler:decode(Req),
{ok, Iprange} = jsxd:get(<<"name">>, Data),
{ok, Network} = jsxd:get(<<"network">>, Data),
{ok, Gateway} = jsxd:get(<<"gateway">>, Data),
@@ -185,10 +187,10 @@ create_path(Req, State = #state{path = [], version = Version}) ->
Vlan = jsxd:get(<<"vlan">>, 0, Data),
case libsniffle:iprange_create(Iprange, Network, Gateway, Netmask, First, Last, Tag, Vlan) of
{ok, UUID} ->
- {<<"/api/", Version/binary, "/ipranges/", UUID/binary>>, Req2, State};
+ {<<"/api/", Version/binary, "/ipranges/", UUID/binary>>, Req1, State#state{body = Data}};
duplicate ->
- {ok, Req3} = cowboy_http_req:reply(409, Req2),
- {halt, Req3, State}
+ {ok, Req2} = cowboy_http_req:reply(409, Req1),
+ {halt, Req2, State}
end.
@@ -203,6 +205,17 @@ from_json(Req, State) ->
end,
{Reply, Req2, State1}.
+from_msgpack(Req, State) ->
+ {ok, Body, Req1} = cowboy_http_req:body(Req),
+ {Reply, Req2, State1} = case Body of
+ <<>> ->
+ handle_write(Req1, State, []);
+ _ ->
+ Decoded = jsxd:from_list(msgpack:unpack(Body, [jsx])),
+ handle_write(Req1, State, Decoded)
+ end,
+ {Reply, Req2, State1}.
+
%% TODO : This is a icky case it is called after post.
handle_write(Req, State = #state{method = 'POST', path = []}, _) ->
{true, Req, State};
39 apps/wiggle/src/wiggle_package_handler.erl
View
@@ -19,10 +19,14 @@
is_authorized/2]).
-export([to_json/2,
- from_json/2]).
+ from_json/2,
+ to_msgpack/2,
+ from_msgpack/2]).
-ignore_xref([to_json/2,
from_json/2,
+ from_msgpack/2,
+ to_msgpack/2,
allowed_methods/2,
content_types_accepted/2,
content_types_provided/2,
@@ -70,7 +74,8 @@ options(Req, State) ->
content_types_provided(Req, State) ->
{[
- {<<"application/json">>, to_json}
+ {<<"application/json">>, to_json},
+ {<<"application/x-msgpack">>, to_msgpack}
], Req, State}.
content_types_accepted(Req, State) ->
@@ -146,6 +151,10 @@ to_json(Req, State) ->
{Reply, Req1, State1} = handle_request(Req, State),
{jsx:encode(Reply), Req1, State1}.
+to_msgpack(Req, State) ->
+ {Reply, Req1, State1} = handle_request(Req, State),
+ {msgpack:pack(Reply, [jsx]), Req1, State1}.
+
handle_request(Req, State = #state{token = Token, path = []}) ->
{ok, Permissions} = libsnarl:user_cache({token, Token}),
{ok, Res} = libsniffle:package_list([{must, 'allowed', [<<"packages">>, {<<"res">>, <<"uuid">>}, <<"get">>], Permissions}]),
@@ -160,23 +169,16 @@ handle_request(Req, State = #state{path = [_Package], obj = Obj}) ->
%%--------------------------------------------------------------------
create_path(Req, State = #state{path = [], version = Version}) ->
- {ok, Body, Req1} = cowboy_http_req:body(Req),
- {Data, Req2} = case Body of
- <<>> ->
- {[], Req1};
- _ ->
- D = jsxd:from_list(jsx:decode(Body)),
- {D, Req1}
- end,
+ {ok, Data, Req1} = wiggle_handler:decode(Req),
Data1 = jsxd:select([<<"cpu_cap">>,<<"quota">>, <<"ram">>, <<"requirements">>], Data),
{ok, Package} = jsxd:get(<<"name">>, Data),
case libsniffle:package_create(Package) of
{ok, UUID} ->
ok = libsniffle:package_set(UUID, Data1),
- {<<"/api/", Version/binary, "/packages/", UUID/binary>>, Req2, State};
+ {<<"/api/", Version/binary, "/packages/", UUID/binary>>, Req1, State#state{body = Data1}};
duplicate ->
- {ok, Req3} = cowboy_http_req:reply(409, Req2),
- {halt, Req3, State}
+ {ok, Req2} = cowboy_http_req:reply(409, Req1),
+ {halt, Req2, State}
end.
from_json(Req, State) ->
@@ -190,6 +192,17 @@ from_json(Req, State) ->
end,
{Reply, Req2, State1}.
+from_msgpack(Req, State) ->
+ {ok, Body, Req1} = cowboy_http_req:body(Req),
+ {Reply, Req2, State1} = case Body of
+ <<>> ->
+ handle_write(Req1, State, null);
+ _ ->
+ Decoded = msgpack:unpack(Body, [jsx]),
+ handle_write(Req1, State, Decoded)
+ end,
+ {Reply, Req2, State1}.
+
%% TODO : This is a icky case it is called after post.
handle_write(Req, State = #state{method = 'POST', path = []}, _) ->
50 apps/wiggle/src/wiggle_session_handler.erl
View
@@ -23,10 +23,14 @@
is_authorized/2]).
-export([to_json/2,
- from_json/2]).
+ from_json/2,
+ to_msgpack/2,
+ from_msgpack/2]).
-ignore_xref([to_json/2,
from_json/2,
+ from_msgpack/2,
+ to_msgpack/2,
create_path/2,
allowed_methods/2,
content_types_accepted/2,
@@ -73,14 +77,12 @@ options(Req, State) ->
content_types_provided(Req, State) ->
{[
- {<<"application/json">>, to_json}
+ {<<"application/json">>, to_json},
+ {<<"application/x-msgpack">>, to_msgpack}
], Req, State}.
content_types_accepted(Req, State) ->
- {[
- {<<"application/json; charset=UTF-8">>, from_json},
- {<<"application/json; charset=utf-8">>, from_json}
- ], Req, State}.
+ {wiggle_handler:accepted(), Req, State}.
allowed_methods(Req, State) ->
{['HEAD', 'OPTIONS' | allowed_methods(State#state.version, State#state.token, State#state.path)], Req, State}.
@@ -116,6 +118,10 @@ to_json(Req, State) ->
{Reply, Req1, State1} = handle_request(Req, State),
{jsx:encode(Reply), Req1, State1}.
+to_msgpack(Req, State) ->
+ {Reply, Req1, State1} = handle_request(Req, State),
+ {msgpack:pack(Reply, [jsx]), Req1, State1}.
+
handle_request(Req, State = #state{path = [Session], obj = Obj}) ->
Obj1 = jsxd:thread([{set, <<"session">>, Session},
{delete, <<"password">>},
@@ -131,24 +137,18 @@ handle_request(Req, State = #state{path = [Session], obj = Obj}) ->
%%--------------------------------------------------------------------
create_path(Req, State = #state{path = [], version = Version}) ->
- {ok, Body, Req1} = cowboy_http_req:body(Req),
- {Decoded, Req2} = case Body of
- <<>> ->
- {[], Req1};
- _ ->
- D = jsx:decode(Body),
- {D, Req1}
- end,
+ {ok, Decoded, Req1} = wiggle_handler:decode(Req),
{ok, User} = jsxd:get(<<"user">>, Decoded),
{ok, Pass} = jsxd:get(<<"password">>, Decoded),
case libsnarl:auth(User, Pass) of
{ok, {token, UUID}} ->
- {ok, Req3} = cowboy_http_req:set_resp_cookie(<<"X-Snarl-Token">>, UUID,
- [{max_age, 364*24*60*60}], Req2),
- {<<"/api/", Version/binary, "/sessions/", UUID/binary>>, Req3, State};
+ {ok, Req2} = cowboy_http_req:set_resp_cookie(<<"X-Snarl-Token">>, UUID,
+ [{max_age, 364*24*60*60}], Req1),
+ {ok, Req3} = cowboy_http_req:set_resp_header(<<"X-Snarl-Token">>, UUID, Req2),
+ {<<"/api/", Version/binary, "/sessions/", UUID/binary>>, Req3, State#state{body = Decoded}};
_ ->
- {ok, Req3} = cowboy_http_req:reply(403, [], <<"Forbidden!">>, Req2),
- {halt, Req3, State}
+ {ok, Req2} = cowboy_http_req:reply(403, [], <<"Forbidden!">>, Req1),
+ {halt, Req2, State}
end.
from_json(Req, State) ->
@@ -163,6 +163,18 @@ from_json(Req, State) ->
{Reply, Req2, State1}.
+from_msgpack(Req, State) ->
+ {ok, Body, Req1} = cowboy_http_req:body(Req),
+ {Reply, Req2, State1} = case Body of
+ <<>> ->
+ handle_write(Req1, State, []);
+ _ ->
+ Decoded = msgpack:unpack(Body, [jsx]),
+ handle_write(Req1, State, Decoded)
+ end,
+
+ {Reply, Req2, State1}.
+
handle_write(Req, State, _) ->
{true, Req, State}.
38 apps/wiggle/src/wiggle_user_handler.erl
View
@@ -23,10 +23,14 @@
is_authorized/2]).
-export([to_json/2,
- from_json/2]).
+ from_json/2,
+ to_msgpack/2,
+ from_msgpack/2]).
-ignore_xref([to_json/2,
from_json/2,
+ from_msgpack/2,
+ to_msgpack/2,
post_is_create/2,
allowed_methods/2,
content_types_accepted/2,
@@ -73,7 +77,8 @@ options(Req, State) ->
content_types_provided(Req, State) ->
{[
- {<<"application/json">>, to_json}
+ {<<"application/json">>, to_json},
+ {<<"application/x-msgpack">>, to_msgpack}
], Req, State}.
content_types_accepted(Req, State) ->
@@ -223,6 +228,10 @@ to_json(Req, State) ->
{Reply, Req1, State1} = handle_request(Req, State),
{jsx:encode(Reply), Req1, State1}.
+to_msgpack(Req, State) ->
+ {Reply, Req1, State1} = handle_request(Req, State),
+ {msgpack:pack(Reply, [jsx]), Req1, State1}.
+
handle_request(Req, State = #state{path = []}) ->
{ok, Res} = libsnarl:user_list(),
{Res, Req, State};
@@ -245,21 +254,13 @@ handle_request(Req, State = #state{path = [_User, <<"groups">>], obj = UserObj})
%% PUT
%%--------------------------------------------------------------------
-
create_path(Req, State = #state{path = [], version = Version}) ->
- {ok, Body, Req1} = cowboy_http_req:body(Req),
- {Decoded, Req2} = case Body of
- <<>> ->
- {[], Req1};
- _ ->
- D = jsx:decode(Body),
- {D, Req1}
- end,
+ {ok, Decoded, Req1} = wiggle_handler:decode(Req),
{ok, User} = jsxd:get(<<"user">>, Decoded),
{ok, Pass} = jsxd:get(<<"password">>, Decoded),
{ok, UUID} = libsnarl:user_add(User),
ok = libsnarl:user_passwd(UUID, Pass),
- {<<"/api/", Version/binary, "/users/", UUID/binary>>, Req2, State}.
+ {<<"/api/", Version/binary, "/users/", UUID/binary>>, Req1, State#state{body = Decoded}}.
from_json(Req, State) ->
{ok, Body, Req1} = cowboy_http_req:body(Req),
@@ -274,6 +275,19 @@ from_json(Req, State) ->
{Reply, Req2, State1}.
+from_msgpack(Req, State) ->
+ {ok, Body, Req1} = cowboy_http_req:body(Req),
+ io:format("[PUT] ~p", [Body]),
+ {Reply, Req2, State1} = case Body of
+ <<>> ->
+ handle_write(Req1, State, []);
+ _ ->
+ Decoded = msgpack:unpack(Body, [jsx]),
+ handle_write(Req1, State, Decoded)
+ end,
+
+ {Reply, Req2, State1}.
+
handle_write(Req, State = #state{path = [User]}, [{<<"password">>, Password}]) ->
85 apps/wiggle/src/wiggle_vm_handler.erl
View
@@ -19,10 +19,14 @@
is_authorized/2]).
-export([to_json/2,
- from_json/2]).
+ from_json/2,
+ to_msgpack/2,
+ from_msgpack/2]).
-ignore_xref([to_json/2,
from_json/2,
+ from_msgpack/2,
+ to_msgpack/2,
allowed_methods/2,
content_types_accepted/2,
content_types_provided/2,
@@ -66,7 +70,8 @@ options(Req, State) ->
content_types_provided(Req, State) ->
{[
- {<<"application/json">>, to_json}
+ {<<"application/json">>, to_json},
+ {<<"application/x-msgpack">>, to_msgpack}
], Req, State}.
content_types_accepted(Req, State) ->
@@ -153,19 +158,13 @@ forbidden(Req, State = #state{method = 'DELETE', path = [Vm]}) ->
{allowed(State#state.token, [<<"vms">>, Vm, <<"delete">>]), Req, State};
forbidden(Req, State = #state{method = 'PUT', path = [Vm]}) ->
- {ok, Body, Req1} = cowboy_http_req:body(Req),
- Decoded = case Body of
- <<>> ->
- [];
- _ ->
- jsx:decode(Body)
- end,
+ {ok, Decoded, Req1} = wiggle_handler:decode(Req),
case Decoded of
[{<<"action">>, <<"start">>}] ->
{allowed(State#state.token, [<<"vms">>, Vm, <<"start">>]), Req1, State#state{body=Decoded}};
- [{<<"action">>, <<"stop">>}] ->
+ [{<<"action">>, <<"stop">>}|_] ->
{allowed(State#state.token, [<<"vms">>, Vm, <<"stop">>]), Req1, State#state{body=Decoded}};
- [{<<"action">>, <<"reboot">>}] ->
+ [{<<"action">>, <<"reboot">>}|_] ->
{allowed(State#state.token, [<<"vms">>, Vm, <<"reboot">>]), Req1, State#state{body=Decoded}};
_ ->
{allowed(State#state.token, [<<"vms">>, Vm, <<"edit">>]), Req1, State#state{body=Decoded}}
@@ -181,13 +180,7 @@ forbidden(Req, State = #state{method = 'GET', path = [Vm, <<"snapshots">>, _Snap
{allowed(State#state.token, [<<"vms">>, Vm, <<"get">>]), Req, State};
forbidden(Req, State = #state{method = 'PUT', path = [Vm, <<"snapshots">>, _Snap]}) ->
- {ok, Body, Req1} = cowboy_http_req:body(Req),
- Decoded = case Body of
- <<>> ->
- [];
- _ ->
- jsx:decode(Body)
- end,
+ {ok, Decoded, Req1} = wiggle_handler:decode(Req),
case Decoded of
[{<<"action">>, <<"rollback">>}] ->
{allowed(State#state.token, [<<"vms">>, Vm, <<"rollback">>]), Req1, State#state{body=Decoded}};
@@ -199,13 +192,7 @@ forbidden(Req, State = #state{method = 'DELETE', path = [Vm, <<"snapshots">>, _S
{allowed(State#state.token, [<<"vms">>, Vm, <<"snapshot_delete">>]), Req, State};
forbidden(Req, State = #state{method = 'PUT', path = [Vm, <<"metadata">> | _]}) ->
- {ok, Body, Req1} = cowboy_http_req:body(Req),
- Decoded = case Body of
- <<>> ->
- [];
- _ ->
- jsx:decode(Body)
- end,
+ {ok, Decoded, Req1} = wiggle_handler:decode(Req),
{allowed(State#state.token, [<<"vms">>, Vm, <<"edit">>]), Req1, State#state{body=Decoded}};
forbidden(Req, State = #state{method = 'DELETE', path = [Vm, <<"metadata">> | _]}) ->
@@ -223,6 +210,10 @@ to_json(Req, State) ->
{Reply, Req1, State1} = handle_request(Req, State),
{jsx:encode(Reply), Req1, State1}.
+to_msgpack(Req, State) ->
+ {Reply, Req1, State1} = handle_request(Req, State),
+ {msgpack:pack(Reply, [jsx]), Req1, State1}.
+
handle_request(Req, State = #state{token = Token, path = []}) ->
{ok, Permissions} = libsnarl:user_cache({token, Token}),
{ok, Res} = libsniffle:vm_list([{must, 'allowed', [<<"vms">>, {<<"res">>, <<"uuid">>}, <<"get">>], Permissions}]),
@@ -246,14 +237,7 @@ handle_request(Req, State = #state{path = [_Vm], obj = Obj}) ->
%%--------------------------------------------------------------------
create_path(Req, State = #state{path = [], version = Version, token = Token}) ->
- {ok, Body, Req1} = cowboy_http_req:body(Req),
- {Decoded, Req2} = case Body of
- <<>> ->
- {[], Req1};
- _ ->
- D = jsx:decode(Body),
- {D, Req1}
- end,
+ {ok, Decoded, Req1} = wiggle_handler:decode(Req),
try
{ok, Dataset} = jsxd:get(<<"dataset">>, Decoded),
{ok, Package} = jsxd:get(<<"package">>, Decoded),
@@ -263,32 +247,25 @@ create_path(Req, State = #state{path = [], version = Version, token = Token}) ->
{ok, User} = libsnarl:user_get({token, Token}),
{ok, Owner} = jsxd:get(<<"uuid">>, User),
{ok, UUID} = libsniffle:create(Package, Dataset, jsxd:set(<<"owner">>, Owner, Config)),
- {<<"/api/", Version/binary, "/vms/", UUID/binary>>, Req2, State#state{body = Decoded}}
+ {<<"/api/", Version/binary, "/vms/", UUID/binary>>, Req1, State#state{body = Decoded}}
catch
G:E ->
lager:error("Error creating VM(~p): ~p / ~p", [Decoded, G, E]),
- {ok, Req3} = cowboy_http_req:reply(500, Req2),
- {halt, Req3, State}
+ {ok, Req2} = cowboy_http_req:reply(500, Req1),
+ {halt, Req2, State}
end
catch
G1:E1 ->
lager:error("Error creating VM(~p): ~p / ~p", [Decoded, G1, E1]),
- {ok, Req4} = cowboy_http_req:reply(400, Req2),
- {halt, Req4, State}
+ {ok, Req3} = cowboy_http_req:reply(400, Req1),
+ {halt, Req3, State}
end;
create_path(Req, State = #state{path = [Vm, <<"snapshots">>], version = Version}) ->
- {ok, Body, Req1} = cowboy_http_req:body(Req),
- {Decoded, Req2} = case Body of
- <<>> ->
- {[], Req1};
- _ ->
- D = jsx:decode(Body),
- {D, Req1}
- end,
+ {ok, Decoded, Req1} = wiggle_handler:decode(Req),
Comment = jsxd:get(<<"comment">>, <<"">>, Decoded),
{ok, UUID} = libsniffle:vm_snapshot(Vm, Comment),
- {<<"/api/", Version/binary, "/vms/", Vm/binary, "/snapshots/", UUID/binary>>, Req2, State}.
+ {<<"/api/", Version/binary, "/vms/", Vm/binary, "/snapshots/", UUID/binary>>, Req1, State#state{body = Decoded}}.
from_json(Req, #state{body = undefined} = State) ->
handle_write(Req, State, []);
@@ -296,6 +273,12 @@ from_json(Req, #state{body = undefined} = State) ->
from_json(Req, #state{body = Decoded} = State) ->
handle_write(Req, State, Decoded).
+from_msgpack(Req, #state{body = undefined} = State) ->
+ handle_write(Req, State, []);
+
+from_msgpack(Req, #state{body = Decoded} = State) ->
+ handle_write(Req, State, Decoded).
+
handle_write(Req, State = #state{path = [Vm, <<"metadata">> | Path]}, [{K, V}]) ->
libsniffle:vm_set(Vm, [<<"metadata">> | Path] ++ [K], jsxd:from_list(V)),
{true, Req, State};
@@ -308,10 +291,18 @@ handle_write(Req, State = #state{path = [Vm]}, [{<<"action">>, <<"stop">>}]) ->
libsniffle:vm_stop(Vm),
{true, Req, State};
+handle_write(Req, State = #state{path = [Vm]}, [{<<"action">>, <<"stop">>}, {<<"force">>, true}]) ->
+ libsniffle:vm_stop(Vm, [force]),
+ {true, Req, State};
+
handle_write(Req, State = #state{path = [Vm]}, [{<<"action">>, <<"reboot">>}]) ->
libsniffle:vm_reboot(Vm),
{true, Req, State};
+handle_write(Req, State = #state{path = [Vm]}, [{<<"action">>, <<"reboot">>}, {<<"force">>, true}]) ->
+ libsniffle:vm_reboot(Vm, [force]),
+ {true, Req, State};
+
handle_write(Req, State = #state{path = [Vm]}, [{<<"config">>, Config},
{<<"package">>, Package}]) ->
libsniffle:vm_update(Vm, Package, Config),
7 rebar.config
View
@@ -10,10 +10,11 @@
{jsx, ".*", {git, "http://github.com/talentdeficit/jsx.git", {tag, "v1.3.3"}}},
{mimetypes, ".*", {git, "http://github.com/spawngrid/mimetypes.git", {branch, master}}},
{cowboy, ".*", {git, "https://github.com/extend/cowboy.git", {tag, "0.6.1"}}},
+ {msgpack, ".*", {git, "git://github.com/msgpack/msgpack-erlang.git", {tag, "0.1.2"}}},
{jsxd, ".*", {git, "https://github.com/Licenser/jsxd.git", {tag, "0.1.4"}}},
- {libhowl, ".*", {git, "http://github.com/project-fifo/libhowl.git", {tag, "0.1.3"}}},
+ {libhowl, ".*", {git, "http://github.com/project-fifo/libhowl.git", {tag, "0.1.5"}}},
{fifo_spec, ".*", {git, "https://github.com/project-fifo/fifo_spec.git", {tag, "0.1.0"}}},
- {libchunter, ".*", {git, "http://github.com/project-fifo/libchunter.git", {tag, "0.1.5"}}},
- {libsniffle, ".*", {git, "http://github.com/project-fifo/libsniffle.git", {tag, "0.2.3"}}},
+ {libchunter, ".*", {git, "http://github.com/project-fifo/libchunter.git", {tag, "0.1.7"}}},
+ {libsniffle, ".*", {git, "http://github.com/project-fifo/libsniffle.git", {tag, "0.2.4"}}},
{libsnarl, ".*", {git, "http://github.com/project-fifo/libsnarl.git", {tag, "0.2.4"}}}
]}.
2  rel/pkg/Makefile
View
@@ -1,4 +1,4 @@
-VERSION=0.4.5
+VERSION=0.4.6
COMPONENT=wiggle
.PHONY: build_info package package_list
2  rel/reltool.config
View
@@ -1,6 +1,6 @@
{sys, [
{lib_dirs, ["../deps", "../apps"]},
- {rel, "wiggle", "0.4.5",
+ {rel, "wiggle", "0.4.6",
[
kernel,
stdlib,
Please sign in to comment.
Something went wrong with that request. Please try again.