feat: kubesphere 4.0 (#6115)

* feat: kubesphere 4.0

Signed-off-by: ci-bot <ci-bot@kubesphere.io>

* feat: kubesphere 4.0

Signed-off-by: ci-bot <ci-bot@kubesphere.io>

---------

Signed-off-by: ci-bot <ci-bot@kubesphere.io>
Co-authored-by: ks-ci-bot <ks-ci-bot@example.com>
Co-authored-by: joyceliu <joyceliu@yunify.com>
This commit is contained in:
KubeSphere CI Bot
2024-09-06 11:05:52 +08:00
committed by GitHub
parent b5015ec7b9
commit 447a51f08b
8557 changed files with 546695 additions and 1146174 deletions

View File

@@ -20,9 +20,9 @@ import (
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/resource"
"k8s.io/client-go/discovery"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
openapiclient "k8s.io/client-go/openapi"
restclient "k8s.io/client-go/rest"
"k8s.io/kubectl/pkg/util/openapi"
"k8s.io/kubectl/pkg/validation"
@@ -61,9 +61,12 @@ type Factory interface {
UnstructuredClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error)
// Returns a schema that can validate objects stored on disk.
Validator(validationDirective string, verifier *resource.QueryParamVerifier) (validation.Schema, error)
// OpenAPISchema returns the parsed openapi schema definition
OpenAPISchema() (openapi.Resources, error)
// OpenAPIGetter returns a getter for the openapi schema document
OpenAPIGetter() discovery.OpenAPISchemaInterface
Validator(validationDirective string) (validation.Schema, error)
// Used for retrieving openapi v2 resources.
openapi.OpenAPIResourcesGetter
// OpenAPIV3Schema returns a client for fetching parsed schemas for
// any group version
OpenAPIV3Client() (openapiclient.Client, error)
}

View File

@@ -30,10 +30,11 @@ import (
"k8s.io/client-go/discovery"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
openapiclient "k8s.io/client-go/openapi"
"k8s.io/client-go/openapi/cached"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/kubectl/pkg/util/openapi"
openapivalidation "k8s.io/kubectl/pkg/util/openapi/validation"
"k8s.io/kubectl/pkg/validation"
)
@@ -42,7 +43,7 @@ type factoryImpl struct {
// Caches OpenAPI document and parsed resources
openAPIParser *openapi.CachedOpenAPIParser
openAPIGetter *openapi.CachedOpenAPIGetter
oapi *openapi.CachedOpenAPIGetter
parser sync.Once
getter sync.Once
}
@@ -142,7 +143,7 @@ func (f *factoryImpl) UnstructuredClientForMapping(mapping *meta.RESTMapping) (r
return restclient.RESTClientFor(cfg)
}
func (f *factoryImpl) Validator(validationDirective string, verifier *resource.QueryParamVerifier) (validation.Schema, error) {
func (f *factoryImpl) Validator(validationDirective string) (validation.Schema, error) {
// client-side schema validation is only performed
// when the validationDirective is strict.
// If the directive is warn, we rely on the ParamVerifyingSchema
@@ -153,22 +154,34 @@ func (f *factoryImpl) Validator(validationDirective string, verifier *resource.Q
return validation.NullSchema{}, nil
}
resources, err := f.OpenAPISchema()
schema := validation.ConjunctiveSchema{
validation.NewSchemaValidation(f),
validation.NoDoubleKeySchema{},
}
dynamicClient, err := f.DynamicClient()
if err != nil {
return nil, err
}
schema := validation.ConjunctiveSchema{
openapivalidation.NewSchemaValidation(resources),
validation.NoDoubleKeySchema{},
// Create the FieldValidationVerifier for use in the ParamVerifyingSchema.
discoveryClient, err := f.ToDiscoveryClient()
if err != nil {
return nil, err
}
return validation.NewParamVerifyingSchema(schema, verifier, string(validationDirective)), nil
// Memory-cache the OpenAPI V3 responses. The disk cache behavior is determined by
// the discovery client.
oapiV3Client := cached.NewClient(discoveryClient.OpenAPIV3())
queryParam := resource.QueryParamFieldValidation
primary := resource.NewQueryParamVerifierV3(dynamicClient, oapiV3Client, queryParam)
secondary := resource.NewQueryParamVerifier(dynamicClient, f.openAPIGetter(), queryParam)
fallback := resource.NewFallbackQueryParamVerifier(primary, secondary)
return validation.NewParamVerifyingSchema(schema, fallback, string(validationDirective)), nil
}
// OpenAPISchema returns metadata and structural information about
// Kubernetes object definitions.
func (f *factoryImpl) OpenAPISchema() (openapi.Resources, error) {
openAPIGetter := f.OpenAPIGetter()
openAPIGetter := f.openAPIGetter()
if openAPIGetter == nil {
return nil, errors.New("no openapi getter")
}
@@ -176,21 +189,30 @@ func (f *factoryImpl) OpenAPISchema() (openapi.Resources, error) {
// Lazily initialize the OpenAPIParser once
f.parser.Do(func() {
// Create the caching OpenAPIParser
f.openAPIParser = openapi.NewOpenAPIParser(f.OpenAPIGetter())
f.openAPIParser = openapi.NewOpenAPIParser(f.openAPIGetter())
})
// Delegate to the OpenAPIPArser
return f.openAPIParser.Parse()
}
func (f *factoryImpl) OpenAPIGetter() discovery.OpenAPISchemaInterface {
func (f *factoryImpl) openAPIGetter() discovery.OpenAPISchemaInterface {
discovery, err := f.clientGetter.ToDiscoveryClient()
if err != nil {
return nil
}
f.getter.Do(func() {
f.openAPIGetter = openapi.NewOpenAPIGetter(discovery)
f.oapi = openapi.NewOpenAPIGetter(discovery)
})
return f.openAPIGetter
return f.oapi
}
func (f *factoryImpl) OpenAPIV3Client() (openapiclient.Client, error) {
discovery, err := f.clientGetter.ToDiscoveryClient()
if err != nil {
return nil, err
}
return cached.NewClient(discovery.OpenAPIV3()), nil
}

View File

@@ -422,6 +422,30 @@ func GetPodRunningTimeoutFlag(cmd *cobra.Command) (time.Duration, error) {
return timeout, nil
}
type FeatureGate string
const (
ApplySet FeatureGate = "KUBECTL_APPLYSET"
CmdPluginAsSubcommand FeatureGate = "KUBECTL_ENABLE_CMD_SHADOW"
InteractiveDelete FeatureGate = "KUBECTL_INTERACTIVE_DELETE"
OpenAPIV3Patch FeatureGate = "KUBECTL_OPENAPIV3_PATCH"
RemoteCommandWebsockets FeatureGate = "KUBECTL_REMOTE_COMMAND_WEBSOCKETS"
)
// IsEnabled returns true iff environment variable is set to true.
// All other cases, it returns false.
func (f FeatureGate) IsEnabled() bool {
return strings.ToLower(os.Getenv(string(f))) == "true"
}
// IsDisabled returns true iff environment variable is set to false.
// All other cases, it returns true.
// This function is used for the cases where feature is enabled by default,
// but it may be needed to provide a way to ability to disable this feature.
func (f FeatureGate) IsDisabled() bool {
return strings.ToLower(os.Getenv(string(f))) == "false"
}
func AddValidateFlags(cmd *cobra.Command) {
cmd.Flags().String(
"validate",
@@ -499,8 +523,25 @@ func AddLabelSelectorFlagVar(cmd *cobra.Command, p *string) {
cmd.Flags().StringVarP(p, "selector", "l", *p, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2). Matching objects must satisfy all of the specified label constraints.")
}
func AddPruningFlags(cmd *cobra.Command, prune *bool, pruneAllowlist *[]string, pruneWhitelist *[]string, all *bool, applySetRef *string) {
// Flags associated with the original allowlist-based alpha
cmd.Flags().StringArrayVar(pruneAllowlist, "prune-allowlist", *pruneAllowlist, "Overwrite the default allowlist with <group/version/kind> for --prune")
cmd.Flags().StringArrayVar(pruneWhitelist, "prune-whitelist", *pruneWhitelist, "Overwrite the default whitelist with <group/version/kind> for --prune") // TODO: Remove this in kubectl 1.28 or later
_ = cmd.Flags().MarkDeprecated("prune-whitelist", "Use --prune-allowlist instead.")
cmd.Flags().BoolVar(all, "all", *all, "Select all resources in the namespace of the specified resource types.")
// Flags associated with the new ApplySet-based alpha
if ApplySet.IsEnabled() {
cmd.Flags().StringVar(applySetRef, "applyset", *applySetRef, "[alpha] The name of the ApplySet that tracks which resources are being managed, for the purposes of determining what to prune. Live resources that are part of the ApplySet but have been removed from the provided configs will be deleted. Format: [RESOURCE][.GROUP]/NAME. A Secret will be used if no resource or group is specified.")
cmd.Flags().BoolVar(prune, "prune", *prune, "Automatically delete previously applied resource objects that do not appear in the provided configs. For alpha1, use with either -l or --all. For alpha2, use with --applyset.")
} else {
// different docs for the shared --prune flag if only alpha1 is enabled
cmd.Flags().BoolVar(prune, "prune", *prune, "Automatically delete resource objects, that do not appear in the configs and are created by either apply or create --save-config. Should be used with either -l or --all.")
}
}
func AddSubresourceFlags(cmd *cobra.Command, subresource *string, usage string, allowedSubresources ...string) {
cmd.Flags().StringVar(subresource, "subresource", "", fmt.Sprintf("%s Must be one of %v. This flag is alpha and may change in the future.", usage, allowedSubresources))
cmd.Flags().StringVar(subresource, "subresource", "", fmt.Sprintf("%s Must be one of %v. This flag is beta and may change in the future.", usage, allowedSubresources))
CheckErr(cmd.RegisterFlagCompletionFunc("subresource", func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
return allowedSubresources, cobra.ShellCompDirectiveNoFileComp
}))