8000 chore: support specifying the status and EOL date for CMPV releases by leon-inf · Pull Request #8794 · apecloud/kubeblocks · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

chore: support specifying the status and EOL date for CMPV releases #8794

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

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
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
5 changes: 5 additions & 0 deletions apis/apps/v1/cluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,11 @@ type ClusterComponentSpec struct {
// +optional
ServiceVersion string `json:"serviceVersion,omitempty"`

// Forces to use the specified service version, ignoring any version constraints.
//
// +optional
ForceServiceVersion *bool `json:"forceServiceVersion,omitempty"`

// Defines a list of ServiceRef for a Component, enabling access to both external services and
// Services provided by other Clusters.
//
Expand Down
5 changes: 5 additions & 0 deletions apis/apps/v1/component_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ type ComponentSpec struct {
// +optional
ServiceVersion string `json:"serviceVersion,omitempty"`

// Forces to use the specified service version, ignoring any version constraints.
//
// +optional
ForceServiceVersion *bool `json:"forceServiceVersion,omitempty"`

// Defines a list of ServiceRef for a Component, enabling access to both external services and
// Services provided by other Clusters.
//
Expand Down
48 changes: 48 additions & 0 deletions apis/apps/v1/componentversion_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ type ComponentVersionCompatibilityRule struct {
// ComponentVersionRelease represents a release of component instances within a ComponentVersion.
type ComponentVersionRelease struct {
// Name is a unique identifier for this release.
//
// Cannot be updated.
//
// +kubebuilder:validation:Required
Expand All @@ -133,8 +134,10 @@ type ComponentVersionRelease struct {
Changes string `json:"changes,omitempty"`

// ServiceVersion defines the version of the well-known service that the component provides.
//
// The version should follow the syntax and semantics of the "Semantic Versioning" specification (http://semver.org/).
// If the release is used, it will serve as the service version for component instances, overriding the one defined in the component definition.
//
// Cannot be updated.
//
// +kubebuilder:validation:Required
Expand All @@ -152,4 +155,49 @@ type ComponentVersionRelease struct {
// +kubebuilder:validation:XValidation:rule="self.all(key, size(key) <= 32)",message="Container, action or external application name may not exceed maximum length of 32 characters"
// +kubebuilder:validation:XValidation:rule="self.all(key, size(self[key]) <= 256)",message="Image name may not exceed maximum length of 256 characters"
Images map[string]string `json:"images"`

// Status represents the status of the release (e.g., "alpha", "beta", "stable", "deprecated").
//
// For a release in the "deprecated" state, the release is no longer supported and the controller will prevent new instances from employing it.
//
// +optional
Status ReleaseStatus `json:"status,omitempty"`

// Reason is the detailed reason for the release status.
//
// For a release in the "deprecated" state, the reason should explain why the release is deprecated. For example:
// {
// Description: "Vulnerability in logging library",
// Severity: "high",
// Mitigation: "Upgrade to logging library v2.0.0",
// CVE: "CVE-2024-12345",
// }
//
// +kubebuilder:validation:MaxLength=256
// +optional
Reason string `json:"reason,omitempty"`

// ReleaseDate is the date when this version was released.
//
// +optional
ReleaseDate metav1.Time `json:"releaseDate,omitempty"`

// EndOfLifeDate is the date when this version is no longer supported.
//
// When this field is set and the release has passed its end-of-life (EOL) date, the controller will prevent new instances from employing it.
//
// +optional
EndOfLifeDate metav1.Time `json:"endOfLifeDate,omitempty"`
}

// ReleaseStatus represents the status of a release.
//
// +kubebuilder:validation:Enum={alpha,beta,stable,deprecated}
type ReleaseStatus string

8000 const (
ReleaseStatusAlpha ReleaseStatus = "alpha"
ReleaseStatusBeta ReleaseStatus = "beta"
ReleaseStatusStable ReleaseStatus = "stable"
ReleaseStatusDeprecated ReleaseStatus = "deprecated"
)
12 changes: 12 additions & 0 deletions apis/apps/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions config/crd/bases/apps.kubeblocks.io_clusters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,10 @@ spec:
- name
type: object
type: array
forceServiceVersion:
description: Forces to use the specified service version, ignoring
any version constraints.
type: boolean
instances:
description: |-
Allows for the customization of configuration values for each instance within a Component.
Expand Down Expand Up @@ -9099,6 +9103,10 @@ spec:
- name
type: object
type: array
forceServiceVersion:
description: Forces to use the specified service version,
ignoring any version constraints.
type: boolean
instances:
description: |-
Allows for the customization of configuration values for each instance within a Component.
Expand Down
4 changes: 4 additions & 0 deletions config/crd/bases/apps.kubeblocks.io_components.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,10 @@ spec:
- name
type: object
type: array
forceServiceVersion:
description: Forces to use the specified service version, ignoring
any version constraints.
type: boolean
instances:
description: |-
Allows for the customization of configuration values for each instance within a Component.
Expand Down
39 changes: 39 additions & 0 deletions config/crd/bases/apps.kubeblocks.io_componentversions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,14 @@ spec:
made in this release.
maxLength: 256
type: string
endOfLifeDate:
description: |-
EndOfLifeDate is the date when this version is no longer supported.


When this field is set and the release has passed its end-of-life (EOL) date, the controller will prevent new instances from employing it.
format: date-time
type: string
images:
additionalProperties:
type: string
Expand All @@ -127,17 +135,48 @@ spec:
name:
description: |-
Name is a unique identifier for this release.


Cannot be updated.
maxLength: 32
type: string
reason:
description: "Reason is the detailed reason for the release
status.\n\n\nFor a release in the \"deprecated\" state, the
reason should explain why the release is deprecated. For example:\n
\ {\n\t\tDescription: \"Vulnerability in logging library\",\n\t\tSeverity:
\ \"high\",\n\t\tMitigation: \"Upgrade to logging library
v2.0.0\",\n\t\tCVE: \"CVE-2024-12345\",\n }"
maxLength: 256
type: string
releaseDate:
description: ReleaseDate is the date when this version was released.
format: date-time
type: string
serviceVersion:
description: |-
ServiceVersion defines the version of the well-known service that the component provides.


The version should follow the syntax and semantics of the "Semantic Versioning" specification (http://semver.org/).
If the release is used, it will serve as the service version for component instances, overriding the one defined in the component definition.


Cannot be updated.
maxLength: 32
type: string
status:
description: |-
Status represents the status of the release (e.g., "alpha", "beta", "stable", "deprecated").


For a release in the "deprecated" state, the release is no longer supported and the controller will prevent new instances from employing it.
enum:
- alpha
- beta
- stable
- deprecated
type: string
required:
- images
- name
Expand Down
47 changes: 37 additions & 10 deletions controllers/apps/cluster/transformer_cluster_normalization.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ import (

"golang.org/x/exp/maps"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/version"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"

appsv1 "github.com/apecloud/kubeblocks/apis/apps/v1"
Expand Down Expand Up @@ -343,9 +345,9 @@ func (t *clusterNormalizationTransformer) resolveCompDefinitionNServiceVersionWi
cli = transCtx.Client
)
if comp == nil || t.checkCompUpgrade(compSpec, comp) {
return resolveCompDefinitionNServiceVersion(ctx, cli, compSpec.ComponentDef, compSpec.ServiceVersion)
return resolveCompDefinitionNServiceVersion(ctx, cli, compSpec.ComponentDef, compSpec.ServiceVersion, compSpec.ForceServiceVersion)
}
return resolveCompDefinitionNServiceVersion(ctx, cli, comp.Spec.CompDef, comp.Spec.ServiceVersion)
return resolveCompDefinitionNServiceVersion(ctx, cli, comp.Spec.CompDef, comp.Spec.ServiceVersion, comp.Spec.ForceServiceVersion)
}

func (t *clusterNormalizationTransformer) checkCompUpgrade(compSpec *appsv1.ClusterComponentSpec, comp *appsv1.Component) bool {
Expand Down Expand Up @@ -575,7 +577,8 @@ func shardsOutOfLimitError(shardingName string, shards int32, limit appsv1.Shard
}

// resolveCompDefinitionNServiceVersion resolves and returns the specific component definition object and the service version supported.
func resolveCompDefinitionNServiceVersion(ctx context.Context, cli client.Reader, compDefName, serviceVersion string) (*appsv1.ComponentDefinition, string, error) {
func resolveCompDefinitionNServiceVersion(ctx context.Context, cli client.Reader,
compDefName, serviceVersion string, forces ...*bool) (*appsv1.ComponentDefinition, string, error) {
var (
compDef *appsv1.ComponentDefinition
)
Expand All @@ -584,8 +587,14 @@ func resolveCompDefinitionNServiceVersion(ctx context.Context, cli client.Reader
return compDef, serviceVersion, err
}

// mapping from <service version> to <[]*appsv1.ComponentDefinition>
serviceVersionToCompDefs, err := serviceVersionToCompDefinitions(ctx, cli, compDefs, serviceVersion)
// whether to force the service version to be specified
force := ptr.To(true)
if len(forces) > 0 {
force = forces[0]
}

// mapping from <service version> to {name -> *appsv1.ComponentDefinition}
serviceVersionToCompDefs, err := serviceVersionToCompDefinitions(ctx, cli, compDefs, serviceVersion, force)
if err != nil {
return compDef, serviceVersion, err
}
Expand All @@ -602,7 +611,8 @@ func resolveCompDefinitionNServiceVersion(ctx context.Context, cli client.Reader
// component definitions that support the service version
compatibleCompDefs := serviceVersionToCompDefs[serviceVersion]
if len(compatibleCompDefs) == 0 {
return compDef, serviceVersion, fmt.Errorf(`no matched component definition found with componentDef "%s" and serviceVersion "%s"`, compDefName, serviceVersion)
return compDef, serviceVersion,
fmt.Errorf(`no matched component definition found with componentDef "%s" and serviceVersion "%s"`, compDefName, serviceVersion)
}

// choose the latest one
Expand Down Expand Up @@ -636,7 +646,7 @@ func listCompDefinitionsWithPattern(ctx context.Context, cli client.Reader, name
}

func serviceVersionToCompDefinitions(ctx context.Context, cli client.Reader,
compDefs []*appsv1.ComponentDefinition, serviceVersion string) (map[string]map[string]*appsv1.ComponentDefinition, error) {
compDefs []*appsv1.ComponentDefinition, serviceVersion string, force *bool) (map[string]map[string]*appsv1.ComponentDefinition, error) {
result := make(map[string]map[string]*appsv1.ComponentDefinition)

insert := func(version string, compDef *appsv1.ComponentDefinition) {
Expand Down Expand Up @@ -666,7 +676,7 @@ func serviceVersionToCompDefinitions(ctx context.Context, cli client.Reader,
serviceVersions.Insert(compDef.Spec.ServiceVersion)
}
for _, compVersion := range compVersions {
serviceVersions = serviceVersions.Union(compatibleServiceVersions4Definition(compDef, compVersion))
serviceVersions = serviceVersions.Union(compatibleServiceVersions4Definition(compDef, compVersion, force))
}

for version := range serviceVersions {
Expand All @@ -679,7 +689,7 @@ func serviceVersionToCompDefinitions(ctx context.Context, cli client.Reader,
}

// compatibleServiceVersions4Definition returns all service versions that are compatible with specified component definition.
func compatibleServiceVersions4Definition(compDef *appsv1.ComponentDefinition, compVersion *appsv1.ComponentVersion) sets.Set[string] {
func compatibleServiceVersions4Definition(compDef *appsv1.ComponentDefinition, compVersion *appsv1.ComponentVersion, force *bool) sets.Set[string] {
match := func(pattern string) bool {
return component.PrefixOrRegexMatched(compDef.Name, pattern)
}
Expand All @@ -693,13 +703,30 @@ func compatibleServiceVersions4Definition(compDef *appsv1.ComponentDefinition, c
}
serviceVersions := sets.New[string]()
for _, release := range compVersion.Spec.Releases {
if releases[release.Name] {
if releases[release.Name] && isReleaseAvailable(release, force) {
serviceVersions = serviceVersions.Insert(release.ServiceVersion)
}
}
return serviceVersions
}

func isReleaseAvailable(release appsv1.ComponentVersionRelease, force *bool) bool {
if force != nil && *force {
return true
}

deprecated := func() bool {
return release.Status == appsv1.ReleaseStatusDeprecated
}
eol := func() bool {
if release.EndOfLifeDate.IsZero() {
return false
}
return release.EndOfLifeDate.Before(ptr.To(metav1.Now()))
}
return !(deprecated() || eol())
}

func serviceVersionComparator(a, b string) int {
if len(a) == 0 {
return -1
Expand Down
8 changes: 8 additions & 0 deletions deploy/helm/crds/apps.kubeblocks.io_clusters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,10 @@ spec:
- name
type: object
type: array
forceServiceVersion:
description: Forces to use the specified service version, ignoring
any version constraints.
type: boolean
instances:
description: |-
Allows for the customization of configuration values for each instance within a Component.
Expand Down Expand Up @@ -9099,6 +9103,10 @@ spec:
- name
type: object
type: array
forceServiceVersion:
description: Forces to use the specified service version,
ignoring any version constraints.
type: boolean
instances:
description: |-
Allows for the customization of configuration values for each instance within a Component.
Expand Down
4 changes: 4 additions & 0 deletions deploy/helm/crds/apps.kubeblocks.io_components.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,10 @@ spec:
- name
type: object
type: array
forceServiceVersion:
description: Forces to use the specified service version, ignoring
any version constraints.
type: boolean
instances:
description: |-
Allows for the customization of configuration values for each instance within a Component.
Expand Down
Loading
Loading
0