Community.routeros.api_modify: add support for containers

Hello everybody :slight_smile:

I am currently in the process of writing support for the container feature in routeros for the community.routeros.api_modify module.

Implementing /container/envs, /container/mounts and /container/config was rather trivial. My fork contains the changes.

Now I’ve got two problems when trying to support the /container path itself.

problem #1: uncertain primary key situation

The primary key for an container entry is the name field.
Unfortunately this field contains an automatically generated uuid that cannot be altered:

[admin@sax-hts1-gw-core01] /container> add remote-image=alpine:latest interface=container_test 
[admin@sax-hts1-gw-core01] /container> print detail 
 0 name="37ab9172-31eb-4fb2-ad55-414f4047a597" tag="alpine:latest" os="" arch="" interface=container_test mounts="" dns="" status=extracting 
[admin@sax-hts1-gw-core01] /container> set name=hello 0

My code for handling this endpoint is this:

    ('container', ): APIData(
        versioned=[
            # available since 7.4beta4
            ('7.4', '>', VersionedAPIData(
                fully_understood=True,
                fields={
[...]
                    'name': KeyInfo(read_only=True),
[...]
                },
            )),
        ],
    ),

I explicitly did not define a primary_key. This seems to work fine with:

     handle_absent_entries: remove
     handle_entries_content: remove_as_much_as_possible

but I am not sure if this is the correct way.

problem #2: remote-image | file -> tag

When creating or manipulating an container one can set the image for it via remote-image (if the image should be pulled from a registry) or via file (if the image is a local .tar archive).

Whichever method is chosen afterwords the resolved image tag will be written into the read only attribute tag (as seen in the routeros cli example above).

The problem with this behaviour is that community.routeros.api_modify does not know that remote-tag (or file) sets tag and is therefore unable to detect changes.
I have already tried to mark tag as automatically_computed_by="remote-image" but that did not do the trick.
This is the relevant code snippet:

    ('container', ): APIData(
        versioned=[
            # available since 7.4beta4
            ('7.4', '>', VersionedAPIData(
                fully_understood=True,
                fields={
[...]
                    'file': KeyInfo(write_only=True),
[...]
                    'remote-image': KeyInfo(write_only=True),
[...]
                    'tag': KeyInfo(read_only=True, automatically_computed_from='remote-image'),
[...]
                },
            )),
        ],
    ),

Could someone help me figure out how to correctly implement the container support for community.routeros.api_modify ?

I only found @felixfontein on the forums therefore you are the only maintainer I am tagging in the post.

Thanks you all so much for reading ! :slight_smile:

For your problem #1, not using a primary key and marking name as read-only looks like the best way forward.

For #2, automatically_computed_from currently doesn’t really do something at the moment (see for example Correction and Bugfix for ip dhcp-server network by phox142 · Pull Request #156 · ansible-collections/community.routeros · GitHub).

I’m currently wondering whether supporting container with the existing api_modify module is a good idea, since that path seems to be pretty “special”. Maybe a more specialized module is needed for it? Or some more specific logic for paths like that (are there others?)?

Thank you for your response @felixfontein ! :slight_smile:

Ok so #1 is a non issue that’s nice.

I’m currently wondering whether supporting container with the existing api_modify module is a good idea, since that path seems to be pretty “special”. Maybe a more specialized module is needed for it? Or some more specific logic for paths like that (are there others?)?

I have no idea if there are other paths besides /container that behave “funny”. In my two year routeros experience I did not encountered anything like that but that obviously is not a conclusive answer.

Supporting remote-image is feasible - file is way more complicated/impossible?

We only need to teach api_modify that remote-image is write_only and sets tag implicitly. Therefore when remote-image does not match tag we have a CHANGE.

If the users sets remote-image to the correct long-name of an image this should work perfectly well. So if remote-image is library/alpine:latest tag will also be library/alpine:latest. Changing remote-image will then trigger the change on the device.
Under this assumption a user setting remote-image to alpine:latest will have a bad time because the resulting tag will be library/alpine:latest therefore always registering a change. We could note this in the module documentation.

Handling file seems to be impossible though.
The container engine in routeros needs to extract the image file to resolve the image name (aka tag). Therefore we have no way of telling api_modify that superdopeimage.tar is actually alpine:latest underneath. We would need to parse the image ourselfs to check if there is a change and that introduces a whole new class of problems.


Long story short: I would like to support container with remote-image in api_modify. And either explicitly not supporting file or supporting it without CHANGE detection.

I am more or less confident that I could build a special case in api_modify for that. On the other hand I am pretty certain that building a whole new module for this is out of my comfort zone.

Do I have your blessing for trying to introduce a new field in KeyInfo()/APIData() which represents this construct ?

Thank you so much and have a nice weekend @felixfontein ! :slight_smile:

It sounds to me like automatically_computed_by would be a good fit here, in a properly implemented way (that doesn’t exist yet). And for remote-image, a new option create_only=True (similar, but not identical to write_only) probably makes sense?

In any case, feel free to propose how this could be implemented, I’ll happily look at proposals / PRs.