Skip to content

Commit

Permalink
new api endpoint for HCL (Terraform .tf). PUT/POST json to ../hcl/, g…
Browse files Browse the repository at this point in the history
…et HCL
  • Loading branch information
dgulinobw committed Mar 7, 2024
1 parent 8646792 commit 8a151bd
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 4 deletions.
4 changes: 3 additions & 1 deletion src/dog_api_router.erl
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ start_link() ->
{"/api/V2/fact/:id", api_handler_v2, #{}},
{"/api/V2/fact/:id/:sub", api_handler_v2, #{}},
{"/api/V2/facts", plural_api_handler_v2, #{}},
{"/api/V2/facts/:sub", plural_api_handler_v2, #{}}
{"/api/V2/facts/:sub", plural_api_handler_v2, #{}},
{"/api/hcl/:sub", hcl_api_handler, #{}},
{"/api/V2/hcl/:sub", hcl_api_handler_v2, #{}}
]}
]),
{ok, _} = cowboy:start_clear(
Expand Down
6 changes: 3 additions & 3 deletions src/dog_ruleset_api_v2.erl
Original file line number Diff line number Diff line change
Expand Up @@ -490,11 +490,11 @@ rule_names_to_ids(Rules, ServicesByName, ZonesByName, GroupsByName) ->
-spec to_hcl_by_id(RulesetId :: iolist()) -> iolist().
to_hcl_by_id(RulesetId) ->
{ok, RulesetWithIds} = get_by_id(RulesetId),
to_hcl(RulesetWithIds).
Ruleset = ids_to_names(RulesetWithIds),
to_hcl(Ruleset).

-spec to_hcl(Ruleset :: map()) -> binary().
to_hcl(RulesetWithIds) ->
Ruleset = ids_to_names(RulesetWithIds),
to_hcl(Ruleset) ->
InboundRules = rules_to_hcl(nested:get([<<"rules">>,<<"inbound">>],Ruleset)),
OutboundRules = rules_to_hcl(nested:get([<<"rules">>,<<"outbound">>],Ruleset)),
Bindings = #{
Expand Down
76 changes: 76 additions & 0 deletions src/hcl_api_handler.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
-module(hcl_api_handler).

-include("dog_trainer.hrl").
-include_lib("kernel/include/logger.hrl").

-export([init/2]).
-export([content_types_provided/2]).
-export([content_types_accepted/2]).
-export([allowed_methods/2]).
-export([from_json/2]).
-export([resource_exists/2]).
-export([extract_module_from_path/3]).

init(Req, Opts) ->
{cowboy_rest, Req, Opts}.

extract_module_from_path(Path, Start, Length) ->
Path@0 = erlang:binary_to_list(Path),
Path@1 = lists:flatten(
lists:join("/", lists:sublist(string:split(Path@0, "/", all), Start, Length))
),
Path@2 = erlang:list_to_binary(Path@1),
Path@2.

get_handler_module(Path) ->
handler_lookup(extract_module_from_path(Path, 4, 1)).

handler_lookup(<<"group">>) -> dog_group_api_v2;
handler_lookup(<<"host">>) -> dog_host_api_v2;
handler_lookup(<<"link">>) -> dog_link_api_v2;
handler_lookup(<<"profile">>) -> dog_profile_api_v2;
handler_lookup(<<"service">>) -> dog_service_api_v2;
handler_lookup(<<"zone">>) -> dog_zone_api_v2;
handler_lookup(<<"ruleset">>) -> dog_ruleset_api_v2;
handler_lookup(<<"fact">>) -> dog_fact_api_v2.

content_types_provided(Req, State) ->
{
[
{<<"text/plain">>, to_hcl}
],
Req,
State
}.

content_types_accepted(Req, State) ->
case cowboy_req:method(Req) of
<<"PUT">> ->
{[{<<"application/json">>, from_json}], Req, State };
<<"POST">> ->
{[{<<"application/json">>, from_json}], Req, State }
end.

allowed_methods(Req, State) ->
{[<<"PUT">>,<<"POST">>], Req, State}.

resource_exists(Req@0, State@0) ->
{false, Req@0, State@0}.

from_json(Req@0, State@0) ->
Body = cowboy_req:read_body(Req@0),
Path = cowboy_req:path(Req@0),
Handler = get_handler_module(Path),
{ok, NewContent, Req@1} = Body,
Map = jsx:decode(NewContent, [return_maps]),
State@1 = maps:put(<<"object">>, Map, State@0),
State@2 = maps:put(<<"content">>, NewContent, State@1),
cowboy_req:reply(
200,
#{
<<"content-type">> => <<"plain/text">>
},
Handler:to_hcl(Map),
Req@1
),
{stop, Req@1, State@2}.
76 changes: 76 additions & 0 deletions src/hcl_api_handler_v2.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
-module(hcl_api_handler_v2).

-include("dog_trainer.hrl").
-include_lib("kernel/include/logger.hrl").

-export([init/2]).
-export([content_types_provided/2]).
-export([content_types_accepted/2]).
-export([allowed_methods/2]).
-export([from_json/2]).
-export([resource_exists/2]).
-export([extract_module_from_path/3]).

init(Req, Opts) ->
{cowboy_rest, Req, Opts}.

extract_module_from_path(Path, Start, Length) ->
Path@0 = erlang:binary_to_list(Path),
Path@1 = lists:flatten(
lists:join("/", lists:sublist(string:split(Path@0, "/", all), Start, Length))
),
Path@2 = erlang:list_to_binary(Path@1),
Path@2.

get_handler_module(Path) ->
handler_lookup(extract_module_from_path(Path, 5, 1)).

handler_lookup(<<"group">>) -> dog_group_api_v2;
handler_lookup(<<"host">>) -> dog_host_api_v2;
handler_lookup(<<"link">>) -> dog_link_api_v2;
handler_lookup(<<"profile">>) -> dog_profile_api_v2;
handler_lookup(<<"service">>) -> dog_service_api_v2;
handler_lookup(<<"zone">>) -> dog_zone_api_v2;
handler_lookup(<<"ruleset">>) -> dog_ruleset_api_v2;
handler_lookup(<<"fact">>) -> dog_fact_api_v2.

content_types_provided(Req, State) ->
{
[
{<<"text/plain">>, to_hcl}
],
Req,
State
}.

content_types_accepted(Req, State) ->
case cowboy_req:method(Req) of
<<"PUT">> ->
{[{<<"application/json">>, from_json}], Req, State };
<<"POST">> ->
{[{<<"application/json">>, from_json}], Req, State }
end.

allowed_methods(Req, State) ->
{[<<"PUT">>,<<"POST">>], Req, State}.

resource_exists(Req@0, State@0) ->
{false, Req@0, State@0}.

from_json(Req@0, State@0) ->
Body = cowboy_req:read_body(Req@0),
Path = cowboy_req:path(Req@0),
Handler = get_handler_module(Path),
{ok, NewContent, Req@1} = Body,
Map = jsx:decode(NewContent, [return_maps]),
State@1 = maps:put(<<"object">>, Map, State@0),
State@2 = maps:put(<<"content">>, NewContent, State@1),
cowboy_req:reply(
200,
#{
<<"content-type">> => <<"plain/text">>
},
Handler:to_hcl(Map),
Req@1
),
{stop, Req@1, State@2}.

0 comments on commit 8a151bd

Please sign in to comment.