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

@@ -6,12 +6,13 @@ package openapi
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"strings"
"sync"
openapi_v2 "github.com/google/gnostic/openapiv2"
openapi_v2 "github.com/google/gnostic-models/openapiv2"
"google.golang.org/protobuf/proto"
"k8s.io/kube-openapi/pkg/validation/spec"
"sigs.k8s.io/kustomize/kyaml/errors"
@@ -21,14 +22,27 @@ import (
k8syaml "sigs.k8s.io/yaml"
)
// globalSchema contains global state information about the openapi
var globalSchema openapiData
var (
// schemaLock is the lock for schema related globals.
//
// NOTE: This lock helps with preventing panics that might occur due to the data
// race that concurrent access on this variable might cause but it doesn't
// fully fix the issue described in https://github.com/kubernetes-sigs/kustomize/issues/4824.
// For instance concurrently running goroutines where each of them calls SetSchema()
// and/or GetSchemaVersion might end up received nil errors (success) whereas the
// seconds one would overwrite the global variable that has been written by the
// first one.
schemaLock sync.RWMutex //nolint:gochecknoglobals
// kubernetesOpenAPIVersion specifies which builtin kubernetes schema to use
var kubernetesOpenAPIVersion string
// kubernetesOpenAPIVersion specifies which builtin kubernetes schema to use.
kubernetesOpenAPIVersion string //nolint:gochecknoglobals
// customSchemaFile stores the custom OpenApi schema if it is provided
var customSchema []byte
// globalSchema contains global state information about the openapi
globalSchema openapiData //nolint:gochecknoglobals
// customSchemaFile stores the custom OpenApi schema if it is provided
customSchema []byte //nolint:gochecknoglobals
)
// openapiData contains the parsed openapi state. this is in a struct rather than
// a list of vars so that it can be reset from tests.
@@ -104,7 +118,7 @@ var precomputedIsNamespaceScoped = map[yaml.TypeMeta]bool{
{APIVersion: "node.k8s.io/v1beta1", Kind: "RuntimeClass"}: false,
{APIVersion: "policy/v1", Kind: "PodDisruptionBudget"}: true,
{APIVersion: "policy/v1beta1", Kind: "PodDisruptionBudget"}: true,
{APIVersion: "policy/v1beta1", Kind: "PodSecurityPolicy"}: false,
{APIVersion: "policy/v1beta1", Kind: "PodSecurityPolicy"}: false, // remove after openapi upgrades to v1.25.
{APIVersion: "rbac.authorization.k8s.io/v1", Kind: "ClusterRole"}: false,
{APIVersion: "rbac.authorization.k8s.io/v1", Kind: "ClusterRoleBinding"}: false,
{APIVersion: "rbac.authorization.k8s.io/v1", Kind: "Role"}: true,
@@ -220,7 +234,7 @@ func definitionRefsFromRNode(object *yaml.RNode) ([]string, error) {
// parseOpenAPI reads openAPIPath yaml and converts it to RNode
func parseOpenAPI(openAPIPath string) (*yaml.RNode, error) {
b, err := ioutil.ReadFile(openAPIPath)
b, err := os.ReadFile(openAPIPath)
if err != nil {
return nil, err
}
@@ -278,9 +292,12 @@ func AddSchema(s []byte) error {
// ResetOpenAPI resets the openapi data to empty
func ResetOpenAPI() {
schemaLock.Lock()
defer schemaLock.Unlock()
globalSchema = openapiData{}
kubernetesOpenAPIVersion = ""
customSchema = nil
kubernetesOpenAPIVersion = ""
}
// AddDefinitions adds the definitions to the global schema.
@@ -400,7 +417,7 @@ func SuppressBuiltInSchemaUse() {
// Elements returns the Schema for the elements of an array.
func (rs *ResourceSchema) Elements() *ResourceSchema {
// load the schema from swagger.json
// load the schema from swagger files
initSchema()
if len(rs.Schema.Type) != 1 || rs.Schema.Type[0] != "array" {
@@ -446,7 +463,7 @@ func (rs *ResourceSchema) Lookup(path ...string) *ResourceSchema {
// Field returns the Schema for a field.
func (rs *ResourceSchema) Field(field string) *ResourceSchema {
// load the schema from swagger.json
// load the schema from swagger files
initSchema()
// locate the Schema
@@ -459,7 +476,7 @@ func (rs *ResourceSchema) Field(field string) *ResourceSchema {
// (the key doesn't matter, they all have the same value type)
s = *rs.Schema.AdditionalProperties.Schema
default:
// no Schema found from either swagger.json or line comments
// no Schema found from either swagger files or line comments
return nil
}
@@ -545,24 +562,28 @@ const (
groupKey = "group"
// versionKey is the key to lookup the version from the GVK extension
versionKey = "version"
// kindKey is the the to lookup the kind from the GVK extension
// kindKey is the to lookup the kind from the GVK extension
kindKey = "kind"
)
// SetSchema sets the kubernetes OpenAPI schema version to use
func SetSchema(openAPIField map[string]string, schema []byte, reset bool) error {
schemaLock.Lock()
defer schemaLock.Unlock()
// this should only be set once
schemaIsSet := (kubernetesOpenAPIVersion != "") || customSchema != nil
if schemaIsSet && !reset {
return nil
}
version, exists := openAPIField["version"]
if exists && schema != nil {
return fmt.Errorf("builtin version and custom schema provided, cannot use both")
}
version, versionProvided := openAPIField["version"]
if schema != nil { // use custom schema
// use custom schema
if schema != nil {
if versionProvided {
return fmt.Errorf("builtin version and custom schema provided, cannot use both")
}
customSchema = schema
kubernetesOpenAPIVersion = "custom"
// if the schema is changed, initSchema should parse the new schema
@@ -571,13 +592,14 @@ func SetSchema(openAPIField map[string]string, schema []byte, reset bool) error
}
// use builtin version
kubernetesOpenAPIVersion = strings.ReplaceAll(version, ".", "")
kubernetesOpenAPIVersion = version
if kubernetesOpenAPIVersion == "" {
return nil
}
if _, ok := kubernetesapi.OpenAPIMustAsset[kubernetesOpenAPIVersion]; !ok {
return fmt.Errorf("the specified OpenAPI version is not built in")
}
customSchema = nil
// if the schema is changed, initSchema should parse the new schema
globalSchema.schemaInit = false
@@ -586,6 +608,9 @@ func SetSchema(openAPIField map[string]string, schema []byte, reset bool) error
// GetSchemaVersion returns what kubernetes OpenAPI version is being used
func GetSchemaVersion() string {
schemaLock.RLock()
defer schemaLock.RUnlock()
switch {
case kubernetesOpenAPIVersion == "" && customSchema == nil:
return kubernetesOpenAPIDefaultVersion
@@ -598,6 +623,9 @@ func GetSchemaVersion() string {
// initSchema parses the json schema
func initSchema() {
schemaLock.Lock()
defer schemaLock.Unlock()
if globalSchema.schemaInit {
return
}
@@ -607,7 +635,7 @@ func initSchema() {
if customSchema != nil {
err := parse(customSchema, JsonOrYaml)
if err != nil {
panic("invalid schema file")
panic(fmt.Errorf("invalid schema file: %w", err))
}
} else {
if kubernetesOpenAPIVersion == "" {
@@ -629,11 +657,10 @@ func parseBuiltinSchema(version string) {
// don't parse the built in schema
return
}
// parse the swagger, this should never fail
assetName := filepath.Join(
"kubernetesapi",
version,
strings.ReplaceAll(version, ".", "_"),
"swagger.pb")
if err := parse(kubernetesapi.OpenAPIMustAsset[version](assetName), Proto); err != nil {