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: implement configuration and user data export/import #10676

Merged
merged 4 commits into from Jun 9, 2023

Conversation

SergeTupchiy
Copy link
Contributor

@SergeTupchiy SergeTupchiy commented May 11, 2023

Fixes EMQX-9203

Summary

🤖 Generated by Copilot at f1dce5c

This pull request adds data backup features for various EMQ X modules and applications, allowing users to export and import their configurations, authentication sources, authorization rules, users, api keys, banned clients, listeners, bridges, and auto subscribe topics as JSON files. It also updates some application versions, comment styles, and formatting functions. It mainly uses base64 encoding and decoding, JSON encoding and decoding, and file reading and writing functions to handle the data backup logic. The main files involved are emqx_authn.erl, emqx_authz.erl, emqx_bridge.erl, emqx_dashboard_admin.erl, emqx_exhook_mgr.erl, emqx_gateway_conf.erl, emqx_listeners.erl, emqx_mgmt_api_api_keys.erl, emqx_mgmt_auth.erl, emqx_mgmt_cli.erl, emqx_mgmt_data_backup.erl, and emqx_tls_lib.erl.

PR Checklist

Please convert it to a draft if any of the following conditions are not met. Reviewers may skip over until all the items are checked:

  • Added tests for the changes
  • Changed lines covered in coverage report
  • Change log has been added to changes/{ce,ee}/(feat|perf|fix)-<PR-id>.en.md files
  • For internal contributor: there is a jira ticket to track this change
  • If there should be document changes, a PR to emqx-docs.git is sent, or a jira ticket is created to follow up
  • Schema changes are backward compatible

Checklist for CI (.github/workflows) changes

  • If changed package build workflow, pass this action (manual trigger)
  • Change log has been added to changes/ dir for user-facing artifacts update

@coveralls
Copy link
Collaborator

coveralls commented May 11, 2023

Pull Request Test Coverage Report for Build 5214393224

  • 383 of 456 (83.99%) changed or added relevant lines in 24 files are covered.
  • 53 unchanged lines in 16 files lost coverage.
  • Overall coverage increased (+0.2%) to 81.921%

Changes Missing Coverage Covered Lines Changed/Added Lines %
apps/emqx_authz/src/emqx_authz.erl 18 19 94.74%
apps/emqx_auto_subscribe/src/emqx_auto_subscribe.erl 9 10 90.0%
apps/emqx_exhook/src/emqx_exhook_mgr.erl 8 9 88.89%
apps/emqx_gateway/src/emqx_gateway_conf.erl 7 8 87.5%
apps/emqx_utils/src/emqx_utils.erl 8 9 88.89%
apps/emqx_authn/src/emqx_authn.erl 9 11 81.82%
apps/emqx_management/src/emqx_mgmt_listeners_conf.erl 22 24 91.67%
apps/emqx_bridge/src/emqx_bridge.erl 27 31 87.1%
apps/emqx_psk/src/emqx_psk.erl 2 8 25.0%
lib-ee/emqx_ee_schema_registry/src/emqx_ee_schema_registry.erl 15 21 71.43%
Files with Coverage Reduction New Missed Lines %
apps/emqx_bridge_kafka/src/emqx_bridge_kafka_impl_consumer.erl 1 81.13%
apps/emqx_gateway_mqttsn/src/emqx_mqttsn_frame.erl 1 63.48%
apps/emqx/src/emqx_connection.erl 1 83.24%
apps/emqx/src/emqx_limiter/src/emqx_limiter_schema.erl 1 81.48%
apps/emqx/src/emqx_limiter/src/emqx_limiter_server.erl 1 90.07%
apps/emqx/src/emqx_quic_data_stream.erl 1 75.21%
apps/emqx/src/emqx_session.erl 1 87.25%
apps/emqx/src/emqx_channel.erl 2 87.71%
apps/emqx/src/emqx_logger_textfmt.erl 2 56.82%
apps/emqx/src/emqx_trace/emqx_trace.erl 2 88.18%
Totals Coverage Status
Change from base Build 5211972019: 0.2%
Covered Lines: 29620
Relevant Lines: 36157

💛 - Coveralls

