**Description**

Allow custom executors subclassed from existing (CeleryExecutor, CeleryKubernetesExecutor, etc.) to use default CLI commands to start workers or flower monitoring.

**Use case / motivation**

Currently, users who decide to roll their own custom Celery-based executor cannot use default commands (i.e. `airflow celery worker`) even though it's built on top of existing CeleryExecutor. If they try to, they'll receive the following error: `airflow command error: argument GROUP_OR_COMMAND: celery subcommand works only with CeleryExecutor, your current executor: custom_package.CustomCeleryExecutor, see help above.`

One workaround for this is to create custom entrypoint script for worker/flower containers/processes that are still going to use the same Celery app as CeleryExecutor. This leads to unnecessary maintaining of this entrypoint script.

I'd suggest two ways of fixing that:

- Check if custom executor is subclassed from Celery executor (which might lead to errors, if custom executor is used to access other celery app, which might be a proper reason for rolling custom executor)
- Store `app` as attribute of Celery-based executors and match the one provided by custom executor with the default one

**Related Issues**

N/A
tests/cli/test_cli_parser.py
a.flags[0] for a in com.args if (len(a.flags) == 1 and not a.flags[0].startswith("-"))
                ]
                conflict_position = [arg for arg, count in Counter(position).items() if count > 1]
                assert [] == conflict_position, (
                    f"Command group {group} function {com.name} have conflict "
                    f"position flags {conflict_position}"
                )
                long_option = [
                    a.flags[0] for a in com.args if (len(a.flags) == 1 and a.flags[0].startswith("-"))
                ] + [a.flags[1] for a in com.args if len(a.flags) == 2]
                conflict_long_option = [arg for arg, count in Counter(long_option).items() if count > 1]
                assert [] == conflict_long_option, (
                    f"Command group {group} function {com.name} have conflict "
                    f"long option flags {conflict_long_option}"
                )
                short_option = [a.flags[0] for a in com.args if len(a.flags) == 2]
                conflict_short_option = [arg for arg, count in Counter(short_option).items() if count > 1]
                assert [] == conflict_short_option, (
                    f"Command group {group} function {com.name} have conflict "
                    f"short option flags {conflict_short_option}"
                )
    def test_falsy_default_value(self):
        arg = cli_parser.Arg(("--test",), default=0, type=int)
        parser = argparse.ArgumentParser()
        arg.add_to_parser(parser)
        args = parser.parse_args(['--test', '10'])
        assert args.test == 10
        args = parser.parse_args([])
        assert args.test == 0
    def test_commands_and_command_group_sections(self):