From 79a764f1176b4c06331b7b3ff61ccb82c6449d3a Mon Sep 17 00:00:00 2001 From: Kjell Winblad Date: Mon, 20 Nov 2023 12:06:21 +0100 Subject: [PATCH] fix: bridge to action upgrade fix up hook should run after upgrade This commit changes how the `emqx_action_info` callback `bridge_v1_to_action_fixup/1` works. It is now called after the automatic upgrade instead of before. Since the full Bridge V1 config might be needed to do the fixup, it is provided in a special field `<<"__bridge_v1_conf__">>`. The `<<"__bridge_v1_conf__">>` field is removed after the callback is called and can thus be ignored if it is not needed. --- .../src/emqx_bridge_kafka_action_info.erl | 6 +- .../src/schema/emqx_connector_schema.erl | 55 +++++++++++++++++-- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/apps/emqx_bridge_kafka/src/emqx_bridge_kafka_action_info.erl b/apps/emqx_bridge_kafka/src/emqx_bridge_kafka_action_info.erl index 66ea2bbd7..8730c1541 100644 --- a/apps/emqx_bridge_kafka/src/emqx_bridge_kafka_action_info.erl +++ b/apps/emqx_bridge_kafka/src/emqx_bridge_kafka_action_info.erl @@ -27,8 +27,10 @@ action_to_bridge_v1_fixup(Config) -> emqx_utils_maps:rename(<<"parameters">>, <<"kafka">>, Config). bridge_v1_to_action_fixup(Config0) -> - Config = emqx_utils_maps:rename(<<"kafka">>, <<"parameters">>, Config0), - maps:with(producer_action_field_keys(), Config). + KafkaMap = emqx_utils_maps:deep_get([<<"parameters">>, <<"kafka">>], Config0), + Config1 = emqx_utils_maps:deep_remove([<<"parameters">>, <<"kafka">>], Config0), + Config2 = maps:put(<<"parameters">>, KafkaMap, Config1), + maps:with(producer_action_field_keys(), Config2). %%------------------------------------------------------------------------------------------ %% Internal helper fns diff --git a/apps/emqx_connector/src/schema/emqx_connector_schema.erl b/apps/emqx_connector/src/schema/emqx_connector_schema.erl index f2b764fdc..a2a79712a 100644 --- a/apps/emqx_connector/src/schema/emqx_connector_schema.erl +++ b/apps/emqx_connector/src/schema/emqx_connector_schema.erl @@ -98,16 +98,16 @@ bridge_configs_to_transform( end. split_bridge_to_connector_and_action( - {ConnectorsMap, {BridgeType, BridgeName, ActionConf, ConnectorFields, PreviousRawConfig}} + {ConnectorsMap, {BridgeType, BridgeName, BridgeV1Conf, ConnectorFields, PreviousRawConfig}} ) -> %% Get connector fields from bridge config ConnectorMap = lists:foldl( fun({ConnectorFieldName, _Spec}, ToTransformSoFar) -> - case maps:is_key(to_bin(ConnectorFieldName), ActionConf) of + case maps:is_key(to_bin(ConnectorFieldName), BridgeV1Conf) of true -> NewToTransform = maps:put( to_bin(ConnectorFieldName), - maps:get(to_bin(ConnectorFieldName), ActionConf), + maps:get(to_bin(ConnectorFieldName), BridgeV1Conf), ToTransformSoFar ), NewToTransform; @@ -125,9 +125,53 @@ split_bridge_to_connector_and_action( _ -> generate_connector_name(ConnectorsMap, BridgeName, 0) end, %% Add connector field to action map - ActionMap = maps:put(<<"connector">>, ConnectorName, ActionConf), + ActionMap = transform_bridge_v1_to_action( + BridgeType, BridgeV1Conf, ConnectorName, ConnectorFields + ), {BridgeType, BridgeName, ActionMap, ConnectorName, ConnectorMap}. +transform_bridge_v1_to_action(BridgeType, BridgeV1Conf, ConnectorName, ConnectorFields) -> + BridgeV1ConfKey = <<"__bridge_v1_conf__">>, + TopKeys = [ + <<"enable">>, + <<"connector">>, + <<"local_topic">>, + <<"resource_opts">>, + <<"description">>, + <<"parameters">>, + BridgeV1ConfKey + ], + %% Remove connector fields + ActionMap0 = lists:foldl( + fun + ({enable, _Spec}, ToTransformSoFar) -> + %% Enable filed is used in both + ToTransformSoFar; + ({ConnectorFieldName, _Spec}, ToTransformSoFar) -> + case maps:is_key(to_bin(ConnectorFieldName), BridgeV1Conf) of + true -> + maps:remove(to_bin(ConnectorFieldName), ToTransformSoFar); + false -> + ToTransformSoFar + end + end, + BridgeV1Conf, + ConnectorFields + ), + %% Add special key as the whole original bridge config might be needed by + %% the fixup function + ActionMap1 = emqx_utils_maps:deep_put([BridgeV1ConfKey], ActionMap0, BridgeV1Conf), + %% Add the connector field + ActionMap2 = maps:put(<<"connector">>, ConnectorName, ActionMap1), + TopMap = maps:with(TopKeys, ActionMap2), + RestMap = maps:without(TopKeys, ActionMap2), + %% Other parameters should be stuffed into `parameters' + ActionMap = emqx_utils_maps:deep_merge(TopMap, #{<<"parameters">> => RestMap}), + %% Run the fixup callback if it is defined + FixedActionMap = emqx_action_info:bridge_v1_to_action_fixup(BridgeType, ActionMap), + %% remove the special key as it is not needed anymore + maps:without([BridgeV1ConfKey], FixedActionMap). + generate_connector_name(ConnectorsMap, BridgeName, Attempt) -> ConnectorNameList = case Attempt of @@ -174,7 +218,7 @@ transform_old_style_bridges_to_connector_and_actions_of_type( ), %% Add connectors and actions and remove bridges lists:foldl( - fun({BridgeType, BridgeName, ActionMap0, ConnectorName, ConnectorMap}, RawConfigSoFar) -> + fun({BridgeType, BridgeName, ActionMap, ConnectorName, ConnectorMap}, RawConfigSoFar) -> %% Add connector RawConfigSoFar1 = emqx_utils_maps:deep_put( [<<"connectors">>, to_bin(ConnectorType), ConnectorName], @@ -186,7 +230,6 @@ transform_old_style_bridges_to_connector_and_actions_of_type( [<<"bridges">>, to_bin(BridgeType), BridgeName], RawConfigSoFar1 ), - ActionMap = emqx_action_info:bridge_v1_to_action_fixup(BridgeType, ActionMap0), %% Add action RawConfigSoFar3 = emqx_utils_maps:deep_put( [actions_config_name(), to_bin(maybe_rename(BridgeType)), BridgeName],