Modulemd

Modulemd — User's Guide for libmodulemd

Stability Level

Stable, unless otherwise indicated

Functions

Description

Working with repodata (DNF use-case)

The libmodulemd API provides a number of convenience tools for interacting with repodata (that is, streams of YAML that contains information on multiple streams, default data and translations). The documentation will use two repositories, called "fedora" and "updates" for demonstrative purposes. It will assume that the content of the YAML module metadata from those two repositories have been loaded into string variables fedora_yaml and updates_yaml, respectively.

Tools such as DNF that are consuming data from a repository should always set strict=False, so that it can safely handle minor, backwards-compatible changes to the modulemd format.

First step is to load the metadata from these two repositories into ModulemdModuleIndex objects. This is done as follows:

In C:

1
2
3
4
5
6
7
ModulemdModuleIndex *fedora_index = modulemd_module_index_new ();
gboolean ret = modulemd_module_index_update_from_string (
  fedora_index, fedora_yaml, FALSE, &failures, &error);

ModulemdModuleIndex *updates_index = modulemd_module_index_new ();
gboolean ret2 = modulemd_module_index_update_from_string (
  updates_index, updates_yaml, FALSE, &failures, &error);

In Python:

1
2
3
4
5
fedora_index = Modulemd.ModuleIndex.new()
ret, failures = fedora_index.update_from_string(fedora_yaml, False)

updates_index = Modulemd.ModuleIndex.new()
ret, failures = updates_index.update_from_string(updates_yaml, False)

The failures are a list of subdocuments in the YAML that failed parsing, along with the reason they failed. Hence, by checking the return value of failures we will know if the YAML parsing was successful or not.

Since it doesn't really make sense to view the contents from separate repositories in isolation (in most cases), the next step is to merge the two indexes into a combined one:

In C:

1
2
3
4
5
6
7
ModulemdModuleIndexMerger *merger = modulemd_module_index_merger_new ();

modulemd_module_index_merger_associate_index (merger, fedora_index, 0);
modulemd_module_index_merger_associate_index (merger, updates_index, 0);

ModulemdModuleIndex *merged_index =
  modulemd_module_index_merger_resolve (merger, &error);

In Python:

1
2
3
4
5
6
merger = Modulemd.ModuleIndexMerger.new()

merger.associate_index(fedora_index, 0)
merger.associate_index(updates_index, 0)

merged_index = merger.resolve()

At this point, you now have either a complete view of the merged repodata, or else have received an error describing why the merge was unable to complete successfully. Additionally, it should be noted that the combined metadata in any ModulemdModuleIndex will have all of its component parts upgraded to match the highest version of those objects seen. So for example if the repodata has a mix of v1 and v2 ModulemdModuleStream objects, the index will contain only v2 objects (with the v1 objects automatically upgraded internally).

Now, we can start operating on the retrieved data. This guide will give only a brief overview of the most common operations. See the API specification for a full list of information that can be retrieved.

Discover the default stream for a particular module.

In C:

1
2
3
4
5
6
7
8
9
ModulemdModule *module =
  modulemd_module_index_get_module (merged_index, "modulename");
ModulemdDefaults *defaults = modulemd_module_get_defaults (module);
if (defaults)
  {
    printf ("Default stream for modulename is %s\n",
            modulemd_defaults_v1_get_default_stream (
              MODULEMD_DEFAULTS_V1 (defaults), NULL));
  }

In Python:

1
2
3
module = merged_index.get_module("modulename")
defaults = module.get_defaults()
print("Default stream for modulename is %s" % defaults.get_default_stream())

Get the list of RPMs defining the public API for a particular module NSVCA

First, query the ModulemdModuleIndex for the module with a given name.

In C:

1
2
ModulemdModule *module =
  modulemd_module_index_get_module (merged_index, "modulename");

In Python:

1
module = merged_index.get_module("modulename")

Then, query the ModulemdModule for the ModulemdModuleStream associated with the provided NSVCA (name-stream-version-context-architecture identifier).

In C:

1
2
ModulemdModuleStream *stream = modulemd_module_get_stream_by_NSVCA (
  module, "modulestream", 0, "deadbeef", "coolarch", &error);

In Python:

1
stream = module.get_stream_by_NSVCA("modulestream", 0, "deadbeef", "coolarch")

Lastly, read the RPM API from the ModulemdModuleStream. Here, api_list is a list of strings containing package names.

In C:

1
2
GStrv api_list = modulemd_module_stream_v2_get_rpm_api_as_strv (
  MODULEMD_MODULE_STREAM_V2 (stream));

In Python:

1
api_list = stream.get_rpm_api()

Also note that in addition to accessor API methods, many objects also have properties that can be accessed directly.

In C:

1
2
3
4
5
6
printf ("Documentation for module stream is at %s\n",
        modulemd_module_stream_v2_get_documentation (
          MODULEMD_MODULE_STREAM_V2 (stream)));
g_autofree gchar *doc;
g_object_get (MODULEMD_MODULE_STREAM_V2 (stream), "documentation", &doc, NULL);
printf ("Documentation for module stream is at %s\n", doc);

In Python:

1
2
print("Documentation for module stream is at %s" % stream.get_documentation())
print("Documentation for module stream is at %s" % stream.props.documentation)

Retrieve the modular runtime dependencies for a particular module NSVCA

In C:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
ModulemdModule *module =
  modulemd_module_index_get_module (merged_index, "modulename");
ModulemdModuleStream *stream = modulemd_module_get_stream_by_NSVCA (
  module, "modulestream", 0, "deadbeef", "coolarch", &error);
GPtrArray *deps_list = modulemd_module_stream_v2_get_dependencies (
  MODULEMD_MODULE_STREAM_V2 (stream));

for (gint i = 0; i < deps_list->len; i++)
  {
    GStrv depmodules_list =
     modulemd_dependencies_get_runtime_modules_as_strv (
       g_ptr_array_index (deps_list, i));

    for (gint j = 0; j < g_strv_length (depmodules_list); j++)
      {
        GStrv depstreams_list =
          modulemd_dependencies_get_runtime_streams_as_strv (
            g_ptr_array_index (deps_list, i), depmodules_list[j]);

        for (gint k = 0; k < g_strv_length (depstreams_list); k++)
          {
            // do stuff with depmodules_list[j], depstreams_list[k]
          }
      }
  }

In Python:

1
2
3
4
5
6
7
8
9
module = merged_index.get_module("modulename")
stream = module.get_stream_by_NSVCA("modulestream", 0, "deadbeef", "coolarch")
deps_list = stream.get_dependencies()
for dep in deps_list:
    depmodules_list = dep.get_runtime_modules()
    for depmod in depmodules_list:
        depstream_list = dep.get_runtime_streams(depmod)
        for depstream in depstream_list:
            # do stuff with depmod, depstream


Working with a single module stream (Packager/MBS use-case)

One limitation of the ModulemdModuleIndex format is that it requires that all module streams loaded into it have both a name and a stream name. This however is not possible when dealing with streams such as a packager would be using (since the build-system auto-generates the module name and stream name from the git repository information. In this case, we need to work with a single module stream document at a time. For this, we will use the ModulemdModuleStream interface.

This example will assume that the module name and stream name have already been determined from the repodata and that they are stored in string variables named module_name and stream_name, respectively.

In Python:

1
2
3
4
5
stream = Modulemd.ModuleStream.read_file(
    "/path/to/module_name.yaml", True, module_name, stream_name
)
v2_stream = stream.upgrade(Modulemd.ModuleStreamVersionEnum.TWO)
v2_stream.validate()

In the example above, we upgraded the stream to v2, in case we were reading from v1 metadata. This will allow us to avoid having to manage multiple code-paths and support only the latest we understand. After that, it calls validate() to ensure that the content that was read in was valid both syntactically and referentially.

Also available is Modulemd.ModuleStreamVersionEnum.LATEST which will always represent the highest-supported version of the ModulemdModuleStream metadata format. This may change at any time.

Functions

modulemd_get_version ()

const gchar *
modulemd_get_version (void);

Returns

A string describing the version of libmodulemd.

[transfer none]

Since: 2.0


modulemd_load_file ()

ModulemdModuleIndex *
modulemd_load_file (const gchar *yaml_file,
                    GError **error);

This is a convenience function that is a wrapper around modulemd_module_index_new() and modulemd_module_index_update_from_file() with strict=False.

It will return the imported module metadata if all subdocuments are parseable and valid. If any part of the document is unreadable or fails validation, it will return NULL and set error appropriately. If you need more detail about which parts of the document failed, use the lower-level functions.

Parameters

yaml_file

A YAML file containing the module metadata and other related information such as default streams.

[in]

error

A GError containing additional information if this function fails in a way that prevents program continuation.

[out]

Returns

A newly-allocated ModulemdModuleIndex object initialized with the content from yaml_file . Returns NULL and sets error if the file is not completely valid.

[transfer full]

Since: 2.10


modulemd_load_string ()

ModulemdModuleIndex *
modulemd_load_string (const gchar *yaml_string,
                      GError **error);

This is a convenience function that is a wrapper around modulemd_module_index_new() and modulemd_module_index_update_from_string() with strict=False.

It will return the imported module metadata if all subdocuments are parseable and valid. If any part of the document is unreadable or fails validation, it will return NULL and set error appropriately. If you need more detail about which parts of the document failed, use the lower-level functions.

Parameters

yaml_string

A YAML string containing the module metadata and other related information such as default streams.

[in]

error

A GError containing additional information if this function fails in a way that prevents program continuation.

[out]

Returns

A newly-allocated ModulemdModuleIndex object initialized with the content from yaml_string . Returns NULL and sets error if the metadata is not completely valid.

[transfer full]

Since: 2.10


modulemd_read_packager_file ()

GType
modulemd_read_packager_file (const gchar *yaml_path,
                             GObject **object,
                             GError **error);

[skip]

Parameters

yaml_path

A path to a YAML file containing a packager document.

[in]

object

(transfer full): A newly allocated ModulemdModuleStreamV2 or ModulemdPackagerV3 object initialized with the content from yaml_path .

[out]

error

A GError containing additional information if this function fails in a way that prevents program continuation.

[out]

Returns

MODULEMD_TYPE_MODULE_STREAM_V2 , MODULEMD_TYPE_PACKAGER_V3 , or G_TYPE_INVALID . Returns the matching GObject through the object parameter. If the return value is G_TYPE_INVALID , returns the reason as error .

Since: 2.11


modulemd_read_packager_file_ext ()

GType
modulemd_read_packager_file_ext (const gchar *yaml_path,
                                 GObject **object,
                                 const gchar *module_name,
                                 const gchar *module_stream,
                                 GError **error);

[rename-to modulemd_read_packager_file]

Parameters

yaml_path

A path to a YAML file containing a packager document.

[in]

object

(transfer full): A newly allocated ModulemdModuleStreamV2 or ModulemdPackagerV3 object initialized with the content from yaml_path .

[out]

module_name

An optional module name to override the document on disk. Mostly useful in cases where the name is being auto-detected from git.

[in][nullable]

module_stream

An optional module stream name to override the document on disk. Mostly useful in cases where the name is being auto-detected from git.

[in][nullable]

error

A GError containing additional information if this function fails in a way that prevents program continuation.

[out]

Returns

MODULEMD_TYPE_MODULE_STREAM_V2 , MODULEMD_TYPE_PACKAGER_V3 , or G_TYPE_INVALID . Returns the matching GObject through the object parameter. If the return value is G_TYPE_INVALID , returns the reason as error .

Since: 2.11


modulemd_read_packager_string ()

GType
modulemd_read_packager_string (const gchar *yaml_string,
                               GObject **object,
                               GError **error);

[skip]

Parameters

yaml_string

A YAML string containing a packager document.

[in]

object

(transfer full): A newly allocated ModulemdModuleStreamV2 or ModulemdPackagerV3 object initialized with the content from yaml_string .

[out]

error

A GError containing additional information if this function fails in a way that prevents program continuation.

[out]

Returns

MODULEMD_TYPE_MODULE_STREAM_V2 , MODULEMD_TYPE_PACKAGER_V3 , or G_TYPE_INVALID . Returns the matching GObject through the object parameter. If the return value is G_TYPE_INVALID , returns the reason as error .

Since: 2.11


modulemd_read_packager_string_ext ()

GType
modulemd_read_packager_string_ext (const gchar *yaml_string,
                                   GObject **object,
                                   const gchar *module_name,
                                   const gchar *module_stream,
                                   GError **error);

[rename-to modulemd_read_packager_string]

Parameters

yaml_string

A YAML string containing a packager document.

[in]

object

(transfer full): A newly allocated ModulemdModuleStreamV2 or ModulemdPackagerV3 object initialized with the content from yaml_string .

[out]

module_name

An optional module name to override the document on disk. Mostly useful in cases where the name is being auto-detected from git.

[in][nullable]

module_stream

An optional module stream name to override the document on disk. Mostly useful in cases where the name is being auto-detected from git.

[in][nullable]

error

A GError containing additional information if this function fails in a way that prevents program continuation.

[out]

Returns

MODULEMD_TYPE_MODULE_STREAM_V2 , MODULEMD_TYPE_PACKAGER_V3 , or G_TYPE_INVALID . Returns the matching GObject through the object parameter. If the return value is G_TYPE_INVALID , returns the reason as error .

Since: 2.11