Dynamically define slot content

Hi,

I want to make a certain file available to another snap-instance. I’ve manager to «connect» them together with slots and plugs, and they can read/write to the given directory.

However, I don’t want the consumer to have access to every file within that location, but only one or more predefined files.

I know that I can use hooks to do some magic when the app connects, but I don’t know what. And I don’t know if it’s even possible.

The file is only supposed to be visible to this instance. If another instance connects, then there should be a totally different file. It can be a copy, but not the same.

Anyone that can help me off. I’ve tried searching around, but without luck.

Is it possible?

This is doable if you switch the roles between the producer snap that wants to share private files with individual snaps, where the producer snap uses a plug and the consumer snaps all use slots. You would have snap.yaml’s (simplified) like this:

producer:

plugs:
  mailbox:
    interface: content
    # put our mail in $SNAP_DATA so it is writable
    target: $SNAP_DATA/mailbox

all consumers:

slots:
  mailbox:
    interface: content
    # put our mail in $SNAP_DATA so it is writable
    write: 
     - $SNAP_DATA/mailbox

What happens then is that the first connection from producer to say consumer-xyz will use the $SNAP_DATA/mailbox dir and the next connection from producer to consumer-123 will use the $SNAP_DATA/mailbox-1 dir and the next connection will use $SNAP_DATA/mailbox-2, etc.

If you need the consumer snaps to provide some kind of data to the producer, you can use interface hooks for this, either by setting attributes on the plug/slot side with snapctl or just by having a prepare-slot-* hook drop files into the mailbox dir (from the consumer side) and then the connect-plug-* hook read those files (from the producer side).

Ah - I want to say - of course - but it wasn’t obvious to me. However, it makes more sense doing it the other way around as you suggest. Thank you so much.

I’m trying to find a way for the two instances to determine the name of the connecting app. It’s not for security, but rather just a way of keeping track of where the apps that have connected.

Lets say that app.a (holding the slot) is connecting with app.b (offering the plug). On connection will app.b use the connect-plug-hook to add to it’s log that app.a got the file x in its writable directory.

Do you by any chance know how I could do this? :slight_smile:

If the only information you need to exchange is the name of the snap, you can have the consumer snap, in your case it sounds like that would be app.a, in it’s prepare-slot-<slot-name> hook do something like:

#!/bin/bash
snapctl set :<plugname> snapname=$SNAP_NAME 

and then in the app.b snap, producing files for the consumer, the connect-plug-<plug-name> do something like this:

#!/bin/bash
OTHER_SNAP_NAME=$(snapctl get --plug :<slotname> snapname)
# do something with $OTHER_SNAP_NAME in $SNAP_DATA/mailbox etc.

It’s a little confusing for your use case since the order of the interface that hooks is backwards from what you would want but your use case should still be doable.

Ah. Thanks! I’m getting an error though.

FILE: prepare-slot-test

#!/usr/bin/env bash
snapctl set :test snapname="${SNAP_NAME}"

FILE: connect-plug-test

#!/usr/bin/env bash
CONNECTED_SNAP=`snapctl get --plug :test snapname`
echo "${CONNECTED_SNAP}"

Error:

 (run hook "connect-plug-test": 
-----
error: error running snapctl: no "snapname" attribute

Not sure why, as I can se in the journal that prepare is executed before connect.

EDIT: I had to use --slot and not --plug. Thank you so much! :slight_smile:

1 Like