mirror of https://github.com/kubevela/kubevela.git
Compare commits
14 Commits
826eafad33
...
4470a6d414
| Author | SHA1 | Date |
|---|---|---|
|
|
4470a6d414 | |
|
|
7cea5962d7 | |
|
|
13289a9f54 | |
|
|
411a68a454 | |
|
|
2fbc8bb5be | |
|
|
9fe67e70ec | |
|
|
4d94f90c9c | |
|
|
1aa47b47d6 | |
|
|
54b3c9982a | |
|
|
9c6dbaef11 | |
|
|
1b67bf9df0 | |
|
|
3612bedba3 | |
|
|
c5a86bed38 | |
|
|
d8c98f0910 |
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
standardcontroller "github.com/oam-dev/kubevela/pkg/controller"
|
||||
)
|
||||
|
||||
// AdmissionConfig contains admission control configuration.
|
||||
type AdmissionConfig struct {
|
||||
// Fields will be populated based on what standardcontroller.AddAdmissionFlags sets
|
||||
}
|
||||
|
||||
// NewAdmissionConfig creates a new AdmissionConfig with defaults.
|
||||
func NewAdmissionConfig() *AdmissionConfig {
|
||||
return &AdmissionConfig{}
|
||||
}
|
||||
|
||||
// AddFlags registers admission configuration flags.
|
||||
func (c *AdmissionConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
standardcontroller.AddAdmissionFlags(fs)
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
commonconfig "github.com/oam-dev/kubevela/pkg/controller/common"
|
||||
)
|
||||
|
||||
// ApplicationConfig contains application-specific configuration.
|
||||
type ApplicationConfig struct {
|
||||
ReSyncPeriod time.Duration
|
||||
}
|
||||
|
||||
// NewApplicationConfig creates a new ApplicationConfig with defaults.
|
||||
func NewApplicationConfig() *ApplicationConfig {
|
||||
return &ApplicationConfig{
|
||||
ReSyncPeriod: commonconfig.ApplicationReSyncPeriod,
|
||||
}
|
||||
}
|
||||
|
||||
// AddFlags registers application configuration flags.
|
||||
func (c *ApplicationConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.DurationVar(&c.ReSyncPeriod,
|
||||
"application-re-sync-period",
|
||||
c.ReSyncPeriod,
|
||||
"Re-sync period for application to re-sync, also known as the state-keep interval.")
|
||||
}
|
||||
|
||||
// SyncToApplicationGlobals syncs the parsed configuration values to application package global variables.
|
||||
// This should be called after flag parsing to ensure the application controller uses the configured values.
|
||||
//
|
||||
// NOTE: This method exists for backward compatibility with legacy code that depends on global
|
||||
// variables in the commonconfig package. Ideally, configuration should be injected rather than using globals.
|
||||
//
|
||||
// The flow is: CLI flags -> ApplicationConfig struct fields -> commonconfig globals (via this method)
|
||||
func (c *ApplicationConfig) SyncToApplicationGlobals() {
|
||||
commonconfig.ApplicationReSyncPeriod = c.ReSyncPeriod
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
pkgclient "github.com/kubevela/pkg/controller/client"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// ClientConfig contains controller client configuration.
|
||||
// This wraps the external package's client configuration flags.
|
||||
type ClientConfig struct {
|
||||
// Note: The actual configuration is managed by the pkgclient package
|
||||
// This is a wrapper to maintain consistency with our config pattern
|
||||
}
|
||||
|
||||
// NewClientConfig creates a new ClientConfig with defaults.
|
||||
func NewClientConfig() *ClientConfig {
|
||||
return &ClientConfig{}
|
||||
}
|
||||
|
||||
// AddFlags registers client configuration flags.
|
||||
// Delegates to the external package's flag registration.
|
||||
func (c *ClientConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
pkgclient.AddTimeoutControllerClientFlags(fs)
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
oamcontroller "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev"
|
||||
)
|
||||
|
||||
// ControllerConfig wraps the oamcontroller.Args configuration.
|
||||
// While this appears to duplicate the Args struct, it serves as the new home for
|
||||
// controller flag registration after the AddFlags method was moved here from
|
||||
// the oamcontroller package during refactoring.
|
||||
type ControllerConfig struct {
|
||||
// Embed the existing Args struct to reuse its fields
|
||||
oamcontroller.Args
|
||||
}
|
||||
|
||||
// NewControllerConfig creates a new ControllerConfig with defaults.
|
||||
func NewControllerConfig() *ControllerConfig {
|
||||
return &ControllerConfig{
|
||||
Args: oamcontroller.Args{
|
||||
RevisionLimit: 50,
|
||||
AppRevisionLimit: 10,
|
||||
DefRevisionLimit: 20,
|
||||
AutoGenWorkloadDefinition: true,
|
||||
ConcurrentReconciles: 4,
|
||||
IgnoreAppWithoutControllerRequirement: false,
|
||||
IgnoreDefinitionWithoutControllerRequirement: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// AddFlags registers controller configuration flags.
|
||||
// This method was moved here from oamcontroller.Args during refactoring
|
||||
// to centralize configuration management.
|
||||
func (c *ControllerConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.IntVar(&c.RevisionLimit, "revision-limit", c.RevisionLimit,
|
||||
"RevisionLimit is the maximum number of revisions that will be maintained. The default value is 50.")
|
||||
fs.IntVar(&c.AppRevisionLimit, "application-revision-limit", c.AppRevisionLimit,
|
||||
"application-revision-limit is the maximum number of application useless revisions that will be maintained, if the useless revisions exceed this number, older ones will be GCed first.The default value is 10.")
|
||||
fs.IntVar(&c.DefRevisionLimit, "definition-revision-limit", c.DefRevisionLimit,
|
||||
"definition-revision-limit is the maximum number of component/trait definition useless revisions that will be maintained, if the useless revisions exceed this number, older ones will be GCed first.The default value is 20.")
|
||||
fs.BoolVar(&c.AutoGenWorkloadDefinition, "autogen-workload-definition", c.AutoGenWorkloadDefinition,
|
||||
"Automatic generated workloadDefinition which componentDefinition refers to.")
|
||||
fs.IntVar(&c.ConcurrentReconciles, "concurrent-reconciles", c.ConcurrentReconciles,
|
||||
"concurrent-reconciles is the concurrent reconcile number of the controller. The default value is 4")
|
||||
fs.BoolVar(&c.IgnoreAppWithoutControllerRequirement, "ignore-app-without-controller-version", c.IgnoreAppWithoutControllerRequirement,
|
||||
"If true, application controller will not process the app without 'app.oam.dev/controller-version-require' annotation")
|
||||
fs.BoolVar(&c.IgnoreDefinitionWithoutControllerRequirement, "ignore-definition-without-controller-version", c.IgnoreDefinitionWithoutControllerRequirement,
|
||||
"If true, trait/component/workflowstep definition controller will not process the definition without 'definition.oam.dev/controller-version-require' annotation")
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
"github.com/kubevela/pkg/cue/cuex"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// CUEConfig contains CUE language configuration.
|
||||
type CUEConfig struct {
|
||||
EnableExternalPackage bool
|
||||
EnableExternalPackageWatch bool
|
||||
}
|
||||
|
||||
// NewCUEConfig creates a new CUEConfig with defaults.
|
||||
func NewCUEConfig() *CUEConfig {
|
||||
return &CUEConfig{
|
||||
EnableExternalPackage: cuex.EnableExternalPackageForDefaultCompiler,
|
||||
EnableExternalPackageWatch: cuex.EnableExternalPackageWatchForDefaultCompiler,
|
||||
}
|
||||
}
|
||||
|
||||
// AddFlags registers CUE configuration flags.
|
||||
func (c *CUEConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.BoolVar(&c.EnableExternalPackage,
|
||||
"enable-external-package-for-default-compiler",
|
||||
c.EnableExternalPackage,
|
||||
"Enable loading third-party CUE packages into the default CUE compiler. When enabled, external CUE packages can be imported and used in CUE templates.")
|
||||
fs.BoolVar(&c.EnableExternalPackageWatch,
|
||||
"enable-external-package-watch-for-default-compiler",
|
||||
c.EnableExternalPackageWatch,
|
||||
"Enable watching for changes in external CUE packages and automatically reload them when modified. Requires enable-external-package-for-default-compiler to be enabled.")
|
||||
}
|
||||
|
||||
// SyncToCUEGlobals syncs the parsed configuration values to CUE package global variables.
|
||||
// This should be called after flag parsing to ensure the CUE compiler uses the configured values.
|
||||
//
|
||||
// NOTE: This method exists for backward compatibility with legacy code that depends on global
|
||||
// variables in the cuex package. Ideally, the CUE compiler configuration should be injected
|
||||
// rather than relying on globals.
|
||||
//
|
||||
// The flow is: CLI flags -> CUEConfig struct fields -> cuex globals (via this method)
|
||||
func (c *CUEConfig) SyncToCUEGlobals() {
|
||||
cuex.EnableExternalPackageForDefaultCompiler = c.EnableExternalPackage
|
||||
cuex.EnableExternalPackageWatchForDefaultCompiler = c.EnableExternalPackageWatch
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
"github.com/spf13/pflag"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
)
|
||||
|
||||
// FeatureConfig contains feature gate configuration.
|
||||
// This wraps the Kubernetes feature gate system.
|
||||
type FeatureConfig struct {
|
||||
// Note: The actual configuration is managed by the utilfeature package
|
||||
// This is a wrapper to maintain consistency with our config pattern
|
||||
}
|
||||
|
||||
// NewFeatureConfig creates a new FeatureConfig with defaults.
|
||||
func NewFeatureConfig() *FeatureConfig {
|
||||
return &FeatureConfig{}
|
||||
}
|
||||
|
||||
// AddFlags registers feature gate configuration flags.
|
||||
// Delegates to the Kubernetes feature gate system.
|
||||
func (c *FeatureConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
utilfeature.DefaultMutableFeatureGate.AddFlag(fs)
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
utillog "github.com/kubevela/pkg/util/log"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// KLogConfig contains klog configuration.
|
||||
// This wraps the Kubernetes logging configuration.
|
||||
type KLogConfig struct {
|
||||
// Reference to observability config for log settings
|
||||
observability *ObservabilityConfig
|
||||
}
|
||||
|
||||
// NewKLogConfig creates a new KLogConfig.
|
||||
func NewKLogConfig(observability *ObservabilityConfig) *KLogConfig {
|
||||
return &KLogConfig{
|
||||
observability: observability,
|
||||
}
|
||||
}
|
||||
|
||||
// AddFlags registers klog configuration flags.
|
||||
func (c *KLogConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
// Add base klog flags
|
||||
utillog.AddFlags(fs)
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// KubernetesConfig contains Kubernetes API client configuration.
|
||||
type KubernetesConfig struct {
|
||||
QPS float64
|
||||
Burst int
|
||||
InformerSyncPeriod time.Duration
|
||||
}
|
||||
|
||||
// NewKubernetesConfig creates a new KubernetesConfig with defaults.
|
||||
func NewKubernetesConfig() *KubernetesConfig {
|
||||
return &KubernetesConfig{
|
||||
QPS: 50,
|
||||
Burst: 100,
|
||||
InformerSyncPeriod: 10 * time.Hour,
|
||||
}
|
||||
}
|
||||
|
||||
// AddFlags registers Kubernetes configuration flags.
|
||||
func (c *KubernetesConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.Float64Var(&c.QPS, "kube-api-qps", c.QPS,
|
||||
"the qps for reconcile clients. Low qps may lead to low throughput. High qps may give stress to api-server. Raise this value if concurrent-reconciles is set to be high.")
|
||||
fs.IntVar(&c.Burst, "kube-api-burst", c.Burst,
|
||||
"the burst for reconcile clients. Recommend setting it qps*2.")
|
||||
fs.DurationVar(&c.InformerSyncPeriod, "informer-sync-period", c.InformerSyncPeriod,
|
||||
"The re-sync period for informer in controller-runtime. This is a system-level configuration.")
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
pkgmulticluster "github.com/kubevela/pkg/multicluster"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// MultiClusterConfig contains multi-cluster configuration.
|
||||
type MultiClusterConfig struct {
|
||||
EnableClusterGateway bool
|
||||
EnableClusterMetrics bool
|
||||
ClusterMetricsInterval time.Duration
|
||||
}
|
||||
|
||||
// NewMultiClusterConfig creates a new MultiClusterConfig with defaults.
|
||||
func NewMultiClusterConfig() *MultiClusterConfig {
|
||||
return &MultiClusterConfig{
|
||||
EnableClusterGateway: false,
|
||||
EnableClusterMetrics: false,
|
||||
ClusterMetricsInterval: 15 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
// AddFlags registers multi-cluster configuration flags.
|
||||
func (c *MultiClusterConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.BoolVar(&c.EnableClusterGateway, "enable-cluster-gateway", c.EnableClusterGateway,
|
||||
"Enable cluster-gateway to use multicluster, disabled by default.")
|
||||
fs.BoolVar(&c.EnableClusterMetrics, "enable-cluster-metrics", c.EnableClusterMetrics,
|
||||
"Enable cluster-metrics-management to collect metrics from clusters with cluster-gateway, disabled by default. When this param is enabled, enable-cluster-gateway should be enabled")
|
||||
fs.DurationVar(&c.ClusterMetricsInterval, "cluster-metrics-interval", c.ClusterMetricsInterval,
|
||||
"The interval that ClusterMetricsMgr will collect metrics from clusters, default value is 15 seconds.")
|
||||
|
||||
// Also register additional multicluster flags from external package
|
||||
pkgmulticluster.AddFlags(fs)
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
)
|
||||
|
||||
// OAMConfig contains OAM-specific configuration.
|
||||
type OAMConfig struct {
|
||||
SystemDefinitionNamespace string
|
||||
}
|
||||
|
||||
// NewOAMConfig creates a new OAMConfig with defaults.
|
||||
func NewOAMConfig() *OAMConfig {
|
||||
return &OAMConfig{
|
||||
SystemDefinitionNamespace: "vela-system",
|
||||
}
|
||||
}
|
||||
|
||||
// AddFlags registers OAM configuration flags.
|
||||
func (c *OAMConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.StringVar(&c.SystemDefinitionNamespace,
|
||||
"system-definition-namespace",
|
||||
c.SystemDefinitionNamespace,
|
||||
"Define the namespace of the system-level definition")
|
||||
}
|
||||
|
||||
// SyncToOAMGlobals syncs the parsed configuration values to OAM package global variables.
|
||||
// This should be called after flag parsing to ensure the OAM runtime uses the configured values.
|
||||
//
|
||||
// NOTE: This method exists for backward compatibility with legacy code that depends on global
|
||||
// variables in the oam package. Ideally, configuration should be injected rather than using globals.
|
||||
//
|
||||
// The flow is: CLI flags -> OAMConfig struct fields -> oam globals (via this method)
|
||||
func (c *OAMConfig) SyncToOAMGlobals() {
|
||||
oam.SystemDefinitionNamespace = c.SystemDefinitionNamespace
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// ObservabilityConfig contains metrics and logging configuration.
|
||||
type ObservabilityConfig struct {
|
||||
MetricsAddr string
|
||||
LogFilePath string
|
||||
LogFileMaxSize uint64
|
||||
LogDebug bool
|
||||
DevLogs bool
|
||||
}
|
||||
|
||||
// NewObservabilityConfig creates a new ObservabilityConfig with defaults.
|
||||
func NewObservabilityConfig() *ObservabilityConfig {
|
||||
return &ObservabilityConfig{
|
||||
MetricsAddr: ":8080",
|
||||
LogFilePath: "",
|
||||
LogFileMaxSize: 1024,
|
||||
LogDebug: false,
|
||||
DevLogs: false,
|
||||
}
|
||||
}
|
||||
|
||||
// AddFlags registers observability configuration flags.
|
||||
func (c *ObservabilityConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.StringVar(&c.MetricsAddr, "metrics-addr", c.MetricsAddr,
|
||||
"The address the metric endpoint binds to.")
|
||||
fs.StringVar(&c.LogFilePath, "log-file-path", c.LogFilePath,
|
||||
"The file to write logs to.")
|
||||
fs.Uint64Var(&c.LogFileMaxSize, "log-file-max-size", c.LogFileMaxSize,
|
||||
"Defines the maximum size a log file can grow to, Unit is megabytes.")
|
||||
fs.BoolVar(&c.LogDebug, "log-debug", c.LogDebug,
|
||||
"Enable debug logs for development purpose")
|
||||
fs.BoolVar(&c.DevLogs, "dev-logs", c.DevLogs,
|
||||
"Enable ANSI color formatting for console logs (ignored when log-file-path is set)")
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
standardcontroller "github.com/oam-dev/kubevela/pkg/controller"
|
||||
commonconfig "github.com/oam-dev/kubevela/pkg/controller/common"
|
||||
)
|
||||
|
||||
// PerformanceConfig contains performance and optimization configuration.
|
||||
type PerformanceConfig struct {
|
||||
PerfEnabled bool
|
||||
}
|
||||
|
||||
// NewPerformanceConfig creates a new PerformanceConfig with defaults.
|
||||
func NewPerformanceConfig() *PerformanceConfig {
|
||||
return &PerformanceConfig{
|
||||
PerfEnabled: commonconfig.PerfEnabled,
|
||||
}
|
||||
}
|
||||
|
||||
// AddFlags registers performance configuration flags.
|
||||
func (c *PerformanceConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.BoolVar(&c.PerfEnabled,
|
||||
"perf-enabled",
|
||||
c.PerfEnabled,
|
||||
"Enable performance logging for controllers, disabled by default.")
|
||||
|
||||
// Add optimization flags from the standard controller
|
||||
standardcontroller.AddOptimizeFlags(fs)
|
||||
}
|
||||
|
||||
// SyncToPerformanceGlobals syncs the parsed configuration values to performance package global variables.
|
||||
// This should be called after flag parsing to ensure the performance monitoring uses the configured values.
|
||||
//
|
||||
// NOTE: This method exists for backward compatibility with legacy code that depends on global
|
||||
// variables in the commonconfig package. Ideally, configuration should be injected rather than using globals.
|
||||
//
|
||||
// The flow is: CLI flags -> PerformanceConfig struct fields -> commonconfig globals (via this method)
|
||||
func (c *PerformanceConfig) SyncToPerformanceGlobals() {
|
||||
commonconfig.PerfEnabled = c.PerfEnabled
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
"github.com/kubevela/pkg/util/profiling"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// ProfilingConfig contains profiling configuration.
|
||||
// This wraps the external package's profiling configuration flags.
|
||||
type ProfilingConfig struct {
|
||||
// Note: The actual configuration is managed by the profiling package
|
||||
// This is a wrapper to maintain consistency with our config pattern
|
||||
}
|
||||
|
||||
// NewProfilingConfig creates a new ProfilingConfig with defaults.
|
||||
func NewProfilingConfig() *ProfilingConfig {
|
||||
return &ProfilingConfig{}
|
||||
}
|
||||
|
||||
// AddFlags registers profiling configuration flags.
|
||||
// Delegates to the external package's flag registration.
|
||||
func (c *ProfilingConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
profiling.AddFlags(fs)
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
ctrlrec "github.com/kubevela/pkg/controller/reconciler"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// ReconcileConfig contains controller reconciliation configuration.
|
||||
// This wraps the external package's reconciler configuration flags.
|
||||
type ReconcileConfig struct {
|
||||
// Note: The actual configuration is managed by the ctrlrec package
|
||||
// This is a wrapper to maintain consistency with our config pattern
|
||||
}
|
||||
|
||||
// NewReconcileConfig creates a new ReconcileConfig with defaults.
|
||||
func NewReconcileConfig() *ReconcileConfig {
|
||||
return &ReconcileConfig{}
|
||||
}
|
||||
|
||||
// AddFlags registers reconcile configuration flags.
|
||||
// Delegates to the external package's flag registration.
|
||||
func (c *ReconcileConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
ctrlrec.AddFlags(fs)
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/resourcekeeper"
|
||||
)
|
||||
|
||||
// ResourceConfig contains resource management configuration.
|
||||
type ResourceConfig struct {
|
||||
MaxDispatchConcurrent int
|
||||
}
|
||||
|
||||
// NewResourceConfig creates a new ResourceConfig with defaults.
|
||||
func NewResourceConfig() *ResourceConfig {
|
||||
return &ResourceConfig{
|
||||
MaxDispatchConcurrent: 10,
|
||||
}
|
||||
}
|
||||
|
||||
// AddFlags registers resource configuration flags.
|
||||
func (c *ResourceConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.IntVar(&c.MaxDispatchConcurrent,
|
||||
"max-dispatch-concurrent",
|
||||
c.MaxDispatchConcurrent,
|
||||
"Set the max dispatch concurrent number, default is 10")
|
||||
}
|
||||
|
||||
// SyncToResourceGlobals syncs the parsed configuration values to resource package global variables.
|
||||
// This should be called after flag parsing to ensure the resource keeper uses the configured values.
|
||||
//
|
||||
// NOTE: This method exists for backward compatibility with legacy code that depends on global
|
||||
// variables in the resourcekeeper package. The long-term goal should be to refactor to use
|
||||
// dependency injection rather than globals.
|
||||
//
|
||||
// The flow is: CLI flags -> ResourceConfig struct fields -> resourcekeeper globals (via this method)
|
||||
func (c *ResourceConfig) SyncToResourceGlobals() {
|
||||
resourcekeeper.MaxDispatchConcurrent = c.MaxDispatchConcurrent
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// ServerConfig contains server-level configuration.
|
||||
type ServerConfig struct {
|
||||
HealthAddr string
|
||||
StorageDriver string
|
||||
EnableLeaderElection bool
|
||||
LeaderElectionNamespace string
|
||||
LeaseDuration time.Duration
|
||||
RenewDeadline time.Duration
|
||||
RetryPeriod time.Duration
|
||||
}
|
||||
|
||||
// NewServerConfig creates a new ServerConfig with defaults.
|
||||
func NewServerConfig() *ServerConfig {
|
||||
return &ServerConfig{
|
||||
HealthAddr: ":9440",
|
||||
StorageDriver: "Local",
|
||||
EnableLeaderElection: false,
|
||||
LeaderElectionNamespace: "",
|
||||
LeaseDuration: 15 * time.Second,
|
||||
RenewDeadline: 10 * time.Second,
|
||||
RetryPeriod: 2 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
// AddFlags registers server configuration flags.
|
||||
func (c *ServerConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.StringVar(&c.HealthAddr, "health-addr", c.HealthAddr,
|
||||
"The address the health endpoint binds to.")
|
||||
fs.StringVar(&c.StorageDriver, "storage-driver", c.StorageDriver,
|
||||
"Application storage driver.")
|
||||
fs.BoolVar(&c.EnableLeaderElection, "enable-leader-election", c.EnableLeaderElection,
|
||||
"Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.")
|
||||
fs.StringVar(&c.LeaderElectionNamespace, "leader-election-namespace", c.LeaderElectionNamespace,
|
||||
"Determines the namespace in which the leader election configmap will be created.")
|
||||
fs.DurationVar(&c.LeaseDuration, "leader-election-lease-duration", c.LeaseDuration,
|
||||
"The duration that non-leader candidates will wait to force acquire leadership")
|
||||
fs.DurationVar(&c.RenewDeadline, "leader-election-renew-deadline", c.RenewDeadline,
|
||||
"The duration that the acting controlplane will retry refreshing leadership before giving up")
|
||||
fs.DurationVar(&c.RetryPeriod, "leader-election-retry-period", c.RetryPeriod,
|
||||
"The duration the LeaderElector clients should wait between tries of actions")
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
"github.com/kubevela/pkg/controller/sharding"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// ShardingConfig contains controller sharding configuration.
|
||||
// This wraps the external package's sharding configuration flags.
|
||||
type ShardingConfig struct {
|
||||
// Note: The actual configuration is managed by the sharding package
|
||||
// This is a wrapper to maintain consistency with our config pattern
|
||||
}
|
||||
|
||||
// NewShardingConfig creates a new ShardingConfig with defaults.
|
||||
func NewShardingConfig() *ShardingConfig {
|
||||
return &ShardingConfig{}
|
||||
}
|
||||
|
||||
// AddFlags registers sharding configuration flags.
|
||||
// Delegates to the external package's flag registration.
|
||||
func (c *ShardingConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
sharding.AddFlags(fs)
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// WebhookConfig contains webhook configuration.
|
||||
type WebhookConfig struct {
|
||||
UseWebhook bool
|
||||
CertDir string
|
||||
WebhookPort int
|
||||
}
|
||||
|
||||
// NewWebhookConfig creates a new WebhookConfig with defaults.
|
||||
func NewWebhookConfig() *WebhookConfig {
|
||||
return &WebhookConfig{
|
||||
UseWebhook: false,
|
||||
CertDir: "/k8s-webhook-server/serving-certs",
|
||||
WebhookPort: 9443,
|
||||
}
|
||||
}
|
||||
|
||||
// AddFlags registers webhook configuration flags.
|
||||
func (c *WebhookConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.BoolVar(&c.UseWebhook, "use-webhook", c.UseWebhook,
|
||||
"Enable Admission Webhook")
|
||||
fs.StringVar(&c.CertDir, "webhook-cert-dir", c.CertDir,
|
||||
"Admission webhook cert/key dir.")
|
||||
fs.IntVar(&c.WebhookPort, "webhook-port", c.WebhookPort,
|
||||
"admission webhook listen address")
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
Copyright 2025 The KubeVela 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 config
|
||||
|
||||
import (
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
wfTypes "github.com/kubevela/workflow/pkg/types"
|
||||
)
|
||||
|
||||
// WorkflowConfig contains workflow engine configuration.
|
||||
type WorkflowConfig struct {
|
||||
MaxWaitBackoffTime int
|
||||
MaxFailedBackoffTime int
|
||||
MaxStepErrorRetryTimes int
|
||||
}
|
||||
|
||||
// NewWorkflowConfig creates a new WorkflowConfig with defaults.
|
||||
func NewWorkflowConfig() *WorkflowConfig {
|
||||
return &WorkflowConfig{
|
||||
MaxWaitBackoffTime: 60,
|
||||
MaxFailedBackoffTime: 300,
|
||||
MaxStepErrorRetryTimes: 10,
|
||||
}
|
||||
}
|
||||
|
||||
// AddFlags registers workflow configuration flags.
|
||||
func (c *WorkflowConfig) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.IntVar(&c.MaxWaitBackoffTime,
|
||||
"max-workflow-wait-backoff-time",
|
||||
c.MaxWaitBackoffTime,
|
||||
"Set the max workflow wait backoff time, default is 60")
|
||||
fs.IntVar(&c.MaxFailedBackoffTime,
|
||||
"max-workflow-failed-backoff-time",
|
||||
c.MaxFailedBackoffTime,
|
||||
"Set the max workflow failed backoff time, default is 300")
|
||||
fs.IntVar(&c.MaxStepErrorRetryTimes,
|
||||
"max-workflow-step-error-retry-times",
|
||||
c.MaxStepErrorRetryTimes,
|
||||
"Set the max workflow step error retry times, default is 10")
|
||||
}
|
||||
|
||||
// SyncToWorkflowGlobals syncs the parsed configuration values to workflow package global variables.
|
||||
// This should be called after flag parsing to ensure the workflow engine uses the configured values.
|
||||
//
|
||||
// NOTE: This method exists for backward compatibility with legacy code that depends on global
|
||||
// variables in the wfTypes package. The long-term goal should be to refactor the workflow
|
||||
// package to accept configuration via dependency injection rather than globals.
|
||||
//
|
||||
// The flow is: CLI flags -> WorkflowConfig struct fields -> wfTypes globals (via this method)
|
||||
func (c *WorkflowConfig) SyncToWorkflowGlobals() {
|
||||
wfTypes.MaxWorkflowWaitBackoffTime = c.MaxWaitBackoffTime
|
||||
wfTypes.MaxWorkflowFailedBackoffTime = c.MaxFailedBackoffTime
|
||||
wfTypes.MaxWorkflowStepErrorRetryTimes = c.MaxStepErrorRetryTimes
|
||||
}
|
||||
|
|
@ -17,88 +17,81 @@ limitations under the License.
|
|||
package options
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/kubevela/pkg/cue/cuex"
|
||||
|
||||
pkgclient "github.com/kubevela/pkg/controller/client"
|
||||
ctrlrec "github.com/kubevela/pkg/controller/reconciler"
|
||||
"github.com/kubevela/pkg/controller/sharding"
|
||||
pkgmulticluster "github.com/kubevela/pkg/multicluster"
|
||||
utillog "github.com/kubevela/pkg/util/log"
|
||||
"github.com/kubevela/pkg/util/profiling"
|
||||
wfTypes "github.com/kubevela/workflow/pkg/types"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
cliflag "k8s.io/component-base/cli/flag"
|
||||
|
||||
standardcontroller "github.com/oam-dev/kubevela/pkg/controller"
|
||||
commonconfig "github.com/oam-dev/kubevela/pkg/controller/common"
|
||||
oamcontroller "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
"github.com/oam-dev/kubevela/pkg/resourcekeeper"
|
||||
"github.com/oam-dev/kubevela/cmd/core/app/config"
|
||||
)
|
||||
|
||||
// CoreOptions contains everything necessary to create and run vela-core
|
||||
type CoreOptions struct {
|
||||
UseWebhook bool
|
||||
CertDir string
|
||||
WebhookPort int
|
||||
MetricsAddr string
|
||||
EnableLeaderElection bool
|
||||
LeaderElectionNamespace string
|
||||
LogFilePath string
|
||||
LogFileMaxSize uint64
|
||||
LogDebug bool
|
||||
DevLogs bool
|
||||
ControllerArgs *oamcontroller.Args
|
||||
HealthAddr string
|
||||
StorageDriver string
|
||||
InformerSyncPeriod time.Duration
|
||||
QPS float64
|
||||
Burst int
|
||||
LeaseDuration time.Duration
|
||||
RenewDeadLine time.Duration
|
||||
RetryPeriod time.Duration
|
||||
EnableClusterGateway bool
|
||||
EnableClusterMetrics bool
|
||||
ClusterMetricsInterval time.Duration
|
||||
// Config modules - clean, well-organized configuration
|
||||
Server *config.ServerConfig
|
||||
Webhook *config.WebhookConfig
|
||||
Observability *config.ObservabilityConfig
|
||||
Kubernetes *config.KubernetesConfig
|
||||
MultiCluster *config.MultiClusterConfig
|
||||
CUE *config.CUEConfig
|
||||
Application *config.ApplicationConfig
|
||||
OAM *config.OAMConfig
|
||||
Performance *config.PerformanceConfig
|
||||
Workflow *config.WorkflowConfig
|
||||
Admission *config.AdmissionConfig
|
||||
Resource *config.ResourceConfig
|
||||
Client *config.ClientConfig
|
||||
Reconcile *config.ReconcileConfig
|
||||
Sharding *config.ShardingConfig
|
||||
Feature *config.FeatureConfig
|
||||
Profiling *config.ProfilingConfig
|
||||
KLog *config.KLogConfig
|
||||
Controller *config.ControllerConfig
|
||||
}
|
||||
|
||||
// NewCoreOptions creates a new NewVelaCoreOptions object with default parameters
|
||||
func NewCoreOptions() *CoreOptions {
|
||||
// Initialize config modules
|
||||
server := config.NewServerConfig()
|
||||
webhook := config.NewWebhookConfig()
|
||||
observability := config.NewObservabilityConfig()
|
||||
kubernetes := config.NewKubernetesConfig()
|
||||
multiCluster := config.NewMultiClusterConfig()
|
||||
cue := config.NewCUEConfig()
|
||||
application := config.NewApplicationConfig()
|
||||
oam := config.NewOAMConfig()
|
||||
performance := config.NewPerformanceConfig()
|
||||
workflow := config.NewWorkflowConfig()
|
||||
admission := config.NewAdmissionConfig()
|
||||
resource := config.NewResourceConfig()
|
||||
client := config.NewClientConfig()
|
||||
reconcile := config.NewReconcileConfig()
|
||||
sharding := config.NewShardingConfig()
|
||||
feature := config.NewFeatureConfig()
|
||||
profiling := config.NewProfilingConfig()
|
||||
klog := config.NewKLogConfig(observability)
|
||||
controller := config.NewControllerConfig()
|
||||
|
||||
s := &CoreOptions{
|
||||
UseWebhook: false,
|
||||
CertDir: "/k8s-webhook-server/serving-certs",
|
||||
WebhookPort: 9443,
|
||||
MetricsAddr: ":8080",
|
||||
EnableLeaderElection: false,
|
||||
LeaderElectionNamespace: "",
|
||||
LogFilePath: "",
|
||||
LogFileMaxSize: 1024,
|
||||
LogDebug: false,
|
||||
DevLogs: false,
|
||||
ControllerArgs: &oamcontroller.Args{
|
||||
RevisionLimit: 50,
|
||||
AppRevisionLimit: 10,
|
||||
DefRevisionLimit: 20,
|
||||
AutoGenWorkloadDefinition: true,
|
||||
ConcurrentReconciles: 4,
|
||||
IgnoreAppWithoutControllerRequirement: false,
|
||||
IgnoreDefinitionWithoutControllerRequirement: false,
|
||||
},
|
||||
HealthAddr: ":9440",
|
||||
StorageDriver: "Local",
|
||||
InformerSyncPeriod: 10 * time.Hour,
|
||||
QPS: 50,
|
||||
Burst: 100,
|
||||
LeaseDuration: 15 * time.Second,
|
||||
RenewDeadLine: 10 * time.Second,
|
||||
RetryPeriod: 2 * time.Second,
|
||||
EnableClusterGateway: false,
|
||||
EnableClusterMetrics: false,
|
||||
ClusterMetricsInterval: 15 * time.Second,
|
||||
// Config modules
|
||||
Server: server,
|
||||
Webhook: webhook,
|
||||
Observability: observability,
|
||||
Kubernetes: kubernetes,
|
||||
MultiCluster: multiCluster,
|
||||
CUE: cue,
|
||||
Application: application,
|
||||
OAM: oam,
|
||||
Performance: performance,
|
||||
Workflow: workflow,
|
||||
Admission: admission,
|
||||
Resource: resource,
|
||||
Client: client,
|
||||
Reconcile: reconcile,
|
||||
Sharding: sharding,
|
||||
Feature: feature,
|
||||
Profiling: profiling,
|
||||
KLog: klog,
|
||||
Controller: controller,
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
|
|
@ -106,75 +99,28 @@ func NewCoreOptions() *CoreOptions {
|
|||
func (s *CoreOptions) Flags() cliflag.NamedFlagSets {
|
||||
fss := cliflag.NamedFlagSets{}
|
||||
|
||||
gfs := fss.FlagSet("generic")
|
||||
gfs.BoolVar(&s.UseWebhook, "use-webhook", s.UseWebhook, "Enable Admission Webhook")
|
||||
gfs.StringVar(&s.CertDir, "webhook-cert-dir", s.CertDir, "Admission webhook cert/key dir.")
|
||||
gfs.IntVar(&s.WebhookPort, "webhook-port", s.WebhookPort, "admission webhook listen address")
|
||||
gfs.StringVar(&s.MetricsAddr, "metrics-addr", s.MetricsAddr, "The address the metric endpoint binds to.")
|
||||
gfs.BoolVar(&s.EnableLeaderElection, "enable-leader-election", s.EnableLeaderElection,
|
||||
"Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.")
|
||||
gfs.StringVar(&s.LeaderElectionNamespace, "leader-election-namespace", s.LeaderElectionNamespace,
|
||||
"Determines the namespace in which the leader election configmap will be created.")
|
||||
gfs.StringVar(&s.LogFilePath, "log-file-path", s.LogFilePath, "The file to write logs to.")
|
||||
gfs.Uint64Var(&s.LogFileMaxSize, "log-file-max-size", s.LogFileMaxSize, "Defines the maximum size a log file can grow to, Unit is megabytes.")
|
||||
gfs.BoolVar(&s.LogDebug, "log-debug", s.LogDebug, "Enable debug logs for development purpose")
|
||||
gfs.BoolVar(&s.DevLogs, "dev-logs", s.DevLogs, "Enable ANSI color formatting for console logs (ignored when log-file-path is set)")
|
||||
gfs.StringVar(&s.HealthAddr, "health-addr", s.HealthAddr, "The address the health endpoint binds to.")
|
||||
gfs.DurationVar(&s.InformerSyncPeriod, "informer-sync-period", s.InformerSyncPeriod,
|
||||
"The re-sync period for informer in controller-runtime. This is a system-level configuration.")
|
||||
gfs.Float64Var(&s.QPS, "kube-api-qps", s.QPS, "the qps for reconcile clients. Low qps may lead to low throughput. High qps may give stress to api-server. Raise this value if concurrent-reconciles is set to be high.")
|
||||
gfs.IntVar(&s.Burst, "kube-api-burst", s.Burst, "the burst for reconcile clients. Recommend setting it qps*2.")
|
||||
gfs.DurationVar(&s.LeaseDuration, "leader-election-lease-duration", s.LeaseDuration,
|
||||
"The duration that non-leader candidates will wait to force acquire leadership")
|
||||
gfs.DurationVar(&s.RenewDeadLine, "leader-election-renew-deadline", s.RenewDeadLine,
|
||||
"The duration that the acting controlplane will retry refreshing leadership before giving up")
|
||||
gfs.DurationVar(&s.RetryPeriod, "leader-election-retry-period", s.RetryPeriod,
|
||||
"The duration the LeaderElector clients should wait between tries of actions")
|
||||
gfs.BoolVar(&s.EnableClusterGateway, "enable-cluster-gateway", s.EnableClusterGateway, "Enable cluster-gateway to use multicluster, disabled by default.")
|
||||
gfs.BoolVar(&s.EnableClusterMetrics, "enable-cluster-metrics", s.EnableClusterMetrics, "Enable cluster-metrics-management to collect metrics from clusters with cluster-gateway, disabled by default. When this param is enabled, enable-cluster-gateway should be enabled")
|
||||
gfs.DurationVar(&s.ClusterMetricsInterval, "cluster-metrics-interval", s.ClusterMetricsInterval, "The interval that ClusterMetricsMgr will collect metrics from clusters, default value is 15 seconds.")
|
||||
gfs.BoolVar(&cuex.EnableExternalPackageForDefaultCompiler, "enable-external-package-for-default-compiler", cuex.EnableExternalPackageForDefaultCompiler, "Enable external package for default compiler")
|
||||
gfs.BoolVar(&cuex.EnableExternalPackageWatchForDefaultCompiler, "enable-external-package-watch-for-default-compiler", cuex.EnableExternalPackageWatchForDefaultCompiler, "Enable external package watch for default compiler")
|
||||
// Use config modules to register flags - clean delegation pattern
|
||||
s.Server.AddFlags(fss.FlagSet("server"))
|
||||
s.Webhook.AddFlags(fss.FlagSet("webhook"))
|
||||
s.Observability.AddFlags(fss.FlagSet("observability"))
|
||||
s.Kubernetes.AddFlags(fss.FlagSet("kubernetes"))
|
||||
s.MultiCluster.AddFlags(fss.FlagSet("multicluster"))
|
||||
s.CUE.AddFlags(fss.FlagSet("cue"))
|
||||
s.Application.AddFlags(fss.FlagSet("application"))
|
||||
s.OAM.AddFlags(fss.FlagSet("oam"))
|
||||
s.Performance.AddFlags(fss.FlagSet("performance"))
|
||||
s.Admission.AddFlags(fss.FlagSet("admission"))
|
||||
s.Resource.AddFlags(fss.FlagSet("resource"))
|
||||
s.Workflow.AddFlags(fss.FlagSet("workflow"))
|
||||
s.Controller.AddFlags(fss.FlagSet("controller"))
|
||||
|
||||
s.ControllerArgs.AddFlags(fss.FlagSet("controllerArgs"), s.ControllerArgs)
|
||||
|
||||
cfs := fss.FlagSet("commonconfig")
|
||||
cfs.DurationVar(&commonconfig.ApplicationReSyncPeriod, "application-re-sync-period", commonconfig.ApplicationReSyncPeriod,
|
||||
"Re-sync period for application to re-sync, also known as the state-keep interval.")
|
||||
cfs.BoolVar(&commonconfig.PerfEnabled, "perf-enabled", commonconfig.PerfEnabled, "Enable performance logging for controllers, disabled by default.")
|
||||
|
||||
ofs := fss.FlagSet("oam")
|
||||
ofs.StringVar(&oam.SystemDefinitionNamespace, "system-definition-namespace", "vela-system", "define the namespace of the system-level definition")
|
||||
|
||||
standardcontroller.AddOptimizeFlags(fss.FlagSet("optimize"))
|
||||
standardcontroller.AddAdmissionFlags(fss.FlagSet("admission"))
|
||||
|
||||
rfs := fss.FlagSet("resourcekeeper")
|
||||
rfs.IntVar(&resourcekeeper.MaxDispatchConcurrent, "max-dispatch-concurrent", 10, "Set the max dispatch concurrent number, default is 10")
|
||||
|
||||
wfs := fss.FlagSet("wfTypes")
|
||||
wfs.IntVar(&wfTypes.MaxWorkflowWaitBackoffTime, "max-workflow-wait-backoff-time", 60, "Set the max workflow wait backoff time, default is 60")
|
||||
wfs.IntVar(&wfTypes.MaxWorkflowFailedBackoffTime, "max-workflow-failed-backoff-time", 300, "Set the max workflow failed backoff time, default is 300")
|
||||
wfs.IntVar(&wfTypes.MaxWorkflowStepErrorRetryTimes, "max-workflow-step-error-retry-times", 10, "Set the max workflow step error retry times, default is 10")
|
||||
|
||||
pkgmulticluster.AddFlags(fss.FlagSet("multicluster"))
|
||||
ctrlrec.AddFlags(fss.FlagSet("controllerreconciles"))
|
||||
utilfeature.DefaultMutableFeatureGate.AddFlag(fss.FlagSet("featuregate"))
|
||||
sharding.AddFlags(fss.FlagSet("sharding"))
|
||||
kfs := fss.FlagSet("klog")
|
||||
pkgclient.AddTimeoutControllerClientFlags(fss.FlagSet("controllerclient"))
|
||||
utillog.AddFlags(kfs)
|
||||
profiling.AddFlags(fss.FlagSet("profiling"))
|
||||
|
||||
if s.LogDebug {
|
||||
_ = kfs.Set("v", strconv.Itoa(int(commonconfig.LogDebug)))
|
||||
}
|
||||
|
||||
if s.LogFilePath != "" {
|
||||
_ = kfs.Set("logtostderr", "false")
|
||||
_ = kfs.Set("log_file", s.LogFilePath)
|
||||
_ = kfs.Set("log_file_max_size", strconv.FormatUint(s.LogFileMaxSize, 10))
|
||||
}
|
||||
// External package configurations (now wrapped in config modules)
|
||||
s.Client.AddFlags(fss.FlagSet("client"))
|
||||
s.Reconcile.AddFlags(fss.FlagSet("reconcile"))
|
||||
s.Sharding.AddFlags(fss.FlagSet("sharding"))
|
||||
s.Feature.AddFlags(fss.FlagSet("feature"))
|
||||
s.Profiling.AddFlags(fss.FlagSet("profiling"))
|
||||
s.KLog.AddFlags(fss.FlagSet("klog"))
|
||||
|
||||
return fss
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,104 +20,915 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/kubevela/pkg/cue/cuex"
|
||||
wfTypes "github.com/kubevela/workflow/pkg/types"
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
oamcontroller "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev"
|
||||
commonconfig "github.com/oam-dev/kubevela/pkg/controller/common"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
"github.com/oam-dev/kubevela/pkg/resourcekeeper"
|
||||
)
|
||||
|
||||
func TestCoreOptions_Flags(t *testing.T) {
|
||||
func TestNewCoreOptions_DefaultValues(t *testing.T) {
|
||||
opt := NewCoreOptions()
|
||||
|
||||
// Test Server defaults
|
||||
assert.Equal(t, ":9440", opt.Server.HealthAddr)
|
||||
assert.Equal(t, "Local", opt.Server.StorageDriver)
|
||||
assert.Equal(t, false, opt.Server.EnableLeaderElection)
|
||||
assert.Equal(t, "", opt.Server.LeaderElectionNamespace)
|
||||
assert.Equal(t, 15*time.Second, opt.Server.LeaseDuration)
|
||||
assert.Equal(t, 10*time.Second, opt.Server.RenewDeadline)
|
||||
assert.Equal(t, 2*time.Second, opt.Server.RetryPeriod)
|
||||
|
||||
// Test Webhook defaults
|
||||
assert.Equal(t, false, opt.Webhook.UseWebhook)
|
||||
assert.Equal(t, "/k8s-webhook-server/serving-certs", opt.Webhook.CertDir)
|
||||
assert.Equal(t, 9443, opt.Webhook.WebhookPort)
|
||||
|
||||
// Test Observability defaults
|
||||
assert.Equal(t, ":8080", opt.Observability.MetricsAddr)
|
||||
assert.Equal(t, false, opt.Observability.LogDebug)
|
||||
assert.Equal(t, "", opt.Observability.LogFilePath)
|
||||
assert.Equal(t, uint64(1024), opt.Observability.LogFileMaxSize)
|
||||
|
||||
// Test Kubernetes defaults
|
||||
assert.Equal(t, 10*time.Hour, opt.Kubernetes.InformerSyncPeriod)
|
||||
assert.Equal(t, float64(50), opt.Kubernetes.QPS)
|
||||
assert.Equal(t, 100, opt.Kubernetes.Burst)
|
||||
|
||||
// Test MultiCluster defaults
|
||||
assert.Equal(t, false, opt.MultiCluster.EnableClusterGateway)
|
||||
assert.Equal(t, false, opt.MultiCluster.EnableClusterMetrics)
|
||||
assert.Equal(t, 15*time.Second, opt.MultiCluster.ClusterMetricsInterval)
|
||||
|
||||
// Test CUE defaults
|
||||
assert.NotNil(t, opt.CUE)
|
||||
|
||||
// Test Application defaults
|
||||
assert.Equal(t, 5*time.Minute, opt.Application.ReSyncPeriod)
|
||||
|
||||
// Test OAM defaults
|
||||
assert.Equal(t, "vela-system", opt.OAM.SystemDefinitionNamespace)
|
||||
|
||||
// Test Performance defaults
|
||||
assert.Equal(t, false, opt.Performance.PerfEnabled)
|
||||
|
||||
// Test Controller defaults
|
||||
assert.Equal(t, 50, opt.Controller.RevisionLimit)
|
||||
assert.Equal(t, 10, opt.Controller.AppRevisionLimit)
|
||||
assert.Equal(t, 20, opt.Controller.DefRevisionLimit)
|
||||
assert.Equal(t, true, opt.Controller.AutoGenWorkloadDefinition)
|
||||
assert.Equal(t, 4, opt.Controller.ConcurrentReconciles)
|
||||
assert.Equal(t, false, opt.Controller.IgnoreAppWithoutControllerRequirement)
|
||||
assert.Equal(t, false, opt.Controller.IgnoreDefinitionWithoutControllerRequirement)
|
||||
|
||||
// Test Workflow defaults
|
||||
assert.Equal(t, 60, opt.Workflow.MaxWaitBackoffTime)
|
||||
assert.Equal(t, 300, opt.Workflow.MaxFailedBackoffTime)
|
||||
assert.Equal(t, 10, opt.Workflow.MaxStepErrorRetryTimes)
|
||||
|
||||
// Test Resource defaults
|
||||
assert.Equal(t, 10, opt.Resource.MaxDispatchConcurrent)
|
||||
|
||||
// Ensure all config modules are initialized
|
||||
assert.NotNil(t, opt.Admission)
|
||||
assert.NotNil(t, opt.Client)
|
||||
assert.NotNil(t, opt.Reconcile)
|
||||
assert.NotNil(t, opt.Sharding)
|
||||
assert.NotNil(t, opt.Feature)
|
||||
assert.NotNil(t, opt.Profiling)
|
||||
assert.NotNil(t, opt.KLog)
|
||||
assert.NotNil(t, opt.Controller)
|
||||
}
|
||||
|
||||
func TestCoreOptions_FlagsCompleteSet(t *testing.T) {
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
opt := &CoreOptions{
|
||||
ControllerArgs: &oamcontroller.Args{},
|
||||
}
|
||||
opt := NewCoreOptions()
|
||||
|
||||
for _, f := range opt.Flags().FlagSets {
|
||||
fs.AddFlagSet(f)
|
||||
}
|
||||
|
||||
args := []string{
|
||||
"--application-re-sync-period=5s",
|
||||
"--cluster-metrics-interval=5s",
|
||||
"--enable-cluster-gateway=true",
|
||||
"--enable-cluster-metrics=true",
|
||||
"--enable-leader-election=true",
|
||||
// Server flags
|
||||
"--health-addr=/healthz",
|
||||
"--informer-sync-period=3s",
|
||||
"--kube-api-burst=500",
|
||||
"--kube-api-qps=200",
|
||||
"--leader-election-lease-duration=3s",
|
||||
"--storage-driver=MongoDB",
|
||||
"--enable-leader-election=true",
|
||||
"--leader-election-namespace=test-namespace",
|
||||
"--leader-election-lease-duration=3s",
|
||||
"--leader-election-renew-deadline=5s",
|
||||
"--leader-election-retry-period=3s",
|
||||
"--log-debug=true",
|
||||
"--log-file-max-size=50",
|
||||
"--log-file-path=/path/to/log",
|
||||
"--max-dispatch-concurrent=5",
|
||||
"--max-workflow-failed-backoff-time=30",
|
||||
"--max-workflow-step-error-retry-times=5",
|
||||
"--max-workflow-wait-backoff-time=5",
|
||||
"--metrics-addr=/metrics",
|
||||
"--perf-enabled=true",
|
||||
// Webhook flags
|
||||
"--use-webhook=true",
|
||||
"--webhook-cert-dir=/path/to/cert",
|
||||
"--webhook-port=8080",
|
||||
// Observability flags
|
||||
"--metrics-addr=/metrics",
|
||||
"--log-debug=true",
|
||||
"--log-file-path=/path/to/log",
|
||||
"--log-file-max-size=50",
|
||||
// Kubernetes flags
|
||||
"--informer-sync-period=3s",
|
||||
"--kube-api-qps=200",
|
||||
"--kube-api-burst=500",
|
||||
// MultiCluster flags
|
||||
"--enable-cluster-gateway=true",
|
||||
"--enable-cluster-metrics=true",
|
||||
"--cluster-metrics-interval=5s",
|
||||
// CUE flags
|
||||
"--enable-external-package-for-default-compiler=true",
|
||||
"--enable-external-package-watch-for-default-compiler=true",
|
||||
// Application flags
|
||||
"--application-re-sync-period=5s",
|
||||
// OAM flags
|
||||
"--system-definition-namespace=custom-namespace",
|
||||
// Performance flags
|
||||
"--perf-enabled=true",
|
||||
// Controller flags
|
||||
"--revision-limit=100",
|
||||
"--application-revision-limit=20",
|
||||
"--definition-revision-limit=30",
|
||||
"--autogen-workload-definition=false",
|
||||
"--concurrent-reconciles=8",
|
||||
"--ignore-app-without-controller-version=true",
|
||||
"--ignore-definition-without-controller-version=true",
|
||||
// Workflow flags
|
||||
"--max-workflow-wait-backoff-time=30",
|
||||
"--max-workflow-failed-backoff-time=150",
|
||||
"--max-workflow-step-error-retry-times=5",
|
||||
// Resource flags
|
||||
"--max-dispatch-concurrent=5",
|
||||
}
|
||||
|
||||
if err := fs.Parse(args); err != nil {
|
||||
t.Errorf("Failed to parse args: %v", err)
|
||||
}
|
||||
err := fs.Parse(args)
|
||||
require.NoError(t, err)
|
||||
|
||||
expected := &CoreOptions{
|
||||
UseWebhook: true,
|
||||
CertDir: "/path/to/cert",
|
||||
WebhookPort: 8080,
|
||||
MetricsAddr: "/metrics",
|
||||
EnableLeaderElection: true,
|
||||
LeaderElectionNamespace: "test-namespace",
|
||||
LogFilePath: "/path/to/log",
|
||||
LogFileMaxSize: 50,
|
||||
LogDebug: true,
|
||||
ControllerArgs: &oamcontroller.Args{},
|
||||
HealthAddr: "/healthz",
|
||||
StorageDriver: "",
|
||||
InformerSyncPeriod: 3 * time.Second,
|
||||
QPS: 200,
|
||||
Burst: 500,
|
||||
LeaseDuration: 3 * time.Second,
|
||||
RenewDeadLine: 5 * time.Second,
|
||||
RetryPeriod: 3 * time.Second,
|
||||
EnableClusterGateway: true,
|
||||
EnableClusterMetrics: true,
|
||||
ClusterMetricsInterval: 5 * time.Second,
|
||||
}
|
||||
// Verify Server flags
|
||||
assert.Equal(t, "/healthz", opt.Server.HealthAddr)
|
||||
assert.Equal(t, "MongoDB", opt.Server.StorageDriver)
|
||||
assert.Equal(t, true, opt.Server.EnableLeaderElection)
|
||||
assert.Equal(t, "test-namespace", opt.Server.LeaderElectionNamespace)
|
||||
assert.Equal(t, 3*time.Second, opt.Server.LeaseDuration)
|
||||
assert.Equal(t, 5*time.Second, opt.Server.RenewDeadline)
|
||||
assert.Equal(t, 3*time.Second, opt.Server.RetryPeriod)
|
||||
|
||||
if !cmp.Equal(opt, expected, cmp.AllowUnexported(CoreOptions{})) {
|
||||
t.Errorf("Flags() diff: %v", cmp.Diff(opt, expected, cmp.AllowUnexported(CoreOptions{})))
|
||||
}
|
||||
// Verify Webhook flags
|
||||
assert.Equal(t, true, opt.Webhook.UseWebhook)
|
||||
assert.Equal(t, "/path/to/cert", opt.Webhook.CertDir)
|
||||
assert.Equal(t, 8080, opt.Webhook.WebhookPort)
|
||||
|
||||
// Verify Observability flags
|
||||
assert.Equal(t, "/metrics", opt.Observability.MetricsAddr)
|
||||
assert.Equal(t, true, opt.Observability.LogDebug)
|
||||
assert.Equal(t, "/path/to/log", opt.Observability.LogFilePath)
|
||||
assert.Equal(t, uint64(50), opt.Observability.LogFileMaxSize)
|
||||
|
||||
// Verify Kubernetes flags
|
||||
assert.Equal(t, 3*time.Second, opt.Kubernetes.InformerSyncPeriod)
|
||||
assert.Equal(t, float64(200), opt.Kubernetes.QPS)
|
||||
assert.Equal(t, 500, opt.Kubernetes.Burst)
|
||||
|
||||
// Verify MultiCluster flags
|
||||
assert.Equal(t, true, opt.MultiCluster.EnableClusterGateway)
|
||||
assert.Equal(t, true, opt.MultiCluster.EnableClusterMetrics)
|
||||
assert.Equal(t, 5*time.Second, opt.MultiCluster.ClusterMetricsInterval)
|
||||
|
||||
// Verify CUE flags
|
||||
assert.True(t, opt.CUE.EnableExternalPackage)
|
||||
assert.True(t, opt.CUE.EnableExternalPackageWatch)
|
||||
|
||||
// Verify Application flags
|
||||
assert.Equal(t, 5*time.Second, opt.Application.ReSyncPeriod)
|
||||
|
||||
// Verify OAM flags
|
||||
assert.Equal(t, "custom-namespace", opt.OAM.SystemDefinitionNamespace)
|
||||
|
||||
// Verify Performance flags
|
||||
assert.Equal(t, true, opt.Performance.PerfEnabled)
|
||||
|
||||
// Verify Controller flags
|
||||
assert.Equal(t, 100, opt.Controller.RevisionLimit)
|
||||
assert.Equal(t, 20, opt.Controller.AppRevisionLimit)
|
||||
assert.Equal(t, 30, opt.Controller.DefRevisionLimit)
|
||||
assert.Equal(t, false, opt.Controller.AutoGenWorkloadDefinition)
|
||||
assert.Equal(t, 8, opt.Controller.ConcurrentReconciles)
|
||||
assert.Equal(t, true, opt.Controller.IgnoreAppWithoutControllerRequirement)
|
||||
assert.Equal(t, true, opt.Controller.IgnoreDefinitionWithoutControllerRequirement)
|
||||
|
||||
// Verify Workflow flags
|
||||
assert.Equal(t, 30, opt.Workflow.MaxWaitBackoffTime)
|
||||
assert.Equal(t, 150, opt.Workflow.MaxFailedBackoffTime)
|
||||
assert.Equal(t, 5, opt.Workflow.MaxStepErrorRetryTimes)
|
||||
|
||||
// Verify Resource flags
|
||||
assert.Equal(t, 5, opt.Resource.MaxDispatchConcurrent)
|
||||
}
|
||||
|
||||
func TestCuexOptions_Flags(t *testing.T) {
|
||||
pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
func TestCuexOptions_SyncToGlobals(t *testing.T) {
|
||||
// Reset globals
|
||||
cuex.EnableExternalPackageForDefaultCompiler = false
|
||||
cuex.EnableExternalPackageWatchForDefaultCompiler = false
|
||||
|
||||
opts := &CoreOptions{
|
||||
ControllerArgs: &oamcontroller.Args{},
|
||||
}
|
||||
opts := NewCoreOptions()
|
||||
fss := opts.Flags()
|
||||
|
||||
args := []string{
|
||||
"--enable-external-package-for-default-compiler=true",
|
||||
"--enable-external-package-watch-for-default-compiler=true",
|
||||
}
|
||||
err := fss.FlagSet("generic").Parse(args)
|
||||
if err != nil {
|
||||
return
|
||||
|
||||
err := fss.FlagSet("cue").Parse(args)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Before sync, globals should still be false
|
||||
assert.False(t, cuex.EnableExternalPackageForDefaultCompiler)
|
||||
assert.False(t, cuex.EnableExternalPackageWatchForDefaultCompiler)
|
||||
|
||||
// After sync, globals should be updated
|
||||
opts.CUE.SyncToCUEGlobals()
|
||||
assert.True(t, cuex.EnableExternalPackageForDefaultCompiler)
|
||||
assert.True(t, cuex.EnableExternalPackageWatchForDefaultCompiler)
|
||||
}
|
||||
|
||||
func TestWorkflowOptions_SyncToGlobals(t *testing.T) {
|
||||
// Store original values
|
||||
origWait := wfTypes.MaxWorkflowWaitBackoffTime
|
||||
origFailed := wfTypes.MaxWorkflowFailedBackoffTime
|
||||
origRetry := wfTypes.MaxWorkflowStepErrorRetryTimes
|
||||
|
||||
// Restore after test
|
||||
defer func() {
|
||||
wfTypes.MaxWorkflowWaitBackoffTime = origWait
|
||||
wfTypes.MaxWorkflowFailedBackoffTime = origFailed
|
||||
wfTypes.MaxWorkflowStepErrorRetryTimes = origRetry
|
||||
}()
|
||||
|
||||
opts := NewCoreOptions()
|
||||
fss := opts.Flags()
|
||||
|
||||
args := []string{
|
||||
"--max-workflow-wait-backoff-time=120",
|
||||
"--max-workflow-failed-backoff-time=600",
|
||||
"--max-workflow-step-error-retry-times=20",
|
||||
}
|
||||
|
||||
assert.True(t, cuex.EnableExternalPackageForDefaultCompiler, "The --enable-external-package-for-default-compiler flag should be enabled")
|
||||
assert.True(t, cuex.EnableExternalPackageWatchForDefaultCompiler, "The --enable-external-package-watch-for-default-compiler flag should be enabled")
|
||||
err := fss.FlagSet("workflow").Parse(args)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify struct fields are updated
|
||||
assert.Equal(t, 120, opts.Workflow.MaxWaitBackoffTime)
|
||||
assert.Equal(t, 600, opts.Workflow.MaxFailedBackoffTime)
|
||||
assert.Equal(t, 20, opts.Workflow.MaxStepErrorRetryTimes)
|
||||
|
||||
// After sync, globals should be updated
|
||||
opts.Workflow.SyncToWorkflowGlobals()
|
||||
assert.Equal(t, 120, wfTypes.MaxWorkflowWaitBackoffTime)
|
||||
assert.Equal(t, 600, wfTypes.MaxWorkflowFailedBackoffTime)
|
||||
assert.Equal(t, 20, wfTypes.MaxWorkflowStepErrorRetryTimes)
|
||||
}
|
||||
|
||||
func TestOAMOptions_SyncToGlobals(t *testing.T) {
|
||||
// Store original value
|
||||
origNamespace := oam.SystemDefinitionNamespace
|
||||
|
||||
// Restore after test
|
||||
defer func() {
|
||||
oam.SystemDefinitionNamespace = origNamespace
|
||||
}()
|
||||
|
||||
opts := NewCoreOptions()
|
||||
fss := opts.Flags()
|
||||
|
||||
args := []string{
|
||||
"--system-definition-namespace=custom-system",
|
||||
}
|
||||
|
||||
err := fss.FlagSet("oam").Parse(args)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify struct field is updated
|
||||
assert.Equal(t, "custom-system", opts.OAM.SystemDefinitionNamespace)
|
||||
|
||||
// After sync, global should be updated
|
||||
opts.OAM.SyncToOAMGlobals()
|
||||
assert.Equal(t, "custom-system", oam.SystemDefinitionNamespace)
|
||||
}
|
||||
|
||||
func TestPerformanceOptions_SyncToGlobals(t *testing.T) {
|
||||
// Store original value
|
||||
origPerf := commonconfig.PerfEnabled
|
||||
|
||||
// Restore after test
|
||||
defer func() {
|
||||
commonconfig.PerfEnabled = origPerf
|
||||
}()
|
||||
|
||||
opts := NewCoreOptions()
|
||||
fss := opts.Flags()
|
||||
|
||||
args := []string{
|
||||
"--perf-enabled=true",
|
||||
}
|
||||
|
||||
err := fss.FlagSet("performance").Parse(args)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify struct field is updated
|
||||
assert.Equal(t, true, opts.Performance.PerfEnabled)
|
||||
|
||||
// After sync, global should be updated
|
||||
opts.Performance.SyncToPerformanceGlobals()
|
||||
assert.True(t, commonconfig.PerfEnabled)
|
||||
}
|
||||
|
||||
func TestApplicationOptions_SyncToGlobals(t *testing.T) {
|
||||
// Store original value
|
||||
origPeriod := commonconfig.ApplicationReSyncPeriod
|
||||
|
||||
// Restore after test
|
||||
defer func() {
|
||||
commonconfig.ApplicationReSyncPeriod = origPeriod
|
||||
}()
|
||||
|
||||
opts := NewCoreOptions()
|
||||
fss := opts.Flags()
|
||||
|
||||
args := []string{
|
||||
"--application-re-sync-period=10m",
|
||||
}
|
||||
|
||||
err := fss.FlagSet("application").Parse(args)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify struct field is updated
|
||||
assert.Equal(t, 10*time.Minute, opts.Application.ReSyncPeriod)
|
||||
|
||||
// After sync, global should be updated
|
||||
opts.Application.SyncToApplicationGlobals()
|
||||
assert.Equal(t, 10*time.Minute, commonconfig.ApplicationReSyncPeriod)
|
||||
}
|
||||
|
||||
func TestResourceOptions_SyncToGlobals(t *testing.T) {
|
||||
// Store original value
|
||||
origDispatch := resourcekeeper.MaxDispatchConcurrent
|
||||
|
||||
// Restore after test
|
||||
defer func() {
|
||||
resourcekeeper.MaxDispatchConcurrent = origDispatch
|
||||
}()
|
||||
|
||||
opts := NewCoreOptions()
|
||||
fss := opts.Flags()
|
||||
|
||||
args := []string{
|
||||
"--max-dispatch-concurrent=25",
|
||||
}
|
||||
|
||||
err := fss.FlagSet("resource").Parse(args)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify struct field is updated
|
||||
assert.Equal(t, 25, opts.Resource.MaxDispatchConcurrent)
|
||||
|
||||
// After sync, global should be updated
|
||||
opts.Resource.SyncToResourceGlobals()
|
||||
assert.Equal(t, 25, resourcekeeper.MaxDispatchConcurrent)
|
||||
}
|
||||
|
||||
func TestCoreOptions_InvalidValues(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
expectError bool
|
||||
errorMsg string
|
||||
}{
|
||||
{
|
||||
name: "invalid boolean value",
|
||||
args: []string{
|
||||
"--enable-leader-election=notabool",
|
||||
},
|
||||
expectError: true,
|
||||
errorMsg: "invalid argument",
|
||||
},
|
||||
{
|
||||
name: "invalid duration value",
|
||||
args: []string{
|
||||
"--leader-election-lease-duration=notaduration",
|
||||
},
|
||||
expectError: true,
|
||||
errorMsg: "invalid argument",
|
||||
},
|
||||
{
|
||||
name: "invalid int value",
|
||||
args: []string{
|
||||
"--webhook-port=notanint",
|
||||
},
|
||||
expectError: true,
|
||||
errorMsg: "invalid argument",
|
||||
},
|
||||
{
|
||||
name: "invalid float value",
|
||||
args: []string{
|
||||
"--kube-api-qps=notafloat",
|
||||
},
|
||||
expectError: true,
|
||||
errorMsg: "invalid argument",
|
||||
},
|
||||
{
|
||||
name: "invalid uint64 value",
|
||||
args: []string{
|
||||
"--log-file-max-size=-100",
|
||||
},
|
||||
expectError: true,
|
||||
errorMsg: "invalid argument",
|
||||
},
|
||||
{
|
||||
name: "unknown flag",
|
||||
args: []string{
|
||||
"--unknown-flag=value",
|
||||
},
|
||||
expectError: true,
|
||||
errorMsg: "unknown flag",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
opt := NewCoreOptions()
|
||||
|
||||
for _, f := range opt.Flags().FlagSets {
|
||||
fs.AddFlagSet(f)
|
||||
}
|
||||
|
||||
err := fs.Parse(tt.args)
|
||||
if tt.expectError {
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), tt.errorMsg)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoreOptions_PartialConfiguration(t *testing.T) {
|
||||
// Test that partial configuration works correctly
|
||||
// and doesn't override other defaults
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
opt := NewCoreOptions()
|
||||
|
||||
for _, f := range opt.Flags().FlagSets {
|
||||
fs.AddFlagSet(f)
|
||||
}
|
||||
|
||||
// Only set a few flags
|
||||
args := []string{
|
||||
"--enable-leader-election=true",
|
||||
"--log-debug=true",
|
||||
"--perf-enabled=true",
|
||||
}
|
||||
|
||||
err := fs.Parse(args)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Check that specified flags are updated
|
||||
assert.Equal(t, true, opt.Server.EnableLeaderElection)
|
||||
assert.Equal(t, true, opt.Observability.LogDebug)
|
||||
assert.Equal(t, true, opt.Performance.PerfEnabled)
|
||||
|
||||
// Check that unspecified flags retain defaults
|
||||
assert.Equal(t, ":9440", opt.Server.HealthAddr)
|
||||
assert.Equal(t, "Local", opt.Server.StorageDriver)
|
||||
assert.Equal(t, false, opt.Webhook.UseWebhook)
|
||||
assert.Equal(t, ":8080", opt.Observability.MetricsAddr)
|
||||
assert.Equal(t, 10*time.Hour, opt.Kubernetes.InformerSyncPeriod)
|
||||
assert.Equal(t, 10, opt.Resource.MaxDispatchConcurrent)
|
||||
}
|
||||
|
||||
func TestCoreOptions_FlagSetsOrganization(t *testing.T) {
|
||||
opt := NewCoreOptions()
|
||||
fss := opt.Flags()
|
||||
|
||||
// Verify that all expected flag sets are created
|
||||
expectedFlagSets := []string{
|
||||
"server",
|
||||
"webhook",
|
||||
"observability",
|
||||
"kubernetes",
|
||||
"multicluster",
|
||||
"cue",
|
||||
"application",
|
||||
"oam",
|
||||
"performance",
|
||||
"admission",
|
||||
"resource",
|
||||
"workflow",
|
||||
"controller",
|
||||
"client",
|
||||
"reconcile",
|
||||
"sharding",
|
||||
"feature",
|
||||
"profiling",
|
||||
"klog",
|
||||
}
|
||||
|
||||
for _, name := range expectedFlagSets {
|
||||
fs := fss.FlagSet(name)
|
||||
assert.NotNil(t, fs, "FlagSet %s should exist", name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoreOptions_FlagHelp(t *testing.T) {
|
||||
opt := NewCoreOptions()
|
||||
fss := opt.Flags()
|
||||
|
||||
// Test that flags have proper help messages
|
||||
serverFS := fss.FlagSet("server")
|
||||
flag := serverFS.Lookup("enable-leader-election")
|
||||
assert.NotNil(t, flag)
|
||||
assert.Contains(t, flag.Usage, "Enable leader election")
|
||||
|
||||
webhookFS := fss.FlagSet("webhook")
|
||||
flag = webhookFS.Lookup("use-webhook")
|
||||
assert.NotNil(t, flag)
|
||||
assert.Contains(t, flag.Usage, "Enable Admission Webhook")
|
||||
|
||||
obsFS := fss.FlagSet("observability")
|
||||
flag = obsFS.Lookup("log-debug")
|
||||
assert.NotNil(t, flag)
|
||||
assert.Contains(t, flag.Usage, "Enable debug logs")
|
||||
}
|
||||
|
||||
func TestCoreOptions_MultipleSyncCalls(t *testing.T) {
|
||||
// Store original values
|
||||
origCUEExternal := cuex.EnableExternalPackageForDefaultCompiler
|
||||
origCUEWatch := cuex.EnableExternalPackageWatchForDefaultCompiler
|
||||
origWait := wfTypes.MaxWorkflowWaitBackoffTime
|
||||
origDispatch := resourcekeeper.MaxDispatchConcurrent
|
||||
origOAMNamespace := oam.SystemDefinitionNamespace
|
||||
origAppPeriod := commonconfig.ApplicationReSyncPeriod
|
||||
origPerf := commonconfig.PerfEnabled
|
||||
|
||||
// Restore after test
|
||||
defer func() {
|
||||
cuex.EnableExternalPackageForDefaultCompiler = origCUEExternal
|
||||
cuex.EnableExternalPackageWatchForDefaultCompiler = origCUEWatch
|
||||
wfTypes.MaxWorkflowWaitBackoffTime = origWait
|
||||
resourcekeeper.MaxDispatchConcurrent = origDispatch
|
||||
oam.SystemDefinitionNamespace = origOAMNamespace
|
||||
commonconfig.ApplicationReSyncPeriod = origAppPeriod
|
||||
commonconfig.PerfEnabled = origPerf
|
||||
}()
|
||||
|
||||
// Test that calling sync multiple times doesn't cause issues
|
||||
opts := NewCoreOptions()
|
||||
|
||||
// Set some values
|
||||
opts.CUE.EnableExternalPackage = true
|
||||
opts.CUE.EnableExternalPackageWatch = false
|
||||
opts.Workflow.MaxWaitBackoffTime = 100
|
||||
opts.Resource.MaxDispatchConcurrent = 20
|
||||
opts.OAM.SystemDefinitionNamespace = "test-system"
|
||||
opts.Application.ReSyncPeriod = 15 * time.Minute
|
||||
opts.Performance.PerfEnabled = true
|
||||
|
||||
// Call sync multiple times
|
||||
opts.CUE.SyncToCUEGlobals()
|
||||
opts.CUE.SyncToCUEGlobals()
|
||||
|
||||
opts.Workflow.SyncToWorkflowGlobals()
|
||||
opts.Workflow.SyncToWorkflowGlobals()
|
||||
|
||||
opts.Resource.SyncToResourceGlobals()
|
||||
opts.Resource.SyncToResourceGlobals()
|
||||
|
||||
opts.OAM.SyncToOAMGlobals()
|
||||
opts.OAM.SyncToOAMGlobals()
|
||||
|
||||
opts.Application.SyncToApplicationGlobals()
|
||||
opts.Application.SyncToApplicationGlobals()
|
||||
|
||||
opts.Performance.SyncToPerformanceGlobals()
|
||||
opts.Performance.SyncToPerformanceGlobals()
|
||||
|
||||
// Verify values are still correct
|
||||
assert.True(t, cuex.EnableExternalPackageForDefaultCompiler)
|
||||
assert.False(t, cuex.EnableExternalPackageWatchForDefaultCompiler)
|
||||
assert.Equal(t, 100, wfTypes.MaxWorkflowWaitBackoffTime)
|
||||
assert.Equal(t, 20, resourcekeeper.MaxDispatchConcurrent)
|
||||
assert.Equal(t, "test-system", oam.SystemDefinitionNamespace)
|
||||
assert.Equal(t, 15*time.Minute, commonconfig.ApplicationReSyncPeriod)
|
||||
assert.True(t, commonconfig.PerfEnabled)
|
||||
}
|
||||
|
||||
func TestCoreOptions_SpecialCharactersInStrings(t *testing.T) {
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
opt := NewCoreOptions()
|
||||
|
||||
for _, f := range opt.Flags().FlagSets {
|
||||
fs.AddFlagSet(f)
|
||||
}
|
||||
|
||||
// Test with special characters and spaces in paths
|
||||
args := []string{
|
||||
`--webhook-cert-dir=/path/with spaces/and-special!@#$%chars`,
|
||||
`--log-file-path=/var/log/kubevela/日本語/логи.log`,
|
||||
`--health-addr=[::1]:8080`,
|
||||
`--metrics-addr=0.0.0.0:9090`,
|
||||
}
|
||||
|
||||
err := fs.Parse(args)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, `/path/with spaces/and-special!@#$%chars`, opt.Webhook.CertDir)
|
||||
assert.Equal(t, `/var/log/kubevela/日本語/логи.log`, opt.Observability.LogFilePath)
|
||||
assert.Equal(t, `[::1]:8080`, opt.Server.HealthAddr)
|
||||
assert.Equal(t, `0.0.0.0:9090`, opt.Observability.MetricsAddr)
|
||||
}
|
||||
|
||||
func TestCoreOptions_ConcurrentAccess(t *testing.T) {
|
||||
// Test that the options can be accessed concurrently safely
|
||||
opt := NewCoreOptions()
|
||||
|
||||
// Set some values
|
||||
opt.Server.EnableLeaderElection = true
|
||||
opt.Workflow.MaxWaitBackoffTime = 100
|
||||
opt.Resource.MaxDispatchConcurrent = 20
|
||||
|
||||
// Simulate concurrent access
|
||||
done := make(chan bool, 3)
|
||||
|
||||
go func() {
|
||||
for i := 0; i < 100; i++ {
|
||||
_ = opt.Server.EnableLeaderElection
|
||||
}
|
||||
done <- true
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for i := 0; i < 100; i++ {
|
||||
_ = opt.Workflow.MaxWaitBackoffTime
|
||||
}
|
||||
done <- true
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for i := 0; i < 100; i++ {
|
||||
_ = opt.Resource.MaxDispatchConcurrent
|
||||
}
|
||||
done <- true
|
||||
}()
|
||||
|
||||
// Wait for all goroutines
|
||||
for i := 0; i < 3; i++ {
|
||||
<-done
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoreOptions_NilPointerSafety(t *testing.T) {
|
||||
// Ensure NewCoreOptions never returns nil pointers
|
||||
opt := NewCoreOptions()
|
||||
|
||||
// All config modules should be non-nil
|
||||
assert.NotNil(t, opt.Server)
|
||||
assert.NotNil(t, opt.Webhook)
|
||||
assert.NotNil(t, opt.Observability)
|
||||
assert.NotNil(t, opt.Kubernetes)
|
||||
assert.NotNil(t, opt.MultiCluster)
|
||||
assert.NotNil(t, opt.CUE)
|
||||
assert.NotNil(t, opt.Application)
|
||||
assert.NotNil(t, opt.OAM)
|
||||
assert.NotNil(t, opt.Performance)
|
||||
assert.NotNil(t, opt.Workflow)
|
||||
assert.NotNil(t, opt.Admission)
|
||||
assert.NotNil(t, opt.Resource)
|
||||
assert.NotNil(t, opt.Client)
|
||||
assert.NotNil(t, opt.Reconcile)
|
||||
assert.NotNil(t, opt.Sharding)
|
||||
assert.NotNil(t, opt.Feature)
|
||||
assert.NotNil(t, opt.Profiling)
|
||||
assert.NotNil(t, opt.KLog)
|
||||
assert.NotNil(t, opt.Controller)
|
||||
}
|
||||
|
||||
func TestCoreOptions_FlagPrecedence(t *testing.T) {
|
||||
// Test that later flags override earlier ones
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
opt := NewCoreOptions()
|
||||
|
||||
for _, f := range opt.Flags().FlagSets {
|
||||
fs.AddFlagSet(f)
|
||||
}
|
||||
|
||||
// Parse with one value, then parse again with different value
|
||||
args1 := []string{"--webhook-port=8080"}
|
||||
err := fs.Parse(args1)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 8080, opt.Webhook.WebhookPort)
|
||||
|
||||
// Reset and parse with different value
|
||||
fs = pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
opt = NewCoreOptions()
|
||||
for _, f := range opt.Flags().FlagSets {
|
||||
fs.AddFlagSet(f)
|
||||
}
|
||||
|
||||
args2 := []string{"--webhook-port=9090"}
|
||||
err = fs.Parse(args2)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 9090, opt.Webhook.WebhookPort)
|
||||
}
|
||||
|
||||
func TestCoreOptions_AllConfigModulesHaveFlags(t *testing.T) {
|
||||
// Ensure every config module registers at least one flag
|
||||
opt := NewCoreOptions()
|
||||
fss := opt.Flags()
|
||||
|
||||
configsWithExpectedFlags := map[string][]string{
|
||||
"server": {"health-addr", "storage-driver", "enable-leader-election"},
|
||||
"webhook": {"use-webhook", "webhook-cert-dir", "webhook-port"},
|
||||
"observability": {"metrics-addr", "log-debug", "log-file-path"},
|
||||
"kubernetes": {"informer-sync-period", "kube-api-qps", "kube-api-burst"},
|
||||
"multicluster": {"enable-cluster-gateway", "enable-cluster-metrics"},
|
||||
"cue": {"enable-external-package-for-default-compiler"},
|
||||
"application": {"application-re-sync-period"},
|
||||
"oam": {"system-definition-namespace"},
|
||||
"controller": {"revision-limit", "application-revision-limit", "definition-revision-limit"},
|
||||
"performance": {"perf-enabled"},
|
||||
"workflow": {"max-workflow-wait-backoff-time"},
|
||||
"resource": {"max-dispatch-concurrent"},
|
||||
}
|
||||
|
||||
for setName, expectedFlags := range configsWithExpectedFlags {
|
||||
fs := fss.FlagSet(setName)
|
||||
assert.NotNil(t, fs, "FlagSet %s should exist", setName)
|
||||
|
||||
for _, flagName := range expectedFlags {
|
||||
flag := fs.Lookup(flagName)
|
||||
assert.NotNil(t, flag, "Flag %s should exist in flagset %s", flagName, setName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoreOptions_CLIOverridesWork(t *testing.T) {
|
||||
// This test verifies that CLI flags correctly override default values
|
||||
// and that the sync methods properly propagate these values to globals
|
||||
|
||||
// Store original globals to restore after test
|
||||
origWait := wfTypes.MaxWorkflowWaitBackoffTime
|
||||
origFailed := wfTypes.MaxWorkflowFailedBackoffTime
|
||||
origRetry := wfTypes.MaxWorkflowStepErrorRetryTimes
|
||||
origDispatch := resourcekeeper.MaxDispatchConcurrent
|
||||
origOAMNamespace := oam.SystemDefinitionNamespace
|
||||
origAppPeriod := commonconfig.ApplicationReSyncPeriod
|
||||
origPerf := commonconfig.PerfEnabled
|
||||
origCUEExternal := cuex.EnableExternalPackageForDefaultCompiler
|
||||
origCUEWatch := cuex.EnableExternalPackageWatchForDefaultCompiler
|
||||
|
||||
defer func() {
|
||||
wfTypes.MaxWorkflowWaitBackoffTime = origWait
|
||||
wfTypes.MaxWorkflowFailedBackoffTime = origFailed
|
||||
wfTypes.MaxWorkflowStepErrorRetryTimes = origRetry
|
||||
resourcekeeper.MaxDispatchConcurrent = origDispatch
|
||||
oam.SystemDefinitionNamespace = origOAMNamespace
|
||||
commonconfig.ApplicationReSyncPeriod = origAppPeriod
|
||||
commonconfig.PerfEnabled = origPerf
|
||||
cuex.EnableExternalPackageForDefaultCompiler = origCUEExternal
|
||||
cuex.EnableExternalPackageWatchForDefaultCompiler = origCUEWatch
|
||||
}()
|
||||
|
||||
opt := NewCoreOptions()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
|
||||
for _, f := range opt.Flags().FlagSets {
|
||||
fs.AddFlagSet(f)
|
||||
}
|
||||
|
||||
// Verify defaults first
|
||||
assert.Equal(t, 60, opt.Workflow.MaxWaitBackoffTime, "Default should be 60")
|
||||
assert.Equal(t, 300, opt.Workflow.MaxFailedBackoffTime, "Default should be 300")
|
||||
assert.Equal(t, 10, opt.Workflow.MaxStepErrorRetryTimes, "Default should be 10")
|
||||
assert.Equal(t, 10, opt.Resource.MaxDispatchConcurrent, "Default should be 10")
|
||||
assert.Equal(t, "vela-system", opt.OAM.SystemDefinitionNamespace, "Default should be vela-system")
|
||||
assert.Equal(t, false, opt.Performance.PerfEnabled, "Default should be false")
|
||||
|
||||
// Parse CLI args with overrides
|
||||
args := []string{
|
||||
"--max-workflow-wait-backoff-time=999",
|
||||
"--max-workflow-failed-backoff-time=888",
|
||||
"--max-workflow-step-error-retry-times=77",
|
||||
"--max-dispatch-concurrent=66",
|
||||
"--system-definition-namespace=custom-ns",
|
||||
"--application-re-sync-period=20m",
|
||||
"--perf-enabled=true",
|
||||
"--enable-external-package-for-default-compiler=true",
|
||||
"--enable-external-package-watch-for-default-compiler=true",
|
||||
}
|
||||
|
||||
err := fs.Parse(args)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify struct fields got CLI values (not defaults)
|
||||
assert.Equal(t, 999, opt.Workflow.MaxWaitBackoffTime, "CLI override should be 999")
|
||||
assert.Equal(t, 888, opt.Workflow.MaxFailedBackoffTime, "CLI override should be 888")
|
||||
assert.Equal(t, 77, opt.Workflow.MaxStepErrorRetryTimes, "CLI override should be 77")
|
||||
assert.Equal(t, 66, opt.Resource.MaxDispatchConcurrent, "CLI override should be 66")
|
||||
assert.Equal(t, "custom-ns", opt.OAM.SystemDefinitionNamespace, "CLI override should be custom-ns")
|
||||
assert.Equal(t, 20*time.Minute, opt.Application.ReSyncPeriod, "CLI override should be 20m")
|
||||
assert.Equal(t, true, opt.Performance.PerfEnabled, "CLI override should be true")
|
||||
assert.Equal(t, true, opt.CUE.EnableExternalPackage, "CLI override should be true")
|
||||
assert.Equal(t, true, opt.CUE.EnableExternalPackageWatch, "CLI override should be true")
|
||||
|
||||
// Now sync to globals
|
||||
opt.Workflow.SyncToWorkflowGlobals()
|
||||
opt.Resource.SyncToResourceGlobals()
|
||||
opt.OAM.SyncToOAMGlobals()
|
||||
opt.Application.SyncToApplicationGlobals()
|
||||
opt.Performance.SyncToPerformanceGlobals()
|
||||
opt.CUE.SyncToCUEGlobals()
|
||||
|
||||
// Verify globals got the CLI values
|
||||
assert.Equal(t, 999, wfTypes.MaxWorkflowWaitBackoffTime, "Global should have CLI value")
|
||||
assert.Equal(t, 888, wfTypes.MaxWorkflowFailedBackoffTime, "Global should have CLI value")
|
||||
assert.Equal(t, 77, wfTypes.MaxWorkflowStepErrorRetryTimes, "Global should have CLI value")
|
||||
assert.Equal(t, 66, resourcekeeper.MaxDispatchConcurrent, "Global should have CLI value")
|
||||
assert.Equal(t, "custom-ns", oam.SystemDefinitionNamespace, "Global should have CLI value")
|
||||
assert.Equal(t, 20*time.Minute, commonconfig.ApplicationReSyncPeriod, "Global should have CLI value")
|
||||
assert.Equal(t, true, commonconfig.PerfEnabled, "Global should have CLI value")
|
||||
assert.Equal(t, true, cuex.EnableExternalPackageForDefaultCompiler, "Global should have CLI value")
|
||||
assert.Equal(t, true, cuex.EnableExternalPackageWatchForDefaultCompiler, "Global should have CLI value")
|
||||
}
|
||||
|
||||
func TestCoreOptions_CompleteIntegration(t *testing.T) {
|
||||
// A comprehensive integration test
|
||||
opt := NewCoreOptions()
|
||||
fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
|
||||
|
||||
for _, f := range opt.Flags().FlagSets {
|
||||
fs.AddFlagSet(f)
|
||||
}
|
||||
|
||||
// Simulate a real-world configuration
|
||||
args := []string{
|
||||
// Production-like settings
|
||||
"--enable-leader-election=true",
|
||||
"--leader-election-namespace=vela-system",
|
||||
"--use-webhook=true",
|
||||
"--webhook-port=9443",
|
||||
"--metrics-addr=:8080",
|
||||
"--health-addr=:9440",
|
||||
"--log-debug=false",
|
||||
"--log-file-path=/var/log/vela/core.log",
|
||||
"--log-file-max-size=100",
|
||||
"--kube-api-qps=100",
|
||||
"--kube-api-burst=200",
|
||||
"--enable-cluster-gateway=true",
|
||||
"--enable-cluster-metrics=true",
|
||||
"--cluster-metrics-interval=30s",
|
||||
"--application-re-sync-period=10m",
|
||||
"--perf-enabled=true",
|
||||
"--max-dispatch-concurrent=20",
|
||||
"--max-workflow-wait-backoff-time=120",
|
||||
"--max-workflow-failed-backoff-time=600",
|
||||
}
|
||||
|
||||
err := fs.Parse(args)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify the configuration is production-ready
|
||||
assert.True(t, opt.Server.EnableLeaderElection, "Leader election should be enabled in production")
|
||||
assert.Equal(t, "vela-system", opt.Server.LeaderElectionNamespace)
|
||||
assert.True(t, opt.Webhook.UseWebhook, "Webhook should be enabled in production")
|
||||
assert.Equal(t, 9443, opt.Webhook.WebhookPort)
|
||||
assert.False(t, opt.Observability.LogDebug, "Debug logging should be disabled in production")
|
||||
assert.NotEmpty(t, opt.Observability.LogFilePath, "Log file path should be set in production")
|
||||
|
||||
// Verify performance settings
|
||||
assert.True(t, opt.Performance.PerfEnabled)
|
||||
assert.Equal(t, 20, opt.Resource.MaxDispatchConcurrent)
|
||||
|
||||
// Verify cluster settings
|
||||
assert.True(t, opt.MultiCluster.EnableClusterGateway)
|
||||
assert.True(t, opt.MultiCluster.EnableClusterMetrics)
|
||||
assert.Equal(t, 30*time.Second, opt.MultiCluster.ClusterMetricsInterval)
|
||||
|
||||
// Sync all configurations that need it
|
||||
opt.CUE.SyncToCUEGlobals()
|
||||
opt.Workflow.SyncToWorkflowGlobals()
|
||||
opt.Resource.SyncToResourceGlobals()
|
||||
opt.OAM.SyncToOAMGlobals()
|
||||
opt.Application.SyncToApplicationGlobals()
|
||||
opt.Performance.SyncToPerformanceGlobals()
|
||||
|
||||
// Verify sync worked
|
||||
assert.Equal(t, 20, resourcekeeper.MaxDispatchConcurrent)
|
||||
assert.Equal(t, 120, wfTypes.MaxWorkflowWaitBackoffTime)
|
||||
assert.Equal(t, 600, wfTypes.MaxWorkflowFailedBackoffTime)
|
||||
assert.Equal(t, "vela-system", oam.SystemDefinitionNamespace)
|
||||
assert.Equal(t, 10*time.Minute, commonconfig.ApplicationReSyncPeriod)
|
||||
assert.True(t, commonconfig.PerfEnabled)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package app
|
|||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
|
@ -98,14 +99,32 @@ func NewCoreCommand() *cobra.Command {
|
|||
}
|
||||
|
||||
func run(ctx context.Context, s *options.CoreOptions) error {
|
||||
// Sync parsed config values to external package global variables
|
||||
s.Workflow.SyncToWorkflowGlobals()
|
||||
s.CUE.SyncToCUEGlobals()
|
||||
s.Application.SyncToApplicationGlobals()
|
||||
s.Performance.SyncToPerformanceGlobals()
|
||||
s.Resource.SyncToResourceGlobals()
|
||||
s.OAM.SyncToOAMGlobals()
|
||||
|
||||
restConfig := ctrl.GetConfigOrDie()
|
||||
restConfig.UserAgent = types.KubeVelaName + "/" + version.GitRevision
|
||||
restConfig.QPS = float32(s.QPS)
|
||||
restConfig.Burst = s.Burst
|
||||
restConfig.QPS = float32(s.Kubernetes.QPS)
|
||||
restConfig.Burst = s.Kubernetes.Burst
|
||||
restConfig.Wrap(auth.NewImpersonatingRoundTripper)
|
||||
|
||||
// Configure klog based on parsed observability settings
|
||||
if s.Observability.LogDebug {
|
||||
_ = flag.Set("v", strconv.Itoa(int(commonconfig.LogDebug)))
|
||||
}
|
||||
if s.Observability.LogFilePath != "" {
|
||||
_ = flag.Set("logtostderr", "false")
|
||||
_ = flag.Set("log_file", s.Observability.LogFilePath)
|
||||
_ = flag.Set("log_file_max_size", strconv.FormatUint(s.Observability.LogFileMaxSize, 10))
|
||||
}
|
||||
|
||||
// Set logger (use --dev-logs=true for local development)
|
||||
if s.DevLogs {
|
||||
if s.Observability.DevLogs {
|
||||
logOutput := newColorWriter(os.Stdout)
|
||||
klog.LogToStderr(false)
|
||||
klog.SetOutput(logOutput)
|
||||
|
|
@ -122,15 +141,15 @@ func run(ctx context.Context, s *options.CoreOptions) error {
|
|||
go profiling.StartProfilingServer(nil)
|
||||
|
||||
// wrapper the round tripper by multi cluster rewriter
|
||||
if s.EnableClusterGateway {
|
||||
if s.MultiCluster.EnableClusterGateway {
|
||||
client, err := multicluster.Initialize(restConfig, true)
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "failed to enable multi-cluster capability")
|
||||
return err
|
||||
}
|
||||
|
||||
if s.EnableClusterMetrics {
|
||||
_, err := multicluster.NewClusterMetricsMgr(context.Background(), client, s.ClusterMetricsInterval)
|
||||
if s.MultiCluster.EnableClusterMetrics {
|
||||
_, err := multicluster.NewClusterMetricsMgr(context.Background(), client, s.MultiCluster.ClusterMetricsInterval)
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "failed to enable multi-cluster-metrics capability")
|
||||
return err
|
||||
|
|
@ -139,32 +158,32 @@ func run(ctx context.Context, s *options.CoreOptions) error {
|
|||
}
|
||||
|
||||
if utilfeature.DefaultMutableFeatureGate.Enabled(features.ApplyOnce) {
|
||||
commonconfig.ApplicationReSyncPeriod = s.InformerSyncPeriod
|
||||
commonconfig.ApplicationReSyncPeriod = s.Kubernetes.InformerSyncPeriod
|
||||
}
|
||||
|
||||
leaderElectionID := util.GenerateLeaderElectionID(types.KubeVelaName, s.ControllerArgs.IgnoreAppWithoutControllerRequirement)
|
||||
leaderElectionID := util.GenerateLeaderElectionID(types.KubeVelaName, s.Controller.IgnoreAppWithoutControllerRequirement)
|
||||
leaderElectionID += sharding.GetShardIDSuffix()
|
||||
mgr, err := ctrl.NewManager(restConfig, ctrl.Options{
|
||||
Scheme: scheme,
|
||||
Metrics: metricsserver.Options{
|
||||
BindAddress: s.MetricsAddr,
|
||||
BindAddress: s.Observability.MetricsAddr,
|
||||
},
|
||||
LeaderElection: s.EnableLeaderElection,
|
||||
LeaderElectionNamespace: s.LeaderElectionNamespace,
|
||||
LeaderElection: s.Server.EnableLeaderElection,
|
||||
LeaderElectionNamespace: s.Server.LeaderElectionNamespace,
|
||||
LeaderElectionID: leaderElectionID,
|
||||
WebhookServer: ctrlwebhook.NewServer(ctrlwebhook.Options{
|
||||
Port: s.WebhookPort,
|
||||
CertDir: s.CertDir,
|
||||
Port: s.Webhook.WebhookPort,
|
||||
CertDir: s.Webhook.CertDir,
|
||||
}),
|
||||
HealthProbeBindAddress: s.HealthAddr,
|
||||
LeaseDuration: &s.LeaseDuration,
|
||||
RenewDeadline: &s.RenewDeadLine,
|
||||
RetryPeriod: &s.RetryPeriod,
|
||||
HealthProbeBindAddress: s.Server.HealthAddr,
|
||||
LeaseDuration: &s.Server.LeaseDuration,
|
||||
RenewDeadline: &s.Server.RenewDeadline,
|
||||
RetryPeriod: &s.Server.RetryPeriod,
|
||||
NewClient: velaclient.DefaultNewControllerClient,
|
||||
NewCache: cache.BuildCache(ctx,
|
||||
ctrlcache.Options{
|
||||
Scheme: scheme,
|
||||
SyncPeriod: &s.InformerSyncPeriod,
|
||||
SyncPeriod: &s.Kubernetes.InformerSyncPeriod,
|
||||
// SyncPeriod is configured with default value, aka. 10h. First, controller-runtime does not
|
||||
// recommend use it as a time trigger, instead, it is expected to work for failure tolerance
|
||||
// of controller-runtime. Additionally, set this value will affect not only application
|
||||
|
|
@ -210,7 +229,7 @@ func run(ctx context.Context, s *options.CoreOptions) error {
|
|||
klog.ErrorS(err, "Failed to run manager")
|
||||
return err
|
||||
}
|
||||
if s.LogFilePath != "" {
|
||||
if s.Observability.LogFilePath != "" {
|
||||
klog.Flush()
|
||||
}
|
||||
klog.Info("Safely stops Program...")
|
||||
|
|
@ -228,7 +247,7 @@ func prepareRunInShardingMode(ctx context.Context, mgr manager.Manager, s *optio
|
|||
}
|
||||
} else {
|
||||
klog.Infof("controller running in sharding mode, current shard id: %s", sharding.ShardID)
|
||||
if err := application.Setup(mgr, *s.ControllerArgs); err != nil {
|
||||
if err := application.Setup(mgr, s.Controller.Args); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -237,16 +256,16 @@ func prepareRunInShardingMode(ctx context.Context, mgr manager.Manager, s *optio
|
|||
}
|
||||
|
||||
func prepareRun(ctx context.Context, mgr manager.Manager, s *options.CoreOptions) error {
|
||||
if s.UseWebhook {
|
||||
klog.InfoS("Enable webhook", "server port", strconv.Itoa(s.WebhookPort))
|
||||
oamwebhook.Register(mgr, *s.ControllerArgs)
|
||||
if err := waitWebhookSecretVolume(s.CertDir, waitSecretTimeout, waitSecretInterval); err != nil {
|
||||
if s.Webhook.UseWebhook {
|
||||
klog.InfoS("Enable webhook", "server port", strconv.Itoa(s.Webhook.WebhookPort))
|
||||
oamwebhook.Register(mgr, s.Controller.Args)
|
||||
if err := waitWebhookSecretVolume(s.Webhook.CertDir, waitSecretTimeout, waitSecretInterval); err != nil {
|
||||
klog.ErrorS(err, "Unable to get webhook secret")
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := oamv1beta1.Setup(mgr, *s.ControllerArgs); err != nil {
|
||||
if err := oamv1beta1.Setup(mgr, s.Controller.Args); err != nil {
|
||||
klog.ErrorS(err, "Unable to setup the oam controller")
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,6 @@ limitations under the License.
|
|||
|
||||
package core_oam_dev
|
||||
|
||||
import (
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// Args args used by controller
|
||||
type Args struct {
|
||||
|
||||
|
|
@ -47,17 +43,3 @@ type Args struct {
|
|||
// IgnoreDefinitionWithoutControllerRequirement indicates that trait/component/workflowstep definition controller will not process the definition without 'definition.oam.dev/controller-version-require' annotation.
|
||||
IgnoreDefinitionWithoutControllerRequirement bool
|
||||
}
|
||||
|
||||
// AddFlags adds flags to the specified FlagSet
|
||||
func (a *Args) AddFlags(fs *pflag.FlagSet, c *Args) {
|
||||
fs.IntVar(&a.RevisionLimit, "revision-limit", c.RevisionLimit,
|
||||
"RevisionLimit is the maximum number of revisions that will be maintained. The default value is 50.")
|
||||
fs.IntVar(&a.AppRevisionLimit, "application-revision-limit", c.AppRevisionLimit,
|
||||
"application-revision-limit is the maximum number of application useless revisions that will be maintained, if the useless revisions exceed this number, older ones will be GCed first.The default value is 10.")
|
||||
fs.IntVar(&a.DefRevisionLimit, "definition-revision-limit", c.DefRevisionLimit,
|
||||
"definition-revision-limit is the maximum number of component/trait definition useless revisions that will be maintained, if the useless revisions exceed this number, older ones will be GCed first.The default value is 20.")
|
||||
fs.BoolVar(&a.AutoGenWorkloadDefinition, "autogen-workload-definition", c.AutoGenWorkloadDefinition, "Automatic generated workloadDefinition which componentDefinition refers to.")
|
||||
fs.IntVar(&a.ConcurrentReconciles, "concurrent-reconciles", c.ConcurrentReconciles, "concurrent-reconciles is the concurrent reconcile number of the controller. The default value is 4")
|
||||
fs.BoolVar(&a.IgnoreAppWithoutControllerRequirement, "ignore-app-without-controller-version", c.IgnoreAppWithoutControllerRequirement, "If true, application controller will not process the app without 'app.oam.dev/controller-version-require' annotation")
|
||||
fs.BoolVar(&a.IgnoreDefinitionWithoutControllerRequirement, "ignore-definition-without-controller-version", c.IgnoreDefinitionWithoutControllerRequirement, "If true, trait/component/workflowstep definition controller will not process the definition without 'definition.oam.dev/controller-version-require' annotation")
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue