Skip to content

Conversation

andfasano
Copy link
Contributor

This patch adds the new InternalReleaseImage CRD. See openshift/enhancements#1821 for additional details

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Sep 29, 2025
@openshift-ci-robot
Copy link

openshift-ci-robot commented Sep 29, 2025

@andfasano: This pull request references AGENT-1330 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.21.0" version, but no target version was set.

In response to this:

This patch adds the new InternalReleaseImage CRD. See openshift/enhancements#1821 for additional details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Sep 29, 2025
Copy link
Contributor

openshift-ci bot commented Sep 29, 2025

Hello @andfasano! Some important instructions when contributing to openshift/api:
API design plays an important part in the user experience of OpenShift and as such API PRs are subject to a high level of scrutiny to ensure they follow our best practices. If you haven't already done so, please review the OpenShift API Conventions and ensure that your proposed changes are compliant. Following these conventions will help expedite the api review process for your PR.

@openshift-ci openshift-ci bot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Sep 29, 2025
Copy link
Contributor

openshift-ci bot commented Sep 29, 2025

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign joelspeed for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@andfasano andfasano force-pushed the add-internalreleaseimage-resource branch from 9ea943a to 9eca225 Compare September 29, 2025 17:19
@andfasano andfasano changed the title [WIP] AGENT-1330: machineconfiguration/v1alpha1: add InternalImageRelease [WIP] AGENT-1330: machineconfiguration/v1alpha1: add InternalReleaseImage Sep 29, 2025
@andfasano andfasano force-pushed the add-internalreleaseimage-resource branch 2 times, most recently from 0d80867 to 7ea433e Compare October 3, 2025 15:32
@andfasano
Copy link
Contributor Author

/retest-required

@JoelSpeed
Copy link
Contributor

I'm currently experimenting with AI for API review, hopefully some of the content it is generating is helpful for you to improve your API

The following code blocks were generated by Claude

⏺ I'll run a comprehensive API review for PR #2510. Let me start by setting up the environment and checking out the PR.

