Skip to content

v1: add immutable distributions endpoint (HMS-9269)#1775

Open
ksiekl wants to merge 1 commit intoosbuild:mainfrom
ksiekl:image-mode
Open

v1: add immutable distributions endpoint (HMS-9269)#1775
ksiekl wants to merge 1 commit intoosbuild:mainfrom
ksiekl:image-mode

Conversation

@ksiekl
Copy link
Contributor

@ksiekl ksiekl commented Mar 10, 2026

  • New endpoint GET /api/image-builder/v1/distributions?kind=bootc returns the list of immutable distributions (id, name, type, image) for the UI dropdown in Image mode
  • Immutable list is read from a JSON file path set by IMMUTABLE_DISTRIBUTIONS_FILE, I added a config/immutable_distributions.json with the structure

@croissanne
Copy link
Member

Why is it a separate endpoint from just /distributions ?

@lzap
Copy link
Collaborator

lzap commented Mar 10, 2026

Why is it a separate endpoint from just /distributions ?

My bad, I assumed this would be a new endpoint. It makes sense to merge it with the existing for sure.

@lzap
Copy link
Collaborator

lzap commented Mar 10, 2026

As a starting point, I think creating just RHEL 10.0 with very limited scope will be the best so we can start developing the UI early and add more combinations later. I now have better idea on how data will be pushed in ECR, we will have dedicated registry just for this purpose and there are no organizations so the resulting URL we will pull from will look like this: 123456789012.dkr.ecr.us-east-1.amazonaws.com/rhel/10.0-ec2 so the path portion will be rhel/10.0-ec2.

Therefore, I propose to shorten the initial configuration to just this:

distributions:
  - id: rhel-10.0-ec2
    name: "Red Hat Enterprise Linux 10.0"
    type: ec2
    image: "rhel/10.0-ec2"
  - id: rhel-10.0-azure
    name: "Red Hat Enterprise Linux 10.0"
    type: azure
    image: "rhel/10.0-azure"
  - id: rhel-10.0-gcp
    name: "Red Hat Enterprise Linux 10.0"
    type: gcp
    image: "rhel/10.0-gcp"
  - id: rhel-10.0-qcow2
    name: "Red Hat Enterprise Linux 10.0"
    type: qcow2
    image: "rhel/10.0-qcow2"

We can add more versions later. @croissanne how do you like such config file?

Copy link
Collaborator

@lzap lzap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall, as I said I think the compose endpoint changes should be a separate PR which we can merge later.

You can keep drafting this as one commit, but going forward it would be really nice if this could be separated into two or more commits.

@ksiekl
Copy link
Contributor Author

ksiekl commented Mar 10, 2026

Just a question to merging with existing distributions - I imagine it could be done through a parameter, like this: GET /distributions?kind=immutable Is that something you guys had in mind?

@croissanne
Copy link
Member

Just a question to merging with existing distributions - I imagine it could be done through a parameter, like this: GET /distributions?kind=immutable Is that something you guys had in mind?

If you just need a list then yea, if you need more details per distro then maybe add something in /distributions/{distro}?

}
if composeRequest.ImageRequests[0].BootcRef != nil && *composeRequest.ImageRequests[0].BootcRef != "" {
entry, _ := common.FindImmutableDistributionByID(h.server.immutableDistributions, *composeRequest.ImageRequests[0].BootcRef)
fullRef := strings.TrimSuffix(h.server.ecrURL, "/") + "/" + strings.TrimPrefix(entry.Image, "/")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we could use https://pkg.go.dev/net/url#URL.JoinPath

@ksiekl
Copy link
Contributor Author

ksiekl commented Mar 10, 2026

Ok ok so I did:

  • merge the endpoint with /distributions (@croissanne I only need the list so I did it through the kind parameter),
  • moved stuff around to the distributions package,
  • used "bootc" instead of "immutable" to keep consistent with the backend,
  • changed the list to JSON format, I think it's better to stay consistent,
  • removed the compose handler change from here altogether (so I think one commit might do @lzap?)

Only one thing remains, and that is Sanne's comment:

Could this become part of the distributions/ folder? Either a file inside of each distribution we want to support or part of the main json somehow?

And honestly, idk. this way we wouldn't have to have another file and config var to maintain, but on the other hand it would made managing new entries for the dropdown kinda tedious since it would be spread throughout multiple other JSON files... Soooo I guess I leave that up to you @lzap @croissanne to decide 😄

@ksiekl ksiekl marked this pull request as ready for review March 11, 2026 09:33
@ksiekl ksiekl requested a review from a team as a code owner March 11, 2026 09:33
@ksiekl ksiekl changed the title v1: add immutable distributions endpoint v1: add immutable distributions endpoint (HMS-9269) Mar 11, 2026
@lzap
Copy link
Collaborator

lzap commented Mar 13, 2026

Could this become part of the distributions/ folder? Either a file inside of each distribution we want to support or part of the main json somehow?

And honestly, idk. this way we wouldn't have to have another file and config var to maintain, but on the other hand it would made managing new entries for the dropdown kinda tedious since it would be spread throughout multiple other JSON files... Soooo I guess I leave that up to you @lzap @croissanne to decide 😄

I think merging this into current distributions JSON makes sense, it is just simply cleaner. That would be something like:

{
  "module_platform_id": "platform:el10",
  "oscap_name": "rhel10",
  "distribution": {
    "name": "rhel-10.1",
    "composer_name": "rhel-10.1",
    "description": "Red Hat Enterprise Linux (RHEL) 10",
    "no_package_list": true
  },
  "x86_64": {
   "bootc": [{
      "id": "rhel-10.0-ec2",
      "type": "ec2",
      "image": "rhel/10.0-ec2"
    },
    ... ]
    
    ...
}

This actually revealed that I forgot about architecture. While those base images are multiarch and we will build both x86_64 and aarm64, the UI user must indicate which architecture do they want. So by putting this under the architecture, this allows is. We can also drop the name since that is already there. Yeah I like this.

Are these JSON files being generated somehow? Will we need to update those generators? @croissanne

Why do we have Fedoras and CentOSes here when the service is RHEL-only?

@ksiekl ksiekl force-pushed the image-mode branch 7 times, most recently from 39d554a to d37658e Compare March 17, 2026 11:46
Copy link
Collaborator

@lzap lzap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks very good, you left architecture out of equation. Also, I suggest to add filtering for less UI code but it is up to you if you want this or not.

Copy link
Contributor

@avitova avitova left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few nitpicks, but could also be me being confused:)

type: string
description: |
Name of the content template. Used when registering the system to Insights.
bootc_ref:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we haven't implemented a compose handler just yet. But having the bootc ref in the image request differs slightly from the way it was implemented in composer. This just means that cockpit and the hosted apis will diverge slightly and it might be trickier to handle this in the frontend, so this is something to keep in mind.

For composer the compose request would look like:

{
  // we omit distribution for bootc compose requests
  // and have a top-level bootc item
  "bootc": {
    "reference": "quay.io/centos-bootc/centos-bootc:stream9"
  },
  "image_request": {
    "architecture": "x86_64",
    "image_type": "aws",
    "repositories": [],
    "upload_options": {
      ...
    }
  }
}

And for ib-crc it would be:

{
  "distribution": "rhel-10",
  "image_requests": [
    {
      "architecture": "x86_64",
      "image_type": "aws",
      "bootc_ref": "rhel-10.0-ec2",
      "upload_request": {
        "type": "aws",
        "options": {
          ...
        }
      }
    }
  ],
  "customizations": {}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed the bootc field to mirror the composer's structure 😄 now it is in the top level of the compose request

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good observation, this is a chance to sync up on the terminology because I made a mistake of referring some fields as "reference" or "boot_ref" but the reality in container world is:

  • quay.io/xxx/yyyy:aaaa: called image reference or ref for short
  • quay.io: called registry (this will be private information on crc)
  • xxx: called organization or namespace (there is none on crc)
  • yyyy: called image name or repository (most likely just rhel)
  • aaaa: called tag (most likely something like 10.1-ec2)

This is just a lot of guesswork, we do not have the crc pipeline yet but I assume it will be something similar to that.

Now, since we do not want to reveal how/where those derived containers are stored, for crc compose request the field should be named something like "bootc_id" or just "id" underneeth "boots" struct. Then the backend can lookup the actual image name and tag part and figure out the complete reference.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now, since we do not want to reveal how/where those derived containers are stored, for crc compose request the field should be named something like "bootc_id" or just "id" underneeth "boots" struct. Then the backend can lookup the actual image name and tag part and figure out the complete reference.

Intentionally changing this though makes it incredibly frustrating to work on the frontend though and adds to the diverging APIs. I am 100% for accuracy and correctness, but then we should either change it in osbuild-composer too. Or wait until we do a v3 api and consolidate everything there. At the moment in the frontend we have to interact with both APIs and it's a massive headache already when there are inconsistencies between the two

Copy link
Contributor

@kingsleyzissou kingsleyzissou Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No maybe it's me that's misunderstood, my bad. So to clarify, is the idea that the user chooses a dropdown for the image they want and we send for example rhel-10.1-ec2 in the request and not the full reference?

If that's the case, I guess this means the APIs will 100% diverge and we will have to handle that differently on-prem

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about this - I've renamed bootc.id to bootc.reference so the field name matches composer's API. This way the frontend sends bootc.reference to both APIs, and cockpit will put in a full container reference and hosted service just the part that we call now image_name. On the ib-crc side, the compose handler (future PR) will validate the reference against the known list of image_name values returned by GET /distributions?kind=bootc, and resolve it to a full container reference before forwarding to composer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd do whatever is in composer currently, I think the benefit of not having diverging APIs is the main thing.

@ksiekl ksiekl force-pushed the image-mode branch 2 times, most recently from 10ec592 to e6a74b7 Compare March 18, 2026 12:54
Copy link
Collaborator

@lzap lzap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few more things. Using existing distributions really helped.

@ksiekl ksiekl force-pushed the image-mode branch 5 times, most recently from a359d1c to 6919504 Compare March 23, 2026 13:47
@lzap
Copy link
Collaborator

lzap commented Mar 23, 2026

@croissanne fyi we talked with @ksiekl and @kingsleyzissou about dropping "id" and using just libcontainer "short name" in bootc-ref. So something like image:tag which will be enforced by the API so registry hostname can be either prepended or configured in short names configuration. Just to keep you in the loop, this will allow for onprem/crc API parity.

@ksiekl ksiekl force-pushed the image-mode branch 2 times, most recently from 468f509 to da78fae Compare March 24, 2026 13:24
@thozza thozza self-requested a review March 25, 2026 11:54
Copy link
Member

@croissanne croissanne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall lgtm, one api tingy and it needs a commit message :)

Copy link
Collaborator

@lzap lzap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the API could be improved a bit and tests might be tabular. Looks good over all! I think this is now ready so you can start working against stage on the UI.

Add bootc image entries in distribution JSON files.
Add BootcDistributionItem schema and edit the general DistributionResponse -
it now returns bootc distributions if the parameter kind=bootc was in the query.
Also possible to filter through them via distro/arch/type parameters in the query.
Add CollectBootcFromRegistry which gathers all the bootc entries.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants