processone / ejabberd

Robust, Ubiquitous and Massively Scalable Messaging Platform (XMPP, MQTT, SIP Server)
https://www.process-one.net/en/ejabberd/
Other
6k stars 1.5k forks source link

[Question] Custom Module deps #4207

Open andrejunqueira1 opened 2 months ago

andrejunqueira1 commented 2 months ago

Before creating a ticket, please consider if this should fit the discussion forum better.

Environment

Configuration (only if needed): grep -Ev '^$|^\s*#' ejabberd.yml

loglevel: 4
...

Errors from error.log/crash.log

No errors

Bug description

It is possible to add deps for a custom module running in Docker ?, from Hex for instance, if yes, how could i do ? thanks in advance

badlop commented 2 months ago

Do you use a specific container image, or do you build your own from scratch, or what? Do you add a custom module source code to ejabberd, and let it get compiled, or do you add the beam files directly to the image, or what?

andrejunqueira1 commented 2 months ago

Do you use a specific container image, or do you build your own from scratch, or what? Do you add a custom module source code to ejabberd, and let it get compiled, or do you add the beam files directly to the image, or what?

@badlop I'm using this image: ghcr.io/processone/ejabberd:master (i'm developing my module in macos, but after finish i will install in production that is ubuntu machine) and i'm adding the custom module source to ejabberd and performing the command ejabberdctl module_install, the module is being installed correctly, but i need add extra deps to use in my module

andrejunqueira1 commented 2 months ago

I've already tried to create a file called rebar.config within my module folder, it looks it tries to install but aways fail with some errors. For instance i'm trying to install a Kafka client to my module interact with, i've already tried all the bellow deps with no success:

{erlkaf, ".*", {git, "https://github.com/silviucpp/erlkaf.git", "master"}}
{brod, "", {git, "https://github.com/kafka4beam/brod.git", {tag, "3.17.1"}}}
{wolff, "", {git, "https://github.com/kafka4beam/wolff", {tag, "1.5.13"}}}
{erlkaf, ".*", {git, "https://github.com/silviucpp/erlkaf", "master"}}
{kafka_ex, "~> 0.11", {git, "https://github.com/kafkaex/kafka_ex"}}

my rebar.config looks like it:

{deps, [
    {brod, _, {git, "https://github.com/kafka4beam/brod.git", {tag, "3.17.1"}}}
]}.

this is the current module structure:

Captura de Tela 2024-04-24 às 16 40 21

badlop commented 2 months ago

The problem is that module_install has very limited support to compile dependencies. It can compile small simple dependencies, but the libraries you want to compile require a full development environment.

I can see two methods to accomplish your task:

A) Get ejabberd source code, do some minor changes to add your module and its dependencies, then build a container image specially suited for your needs in your development machine. Then export the image to a file, and finally copy that file to the production machine.

B) Using the existing container image, install in it the required programs to compile erlang and elixir libraries. Then compile the dependencies, and copy to the corresponding place in the image. Finally install your module as you do right now.

Right now I don't know which method is easier. Which one do you consider more suitable for your case? I can experiment and tell you more specific instructions for method A or B.

andrejunqueira1 commented 2 months ago

The problem is that module_install has very limited support to compile dependencies. It can compile small simple dependencies, but the libraries you want to compile require a full development environment.

I can see two methods to accomplish your task:

A) Get ejabberd source code, do some minor changes to add your module and its dependencies, then build a container image specially suited for your needs in your development machine. Then export the image to a file, and finally copy that file to the production machine.

B) Using the existing container image, install in it the required programs to compile erlang and elixir libraries. Then compile the dependencies, and copy to the corresponding place in the image. Finally install your module as you do right now.

Right now I don't know which method is easier. Which one do you consider more suitable for your case? I can experiment and tell you more specific instructions for method A or B.

Thank you very much @badlop i'll wait your specific instructions ! and thanks again

badlop commented 2 months ago

Which method do you consider more suitable for your case, A or B?

andrejunqueira1 commented 2 months ago

Which method do you consider more suitable for your case, A or B?

I think the B option could be better

badlop commented 1 month ago

Hi! It took me quite some time to find a nice way to download, compile and install the dependencies.

Here is an example:

# Create and start the ejabberd container.
# In my case I'll use live mode to view messages in the console:
podman run --name ejabberd -it -p 5222:5222 ghcr.io/processone/ejabberd live

# Install the packages required to compile all the dependencies:
podman exec --user root ejabberd apk add elixir g++

# Let's create a temporary Mix project to get and compile your dependencies:
podman exec ejabberd mix new temp

# Now add the required dependencies to that mix.exs file.
# You can install a text editor like nano, and use it.
# But in this example, I'll add one dependency using Sed:
podman exec ejabberd sed -i 's|# {:dep_from_hexpm|{:brod, ">= 3.17.0"} #|' /opt/ejabberd/temp/mix.exs

# Time to download the dependencies, compile them and generate an OTP release
podman exec -w /opt/ejabberd/temp ejabberd mix do deps.get + release

# Finally, copy the compiled dependencies to a place where ejabberd can find them:
podman exec -u root ejabberd cp -r /opt/ejabberd/temp/_build/dev/rel/deps/lib /opt/ejabberd-24.02

Now hopefully, when you install and attempt to compile your ejabberd module, the dependencies will be available there.

Now let's see if this works for your module.