⏺ Bash(CURRENT_BRANCH=$(git branch --show-current); echo "📍 Current branch: $CURRENT_BRANCH"; if ! git diff --quiet || ! git diff --cached --quiet; then echo "❌ ERROR…)
  ⎿  📍 Current branch: agents                           
     ✅ No uncommitted changes detected. Safe to proceed.

⏺ Bash(echo "🔍 Reviewing PR #2510"; echo "🔄 Checking out PR #2510..."; gh pr checkout "2510")
  ⎿  🔍 Reviewing PR #2510                
     🔄 Checking out PR #2510...
     From https://github.com/openshift/api
     … +2 lines (ctrl+o to expand)

⏺ Bash(echo "📁 Analyzing changed files..."; gh pr view "2510" --json files --jq '.files[].path' | grep '\.go$' | grep -E '/(v1|v1alpha1|v1beta1)/')
  ⎿  📁 Analyzing changed files...                              
     machineconfiguration/v1alpha1/register.go
     machineconfiguration/v1alpha1/types_internalreleaseimage.go
     … +2 lines (ctrl+o to expand)

⏺ Bash(echo "⏳ Running linting checks on PR changes..."; make lint)
  ⎿  Error: make: *** [lint] Error 1

     ⏳ Running linting checks on PR changes...
     hack/golangci-lint.sh run --new-from-rev=master 
     Tools vendor version mismatch, removing old utils
     Writing tools vendor version 206d340a14a3ede2d30e25b37757397aacac6799
     go build -mod=vendor -o /Users/jspeed/go/src/github.com/openshift/api/tools/_output/bin/darwin/arm64/golangci-lint ./vendor/github.com/golangci/golangci-lint/v2/cmd/golangci-lint
     go build -mod=vendor -buildmode=plugin -o /Users/jspeed/go/src/github.com/openshift/api/tools/_output/bin/darwin/arm64/kube-api-linter.so ./vendor/sigs.k8s.io/kube-api-linter/pkg/plugin
     ln -fs /Users/jspeed/go/src/github.com/openshift/api/tools/_output/bin/darwin/arm64/kube-api-linter.so /Users/jspeed/go/src/github.com/openshift/api/tools/_output/bin/kube-api-linter.so
     machineconfiguration/v1alpha1/types_internalreleaseimage.go:35:2: requiredfields: field Spec has a valid zero value ({}), but the validation is not complete (e.g. min properties/adding required fields). The field should be a pointer to allow the zero value to be set. If the zero value is not a valid use case, complete the validation and remove the 
     pointer. (kubeapilinter)
     … +7 lines (ctrl+o to see all)

⏺ Now let me analyze the main API file for documentation requirements:

⏺ Read(machineconfiguration/v1alpha1/types_internalreleaseimage.go)
  ⎿  Read 111 lines (ctrl+o to expand)

⏺ Let me also check the PR diff to understand exactly what changed:

⏺ Bash(gh pr diff "2510")
  ⎿  diff --git a/machineconfiguration/v1alpha1/register.go b/machineconfiguration/v1alpha1/register.go
     index c60f521f940..451be959977 100644
     --- a/machineconfiguration/v1alpha1/register.go
     … +601 lines (ctrl+o to expand)

⏺ API Review Report for PR #2510

  ❌ REVIEW FAILED - Issues Found

  The API review has identified several critical issues that must be addressed before this PR can be approved.

  🚨 Linting Errors (CRITICAL)

  The make lint command failed with kubeapilinter errors:

  +35: Spec field validation issue
  Current (problematic) code:
  Spec InternalReleaseImageSpec `json:"spec,omitzero"`

  Suggested change:
  - Spec InternalReleaseImageSpec `json:"spec,omitzero"`
  + Spec *InternalReleaseImageSpec `json:"spec,omitzero"`

  Explanation: The field has a valid zero value ({}) but incomplete validation. Since it's marked as +required, it should be a pointer to allow the zero value to be set, or the validation should be completed to make the zero value invalid.

  +39: Status field validation issue
  Current (problematic) code:
  Status InternalReleaseImageStatus `json:"status"`

  Suggested change:
  - Status InternalReleaseImageStatus `json:"status"`
  + Status *InternalReleaseImageStatus `json:"status"`

  Explanation: The field has a valid zero value ({}) but incomplete validation. Since status subresources typically allow empty initial states, this should be a pointer to allow the zero value to be set.

  📚 Documentation Issues (MODERATE)

  +48: Missing optional field behavior documentation
  Current (problematic) code:
  // conditions represent the observations of an internal release image current state.
  // +listType=map
  // +listMapKey=type
  // +kubebuilder:validation:MaxItems=20
  // +optional
  Conditions []metav1.Condition `json:"conditions,omitempty"`

  Suggested change:
  - // conditions represent the observations of an internal release image current state.
  + // conditions represent the observations of an internal release image current state.
  + // When omitted, the resource has no status conditions to report.

  Explanation: Optional fields must explain what happens when they are omitted. The field comment should state the behavior when the field is not present.

  +57: Missing optional field behavior documentation
  Current (problematic) code:
  // availableReleases is a list of release bundle identifiers currently detected
  // from the attached ISO.
  // +listType=map
  // +listMapKey=name
  // +kubebuilder:validation:MinItems=1
  // +kubebuilder:validation:MaxItems=64
  // +optional
  AvailableReleases []InternalReleaseImageRef `json:"availableReleases,omitempty"`

  Suggested change:
  - // availableReleases is a list of release bundle identifiers currently detected
  - // from the attached ISO.
  + // availableReleases is a list of release bundle identifiers currently detected
  + // from the attached ISO.
  + // When omitted or empty, no release bundles have been detected from the attached ISO.

  Explanation: Optional fields must explain what happens when they are omitted. Also, the validation constraints (MinItems=1, MaxItems=64) should be documented.

  +66: Missing optional field behavior documentation
  Current (problematic) code:
  // releases is a list of the currently managed release bundles.
  // +listType=map
  // +listMapKey=name
  // +kubebuilder:validation:MinItems=1
  // +kubebuilder:validation:MaxItems=64
  // +optional
  Releases []InternalReleaseImageRef `json:"releases,omitempty"`

  Suggested change:
  - // releases is a list of the currently managed release bundles.
  + // releases is a list of the currently managed release bundles.
  + // When omitted or empty, no release bundles are currently being managed.

  Explanation: Optional fields must explain what happens when they are omitted. Also, the validation constraints (MinItems=1, MaxItems=64) should be documented.

  +78: Missing optional field behavior documentation
  Current (problematic) code:
  // releases is a list of release bundle identifiers that the user wants to
  // add/remove to/from the control plane nodes.
  // +optional
  // +kubebuilder:validation:MinItems=1
  // +kubebuilder:validation:MaxItems=20
  // +listType=map
  // +listMapKey=name
  Releases []InternalReleaseImageRef `json:"releases,omitempty"`

  Suggested change:
  - // releases is a list of release bundle identifiers that the user wants to
  - // add/remove to/from the control plane nodes.
  + // releases is a list of release bundle identifiers that the user wants to
  + // add/remove to/from the control plane nodes.
  + // When omitted or empty, no release bundle operations are requested.
  + // Must contain between 1 and 20 items when specified.

  Explanation: Optional fields must explain what happens when they are omitted. The validation constraints (MinItems=1, MaxItems=20) must also be documented in the field comment.

  +93: Missing optional field behavior documentation
  Current (problematic) code:
  // image is an OCP release imaged referenced by digest.
  // The format of the image pull spec is: host[:port][/namespace]/name@sha256:<digest>,
  // where the digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9.
  // The length of the whole spec must be between 1 to 447 characters.
  // +optional
  Image machineosconfig.ImageDigestFormat `json:"image,omitempty"`

  Suggested change:
  - // image is an OCP release imaged referenced by digest.
  - // The format of the image pull spec is: host[:port][/namespace]/name@sha256:<digest>,
  - // where the digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9.
  - // The length of the whole spec must be between 1 to 447 characters.
  + // image is an OCP release imaged referenced by digest.
  + // The format of the image pull spec is: host[:port][/namespace]/name@sha256:<digest>,
  + // where the digest must be 64 characters long, and consist only of lowercase hexadecimal characters, a-f and 0-9.
  + // The length of the whole spec must be between 1 to 447 characters.
  + // When omitted, the release bundle identifier refers to the name only without an associated image.

  Explanation: Optional fields must explain what happens when they are omitted. This field needs to clarify what happens when no image is specified for a release bundle.

  ✅ Positive Findings

  - API Structure: Well-organized with appropriate separation between spec and status
  - Feature Gate: Properly gated behind NoRegistryClusterOperations feature gate
  - Validation Rules: Comprehensive validation using kubebuilder markers and CEL expressions
  - Generated Files: All required generated files (deepcopy, CRDs, swagger docs) are present and properly updated
  - List Support: Proper list type and map key annotations for array fields
  - Compatibility: Correctly marked as compatibility level 4 for alpha API

  📋 Action Required

  1. CRITICAL: Fix the linting errors by addressing the pointer vs value type issues for Spec and Status fields
  2. REQUIRED: Add proper documentation for all optional fields explaining behavior when omitted
  3. RECOMMENDED: Document validation constraints in field comments for better developer experience

  The PR cannot be approved until the critical linting errors are resolved and all optional fields have proper behavior documentation.

I think the linting issues are actually not the response I'd like. Instead lets try and make the zero values not valid (required fields or MinProperties markers. The linter should be prompting you on these already

For the comments, it has highlighted that you haven't explained what happens when the optional fields are omitted, though I'm not sure its suggestions are super helpful, please review and think about what you'd actually like to put in. If it has identified something where you can't think of a reason why it wouldn't be present, then maybe the field should actually be required


Quizzing specifically about whether all validations were documented, some further output

⏺ You're absolutely right. Looking more carefully at the validation markers, I missed several undocumented validation markers:

  Additional Undocumented Validation Markers I Missed:

  +47: MaxItems validation not documented
  // +kubebuilder:validation:MaxItems=20
  The comment doesn't mention the maximum of 20 items for conditions.

  +55-56: MinItems and MaxItems validation not documented
  // +kubebuilder:validation:MinItems=1
  // +kubebuilder:validation:MaxItems=64
  The comment doesn't mention the 1-64 item range for availableReleases.

  +63-64: MinItems and MaxItems validation not documented
  // +kubebuilder:validation:MinItems=1  
  // +kubebuilder:validation:MaxItems=64
  The comment doesn't mention the 1-64 item range for releases in status.

  +84-85: MinLength and MaxLength validation not documented
  // +kubebuilder:validation:MinLength=1
  // +kubebuilder:validation:MaxLength=64
  The comment doesn't mention the 1-64 character length constraints for the name field.

  So no, my original review was incomplete. I identified the optional field behavior issues but missed documenting several validation constraints that should be included in the field comments according to OpenShift API documentation standards.

@andfasano andfasano force-pushed the add-internalreleaseimage-resource branch 2 times, most recently from 7b60a33 to ab6545c Compare October 7, 2025 16:29
@andfasano
Copy link
Contributor Author

/api-review

@andfasano andfasano force-pushed the add-internalreleaseimage-resource branch 3 times, most recently from cf83224 to c2f669c Compare October 10, 2025 15:46
@andfasano
Copy link
Contributor Author

/test verify


// MachineConfigNodeStatusInternalReleaseImage holds information about the current, desidered and discovered release bundles for the observed machine
// config node.
type MachineConfigNodeStatusInternalReleaseImage InternalReleaseImageStatus
Copy link
Contributor

Choose a reason for hiding this comment

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

The Alpha MCN type is no longer deployed anywhere, even in techpreview. These probably should just be +openshift:enable:FeatureGate=NoRegistryClusterOperations'ed in the v1 API for MCN.

(although I noticed that #2531 was opened. I assume we plan to do that there? I don't see the MCN fields yet)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, after a discussion with @pablintino I realized that the current one wasn't the right approach, for the same reasons you mentioned. So I opened a new PR just to try out a new approach, if it make more sense from a structural/type organization point of view (but the plan was to keep working here).
I think also this issue could be somehow simplified after the type split discussed before

// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=256
// +optional
Conditions []metav1.Condition `json:"conditions,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Trying to understand the conditions a bit better: since this will show up in both the MCN object and the overall IRI object, would the actual conditions look the same?

More concretely, the MCN object would reflect each IRI status on each node (since it would have a list of status's) but we'd only define a singular IRI object with a list of releases. If say, we had 3 releases and 5 nodes, we end up with (number of nodes) * (number of releases defined for those nodes) = 15 lists of conditions reflected in the MCN, but only a singular list of conditions here. So would this just be reflecting if any of those nodes are available/progressing/failing? I'm having a hard time thinking of the user experience when I read this field.

If that's the case, I think I would lean doing two things here:

  1. separate the InternalReleaseImageStatus type into two types in MCN and IRI object:
    a) per guidance of the API team, it's generally better to not inter-mingle object references
    b) this would allow us to define different conditions per subtype, like we have in e.g. https://github.com/openshift/api/blob/master/machineconfiguration/v1/types_machineosbuild.go#L81-L90
  2. concretely define what we want to see in this field. There's a few options as I understand it: some vague overall state, per-release state (in that case, should the conditions be nested in the AvailableReleases subfield, so we can see what each release's status is?) or have this be more akin to what we do for PinnedImageSet and not have status conditions at all, and make it purely an MCN only thing?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The intention was to avoid duplicating the same code for representing both the singleton IRI status and each MCN sub-IRI statuses. From this point of view, the singleton IRI is an aggregator, since it monitors all the MCNs and reports a summarized view for the end user.
But if you think that it will more clear, especially from an API point of view, to have different structs, then it's fine for me.
Regarding point 2, I was planning to add a more detailed enum for the Conditions later (like the MCN StateProgress), once the high-level types organization will be consolidated - but if it helps I can start adding them right now

Copy link
Contributor

Choose a reason for hiding this comment

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

Good one, I must agree with the hint that 15 conditions are, in general, unmanegable from the user point of view to the point of, would it be useful? Do we really need to report that fine-grained level of details in the conditions? I have never seen such of a report strategy in conditions, that are usually a bit higher level scoped. I do like the idea of re-using the availableReleases field (or a new one if it doesn't fit) to report fine-grain details of the release and report a single, Ready condition that the user can watch when he/she adds a new release and wants to wait for it to be available and propagated.

Copy link
Contributor

Choose a reason for hiding this comment

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

But if you think that it will more clear, especially from an API point of view, to have different structs, then it's fine for me.

While that's the general preference as I understand it, I think there's an argument here for either method, depending on how it would actually look.

When you say aggregator, what would I be expecting if, say, I have 2 releases, 1 installed for all nodes, and 1 failing for 2 nodes and waiting for pull for the other 3? Would i expect to see:

  1. 5 installed conditions, 2 failing conditions, 3 ready conditions (1 per status)
  2. 3 progressing conditions and 2 failing conditions (1 per node)
  3. 1 failing condition, 1 available condition, 1 ready condition (1 per type with a list of nodes in each state)


// InternalReleaseImageSpec defines the desired state of a InternalReleaseImage.
type InternalReleaseImageSpec struct {
// releases is a list of release bundle identifiers that the user wants to
Copy link
Contributor

Choose a reason for hiding this comment

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

(suggestion from claude): we should document the constraints (maximum # you can specify)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Isn't sufficient to specify the +kubebuilder:validation:MaxItems value?

Copy link
Contributor

Choose a reason for hiding this comment

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

Right, that's the validation, it's asking for the godoc to explicitly state for the user what the maximum is, something like This field can contain between x and y release bundles

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah ok

// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=256
// +optional
Conditions []metav1.Condition `json:"conditions,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Good one, I must agree with the hint that 15 conditions are, in general, unmanegable from the user point of view to the point of, would it be useful? Do we really need to report that fine-grained level of details in the conditions? I have never seen such of a report strategy in conditions, that are usually a bit higher level scoped. I do like the idea of re-using the availableReleases field (or a new one if it doesn't fit) to report fine-grain details of the release and report a single, Ready condition that the user can watch when he/she adds a new release and wants to wait for it to be available and propagated.

@andfasano andfasano force-pushed the add-internalreleaseimage-resource branch from a9c080e to 5bb2da8 Compare October 17, 2025 14:49
@andfasano
Copy link
Contributor Author

/retest

@andfasano andfasano force-pushed the add-internalreleaseimage-resource branch from 5bb2da8 to ee91dd4 Compare October 17, 2025 17:02
@andfasano
Copy link
Contributor Author

/retest

Copy link
Contributor

openshift-ci bot commented Oct 17, 2025

@andfasano: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/verify ee91dd4 link true /test verify
ci/prow/okd-scos-e2e-aws-ovn ee91dd4 link false /test okd-scos-e2e-aws-ovn

Full PR test history. Your PR dashboard.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Copy link
Contributor

@yuqi-zhang yuqi-zhang left a comment

Choose a reason for hiding this comment

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

Overall the structure makes more sense to me. A few questions/comments on the new MCN fields (and the previous question on the conditions)

// +optional
IrreconcilableChanges []IrreconcilableChangeDiff `json:"irreconcilableChanges,omitempty"`
// internalReleaseImage describes the status of the release payloads stored in the node.
// +optional
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this field also needs the +openshift:enable:FeatureGate=NoRegistryClusterOperations?

Also may be good to add a few more lines of description, something like:

When specified, an internalReleaseImage custom resource exists on the cluster, and the specified images will be made available on the control plane nodes. This field will reflect the actual on-disk state of those release images.

InternalReleaseImage *MachineConfigNodeStatusInternalReleaseImage `json:"internalReleaseImage,omitempty"`
}

// MachineConfigNodeStatusInternalReleaseImage holds information about the current, desidered and discovered release bundles for the observed machine
Copy link
Contributor

Choose a reason for hiding this comment

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

desidered -> desired

Also this reads to me like there would be three types: "current, desired and discovered". I think based on the actual fields, it's just "current" (installedReleases) and "discovered"(availableReleases)? The actual "desired" we have to specify via the IRI object?

Maybe it's worth it to have a third field? So the workflow would be:

  1. the user mounts the release image
  2. the user sees that currently the MCN object for that node has it under "discovered"
  3. the user updates the IRI object to add that release
  4. the MCD ack's that change to the IRI object, so now "discovered" and "desired" both have that field
  5. the MCD finishes setting up the registry and makes it available, thereby having it in "discovered" "desired" and "current"

I'm not sure if that's necessarily helpful. It's a bit weird since the inputs for "discovered" and "desired" and "current" are not all the same (a mounted disk, the user specified IRI object, the MCD's actions), so if we want to keep it simpler maybe we just have the two fields we have now and skip the "desired" part. WDYT @pablintino @JoelSpeed ?

// +listType=map
// +listMapKey=type
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=256
Copy link
Contributor

Choose a reason for hiding this comment

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

My question for #2510 (comment) kinda applies here as well, but maybe we're ok with just having a few general status's for the node to indicate if anything is failing. In that case, I think 256 is a bit overkill. Maybe we can shorten this and then similar to https://github.com/openshift/api/blob/master/machineconfiguration/v1/types_machineosbuild.go#L81-L90 have a list of what we'd expect.

// +listType=map
// +listMapKey=name
// +kubebuilder:validation:MaxItems=5
// +optional
Copy link
Contributor

Choose a reason for hiding this comment

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

Just thinking out loud, maybe we should have this be required (if the IRI status exists) so at it would always reflect what the daemon is currently detecting? And if we don't detect anything we just have an empty list?

// +listMapKey=name
// +kubebuilder:validation:MaxItems=5
// +optional
AvailableReleases []InternalReleaseImageRef `json:"availableReleases,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Now that we have the split, what get's reflected here? If e.g. each control plane node doesn't currently have the same available (mounted) releases, would this reflect it as available if any control plane node is hosting that image? Or only when all control plane nodes have it mounted and reporting?

// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=5
// +optional
InstalledReleases []InternalReleaseImageDetailedRef `json:"installedReleases,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Same question as above

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants