Merge pull request #2794 from jameszhangyukun/pr-interpret-interfaces
Resource Interpreter implements the interfaces
This commit is contained in:
commit
ba084975d7
|
@ -58,31 +58,52 @@ func NewResourceCustomAccessorAccessor(customization *configv1alpha1.ResourceInt
|
|||
}
|
||||
|
||||
func (a *resourceCustomAccessor) GetRetentionLuaScript() string {
|
||||
if a.retention == nil {
|
||||
return ""
|
||||
}
|
||||
return a.retention.LuaScript
|
||||
}
|
||||
|
||||
func (a *resourceCustomAccessor) GetReplicaResourceLuaScript() string {
|
||||
return a.replicaRevision.LuaScript
|
||||
}
|
||||
|
||||
func (a *resourceCustomAccessor) GetReplicaRevisionLuaScript() string {
|
||||
if a.replicaResource == nil {
|
||||
return ""
|
||||
}
|
||||
return a.replicaResource.LuaScript
|
||||
}
|
||||
|
||||
func (a *resourceCustomAccessor) GetReplicaRevisionLuaScript() string {
|
||||
if a.replicaRevision == nil {
|
||||
return ""
|
||||
}
|
||||
return a.replicaRevision.LuaScript
|
||||
}
|
||||
|
||||
func (a *resourceCustomAccessor) GetStatusReflectionLuaScript() string {
|
||||
if a.statusReflection == nil {
|
||||
return ""
|
||||
}
|
||||
return a.statusReflection.LuaScript
|
||||
}
|
||||
|
||||
func (a *resourceCustomAccessor) GetStatusAggregationLuaScript() string {
|
||||
if a.statusAggregation == nil {
|
||||
return ""
|
||||
}
|
||||
return a.statusAggregation.LuaScript
|
||||
}
|
||||
|
||||
func (a *resourceCustomAccessor) GetHealthInterpretationLuaScript() string {
|
||||
if a.healthInterpretation == nil {
|
||||
return ""
|
||||
}
|
||||
return a.healthInterpretation.LuaScript
|
||||
}
|
||||
|
||||
func (a *resourceCustomAccessor) GetDependencyInterpretationLuaScript() string {
|
||||
return a.healthInterpretation.LuaScript
|
||||
if a.dependencyInterpretation == nil {
|
||||
return ""
|
||||
}
|
||||
return a.dependencyInterpretation.LuaScript
|
||||
}
|
||||
|
||||
func (a *resourceCustomAccessor) Name() string {
|
||||
|
|
|
@ -24,7 +24,7 @@ var resourceInterpreterCustomizationsGVR = schema.GroupVersionResource{
|
|||
|
||||
// ConfigManager can list custom resource interpreter.
|
||||
type ConfigManager interface {
|
||||
LuaScriptAccessors() map[schema.GroupVersionKind]LuaScriptAccessor
|
||||
LuaScriptAccessors() map[schema.GroupVersionKind]CustomAccessor
|
||||
HasSynced() bool
|
||||
}
|
||||
|
||||
|
@ -36,8 +36,8 @@ type interpreterConfigManager struct {
|
|||
}
|
||||
|
||||
// LuaScriptAccessors returns all cached configurations.
|
||||
func (configManager *interpreterConfigManager) LuaScriptAccessors() map[schema.GroupVersionKind]LuaScriptAccessor {
|
||||
return configManager.configuration.Load().(map[schema.GroupVersionKind]LuaScriptAccessor)
|
||||
func (configManager *interpreterConfigManager) LuaScriptAccessors() map[schema.GroupVersionKind]CustomAccessor {
|
||||
return configManager.configuration.Load().(map[schema.GroupVersionKind]CustomAccessor)
|
||||
}
|
||||
|
||||
// HasSynced returns true when the cache is synced.
|
||||
|
@ -46,8 +46,13 @@ func (configManager *interpreterConfigManager) HasSynced() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
if configManager.HasSynced() {
|
||||
if configuration, err := configManager.lister.List(labels.Everything()); err == nil && len(configuration) == 0 {
|
||||
// the empty list we initially stored is valid to use.
|
||||
// Setting initialSynced to true, so subsequent checks
|
||||
// would be able to take the fast path on the atomic boolean in a
|
||||
// cluster without any customization configured.
|
||||
configManager.initialSynced.Store(true)
|
||||
// the informer has synced, and we don't have any items
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
@ -61,7 +66,7 @@ func NewInterpreterConfigManager(inform genericmanager.SingleClusterInformerMana
|
|||
initialSynced: &atomic.Value{},
|
||||
configuration: &atomic.Value{},
|
||||
}
|
||||
manager.configuration.Store(make(map[schema.GroupVersionKind]LuaScriptAccessor))
|
||||
manager.configuration.Store(make(map[schema.GroupVersionKind]CustomAccessor))
|
||||
manager.initialSynced.Store(false)
|
||||
configHandlers := fedinformer.NewHandlerOnEvents(
|
||||
func(_ interface{}) { manager.updateConfiguration() },
|
||||
|
@ -88,7 +93,6 @@ func (configManager *interpreterConfigManager) updateConfiguration() {
|
|||
key := schema.FromAPIVersionAndKind(config.Spec.Target.APIVersion, config.Spec.Target.Kind)
|
||||
configs[key] = NewResourceCustomAccessorAccessor(config)
|
||||
}
|
||||
|
||||
configManager.configuration.Store(configs)
|
||||
configManager.initialSynced.Store(true)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package configurableinterpreter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
@ -11,6 +9,7 @@ import (
|
|||
configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
|
||||
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
|
||||
"github.com/karmada-io/karmada/pkg/resourceinterpreter/configurableinterpreter/configmanager"
|
||||
"github.com/karmada-io/karmada/pkg/resourceinterpreter/configurableinterpreter/luavm"
|
||||
"github.com/karmada-io/karmada/pkg/util/fedinformer/genericmanager"
|
||||
)
|
||||
|
||||
|
@ -30,128 +29,112 @@ func NewConfigurableInterpreter(informer genericmanager.SingleClusterInformerMan
|
|||
|
||||
// HookEnabled tells if any hook exist for specific resource gvk and operation type.
|
||||
func (c *ConfigurableInterpreter) HookEnabled(kind schema.GroupVersionKind, operationType configv1alpha1.InterpreterOperation) bool {
|
||||
if !c.configManager.HasSynced() {
|
||||
klog.Errorf("not yet ready to handle request")
|
||||
return false
|
||||
}
|
||||
accessors, exist := c.configManager.LuaScriptAccessors()[kind]
|
||||
if !exist {
|
||||
return false
|
||||
}
|
||||
switch operationType {
|
||||
case configv1alpha1.InterpreterOperationAggregateStatus:
|
||||
return len(accessors.GetStatusAggregationLuaScript()) > 0
|
||||
case configv1alpha1.InterpreterOperationInterpretHealth:
|
||||
return len(accessors.GetHealthInterpretationLuaScript()) > 0
|
||||
case configv1alpha1.InterpreterOperationInterpretDependency:
|
||||
return len(accessors.GetDependencyInterpretationLuaScript()) > 0
|
||||
case configv1alpha1.InterpreterOperationInterpretReplica:
|
||||
return len(accessors.GetReplicaResourceLuaScript()) > 0
|
||||
case configv1alpha1.InterpreterOperationInterpretStatus:
|
||||
return len(accessors.GetStatusReflectionLuaScript()) > 0
|
||||
case configv1alpha1.InterpreterOperationRetain:
|
||||
return len(accessors.GetRetentionLuaScript()) > 0
|
||||
case configv1alpha1.InterpreterOperationReviseReplica:
|
||||
return len(accessors.GetReplicaRevisionLuaScript()) > 0
|
||||
}
|
||||
return false
|
||||
_, exist := c.getInterpreter(kind, operationType)
|
||||
return exist
|
||||
}
|
||||
|
||||
// GetReplicas returns the desired replicas of the object as well as the requirements of each replica.
|
||||
func (c *ConfigurableInterpreter) GetReplicas(object *unstructured.Unstructured) (int32, *workv1alpha2.ReplicaRequirements, error) {
|
||||
klog.Infof("ConfigurableInterpreter Execute ReviseReplica")
|
||||
customAccessor := c.configManager.LuaScriptAccessors()[object.GroupVersionKind()]
|
||||
if len(customAccessor.GetReplicaResourceLuaScript()) == 0 {
|
||||
return 0, nil, fmt.Errorf("customized interpreter operation GetReplicas for %q not found", object.GroupVersionKind())
|
||||
func (c *ConfigurableInterpreter) GetReplicas(object *unstructured.Unstructured) (replicas int32, requires *workv1alpha2.ReplicaRequirements, enabled bool, err error) {
|
||||
luaScript, enabled := c.getInterpreter(object.GroupVersionKind(), configv1alpha1.InterpreterOperationInterpretReplica)
|
||||
if !enabled {
|
||||
return
|
||||
}
|
||||
|
||||
luaScript := customAccessor.GetReplicaResourceLuaScript
|
||||
klog.Infof("lua script %s", luaScript)
|
||||
|
||||
return 0, nil, nil
|
||||
vm := luavm.VM{UseOpenLibs: false}
|
||||
replicas, requires, err = vm.GetReplicas(object, luaScript)
|
||||
return
|
||||
}
|
||||
|
||||
// ReviseReplica revises the replica of the given object.
|
||||
func (c *ConfigurableInterpreter) ReviseReplica(object *unstructured.Unstructured, replica int64) (*unstructured.Unstructured, error) {
|
||||
klog.Infof("ConfigurableInterpreter Execute ReviseReplica")
|
||||
customAccessor := c.configManager.LuaScriptAccessors()[object.GroupVersionKind()]
|
||||
if len(customAccessor.GetReplicaRevisionLuaScript()) == 0 {
|
||||
return nil, fmt.Errorf("customized interpreter operation ReviseReplica for %q not found", object.GroupVersionKind())
|
||||
func (c *ConfigurableInterpreter) ReviseReplica(object *unstructured.Unstructured, replica int64) (revised *unstructured.Unstructured, enabled bool, err error) {
|
||||
luaScript, enabled := c.getInterpreter(object.GroupVersionKind(), configv1alpha1.InterpreterOperationReviseReplica)
|
||||
if !enabled {
|
||||
return
|
||||
}
|
||||
|
||||
luaScript := customAccessor.GetReplicaRevisionLuaScript()
|
||||
klog.Infof("lua script %s", luaScript)
|
||||
|
||||
return nil, nil
|
||||
vm := luavm.VM{UseOpenLibs: false}
|
||||
revised, err = vm.ReviseReplica(object, replica, luaScript)
|
||||
return
|
||||
}
|
||||
|
||||
// Retain returns the objects that based on the "desired" object but with values retained from the "observed" object.
|
||||
func (c *ConfigurableInterpreter) Retain(desired *unstructured.Unstructured, observed *unstructured.Unstructured) (retained *unstructured.Unstructured, err error) {
|
||||
klog.Infof("ConfigurableInterpreter Execute Retain")
|
||||
customAccessor := c.configManager.LuaScriptAccessors()[desired.GroupVersionKind()]
|
||||
if len(customAccessor.GetRetentionLuaScript()) == 0 {
|
||||
return nil, fmt.Errorf("customized interpreter operation Retain for %q not found", desired.GroupVersionKind())
|
||||
func (c *ConfigurableInterpreter) Retain(desired *unstructured.Unstructured, observed *unstructured.Unstructured) (retained *unstructured.Unstructured, enabled bool, err error) {
|
||||
luaScript, enabled := c.getInterpreter(desired.GroupVersionKind(), configv1alpha1.InterpreterOperationRetain)
|
||||
if !enabled {
|
||||
return
|
||||
}
|
||||
|
||||
luaScript := customAccessor.GetRetentionLuaScript()
|
||||
klog.Infof("lua script %s", luaScript)
|
||||
|
||||
return nil, err
|
||||
vm := luavm.VM{UseOpenLibs: false}
|
||||
retained, err = vm.Retain(desired, observed, luaScript)
|
||||
return
|
||||
}
|
||||
|
||||
// AggregateStatus returns the objects that based on the 'object' but with status aggregated.
|
||||
func (c *ConfigurableInterpreter) AggregateStatus(object *unstructured.Unstructured, aggregatedStatusItems []workv1alpha2.AggregatedStatusItem) (*unstructured.Unstructured, error) {
|
||||
klog.Infof("ConfigurableInterpreter Execute AggregateStatus")
|
||||
customAccessor := c.configManager.LuaScriptAccessors()[object.GroupVersionKind()]
|
||||
if len(customAccessor.GetStatusAggregationLuaScript()) == 0 {
|
||||
return nil, fmt.Errorf("customized interpreter AggregateStatus Retain for %q not found", object.GroupVersionKind())
|
||||
func (c *ConfigurableInterpreter) AggregateStatus(object *unstructured.Unstructured, aggregatedStatusItems []workv1alpha2.AggregatedStatusItem) (status *unstructured.Unstructured, enabled bool, err error) {
|
||||
luaScript, enabled := c.getInterpreter(object.GroupVersionKind(), configv1alpha1.InterpreterOperationAggregateStatus)
|
||||
if !enabled {
|
||||
return
|
||||
}
|
||||
|
||||
luaScript := customAccessor.GetStatusAggregationLuaScript()
|
||||
klog.Infof("lua script %s", luaScript)
|
||||
|
||||
return nil, nil
|
||||
vm := luavm.VM{UseOpenLibs: false}
|
||||
status, err = vm.AggregateStatus(object, aggregatedStatusItems, luaScript)
|
||||
return
|
||||
}
|
||||
|
||||
// GetDependencies returns the dependent resources of the given object.
|
||||
func (c *ConfigurableInterpreter) GetDependencies(object *unstructured.Unstructured) (dependencies []configv1alpha1.DependentObjectReference, err error) {
|
||||
klog.Infof("ConfigurableInterpreter Execute GetDependencies")
|
||||
|
||||
customAccessor := c.configManager.LuaScriptAccessors()[object.GroupVersionKind()]
|
||||
if len(customAccessor.GetDependencyInterpretationLuaScript()) == 0 {
|
||||
return nil, fmt.Errorf("customized interpreter GetDependencies Retain for %q not found", object.GroupVersionKind())
|
||||
func (c *ConfigurableInterpreter) GetDependencies(object *unstructured.Unstructured) (dependencies []configv1alpha1.DependentObjectReference, enabled bool, err error) {
|
||||
luaScript, enabled := c.getInterpreter(object.GroupVersionKind(), configv1alpha1.InterpreterOperationInterpretDependency)
|
||||
if !enabled {
|
||||
return
|
||||
}
|
||||
|
||||
luaScript := customAccessor.GetDependencyInterpretationLuaScript()
|
||||
klog.Infof("lua script %s", luaScript)
|
||||
|
||||
return nil, err
|
||||
vm := luavm.VM{UseOpenLibs: false}
|
||||
dependencies, err = vm.GetDependencies(object, luaScript)
|
||||
return
|
||||
}
|
||||
|
||||
// ReflectStatus returns the status of the object.
|
||||
func (c *ConfigurableInterpreter) ReflectStatus(object *unstructured.Unstructured) (status *runtime.RawExtension, err error) {
|
||||
klog.Infof("ConfigurableInterpreter Execute ReflectStatus")
|
||||
customAccessor := c.configManager.LuaScriptAccessors()[object.GroupVersionKind()]
|
||||
if len(customAccessor.GetStatusAggregationLuaScript()) == 0 {
|
||||
return nil, fmt.Errorf("customized interpreter GetDependencies Retain for %q not found", object.GroupVersionKind())
|
||||
func (c *ConfigurableInterpreter) ReflectStatus(object *unstructured.Unstructured) (status *runtime.RawExtension, enabled bool, err error) {
|
||||
luaScript, enabled := c.getInterpreter(object.GroupVersionKind(), configv1alpha1.InterpreterOperationInterpretStatus)
|
||||
if !enabled {
|
||||
return
|
||||
}
|
||||
|
||||
luaScript := customAccessor.GetStatusAggregationLuaScript()
|
||||
klog.Infof("lua script %s", luaScript)
|
||||
|
||||
return nil, err
|
||||
vm := luavm.VM{UseOpenLibs: false}
|
||||
status, err = vm.ReflectStatus(object, luaScript)
|
||||
return
|
||||
}
|
||||
|
||||
// InterpretHealth returns the health state of the object.
|
||||
func (c *ConfigurableInterpreter) InterpretHealth(object *unstructured.Unstructured) (bool, error) {
|
||||
klog.Infof("ConfigurableInterpreter Execute InterpretHealth")
|
||||
customAccessor := c.configManager.LuaScriptAccessors()[object.GroupVersionKind()]
|
||||
if len(customAccessor.GetHealthInterpretationLuaScript()) == 0 {
|
||||
return false, fmt.Errorf("customized interpreter GetHealthInterpretation for %q not found", object.GroupVersionKind())
|
||||
func (c *ConfigurableInterpreter) InterpretHealth(object *unstructured.Unstructured) (health bool, enabled bool, err error) {
|
||||
luaScript, enabled := c.getInterpreter(object.GroupVersionKind(), configv1alpha1.InterpreterOperationInterpretHealth)
|
||||
if !enabled {
|
||||
return
|
||||
}
|
||||
|
||||
luaScript := customAccessor.GetHealthInterpretationLuaScript()
|
||||
klog.Infof("lua script %s", luaScript)
|
||||
|
||||
return false, nil
|
||||
vm := luavm.VM{UseOpenLibs: false}
|
||||
health, err = vm.InterpretHealth(object, luaScript)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *ConfigurableInterpreter) getInterpreter(kind schema.GroupVersionKind, operationType configv1alpha1.InterpreterOperation) (string, bool) {
|
||||
if !c.configManager.HasSynced() {
|
||||
klog.Errorf("not yet ready to handle request")
|
||||
return "", false
|
||||
}
|
||||
accessors, exist := c.configManager.LuaScriptAccessors()[kind]
|
||||
if !exist {
|
||||
return "", false
|
||||
}
|
||||
var script string
|
||||
switch operationType {
|
||||
case configv1alpha1.InterpreterOperationAggregateStatus:
|
||||
script = accessors.GetStatusAggregationLuaScript()
|
||||
case configv1alpha1.InterpreterOperationInterpretHealth:
|
||||
script = accessors.GetHealthInterpretationLuaScript()
|
||||
case configv1alpha1.InterpreterOperationInterpretDependency:
|
||||
script = accessors.GetDependencyInterpretationLuaScript()
|
||||
case configv1alpha1.InterpreterOperationInterpretReplica:
|
||||
script = accessors.GetReplicaResourceLuaScript()
|
||||
case configv1alpha1.InterpreterOperationInterpretStatus:
|
||||
script = accessors.GetStatusReflectionLuaScript()
|
||||
case configv1alpha1.InterpreterOperationRetain:
|
||||
script = accessors.GetRetentionLuaScript()
|
||||
case configv1alpha1.InterpreterOperationReviseReplica:
|
||||
script = accessors.GetReplicaRevisionLuaScript()
|
||||
}
|
||||
return script, len(script) > 0
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ import (
|
|||
|
||||
configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
|
||||
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
|
||||
"github.com/karmada-io/karmada/pkg/util/helper"
|
||||
"github.com/karmada-io/karmada/pkg/util/lifted"
|
||||
)
|
||||
|
||||
|
@ -214,7 +213,7 @@ func (vm VM) Retain(desired *unstructured.Unstructured, observed *unstructured.U
|
|||
}
|
||||
|
||||
// AggregateStatus returns the objects that based on the 'object' but with status aggregated by lua.
|
||||
func (vm VM) AggregateStatus(object *unstructured.Unstructured, item []map[string]interface{}, script string) (*unstructured.Unstructured, error) {
|
||||
func (vm VM) AggregateStatus(object *unstructured.Unstructured, items []workv1alpha2.AggregatedStatusItem, script string) (*unstructured.Unstructured, error) {
|
||||
l := lua.NewState(lua.Options{
|
||||
SkipOpenLibs: !vm.UseOpenLibs,
|
||||
})
|
||||
|
@ -245,7 +244,7 @@ func (vm VM) AggregateStatus(object *unstructured.Unstructured, item []map[strin
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args[1], err = decodeValue(l, item)
|
||||
args[1], err = decodeValue(l, items)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -344,7 +343,7 @@ func (vm VM) ReflectStatus(object *unstructured.Unstructured, script string) (st
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = l.CallByParam(lua.P{Fn: f, NRet: 2, Protect: true}, args...)
|
||||
err = l.CallByParam(lua.P{Fn: f, NRet: 1, Protect: true}, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -354,26 +353,9 @@ func (vm VM) ReflectStatus(object *unstructured.Unstructured, script string) (st
|
|||
return nil, fmt.Errorf("expect the returned replica type is table but got %s", luaStatusResult.Type())
|
||||
}
|
||||
|
||||
luaExistResult := l.Get(l.GetTop())
|
||||
var exist bool
|
||||
exist, err = ConvertLuaResultToBool(luaExistResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if exist {
|
||||
resultMap := make(map[string]interface{})
|
||||
jsonBytes, err := luajson.Encode(luaStatusResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = json.Unmarshal(jsonBytes, &resultMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return helper.BuildStatusRawExtension(resultMap)
|
||||
}
|
||||
return nil, err
|
||||
status = &runtime.RawExtension{}
|
||||
err = ConvertLuaResultInto(luaStatusResult, status)
|
||||
return status, err
|
||||
}
|
||||
|
||||
// GetDependencies returns the dependent resources of the given object by lua.
|
||||
|
@ -414,18 +396,11 @@ func (vm VM) GetDependencies(object *unstructured.Unstructured, script string) (
|
|||
}
|
||||
|
||||
luaResult := l.Get(l.GetTop())
|
||||
if luaResult.Type() == lua.LTTable {
|
||||
jsonBytes, err := luajson.Encode(luaResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = json.Unmarshal(jsonBytes, &dependencies)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
|
||||
if luaResult.Type() != lua.LTTable {
|
||||
return nil, fmt.Errorf("expect the returned requires type is table but got %s", luaResult.Type())
|
||||
}
|
||||
err = ConvertLuaResultInto(luaResult, &dependencies)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -11,22 +11,23 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/utils/pointer"
|
||||
|
||||
configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
|
||||
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
|
||||
"github.com/karmada-io/karmada/pkg/util/helper"
|
||||
)
|
||||
|
||||
func TestGetReplicas(t *testing.T) {
|
||||
var replicas int32 = 1
|
||||
// quantity := *resource.NewQuantity(1000, resource.BinarySI)
|
||||
vm := VM{UseOpenLibs: false}
|
||||
tests := []struct {
|
||||
name string
|
||||
deploy *appsv1.Deployment
|
||||
luaScript string
|
||||
expected bool
|
||||
name string
|
||||
deploy *appsv1.Deployment
|
||||
luaScript string
|
||||
expected bool
|
||||
wantReplica int32
|
||||
wantRequires *workv1alpha2.ReplicaRequirements
|
||||
}{
|
||||
{
|
||||
name: "Test GetReplica",
|
||||
|
@ -63,6 +64,8 @@ func TestGetReplicas(t *testing.T) {
|
|||
result.nodeClaim = nil
|
||||
return replica, {}
|
||||
end`,
|
||||
wantReplica: 1,
|
||||
wantRequires: &workv1alpha2.ReplicaRequirements{},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -70,11 +73,15 @@ func TestGetReplicas(t *testing.T) {
|
|||
t.Run(tt.name, func(t *testing.T) {
|
||||
toUnstructured, _ := helper.ToUnstructured(tt.deploy)
|
||||
replicas, requires, err := vm.GetReplicas(toUnstructured, tt.luaScript)
|
||||
klog.Infof("replicas %v", replicas)
|
||||
klog.Infof("requires %v", requires)
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
}
|
||||
if !reflect.DeepEqual(replicas, tt.wantReplica) {
|
||||
t.Errorf("GetReplicas() got = %v, want %v", replicas, tt.wantReplica)
|
||||
}
|
||||
if !reflect.DeepEqual(requires, tt.wantRequires) {
|
||||
t.Errorf("GetReplicas() got = %v, want %v", requires, tt.wantRequires)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -166,9 +173,9 @@ func TestReviseDeploymentReplica(t *testing.T) {
|
|||
func TestAggregateDeploymentStatus(t *testing.T) {
|
||||
statusMap := map[string]interface{}{
|
||||
"replicas": 0,
|
||||
"readyReplicas": 0,
|
||||
"readyReplicas": 1,
|
||||
"updatedReplicas": 0,
|
||||
"availableReplicas": 1,
|
||||
"availableReplicas": 0,
|
||||
"unavailableReplicas": 0,
|
||||
}
|
||||
raw, _ := helper.BuildStatusRawExtension(statusMap)
|
||||
|
@ -186,37 +193,25 @@ func TestAggregateDeploymentStatus(t *testing.T) {
|
|||
oldDeploy.Status = appsv1.DeploymentStatus{
|
||||
Replicas: 0, ReadyReplicas: 1, UpdatedReplicas: 0, AvailableReplicas: 0, UnavailableReplicas: 0}
|
||||
|
||||
newDeploy := &appsv1.Deployment{Status: appsv1.DeploymentStatus{Replicas: 0, ReadyReplicas: 0, UpdatedReplicas: 0, AvailableReplicas: 2, UnavailableReplicas: 0}}
|
||||
newDeploy := &appsv1.Deployment{Status: appsv1.DeploymentStatus{Replicas: 0, ReadyReplicas: 3, UpdatedReplicas: 0, AvailableReplicas: 0, UnavailableReplicas: 0}}
|
||||
oldObj, _ := helper.ToUnstructured(oldDeploy)
|
||||
newObj, _ := helper.ToUnstructured(newDeploy)
|
||||
|
||||
var aggregateItem []map[string]interface{}
|
||||
for _, item := range aggregatedStatusItems {
|
||||
if item.Status == nil {
|
||||
continue
|
||||
}
|
||||
temp := make(map[string]interface{})
|
||||
if err := json.Unmarshal(item.Status.Raw, &temp); err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
aggregateItem = append(aggregateItem, temp)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
curObj *unstructured.Unstructured
|
||||
aggregatedStatusItems []map[string]interface{}
|
||||
aggregatedStatusItems []workv1alpha2.AggregatedStatusItem
|
||||
expectedObj *unstructured.Unstructured
|
||||
luaScript string
|
||||
}{
|
||||
{
|
||||
name: "Test AggregateDeploymentStatus",
|
||||
curObj: oldObj,
|
||||
aggregatedStatusItems: aggregateItem,
|
||||
aggregatedStatusItems: aggregatedStatusItems,
|
||||
expectedObj: newObj,
|
||||
luaScript: `function AggregateStatus(desiredObj, statusItems)
|
||||
luaScript: `function AggregateStatus(desiredObj, statusItems)
|
||||
for i = 1, #statusItems do
|
||||
desiredObj.status.readyReplicas = desiredObj.status.readyReplicas + statusItems[i].readyReplicas
|
||||
desiredObj.status.readyReplicas = desiredObj.status.readyReplicas + statusItems[i].status.readyReplicas
|
||||
end
|
||||
return desiredObj
|
||||
end`,
|
||||
|
@ -236,8 +231,8 @@ func TestAggregateDeploymentStatus(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
if reflect.DeepEqual(expectDeploy, actualDeploy) {
|
||||
t.Log("Success \n")
|
||||
if !reflect.DeepEqual(expectDeploy, actualDeploy) {
|
||||
t.Errorf("AggregateStatus() got = %v, want %v", actualDeploy, expectDeploy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -273,10 +268,13 @@ func TestHealthDeploymentStatus(t *testing.T) {
|
|||
vm := VM{UseOpenLibs: false}
|
||||
|
||||
for _, tt := range tests {
|
||||
flag, _ := vm.InterpretHealth(tt.curObj, tt.luaScript)
|
||||
flag, err := vm.InterpretHealth(tt.curObj, tt.luaScript)
|
||||
|
||||
if reflect.DeepEqual(flag, tt.expectedObj) {
|
||||
t.Log("Success \n")
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
}
|
||||
if !reflect.DeepEqual(flag, tt.expectedObj) {
|
||||
t.Errorf("AggregateStatus() got = %v, want %v", flag, tt.expectedObj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -290,7 +288,7 @@ func TestRetainDeployment(t *testing.T) {
|
|||
luaScript string
|
||||
}{
|
||||
{
|
||||
name: "Test RetainDeployment",
|
||||
name: "Test RetainDeployment1",
|
||||
desiredObj: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "apps/v1",
|
||||
|
@ -299,7 +297,7 @@ func TestRetainDeployment(t *testing.T) {
|
|||
"name": "fake-deployment",
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"replicas": 1,
|
||||
"replicas": 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -319,7 +317,7 @@ func TestRetainDeployment(t *testing.T) {
|
|||
luaScript: "function Retain(desiredObj, observedObj)\n desiredObj = observedObj\n return desiredObj\n end",
|
||||
},
|
||||
{
|
||||
name: "revise deployment replica",
|
||||
name: "Test RetainDeployment2",
|
||||
desiredObj: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "apps/v1",
|
||||
|
@ -340,7 +338,7 @@ func TestRetainDeployment(t *testing.T) {
|
|||
"name": "fake-deployment",
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"replicas": int64(2),
|
||||
"replicas": int64(1),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -359,13 +357,8 @@ func TestRetainDeployment(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
}
|
||||
deploy := &appsv1.Deployment{}
|
||||
err = runtime.DefaultUnstructuredConverter.FromUnstructured(res.UnstructuredContent(), deploy)
|
||||
if err == nil && reflect.DeepEqual(deploy, tt.observedObj) {
|
||||
t.Log("Success Test")
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
if !reflect.DeepEqual(res.UnstructuredContent(), tt.observedObj.Object) {
|
||||
t.Errorf("Retain() got = %v, want %v", res.UnstructuredContent(), tt.observedObj.Object)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -397,9 +390,9 @@ func TestStatusReflection(t *testing.T) {
|
|||
false,
|
||||
`function ReflectStatus (observedObj)
|
||||
if observedObj.status == nil then
|
||||
return false, nil
|
||||
return nil
|
||||
end
|
||||
return true, observedObj.status
|
||||
return observedObj.status
|
||||
end`,
|
||||
},
|
||||
}
|
||||
|
@ -438,11 +431,18 @@ func TestGetDeployPodDependencies(t *testing.T) {
|
|||
},
|
||||
}
|
||||
newObj, _ := helper.ToUnstructured(&newDeploy)
|
||||
|
||||
expect := make([]configv1alpha1.DependentObjectReference, 1)
|
||||
expect[0] = configv1alpha1.DependentObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "ServiceAccount",
|
||||
Namespace: "test",
|
||||
Name: "test",
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
curObj *unstructured.Unstructured
|
||||
luaScript string
|
||||
want []configv1alpha1.DependentObjectReference
|
||||
}{
|
||||
{
|
||||
name: "Get GetDeployPodDependencies",
|
||||
|
@ -450,30 +450,36 @@ func TestGetDeployPodDependencies(t *testing.T) {
|
|||
luaScript: `function GetDependencies(desiredObj)
|
||||
dependentSas = {}
|
||||
refs = {}
|
||||
if desiredObj.spec.template.spec.serviceAccountName ~= \"\" and desiredObj.spec.template.spec.serviceAccountName ~= \"default\" then
|
||||
if desiredObj.spec.template.spec.serviceAccountName ~= '' and desiredObj.spec.template.spec.serviceAccountName ~= 'default' then
|
||||
dependentSas[desiredObj.spec.template.spec.serviceAccountName] = true
|
||||
end
|
||||
local idx = 1
|
||||
for key, value in pairs(dependentSas) do
|
||||
dependObj = {}
|
||||
dependObj.apiVersion = \"v1\"
|
||||
dependObj.kind = \"ServiceAccount\"
|
||||
dependObj.apiVersion = 'v1'
|
||||
dependObj.kind = 'ServiceAccount'
|
||||
dependObj.name = key
|
||||
dependObj.namespace = desiredObj.namespace
|
||||
dependObj.namespace = desiredObj.metadata.namespace
|
||||
refs[idx] = {}
|
||||
refs[idx] = dependObj
|
||||
idx = idx + 1
|
||||
end
|
||||
return refs
|
||||
end`,
|
||||
want: expect,
|
||||
},
|
||||
}
|
||||
|
||||
vm := VM{UseOpenLibs: false}
|
||||
|
||||
for _, tt := range tests {
|
||||
res, _ := vm.GetDependencies(tt.curObj, tt.luaScript)
|
||||
t.Logf("res %v", res)
|
||||
res, err := vm.GetDependencies(tt.curObj, tt.luaScript)
|
||||
if err != nil {
|
||||
t.Errorf("GetDependencies err %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(res, tt.want) {
|
||||
t.Errorf("GetDependencies() got = %v, want %v", res, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -84,8 +84,9 @@ func (i *customResourceInterpreterImpl) Start(ctx context.Context) (err error) {
|
|||
|
||||
// HookEnabled tells if any hook exist for specific resource type and operation.
|
||||
func (i *customResourceInterpreterImpl) HookEnabled(objGVK schema.GroupVersionKind, operation configv1alpha1.InterpreterOperation) bool {
|
||||
return i.customizedInterpreter.HookEnabled(objGVK, operation) ||
|
||||
i.defaultInterpreter.HookEnabled(objGVK, operation)
|
||||
return i.defaultInterpreter.HookEnabled(objGVK, operation) ||
|
||||
i.configurableInterpreter.HookEnabled(objGVK, operation) ||
|
||||
i.customizedInterpreter.HookEnabled(objGVK, operation)
|
||||
}
|
||||
|
||||
// GetReplicas returns the desired replicas of the object as well as the requirements of each replica.
|
||||
|
@ -93,6 +94,15 @@ func (i *customResourceInterpreterImpl) GetReplicas(object *unstructured.Unstruc
|
|||
klog.V(4).Infof("Begin to get replicas for request object: %v %s/%s.", object.GroupVersionKind(), object.GetNamespace(), object.GetName())
|
||||
|
||||
var hookEnabled bool
|
||||
|
||||
replica, requires, hookEnabled, err = i.configurableInterpreter.GetReplicas(object)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if hookEnabled {
|
||||
return
|
||||
}
|
||||
|
||||
replica, requires, hookEnabled, err = i.customizedInterpreter.GetReplicas(context.TODO(), &webhook.RequestAttributes{
|
||||
Operation: configv1alpha1.InterpreterOperationInterpretReplica,
|
||||
Object: object,
|
||||
|
@ -112,7 +122,15 @@ func (i *customResourceInterpreterImpl) GetReplicas(object *unstructured.Unstruc
|
|||
func (i *customResourceInterpreterImpl) ReviseReplica(object *unstructured.Unstructured, replica int64) (*unstructured.Unstructured, error) {
|
||||
klog.V(4).Infof("Begin to revise replicas for object: %v %s/%s.", object.GroupVersionKind(), object.GetNamespace(), object.GetName())
|
||||
|
||||
obj, hookEnabled, err := i.customizedInterpreter.Patch(context.TODO(), &webhook.RequestAttributes{
|
||||
obj, hookEnabled, err := i.configurableInterpreter.ReviseReplica(object, replica)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if hookEnabled {
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
obj, hookEnabled, err = i.customizedInterpreter.Patch(context.TODO(), &webhook.RequestAttributes{
|
||||
Operation: configv1alpha1.InterpreterOperationReviseReplica,
|
||||
Object: object,
|
||||
ReplicasSet: int32(replica),
|
||||
|
@ -131,7 +149,15 @@ func (i *customResourceInterpreterImpl) ReviseReplica(object *unstructured.Unstr
|
|||
func (i *customResourceInterpreterImpl) Retain(desired *unstructured.Unstructured, observed *unstructured.Unstructured) (*unstructured.Unstructured, error) {
|
||||
klog.V(4).Infof("Begin to retain object: %v %s/%s.", desired.GroupVersionKind(), desired.GetNamespace(), desired.GetName())
|
||||
|
||||
obj, hookEnabled, err := i.customizedInterpreter.Patch(context.TODO(), &webhook.RequestAttributes{
|
||||
obj, hookEnabled, err := i.configurableInterpreter.Retain(desired, observed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if hookEnabled {
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
obj, hookEnabled, err = i.customizedInterpreter.Patch(context.TODO(), &webhook.RequestAttributes{
|
||||
Operation: configv1alpha1.InterpreterOperationRetain,
|
||||
Object: desired,
|
||||
ObservedObj: observed,
|
||||
|
@ -150,7 +176,15 @@ func (i *customResourceInterpreterImpl) Retain(desired *unstructured.Unstructure
|
|||
func (i *customResourceInterpreterImpl) AggregateStatus(object *unstructured.Unstructured, aggregatedStatusItems []workv1alpha2.AggregatedStatusItem) (*unstructured.Unstructured, error) {
|
||||
klog.V(4).Infof("Begin to aggregate status for object: %v %s/%s.", object.GroupVersionKind(), object.GetNamespace(), object.GetName())
|
||||
|
||||
obj, hookEnabled, err := i.customizedInterpreter.Patch(context.TODO(), &webhook.RequestAttributes{
|
||||
obj, hookEnabled, err := i.configurableInterpreter.AggregateStatus(object, aggregatedStatusItems)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if hookEnabled {
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
obj, hookEnabled, err = i.customizedInterpreter.Patch(context.TODO(), &webhook.RequestAttributes{
|
||||
Operation: configv1alpha1.InterpreterOperationAggregateStatus,
|
||||
Object: object.DeepCopy(),
|
||||
AggregatedStatus: aggregatedStatusItems,
|
||||
|
@ -168,8 +202,15 @@ func (i *customResourceInterpreterImpl) AggregateStatus(object *unstructured.Uns
|
|||
// GetDependencies returns the dependent resources of the given object.
|
||||
func (i *customResourceInterpreterImpl) GetDependencies(object *unstructured.Unstructured) (dependencies []configv1alpha1.DependentObjectReference, err error) {
|
||||
klog.V(4).Infof("Begin to get dependencies for object: %v %s/%s.", object.GroupVersionKind(), object.GetNamespace(), object.GetName())
|
||||
dependencies, hookEnabled, err := i.configurableInterpreter.GetDependencies(object)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if hookEnabled {
|
||||
return
|
||||
}
|
||||
|
||||
dependencies, hookEnabled, err := i.customizedInterpreter.GetDependencies(context.TODO(), &webhook.RequestAttributes{
|
||||
dependencies, hookEnabled, err = i.customizedInterpreter.GetDependencies(context.TODO(), &webhook.RequestAttributes{
|
||||
Operation: configv1alpha1.InterpreterOperationInterpretDependency,
|
||||
Object: object,
|
||||
})
|
||||
|
@ -188,7 +229,14 @@ func (i *customResourceInterpreterImpl) GetDependencies(object *unstructured.Uns
|
|||
func (i *customResourceInterpreterImpl) ReflectStatus(object *unstructured.Unstructured) (status *runtime.RawExtension, err error) {
|
||||
klog.V(4).Infof("Begin to grab status for object: %v %s/%s.", object.GroupVersionKind(), object.GetNamespace(), object.GetName())
|
||||
|
||||
status, hookEnabled, err := i.customizedInterpreter.ReflectStatus(context.TODO(), &webhook.RequestAttributes{
|
||||
status, hookEnabled, err := i.configurableInterpreter.ReflectStatus(object)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if hookEnabled {
|
||||
return
|
||||
}
|
||||
status, hookEnabled, err = i.customizedInterpreter.ReflectStatus(context.TODO(), &webhook.RequestAttributes{
|
||||
Operation: configv1alpha1.InterpreterOperationInterpretStatus,
|
||||
Object: object,
|
||||
})
|
||||
|
@ -207,7 +255,15 @@ func (i *customResourceInterpreterImpl) ReflectStatus(object *unstructured.Unstr
|
|||
func (i *customResourceInterpreterImpl) InterpretHealth(object *unstructured.Unstructured) (healthy bool, err error) {
|
||||
klog.V(4).Infof("Begin to check health for object: %v %s/%s.", object.GroupVersionKind(), object.GetNamespace(), object.GetName())
|
||||
|
||||
healthy, hookEnabled, err := i.customizedInterpreter.InterpretHealth(context.TODO(), &webhook.RequestAttributes{
|
||||
healthy, hookEnabled, err := i.configurableInterpreter.InterpretHealth(object)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if hookEnabled {
|
||||
return
|
||||
}
|
||||
|
||||
healthy, hookEnabled, err = i.customizedInterpreter.InterpretHealth(context.TODO(), &webhook.RequestAttributes{
|
||||
Operation: configv1alpha1.InterpreterOperationInterpretHealth,
|
||||
Object: object,
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue