Skip to content
Henne Vogelsang edited this page Sep 19, 2023 · 37 revisions

This is developer documentation about the different types of "links" that exist in the OBS

Interconnect Links

The OBS instance to OBS instance link. If a Project has the attribute remoteurl it acts as an read only interface to the OBS API behind this URL.

Example:

[1] pry(main)> Project.find_by(name: 'openSUSE.org').remoteurl
=> "https://api.opensuse.org/public"

The backend supports reading from such interconnects by using the sub-project syntax (project:sub-project). So in the example above openSUSE.org:home:hennevogel will fetch the data from project home:hennevogel on the remote OBS instance. Those "projects" are often called remote-projects.

Pitfalls

Spotty Support

The support in the frontend for remote-projects is spotty. Some features, workflows etc. will simply not work for them. Most prominent: You can not view them in the UI.

Instantiation returns string

If you try to instantiate a Project from an interconnect you will get a string and not an Project object... 🤯

[1] pry(main)> Project.get_by_name('home:Admin').class.name
=> "Project"
[2] pry(main)> Project.get_by_name('openSUSE.org:home:hennevogel').class.name
Found local project openSUSE.org for home:hennevogel with remoteurl https://api.opensuse.org/public
=> "String"

Remote vs. Sub-Project

You can create sub-projects of interconnect links which will supersede the remote projects. This will turn those into "real" projects so you can have a mixture of local and remote projects below an interconnect-link.

[1] pry(main)> Project.get_by_name('openSUSE.org:home').class.name
=> "String"
[2] pry(main)> Project.get_by_name('openSUSE.org:home:hennevogel').class.name
=> "Project"
[3] pry(main)> Project.get_by_name('openSUSE.org:home:dmarcoux').class.name
=> "String"

Remote projects are not checked for existence

[1] pry(main)> Project.get_by_name('openSUSE.org:I:dont:exist')
Found local project openSUSE.org for I:dont:exist with remoteurl https://api.opensuse.org/public
=> "openSUSE.org:I:dont:exist"

SCM Bridge Links

The OBS instance to SCM instance link. If a Project has the attribute scmsync it acts as an read only interface to the SCM API behind this URL.

Pitfalls

Spotty Support

The support in the frontend for scmsync-projects is spotty. Some features, workflows etc. will simply not work for them. Most prominent: You can not view their packages in the UI.

Project Links

The OBS project to OBS project links. A project-link is a Project that has a LinkedProject associated. This association points to the project this Project gets its packages from.

Pitfalls

"Wrong" Project Association

Instantiating a Package will follow project-links by default. That means that the Package object you get might have a different Project associated with it than the project name you used for instantiation... 🤯

[1] pry(main)> Package.get_by_project_and_name('openSUSE:Factory:Staging:O', 'aaa_base').project.name
=> "openSUSE:Factory:Rings:0-Bootstrap"

Links to Remote

The LinkedProject association can point to an local Project object or to a String (see interconnect link)

Instantiating returns nil

If the LinkedProject association points to a remote-project then instantiating the package will return nil... 🤯

[1] pry(main)> Package.get_by_project_and_name('home:hennevogel:hans', 'ctris')
=> nil

.position

You can have more than one project link. In this case the order in which packages are searched is defined by the attribute LinkedProject.position.

Local package trumps linked package

If you create a Package inside a Project it will supersede the Package from the project-link.

Package Links

The OBS package sources to OBS package sources link. A package link is a Package that has a PackageKind with the attribute kind: 'link' associated. This association is created as soon as the package has a file called _link in it's sources. Package links get their sources from the package they link to.

Pitfalls

There is no association between the two package objects.

Remote Packages

The package it links to might not be an object on our instance (see interconnect link).

File links are not expanded (followed) by default

A package-link files consist of

The file methods in the Package class (.file_exists?, .dir_hash, .source_file etc.) or the Backend::Api::Sources::Package library do not expand the link by default. So by default you might see way less files 🤯

[1] pry(main)> package.dir_hash['entry']
[backend] GET: /source/OBS:Server:Unstable/loki
request took 0.008485511 0.12403282
=> [{"name"=>"_link", "md5"=>"8b65e30bd8d5c36ed24a5c257a95f3df", "size"=>"455", "mtime"=>"1605175016"},
 {"name"=>"loki.spec", "md5"=>"6ebdd958ddf07f1627e8c7081cf4d846", "size"=>"3940", "mtime"=>"1605179994"}]
[2] pry(main)> package.dir_hash(expand: 1)['entry']
[backend] GET: /source/OBS:Server:Unstable/loki?expand=1
request took 0.013995835 0.138028655
=> [{"name"=>"_service", "md5"=>"27728f1f02b76f4be226255830a4cff7", "size"=>"637", "mtime"=>"1590685613"},
 {"name"=>"_servicedata", "md5"=>"031eea5fced354c42244bf66d771fa6c", "size"=>"416", "mtime"=>"1590685614"},
 {"name"=>"loki-1.5.0.tar.bz2", "md5"=>"24062a7ba6e38134893ee46184ac634c", "size"=>"13800021", "mtime"=>"1590685617"},
 {"name"=>"loki.changes", "md5"=>"524b6c1386619c3594637a81aaf11d74", "size"=>"10377", "mtime"=>"1599060008"},
 {"name"=>"loki.service", "md5"=>"3b47475b173d1f7e4e8bbab8fa61acf6", "size"=>"362", "mtime"=>"1595852625"},
 {"name"=>"loki.spec", "md5"=>"6ebdd958ddf07f1627e8c7081cf4d846", "size"=>"3940", "mtime"=>"1605179994"},
 {"name"=>"promtail.service", "md5"=>"ad7c6466ba96e97156335c358947e439", "size"=>"391", "mtime"=>"1595860828"},
 {"name"=>"sysconfig.loki", "md5"=>"fae3a45b5ceeaba7d33d018fce9289d8", "size"=>"40", "mtime"=>"1570727908"},
 {"name"=>"sysconfig.promtail", "md5"=>"d734bea202951661bb388ee26070f8f6", "size"=>"44", "mtime"=>"1570741476"}]

Multibuild Packages

The OBS Package.name to build description file name link. A Package can have a special file called _multibuild in its sources which turns it into a multibuild-package.

Pitfalls

follow_multibuild

Instantiating a Package with a multibuild flavor doesn't work.

[1] pry(main)> Package.get_by_project_and_name('OBS:Server:Unstable', 'obs-server:obs-api-testsuite-rspec')&.name
=> Package::Errors::UnknownObjectError: Package not found: OBS:Server:Unstable/obs-server:obs-api-testsuite-rspec

But you can pass an option to the instantiation method for this. So depending on how you instantiated the Package object in your feature/workflow/method it works for mulibuild-packages or not... 🤯

[1] pry(main)> Package.get_by_project_and_name('OBS:Server:Unstable', 'obs-server:obs-api-testsuite-rspec', {follow_multibuild: true})&.name
=> "obs-server"

Flavors are not validated for existence 🤯

Package.get_by_project_and_name('OBS:Server:Unstable', 'obs-server:thisflavordoesnotexist', {follow_multibuild: true}).name
=> "obs-server"

Aggregate Packages

All the previous links we talked about are links about the sources of the Package. There are also links about the binaries a Package has produced: aggregates. We only mention this for completeness. They are controlled by the _aggregate file. You can find details about them in the openSUSE wiki.

General Pitfalls

Combinations/Cycles

In general, combine any of the "links" above OR introduce a link cycle (link pointing to link that points back to the link) and it goes

boom

Spotty Support

Also as stated above, not every feature, class or method you will find will support all of the different link types.

Read the source Luke, good luck!

Clone this wiki locally