The new client library version returns reason
`{shutdown, connack_timeout}` in the monitor message.
Delete the monitor since the test case already asserts on the
`{error, connack_timeout}` return value from emqtt:connect/1.
Namely, 'starting'.
Previously, a Prometheus scraping endpoint hit
just at the right moment (when a shovel was
in the 'starting' state) would produce
a function_clause exception.
Bumps the dev-deps group with 1 update in the /deps/rabbit/test/amqp_jms_SUITE_data directory: org.apache.qpid:qpid-jms-client.
Updates `org.apache.qpid:qpid-jms-client` from 2.7.0 to 2.8.0
---
updated-dependencies:
- dependency-name: org.apache.qpid:qpid-jms-client
dependency-version: 2.8.0
dependency-type: direct:development
update-type: version-update:semver-minor
dependency-group: dev-deps
...
Signed-off-by: dependabot[bot] <support@github.com>
These lines can be very useful for determining why a subset of feature
flags is/isn't being enabled on boot. They're currently at debug level.
However a first-time boot of an unclustered node is a rare event, so
these lines shouldn't be noisy.
## What?
Refuse or detach the link instead of ending the session for many
link-level errors, including the following:
* Source queue or target exchange doesn't exist during attach
* Trying to consume from an exclusive queue on a different connection
* Delivery of message to a target queue fails
* Wrong delivery-id
* Wrong settled flag
* Queue declaration fails for dynamic queues
* Publishing to internal exchange
## Why?
Because many errors are scoped to a single terminus, detaching just that link
preserves the rest of the session’s links - avoiding needless disruption of
other traffic. AMQP 1.0’s error model is hierarchical; RabbitMQ should escalate to
ending the session only for session-level faults or if the client keeps
using a destroyed link.
## How?
Refuse link as per figure 2.33
Sometimes you want a plugin to act as a library
and not an application. That is, for its modules
to be available at compile time and on a running
node but, say, the actual runtime parameter
handling and supervision of shovels to be
handled by another plugin.
Since we do not currently have a concept of
"library plugins" or "library dependencies",
this approach demonstrates one example of how
some plugins can be used as libraries.
Then wait for elections to complete before shutting further
members down.
This should help avoid election storms when enabling maintenance
mode.
Transfer khepri before queues to ensure meta data store is
ready to accept pid updates.
Some other state related tweaks.
In some environments it may be tricky to run a command
before RabbitMQ is started. Kubernetes For example, upgrading
to Containerd 2.0 accidentally lowered the value of available
descriptors in GKE
(https://cloud.google.com/kubernetes-engine/docs/troubleshooting/known-issues#containerd-ulimit-reduced).
While this particular issue is resolved in newer GKE versions,
it was a good example of why a variable like this would be helpful.
Kubernetes-level solutions (on the node or with a daemonset) would
require a different level of access for users.
[Why]
When the module wanted to create an exchange in Khepri, it used
`rabbit_khepri:create/2` which ensures that the tree node doesn't exist
before. If the tree node exists, it expects it to contain an exchange
record which is returned to the caller, indicating an exchange with that
name already exists.
However, there are several other resources stored under an exchange tree
node, like bindings and topic permissions.
In particular, during a definitions import, topic permissions used to be
imported before exchanges. This caused a crash because the write of the
topic permission automatically created a parent tree node for the
exchange it dpends on, but without an exchange record obviously (see
previous commit).
[How]
As an addition improvement to the previous commit, we change the
conditions: instead of matching on the fact the tree node doesn't exist,
the module also accepts that the tree node exists but has no payload.
Under any of these conditions, the exchange is considered to be new and
written to Khepri.
[Why]
Topic permissions depend on an exchange, in addition to a user and a
vhost like other permissions.
This fixes a bug where an exchange imported after a topic permission
that depends on it caused the following crash when Khepri is used:
{case_clause,{error,{khepri,mismatching_node,
#{node_name => <<"exchange_name">>,
node_props => #{payload_version => 1},
node_path =>
[rabbitmq,vhosts,<<"/">>,exchanges,
<<"exchange_name">>],
condition => {if_node_exists,false},
node_is_target => true}}}}
The crash comes from the fact that the exchange code expect to either
create the tree node in Khepri for that exchange, or there is an
existing tree node holding an exchange tree node. Here, there was a tree
node created implicitly when the topic permission was stored, but that
tree node didn't have an exchange record (because the exchange was not
imported yet).
[How]
We simply swap the import of topic permissions and exchanges.
[Why]
The testcase tries to replicate the steps described in issue #12934.
[How]
It uses intermediate Erlang nodes between the common_test control node
and the RabbitMQ nodes, using `peer` standard_io communication. The goal
is to make sure the common_test control node doesn't interfere with the
nodes the RabbitMQ nodes can see, despite the blocking of the Erlang
distribution connection.
So far, I couldn't reproduce the problem reported in #12934. @mkuratczyk
couldn't either, so it might have been fixed as a side effect of another
change...
References #12934.
This is a follow-up to commit 93db480bc4
`erlang.mk` supports the `YRL_ERLC_OPTS` variable to set `erlc`-specific
compiler options when processing `.yrl` and `.xrl` files. By using this
variable, it allows `make RMQ_ERLC_OPTS=` to disable the
`+deterministic` option. This allows using `c()` in the erl shell to
recompile modules on the fly when a cluster is running.
You can see that, when `make RMQ_ERLC_OPTS=` is run, these generated
files were produced with the `+deterministic` option, because their
`-file` directives use only basenames.
* `deps/rabbit/src/rabbit_amqp_sql_lexer.erl`
* `deps/rabbit/src/rabbit_amqp_sql_parser.erl`
```
-file("rabbit_amqp_sql_parser.yrl", 0).
-module(rabbit_amqp_sql_parser).
-file("rabbit_amqp_sql_parser.erl", 3).
-export([parse/1, parse_and_scan/1, format_error/1]).
-file("rabbit_amqp_sql_parser.yrl", 122).
```
This commit also ignores those two files, as they will always be
auto-generated.
[Why]
If a user configures an auth backend module, but doesn't enabled the
plugin that provides it, it will get a crash and a stacktrace when
authentication is performed. The error is not helpful to understand what
the problem is.
[How]
We add a boot step that go through the configured auth backends and
query the core of RabbitMQ and the plugins. If an auth backend is
provided by a plugin, the plugin must be enabled to consider the auth
backend to be valid.
In the end, at least one auth backend must be valid, otherwise the boot
is aborted.
If only some of the configured auth backends were filtered out, but
there are still some valid auth backends, we store the filtered list in
the application environment variable so that
authentication/authorization doesn't try to use them later.
We also report invalid auth backends in the logs:
* Info message for a single invalid auth backend:
[info] <0.213.0> The `rabbit_auth_backend_ldap` auth backend module is configured. However, the `rabbitmq_auth_backend_ldap` plugin must be enabled in order to use this auth backend. Until then it will be skipped during authentication/authorization
* Warning message when some auth backends were filtered out:
[warning] <0.213.0> Some configured backends were dropped because their corresponding plugins are disabled. Please look at the info messages above to learn which plugin(s) should be enabled. Here is the list of auth backends kept after filering:
[warning] <0.213.0> [rabbit_auth_backend_internal]
* Error message when no auth backends are valid:
[error] <0.213.0> None of the configured auth backends are usable because their corresponding plugins were not enabled. Please look at the info messages above to learn which plugin(s) should be enabled.
V2: In fact, `rabbit_plugins:is_enabled/1` indicates if a plugin is
running, not if it is enabled... The new check runs as a boot step
and thus is executed before plugins are started. Therefore we can't
use this API. Instead, we use `rabbit_plugins:enabled_plugins/0'
which lists explicitly enabled plugins. The drawback is that in the
auth backend is enabled implicitly because it is a dependency of
another explicitly enabled plugin, the check will still consider it
is disabled and thus abort the boot.
Fixes#13783.
[Why]
This will be used in a later commit to find the auth backend plugin that
provides a configured auth backend module.
[How]
We go through the list of available plugins, regardless if they are
enabled or not, then look up the given module in the list of modules
associated with each plugin's application.
... without having to pass a plugins path.
[Why]
It's painful to have to get the plugins path, then pass it to `list/1`
every time. It's also more difficult to discover how to use
`rabbit_plugins` to get that list of plugins.
The code path in question is executed every time
rabbit_plugins:list/2 (e.g. rabbit_plugins:is_enabled/1)
is used, which with some distributed plugins can
happen once or several times a minute.
Given the maturity of the plugins subsystem, we
arguably can drop those messages.
This elimiantes a race condition between the destination
granting the sender link credit and the rest of what
the test does.
Note: the amqp_utils module in server core cannot be easily
moved to, say, rabbit_ct_helpers because it combines
two kinds of helpers that belong to two of our
CT helper subprojects.
So we've copied two small functions from it for
the needs of this suite.
This implementation intentionally ignores the
drain property of AMQP 1.0 flow control because
local shovels does not use this feature, and no
external component can "enable" it, so we can
simply ignore it.
Pair: @dcorbacho.
Co-authored-by: Diana Parra Corbacho <diana.parra-corbacho@broadcom.com>
Co-authored-by: Michael Klishin <michaelklishin@icloud.com>