mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-07-18 04:54:54 +00:00
Add +k8s:alpha and +k8s:beta tags support
This commit is contained in:
@@ -1419,6 +1419,12 @@ func emitCallsToValidators(c *generator.Context, validations []validators.Functi
|
||||
toGolangSourceDataLiteral(sw, c, arg)
|
||||
}
|
||||
sw.Do(")", targs)
|
||||
switch v.StabilityLevel {
|
||||
case validators.ValidationStabilityLevelAlpha:
|
||||
sw.Do(".MarkAlpha()", nil)
|
||||
case validators.ValidationStabilityLevelBeta:
|
||||
sw.Do(".MarkBeta()", nil)
|
||||
}
|
||||
}
|
||||
|
||||
// If validation is conditional, wrap the validation function with a conditions check.
|
||||
@@ -1786,6 +1792,12 @@ func emitFunctionCall(sw *generator.SnippetWriter, c *generator.Context, v valid
|
||||
toGolangSourceDataLiteral(sw, c, arg)
|
||||
}
|
||||
sw.Do(")", nil)
|
||||
switch v.StabilityLevel {
|
||||
case validators.ValidationStabilityLevelAlpha:
|
||||
sw.Do(".MarkAlpha()", nil)
|
||||
case validators.ValidationStabilityLevelBeta:
|
||||
sw.Do(".MarkBeta()", nil)
|
||||
}
|
||||
}
|
||||
|
||||
// getLeafTypeAndPrefixes returns the "leaf value type" for a given type, as
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
Copyright 2025 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package validators
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/gengo/v2/codetags"
|
||||
)
|
||||
|
||||
var kubeVersionRegex = regexp.MustCompile(`^1\.\d+$`)
|
||||
|
||||
const (
|
||||
alphaTagName = "k8s:alpha"
|
||||
betaTagName = "k8s:beta"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterTagValidator(&levelTagValidator{tagName: alphaTagName, level: ValidationStabilityLevelAlpha})
|
||||
RegisterTagValidator(&levelTagValidator{tagName: betaTagName, level: ValidationStabilityLevelBeta})
|
||||
}
|
||||
|
||||
type levelTagValidator struct {
|
||||
validator Validator
|
||||
tagName string
|
||||
level ValidationStabilityLevel
|
||||
}
|
||||
|
||||
func (ltv *levelTagValidator) Init(cfg Config) {
|
||||
ltv.validator = cfg.Validator
|
||||
}
|
||||
|
||||
func (ltv *levelTagValidator) TagName() string {
|
||||
return ltv.tagName
|
||||
}
|
||||
|
||||
var levelTagsValidScopes = sets.New(ScopeType, ScopeField, ScopeListVal, ScopeMapKey, ScopeMapVal)
|
||||
|
||||
func (levelTagValidator) ValidScopes() sets.Set[Scope] {
|
||||
return levelTagsValidScopes
|
||||
}
|
||||
|
||||
// LateTagValidator indicates that this validator has to run AFTER the listType
|
||||
// and listMapKey tags.
|
||||
func (levelTagValidator) LateTagValidator() {}
|
||||
|
||||
func (ltv *levelTagValidator) GetValidations(context Context, tag codetags.Tag) (Validations, error) {
|
||||
if tag.ValueType != codetags.ValueTypeTag || tag.ValueTag == nil {
|
||||
return Validations{}, fmt.Errorf("requires a validation tag as its value payload")
|
||||
}
|
||||
|
||||
if len(tag.Args) > 1 {
|
||||
return Validations{}, fmt.Errorf("at most one optional kubernetes version argument is supported")
|
||||
}
|
||||
|
||||
var version string
|
||||
if len(tag.Args) == 1 {
|
||||
arg := tag.Args[0]
|
||||
version = arg.Value
|
||||
if !kubeVersionRegex.MatchString(version) {
|
||||
return Validations{}, fmt.Errorf("invalid kubernetes version format, expected 1.<minor version>, got %s", version)
|
||||
}
|
||||
}
|
||||
|
||||
context.StabilityLevel = ltv.level
|
||||
validations, err := ltv.validator.ExtractTagValidations(context, *tag.ValueTag)
|
||||
if err != nil {
|
||||
return Validations{}, err
|
||||
}
|
||||
|
||||
result := Validations{}
|
||||
result.Variables = append(result.Variables, validations.Variables...)
|
||||
for _, fn := range validations.Functions {
|
||||
f := fn
|
||||
f.StabilityLevel = ltv.level
|
||||
result.AddFunction(f)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (ltv *levelTagValidator) Docs() TagDoc {
|
||||
doc := TagDoc{
|
||||
Tag: ltv.TagName(),
|
||||
StabilityLevel: TagStabilityLevelAlpha,
|
||||
Scopes: ltv.ValidScopes().UnsortedList(),
|
||||
Description: fmt.Sprintf("Marks the given payload validation as a %s validation of the handwritten validation code. An optional Kubernetes version can be specified.", ltv.level),
|
||||
Args: []TagArgDoc{{
|
||||
Description: "The Kubernetes version (e.g. `1.34`) at which this validation was added.",
|
||||
Type: codetags.ArgTypeString,
|
||||
Name: "since",
|
||||
}},
|
||||
Payloads: []TagPayloadDoc{{
|
||||
Description: "<validation-tag>",
|
||||
Docs: fmt.Sprintf("The validation tag to evaluate as a %s validation.", ltv.level),
|
||||
}},
|
||||
PayloadsType: codetags.ValueTypeTag,
|
||||
PayloadsRequired: true,
|
||||
}
|
||||
return doc
|
||||
}
|
||||
@@ -230,6 +230,9 @@ type Context struct {
|
||||
// Constants provides access to all constants of the type being
|
||||
// validated. Only set when Scope is ScopeType.
|
||||
Constants []*Constant
|
||||
|
||||
// StabilityLevel indicates the stability on the corresponding validation.
|
||||
StabilityLevel ValidationStabilityLevel
|
||||
}
|
||||
|
||||
// Constant represents a constant value.
|
||||
@@ -267,6 +270,16 @@ var stabilityOrder = map[TagStabilityLevel]int{
|
||||
TagStabilityLevelStable: 2,
|
||||
}
|
||||
|
||||
// Validation stability level denotes the stability of a validation.
|
||||
type ValidationStabilityLevel string
|
||||
|
||||
const (
|
||||
// Alpha denotes the declarative validations should be run with the handwritten validation. But the handwritten validations are the authoritative.
|
||||
ValidationStabilityLevelAlpha ValidationStabilityLevel = "Alpha"
|
||||
// Beta denotes the declarative validations should be run with the handwritten validation. Declarative validations are authoritative.
|
||||
ValidationStabilityLevelBeta ValidationStabilityLevel = "Beta"
|
||||
)
|
||||
|
||||
// Min returns the minimum of two stability levels, or an error if either
|
||||
// stability level is unknown.
|
||||
func (s TagStabilityLevel) Min(other TagStabilityLevel) (TagStabilityLevel, error) {
|
||||
@@ -527,6 +540,9 @@ type FunctionGen struct {
|
||||
// Comments holds optional comments that should be added to the generated
|
||||
// code (without the leading "//").
|
||||
Comments []string
|
||||
|
||||
// StabilityLevel indicates the stability level of the corresponding validation.
|
||||
StabilityLevel ValidationStabilityLevel
|
||||
}
|
||||
|
||||
// WithTypeArgs returns a derived FunctionGen with type arguments.
|
||||
@@ -552,6 +568,12 @@ func (fg FunctionGen) WithComment(comment string) FunctionGen {
|
||||
return fg.WithComments(comment)
|
||||
}
|
||||
|
||||
// WithStabilityLevel returns a new FunctionGen with the given stability level.
|
||||
func (fg FunctionGen) WithStabilityLevel(level ValidationStabilityLevel) FunctionGen {
|
||||
fg.StabilityLevel = level
|
||||
return fg
|
||||
}
|
||||
|
||||
// Variable creates a VariableGen for a given variable name and init value.
|
||||
func Variable(variable PrivateVar, initializer any) VariableGen {
|
||||
return VariableGen{
|
||||
|
||||
Reference in New Issue
Block a user