@SergeTupchiy SergeTupchiy force-pushed the EMQX-9203-config-backup branch 6 times, most recently from bb72066 to af5231f Compare May 15, 2023 10:51
@SergeTupchiy SergeTupchiy force-pushed the EMQX-9203-config-backup branch 4 times, most recently from 0241e41 to 4ae42de Compare May 23, 2023 19:05
Comment on lines 145 to 157
AuthnList = maps:get(<<"authentication">>, RawConf, []),
lists:foreach(
fun(Authn) ->
case update_conf(update_req(Authn)) of
%% Assume not_found error
{error, _} ->
{ok, _} = update_conf(create_req(Authn));
{ok, _} ->
ok
end
end,
AuthnList
).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need support delete action, for deleting authn not exist in rawConf.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: it has been agreed to merge imported data with the existing one (without deleting) in the first iteration to keep it consistent with EMQX4.4 data import behaviour (https://emqx.atlassian.net/browse/EMQX-9203?focusedCommentId=28667).
Replacing (restore backup) may be implemented later, as it was discussed on the demo meeting.

@SergeTupchiy SergeTupchiy force-pushed the EMQX-9203-config-backup branch 4 times, most recently from 85039da to a796f46 Compare May 29, 2023 18:38
@SergeTupchiy SergeTupchiy force-pushed the EMQX-9203-config-backup branch 3 times, most recently from ef5367c to 28cab51 Compare May 31, 2023 18:20
@SergeTupchiy SergeTupchiy changed the title feat: implement configuration and user data backup/restore feat: implement configuration and user data export/import May 31, 2023
@SergeTupchiy SergeTupchiy marked this pull request as ready for review May 31, 2023 20:12
true ->
%% 4.x backup files are anyway not compatible and will be treated as invalid,
%% before this step.
maybe_print(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be done differently.
My point was that: it's hard to ensure forward compatibility, but at the same time, disallowing newer version imports may be too strict.
Alternatively, we can add some info about forward-compatibility to META.hocon, e.g.

min_major_version=5
min_minor_version=1

And when we import the backup, we can compare it with EMQX version and disallow import if it's not supported.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Group review feedback: disallow 'downgrade' import (if backup is newer than EMQX - don't allow import).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed to disallow importing data if backup version is newer than EMQX version.

RawConf1 = emqx_authz:maybe_write_acl_file(RawConf),
emqx_hocon:check(
emqx_conf:schema_module(),
maps:merge(emqx:get_raw_config([]), RawConf1),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is to validate the whole config before trying to import its individual root keys.
I use maps:merge/2 just to put existing values for required keys like node (no need for deep merging).
I wonder if there are better alternatives.. 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed and agreed that it must be fine.

prepare_new_backup(Opts) ->
{{Y, M, D}, {H, MM, S}} = _DateTime = local_datetime(),
BackupBaseName = str(
io_lib:format("emqx-export-~p-~p-~p-~p-~p-~p", [Y, M, D, H, MM, S])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Maybe smth like

io_lib:format(
        "~0p.~2..0b.~2..0b.~2..0b.~2..0b.~2..0b.~3..0b",
        [Y, M, D, HH, MM, SS, Ts rem 1000]
    )

as in recent Stone's commit to make e.g. names more sorting-friendly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, great idea!
But I think it's better to keep dashes as separators for date/time, e,g:

io_lib:format("emqx-export-~0p-~2..0b-~2..0b-~2..0b-~2..0b-~2..0b.~3..0b",
                      [Y, M, D, HH, MM, SS, Ts rem 1000])
%% emqx-export-2023-06-01-13-06-49.135.tar.gz.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

end
end,
{[], #{}},
AuthnList
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EMQX schema also supports individual authenticator config as "authentication" value, so it may appear in the raw config:

converter => fun ensure_array/2,

Do we handle this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a helper to handle it, thanks!

-define(IMPORT_OPTS, #{rawconf_with_defaults => true, override_to => cluster}).

import_data(RawConf) ->
AuthnList = maps:get(<<"authentication">>, RawConf, []),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
AuthnList = maps:get(<<"authentication">>, RawConf, []),
AuthnList = maps:get(?CONF_NS_BINARY, RawConf, []),

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, changed all the occurrences in authn and authz

@SergeTupchiy SergeTupchiy force-pushed the EMQX-9203-config-backup branch 2 times, most recently from b272c1a to 8aeebc4 Compare June 1, 2023 17:20
apps/emqx_authz/src/emqx_authz.erl Outdated Show resolved Hide resolved
apps/emqx/src/emqx_listeners.erl Show resolved Hide resolved
zhongwencool
zhongwencool previously approved these changes Jun 9, 2023
@@ -0,0 +1,4 @@
Implement configuration and user data import/export CLI.

The tool allows to export configuration and built-in database data from a running
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
The tool allows to export configuration and built-in database data from a running
The `emqx ctl export` and `emqx ctl import` commands allow to export configuration and built-in database data from a running

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed, thanks

zmstone
zmstone previously approved these changes Jun 9, 2023
@SergeTupchiy SergeTupchiy merged commit e61b210 into emqx:master Jun 9, 2023
41 checks passed
@yanzhiemq
Copy link
Collaborator

yanzhiemq commented Jun 13, 2023

Enhancements

  • Added CLI commands emqx ctl export and emqx ctl import for importing/exporting configuration and user data. This allows exporting configurations and built-in database data from a running EMQX cluster and importing them into the same or another running EMQX cluster.

@yanzhiemq
Copy link
Collaborator

yanzhiemq commented Jun 13, 2023

增强

  • 新增了用于导入/导出配置和用户数据的命令 emqx ctl export emqx ctl import, 允许从正在运行的 EMQX 集群中导出配置和内置数据库数据,然后将其导入到相同或另一个正在运行的 EMQX 集群中。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants