Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: validate avsc and hocon when packaging #11

Merged
merged 3 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 25 additions & 12 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
.rebar3
_*
.eunit
deps
*.o
*.beam
*.plt
*.swp
*.swo
.erlang.cookie
ebin
log
erl_crash.dump
ebin
rel/example_project
.concrete/DEV_MODE
.rebar
logs
_build
.idea
*.iml
.erlang.mk/
data/
emqx_plugin_template.d
.DS_Store
erlang.mk
_build/
rebar.lock
test/ct.cover.spec
.rebar3
/.idea/
rebar3.crashdump
rebar3
erlang_ls.config
# VSCode files
.vs/
.vscode/
# Emacs Backup files
*~
rebar.lock
# Emacs temporary files
.#*
*#
# For direnv
.envrc
3 changes: 2 additions & 1 deletion rebar.config
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
%% -*- mode: erlang -*-

{erl_opts, [debug_info, {feature, maybe_expr, enable}]}.
{erl_opts, [debug_info]}.

{deps, [
{hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.42.2"}}},
{erlavro, {git, "https://github.com/emqx/erlavro.git", {tag, "2.10.0"}}}
]}.
41 changes: 31 additions & 10 deletions src/emqx_plugrel.erl
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
-module(emqx_plugrel).

-feature(maybe_expr, enable).

-export([init/1, do/1, format_error/1]).

-define(METADATA_VSN, <<"0.1.0">>).

-define(plugin_readme_file, "README.md").
-define(plugin_avsc_file, "priv/config_schema.avsc").
-define(plugin_i18n_file, "priv/config_i18n.json").
-define(plugin_hocon_file, "priv/config.hocon").
-define(validate_but_no_copy, undefined).


-define(LOG(LEVEL, FORMAT, ARGS),
rebar_api:LEVEL("[emqx_plugrel] " ++ FORMAT, ARGS)).
Expand Down Expand Up @@ -145,18 +150,21 @@ do_make_tar(Cwd, NameWithVsn) ->

maybe_copy_files(LibDir) ->
lists:foreach(
fun(F) ->
fun({F, TargetDir}) ->
maybe
true ?= filelib:is_regular(F),
true ?= validate_file(F), %% validate only when file existed
rebar_file_utils:cp_r([F], LibDir)
case TargetDir of
?validate_but_no_copy -> ok;
_ -> rebar_file_utils:cp_r([F], TargetDir), ok
end
else
_ -> ok
end
end,
[ ?plugin_readme_file
, ?plugin_avsc_file
, ?plugin_i18n_file
[ {?plugin_readme_file, LibDir}
, {?plugin_avsc_file, ?validate_but_no_copy}
, {?plugin_i18n_file, ?validate_but_no_copy}
]
),
ok.
Expand All @@ -170,14 +178,27 @@ validate_file(F) ->
true.

validate_avsc(F) ->
{ok, Bin} = file:read_file(F),
try avro:decode_schema(Bin) of
_ ->
?LOG(debug, "Valid AVRO schema file: ~ts", [F]),
Name = <<"TryDecodeDefaultAvro">>,
try
begin
{ok, HoconMap} = hocon:load(?plugin_hocon_file),
JsonEncodedAvroBin = jsone:encode(HoconMap, [native_forward_slash, {space, 1}, {indent, 4}]),
Store0 = avro_schema_store:new([map]),
{ok, AvscBin} = file:read_file(?plugin_avsc_file),
Store = avro_schema_store:import_schema_json(Name, AvscBin, Store0),
Opts = avro:make_decoder_options([{map_type, map}, {record_type, map}, {encoding, avro_json}]),
{ok, avro_json_decoder:decode_value(JsonEncodedAvroBin, Name, Store, Opts)}
end

of
{ok, _Value} ->
?LOG(debug, "Schema matched. Valid Plugin Hocon and Schema files: ~ts, ~ts", [?plugin_hocon_file, ?plugin_avsc_file]),
true
catch
E : R : S ->
?LOG(error, "Invalid AVRO schema file. Error = ~p, Reason = ~p, Stacktrace=~p", [E, R, S]),
?LOG(error, "Invalid plugin Hocon or Schema. Please check ~ts and ~ts.~n"
"Error = ~p, Reason = ~p, Stacktrace=~p",
[?plugin_hocon_file, ?plugin_avsc_file, E, R, S]),
error({failed_to_validate_avsc_file, F})
end.

Expand Down
Loading