Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support the CentOS based CoreOS images #503

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
189 changes: 108 additions & 81 deletions pkg/rhcos/rhcos.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,26 @@ import (
"strings"
)

const (
rhelCoreOs = "Red Hat Enterprise Linux CoreOS"
centosStreamCoreOs = "CentOS Stream CoreOS"
)

var (
changeoverTimestamp = 202212000000

serviceScheme = "https"
serviceUrl = "releases-rhcos-art.apps.ocp-virt.prod.psi.redhat.com"

reMdPromotedFrom = regexp.MustCompile("Promoted from (.*):(.*)")

reMdRHCoSDiff = regexp.MustCompile(`\* Red Hat Enterprise Linux CoreOS upgraded from ((\d)(\d+)\.[\w\.\-]+) to ((\d)(\d+)\.[\w\.\-]+)\n`)
reMdRHCoSVersion = regexp.MustCompile(`\* Red Hat Enterprise Linux CoreOS ((\d)(\d+)\.[\w\.\-]+)\n`)

reJsonRHCoSVersion2 = regexp.MustCompile(`((\d)(\d+))\.(\d+)\.(\d+)-(\d+)`)
reMdCentOSCoSDiff = regexp.MustCompile(`\* CentOS Stream CoreOS upgraded from ((\d)(\d+)\.[\w\.\-]+) to ((\d)(\d+)\.[\w\.\-]+)\n`)
reMdCentOSCoSVersion = regexp.MustCompile(`\* CentOS Stream CoreOS ((\d)(\d+)\.[\w\.\-]+)\n`)

reCoreOsVersion = regexp.MustCompile(`((\d)(\d+))\.(\d+)\.(\d+)-(\d+)`)
)

func TransformMarkDownOutput(markdown, fromTag, toTag, architecture, architectureExtension string) (string, error) {
Expand All @@ -43,86 +52,14 @@ func TransformMarkDownOutput(markdown, fromTag, toTag, architecture, architectur
// TODO: As we get more comfortable with these sorts of transformations, we could make them more generic.
// For now, this will have to do.
if m := reMdRHCoSDiff.FindStringSubmatch(markdown); m != nil {
var ok bool
var fromURL, toURL url.URL
var fromStream, toStream string

fromRelease := m[1]
if fromStream, ok = getRHCoSReleaseStream(fromRelease, architectureExtension); ok {
fromURL = url.URL{
Scheme: serviceScheme,
Host: serviceUrl,
Path: "/",
Fragment: fromRelease,
RawQuery: (url.Values{
"stream": []string{fromStream},
"arch": []string{architecture},
"release": []string{fromRelease},
}).Encode(),
}
}

toRelease := m[4]
if toStream, ok = getRHCoSReleaseStream(toRelease, architectureExtension); ok {
toURL = url.URL{
Scheme: serviceScheme,
Host: serviceUrl,
Path: "/",
Fragment: toRelease,
RawQuery: (url.Values{
"stream": []string{toStream},
"arch": []string{architecture},
"release": []string{toRelease},
}).Encode(),
}
}
diffURL := url.URL{
Scheme: serviceScheme,
Host: serviceUrl,
Path: "/diff.html",
RawQuery: (url.Values{
"first_stream": []string{fromStream},
"first_release": []string{fromRelease},
"second_stream": []string{toStream},
"second_release": []string{toRelease},
"arch": []string{architecture},
}).Encode(),
}
replace := fmt.Sprintf(
`* Red Hat Enterprise Linux CoreOS upgraded from [%s](%s) to [%s](%s) ([diff](%s))`+"\n",
fromRelease,
fromURL.String(),
toRelease,
toURL.String(),
diffURL.String(),
)
markdown = strings.ReplaceAll(markdown, m[0], replace)
markdown = transformCoreOSUpgradeLinks(rhelCoreOs, architecture, architectureExtension, markdown, m)
} else if m = reMdCentOSCoSDiff.FindStringSubmatch(markdown); m != nil {
markdown = transformCoreOSUpgradeLinks(centosStreamCoreOs, architecture, architectureExtension, markdown, m)
}
if m := reMdRHCoSVersion.FindStringSubmatch(markdown); m != nil {
var ok bool
var fromURL url.URL
var fromStream string

fromRelease := m[1]
if fromStream, ok = getRHCoSReleaseStream(fromRelease, architectureExtension); ok {
fromURL = url.URL{
Scheme: serviceScheme,
Host: serviceUrl,
Path: "/",
Fragment: fromRelease,
RawQuery: (url.Values{
"stream": []string{fromStream},
"arch": []string{architecture},
"release": []string{fromRelease},
}).Encode(),
}
}
replace := fmt.Sprintf(
`* Red Hat Enterprise Linux CoreOS [%s](%s)`+"\n",
fromRelease,
fromURL.String(),
)
markdown = strings.ReplaceAll(markdown, m[0], replace)
markdown = transformCoreOSLinks(rhelCoreOs, architecture, architectureExtension, markdown, m)
} else if m = reMdCentOSCoSVersion.FindStringSubmatch(markdown); m != nil {
markdown = transformCoreOSLinks(rhelCoreOs, architecture, architectureExtension, markdown, m)
}
return markdown, nil
}
Expand All @@ -136,7 +73,7 @@ func TransformJsonOutput(output, architecture, architectureExtension string) (st

for i, component := range changeLogJson.Components {
switch component.Name {
case "Red Hat Enterprise Linux CoreOS":
case rhelCoreOs, centosStreamCoreOs:
var ok bool
var fromStream, toStream string
if len(component.Version) == 0 {
Expand Down Expand Up @@ -200,7 +137,7 @@ func TransformJsonOutput(output, architecture, architectureExtension string) (st
}

func getRHCoSReleaseStream(version, architectureExtension string) (string, bool) {
if m := reJsonRHCoSVersion2.FindStringSubmatch(version); m != nil {
if m := reCoreOsVersion.FindStringSubmatch(version); m != nil {
ts, err := strconv.Atoi(m[5])
if err != nil {
return "", false
Expand All @@ -211,10 +148,100 @@ func getRHCoSReleaseStream(version, architectureExtension string) (string, bool)
}
switch {
case ts > changeoverTimestamp && minor >= 9:
// TODO: This should hopefully only be temporary...
if m[4] == "92" {
return fmt.Sprintf("prod/streams/%s.%s-9.2", m[2], m[3]), true
}
Comment on lines +151 to +154
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is gross and I hope it's only temporary...
@cgwalters and/or @jlebon Do you either of you know what the long term plan for how the release browser is going to handle new 9.2 CentOS based images?

Copy link
Member

Choose a reason for hiding this comment

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

Ouch. I think we should probably figure out how to have this code have access to more information so it doesn't have to do this kind of guessing. Does it have access to the RHCOS container image labels? We could put the pipeline stream name the build came from in there.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, embedding this information in the container image makes sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This code is the thing nightmares are made of... the information we have is what we're parsing from the output of an oc adm release info --changelog command. 😢

Copy link
Member

Choose a reason for hiding this comment

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

How hard would it be to change that? Can the code do another call to e.g. skopeo on the RHCOS image? Can the oc adm release info output be augmented to also output labels of the referred images?

OK, I see --includes-images which does work but it's super expensive because it's querying the metadata for all the images. Maybe simplest is to add an --include-image so then it can do --include-image rhel-coreos to only add the info for that one?

I also see annotations in the default output like this:

        {
          "name": "rhel-coreos-8",
          "annotations": {
            "io.openshift.build.commit.id": "",
            "io.openshift.build.commit.ref": "",
            "io.openshift.build.source-location": ""
          },
          "from": {
            "kind": "DockerImage",
            "name": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:65f00f7a151a6a393f2d12a504f5ae14e1e7a249a35db23b0d053466d6469cad"
          },
          "generation": null,
          "importPolicy": {},
          "referencePolicy": {
            "type": ""
          }
        },

Not sure how those get there. They should be filled with info from https://github.com/openshift/os, but maybe we can also enhance it so it includes additional annotations.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We could certainly add some logic to extract the information if/when it exists. Something like this should be sufficient and not too time consuming:

$ oc adm release info --image-for=rhel-coreos registry.ci.openshift.org/ocp/release:4.14.0-0.nightly-2023-03-08-194110
quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:cd299b2bf3cc98fb70907f152b4281633064fe33527b5d6a42ddc418ff00eec1
$ oc image info quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:cd299b2bf3cc98fb70907f152b4281633064fe33527b5d6a42ddc418ff00eec1

Copy link
Member

Choose a reason for hiding this comment

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

return fmt.Sprintf("prod/streams/%s.%s", m[2], m[3]), true
default:
return fmt.Sprintf("releases/rhcos-%s.%s%s", m[2], m[3], architectureExtension), true
}
}
return "", false
}

func transformCoreOSUpgradeLinks(name, architecture, architectureExtension, input string, matches []string) string {
var ok bool
var fromURL, toURL url.URL
var fromStream, toStream string

fromRelease := matches[1]
if fromStream, ok = getRHCoSReleaseStream(fromRelease, architectureExtension); ok {
fromURL = url.URL{
Scheme: serviceScheme,
Host: serviceUrl,
Path: "/",
Fragment: fromRelease,
RawQuery: (url.Values{
"stream": []string{fromStream},
"arch": []string{architecture},
"release": []string{fromRelease},
}).Encode(),
}
}

toRelease := matches[4]
if toStream, ok = getRHCoSReleaseStream(toRelease, architectureExtension); ok {
toURL = url.URL{
Scheme: serviceScheme,
Host: serviceUrl,
Path: "/",
Fragment: toRelease,
RawQuery: (url.Values{
"stream": []string{toStream},
"arch": []string{architecture},
"release": []string{toRelease},
}).Encode(),
}
}
diffURL := url.URL{
Scheme: serviceScheme,
Host: serviceUrl,
Path: "/diff.html",
RawQuery: (url.Values{
"first_stream": []string{fromStream},
"first_release": []string{fromRelease},
"second_stream": []string{toStream},
"second_release": []string{toRelease},
"arch": []string{architecture},
}).Encode(),
}
replace := fmt.Sprintf(
`* %s upgraded from [%s](%s) to [%s](%s) ([diff](%s))`+"\n",
name,
fromRelease,
fromURL.String(),
toRelease,
toURL.String(),
diffURL.String(),
)
return strings.ReplaceAll(input, matches[0], replace)
}

func transformCoreOSLinks(name, architecture, architectureExtension, input string, matches []string) string {
var ok bool
var fromURL url.URL
var fromStream string

fromRelease := matches[1]
if fromStream, ok = getRHCoSReleaseStream(fromRelease, architectureExtension); ok {
fromURL = url.URL{
Scheme: serviceScheme,
Host: serviceUrl,
Path: "/",
Fragment: fromRelease,
RawQuery: (url.Values{
"stream": []string{fromStream},
"arch": []string{architecture},
"release": []string{fromRelease},
}).Encode(),
}
}
replace := fmt.Sprintf(
`* %s [%s](%s)`+"\n",
name,
fromRelease,
fromURL.String(),
)
return strings.ReplaceAll(input, matches[0], replace)
}