Note: I'm close to splitting the streams into candidate and stable. candidate replaces daily so I'll do the same below.
A SimpleStream is a collection of product streams, each product stream contains a list of products, and each product contains a list of versions. For example the MAAS stream contains three product streams, one for Ubuntu, one for CentOS, and one for bootloaders. Each product stream contains a collection of products such as 14.04, 16.04, 18.04, and 20.04. And each product contains a list of versions which are based on the date (20200720.0, 20200720.1, 20200724.0, etc).
You are creating a new product stream. SimpleStreams expects this to be a collection of products, even if we only have one product now. As such I think the product stream name should be "com.ubuntu.maas:candidate:1:maas-notifications" and the product name should be "com.ubuntu.com.candidate:1:release-notifications". In the future we can add more products for things like feature-deprecation or image removal.
Streams only contain metadata and the only metadata that changes in a stream is the versions. We can try to change that but the stream needs to be readable by older versions of MAAS. I do think the metadata needs to be consistent with content changing in a specific key. This format may work(I didn't test)
{
"content_id": "com.ubuntu.maas:candidate:1:maas-notifications",
"datatype": "notifications",
"format": "products:1.0",
"products": {
"com.ubuntu.com.candidate:1:release-notifications": {
"name": "release-notifications",
"label", "candidate",
"notifications": {
[
{
"maas_version": "< 2.8",
"message": "We\u2019ve released MAAS 2.8. This version supports LXD VM hosts, faster UI and many bug fixes. Find out what\u2019s new in 2.8.\n",
"version": "1.0"
}
]
}
}
}
}
Your challenge is create a format that works now and in the future while not breaking previous versions of MAAS. This may require you to add fields which don't make sense. For example every product defines arch, arches, and os MAAS may assume those values are always available. What you should do is create a format, merge it into the MAAS stream, point a running MAAS at the stream, and verify MAAS can still download images and no errors/exceptions have been raised in the logs. You can do that as follows
1. Create a mirror of our stream
KEYRING_FILE=/usr/share/keyrings/ubuntu-cloudimage-keyring.gpg
IMAGE_SRC=images.maas.io/ephemeral-v3/daily
IMAGE_DIR=$HOME/maas-v3-images
sstream-mirror --keyring=$KEYRING_FILE \
http://images.maas.io/ephemeral-v3/daily $IMAGE_DIR \
'arch=amd64' 'release~(centos70|xenial|bionic|focal)' --max=1 --progress
sstream-mirror --keyring=$KEYRING_FILE \
http://images.maas.io/ephemeral-v3/daily $IMAGE_DIR \
'os~(grub*|pxelinux)' --max=1 --progress
# sstream doesn't grab the unsigned streams
rsync -xavzhP --del --exclude .bzr \
rsync://images.maas.io/maas-images/ephemeral-v3/daily/streams $IMAGE_DIR
2. Create a modifiable copy of the mirror. I use this to save disk space and speed up the copy process
src=$(realpath $IMAGE_DIR)
dest="$HOME/maas-stream-with-notifications"
for file in $(find $src -not -type d); do
dest_file="${dest}/${file:${#src}}"
mkdir -p "$(dirname $dest_file)"
ln -sr "$file" "$dest_file"
done
for file in $src/streams/v1/*; do
# Remove the sym link created above and create a copy we can modify
dest_file="${dest}/${file:${#src}}"
rm "$dest_file"
cp "$file" "$dest_file"
done
3. Create your stream
meph2-util import release-notifications.yaml $HOME/release-notifications.d
4. Merge it into the copied mirror stream
meph2-util merge $HOME/release-notifications.d $HOME/maas-stream-with-notifications
5. Make the stream available over HTTP, I use Python's builtin server for this
cd $HOME/maas-stream-with-notifications
python3 -m http.server 8000
6. Point MAAS at your stream and verify you can add or remove items without causing any errors or exceptions.