kaizendorks / pymongo_inmemory

A mongo mocking library with an ephemeral MongoDB running in memory.
MIT License
39 stars 13 forks source link

pymongo_inmemory does not work in a docker container when /tmp directory is mounted. No bypass available. #87

Closed sig-piskule closed 11 months ago

sig-piskule commented 1 year ago

Describe the bug I have a complicated CLI docker container that I share with my developers. In it, I have created a kubernetes plugin, kubectl query which allows us to load internal data into an in-memory and search it. It works great and as expected when running on MacOS.

When packaged and launched our docker container, we mount the /tmp directory as a method of porting data inbetween the Mac and the Ubuntu container. This allows us to easily transfer our scratch data between the OS in Ubuntu and Mac. This is often used for other kubectl plugins that we have written.

The fact that we are mounting the /tmp directory is not playing well with pymongo_inmemory. I have discovered that if we opt not to mount the /tmp directory, then pymongo_inmemory correctly starts. Only when we mount the /tmp directory, does pymongo_inmemory fail to connect. This is reproducible with the code below.

I have attempted furthermore to bypass this issue by setting the TMPDIR, TEMP, and TMP directories, so that the tempfile package ignores the volume mounting. However, I am still exhibiting this problem.

To Reproduce Steps to reproduce the behavior:

  1. Create a Dockerfile:
    FROM ubuntu:20.04
    RUN apt-get update && apt-get -y install \
    bash \
    bash-completion \
    bash-doc \
    python3 \
    python3-dev \
    python3-pip
    RUN pip3 install --upgrade pymongo_inmemory==0.3.0
    RUN echo '\n\
    from pymongo_inmemory import MongoClient \n\
    client = MongoClient() \n\
    db = client["testdb"] \n\
    collection = db["test-collection"] \n\
    # etc., etc. \n\
    client.close() \n'\
    > /query.py
    CMD /bin/bash
  2. Build Dockerfile
    docker build ./ -t temp --platform=linux/x86_64
  3. Run Docker file, everything will be OK:
    docker run --platform=linux/x86_64 -it temp python3 query.py
  4. Run Docker file, override mount, this will fail:
    docker run -v /tmp:/tmp --platform=linux/x86_64 -it temp python3 query.py
  5. Attempt patching with different tempdir, Run Docker file, override mount, this will fail:
    docker run -e TMPDIR=/pytemp -v /tmp:/tmp  --platform=linux/x86_64 -it temp python3 query.py

    Full Error

    $ docker run -e TMPDIR=/pytemp -v /tmp:/tmp  --platform=linux/x86_64 -it temp python3 query.py
    Starting from MongoDB 4.0.23 there isn't a generic Linux version of MongoDB
    Traceback (most recent call last):
    File "query.py", line 3, in <module>
    client = MongoClient() 
    File "/usr/local/lib/python3.8/dist-packages/pymongo_inmemory/_pim.py", line 11, in __init__
    self._mongod.start()
    File "/usr/local/lib/python3.8/dist-packages/pymongo_inmemory/mongod.py", line 130, in start
    while not self.is_healthy:
    File "/usr/local/lib/python3.8/dist-packages/pymongo_inmemory/mongod.py", line 164, in is_healthy
    status = db.command("serverStatus")
    File "/usr/local/lib/python3.8/dist-packages/pymongo/_csot.py", line 108, in csot_wrapper
    return func(self, *args, **kwargs)
    File "/usr/local/lib/python3.8/dist-packages/pymongo/database.py", line 892, in command
    with self.__client._conn_for_reads(read_preference, session) as (
    File "/usr/local/lib/python3.8/dist-packages/pymongo/mongo_client.py", line 1340, in _conn_for_reads
    server = self._select_server(read_preference, session)
    File "/usr/local/lib/python3.8/dist-packages/pymongo/mongo_client.py", line 1297, in _select_server
    server = topology.select_server(server_selector)
    File "/usr/local/lib/python3.8/dist-packages/pymongo/topology.py", line 312, in select_server
    server = self._select_server(selector, server_selection_timeout, address)
    File "/usr/local/lib/python3.8/dist-packages/pymongo/topology.py", line 296, in _select_server
    servers = self.select_servers(selector, server_selection_timeout, address)
    File "/usr/local/lib/python3.8/dist-packages/pymongo/topology.py", line 247, in select_servers
    server_descriptions = self._select_servers_loop(selector, server_timeout, address)
    File "/usr/local/lib/python3.8/dist-packages/pymongo/topology.py", line 269, in _select_servers_loop
    raise ServerSelectionTimeoutError(
    pymongo.errors.ServerSelectionTimeoutError: 127.0.0.1:27017: [Errno 111] Connection refused, Timeout: 30s, Topology Description: <TopologyDescription id: 650b42c35fed3c72b372d834, topology_type: Unknown, servers: [<ServerDescription ('127.0.0.1', 27017) server_type: Unknown, rtt: None, error=AutoReconnect('127.0.0.1:27017: [Errno 111] Connection refused')>]>

Expected behavior I was expecting successful startup of Mongo DB:

$ docker run --platform=linux/x86_64 -it temp python3 query.py
Starting from MongoDB 4.0.23 there isn't a generic Linux version of MongoDB

In the event that MongoDB can't share the /tmp directory with MacOS, I was expecting TMPDIR to get the system working. NOTE: pymongo_inmemory is respecting the TMPDIR environment variable, it just isn't starting Mongodb, and I'm not sure why.

Logs See above error.

Screenshots N/A

Context:

Workarounds instead of direct fixes are acceptable to me.

sig-piskule commented 1 year ago

Partial resolution discovered by switching Docker Desktop to use gRPC Fuse under General -> Choose file sharing implementation for your containers.

ekarademir commented 1 year ago

Yes, currently there is no way to overwrite the db path for the mongod instance created, and we assign a temporary folder. We can add that option.