mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 04:33:26 +00:00
Fix scale subresource when used with admission webhooks
This commit is contained in:
parent
3bbd9b2c55
commit
dced88e703
@ -293,7 +293,15 @@ func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.Update
|
|||||||
|
|
||||||
deployment.Spec.Replicas = scale.Spec.Replicas
|
deployment.Spec.Replicas = scale.Spec.Replicas
|
||||||
deployment.ResourceVersion = scale.ResourceVersion
|
deployment.ResourceVersion = scale.ResourceVersion
|
||||||
obj, _, err = r.store.Update(ctx, deployment.Name, rest.DefaultUpdatedObjectInfo(deployment), createValidation, updateValidation, false, options)
|
obj, _, err = r.store.Update(
|
||||||
|
ctx,
|
||||||
|
deployment.Name,
|
||||||
|
rest.DefaultUpdatedObjectInfo(deployment),
|
||||||
|
toScaleCreateValidation(createValidation),
|
||||||
|
toScaleUpdateValidation(updateValidation),
|
||||||
|
false,
|
||||||
|
options,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
@ -305,6 +313,30 @@ func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.Update
|
|||||||
return newScale, false, nil
|
return newScale, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toScaleCreateValidation(f rest.ValidateObjectFunc) rest.ValidateObjectFunc {
|
||||||
|
return func(obj runtime.Object) error {
|
||||||
|
scale, err := scaleFromDeployment(obj.(*apps.Deployment))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return f(scale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toScaleUpdateValidation(f rest.ValidateObjectUpdateFunc) rest.ValidateObjectUpdateFunc {
|
||||||
|
return func(obj, old runtime.Object) error {
|
||||||
|
newScale, err := scaleFromDeployment(obj.(*apps.Deployment))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
oldScale, err := scaleFromDeployment(old.(*apps.Deployment))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return f(newScale, oldScale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// scaleFromDeployment returns a scale subresource for a deployment.
|
// scaleFromDeployment returns a scale subresource for a deployment.
|
||||||
func scaleFromDeployment(deployment *apps.Deployment) (*autoscaling.Scale, error) {
|
func scaleFromDeployment(deployment *apps.Deployment) (*autoscaling.Scale, error) {
|
||||||
selector, err := metav1.LabelSelectorAsSelector(deployment.Spec.Selector)
|
selector, err := metav1.LabelSelectorAsSelector(deployment.Spec.Selector)
|
||||||
|
@ -201,7 +201,15 @@ func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.Update
|
|||||||
|
|
||||||
rs.Spec.Replicas = scale.Spec.Replicas
|
rs.Spec.Replicas = scale.Spec.Replicas
|
||||||
rs.ResourceVersion = scale.ResourceVersion
|
rs.ResourceVersion = scale.ResourceVersion
|
||||||
obj, _, err = r.store.Update(ctx, rs.Name, rest.DefaultUpdatedObjectInfo(rs), createValidation, updateValidation, false, options)
|
obj, _, err = r.store.Update(
|
||||||
|
ctx,
|
||||||
|
rs.Name,
|
||||||
|
rest.DefaultUpdatedObjectInfo(rs),
|
||||||
|
toScaleCreateValidation(createValidation),
|
||||||
|
toScaleUpdateValidation(updateValidation),
|
||||||
|
false,
|
||||||
|
options,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
@ -213,6 +221,30 @@ func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.Update
|
|||||||
return newScale, false, err
|
return newScale, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toScaleCreateValidation(f rest.ValidateObjectFunc) rest.ValidateObjectFunc {
|
||||||
|
return func(obj runtime.Object) error {
|
||||||
|
scale, err := scaleFromReplicaSet(obj.(*apps.ReplicaSet))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return f(scale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toScaleUpdateValidation(f rest.ValidateObjectUpdateFunc) rest.ValidateObjectUpdateFunc {
|
||||||
|
return func(obj, old runtime.Object) error {
|
||||||
|
newScale, err := scaleFromReplicaSet(obj.(*apps.ReplicaSet))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
oldScale, err := scaleFromReplicaSet(old.(*apps.ReplicaSet))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return f(newScale, oldScale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// scaleFromReplicaSet returns a scale subresource for a replica set.
|
// scaleFromReplicaSet returns a scale subresource for a replica set.
|
||||||
func scaleFromReplicaSet(rs *apps.ReplicaSet) (*autoscaling.Scale, error) {
|
func scaleFromReplicaSet(rs *apps.ReplicaSet) (*autoscaling.Scale, error) {
|
||||||
selector, err := metav1.LabelSelectorAsSelector(rs.Spec.Selector)
|
selector, err := metav1.LabelSelectorAsSelector(rs.Spec.Selector)
|
||||||
|
@ -188,7 +188,15 @@ func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.Update
|
|||||||
|
|
||||||
ss.Spec.Replicas = scale.Spec.Replicas
|
ss.Spec.Replicas = scale.Spec.Replicas
|
||||||
ss.ResourceVersion = scale.ResourceVersion
|
ss.ResourceVersion = scale.ResourceVersion
|
||||||
obj, _, err = r.store.Update(ctx, ss.Name, rest.DefaultUpdatedObjectInfo(ss), createValidation, updateValidation, false, options)
|
obj, _, err = r.store.Update(
|
||||||
|
ctx,
|
||||||
|
ss.Name,
|
||||||
|
rest.DefaultUpdatedObjectInfo(ss),
|
||||||
|
toScaleCreateValidation(createValidation),
|
||||||
|
toScaleUpdateValidation(updateValidation),
|
||||||
|
false,
|
||||||
|
options,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
@ -200,6 +208,30 @@ func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.Update
|
|||||||
return newScale, false, err
|
return newScale, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toScaleCreateValidation(f rest.ValidateObjectFunc) rest.ValidateObjectFunc {
|
||||||
|
return func(obj runtime.Object) error {
|
||||||
|
scale, err := scaleFromStatefulSet(obj.(*apps.StatefulSet))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return f(scale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toScaleUpdateValidation(f rest.ValidateObjectUpdateFunc) rest.ValidateObjectUpdateFunc {
|
||||||
|
return func(obj, old runtime.Object) error {
|
||||||
|
newScale, err := scaleFromStatefulSet(obj.(*apps.StatefulSet))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
oldScale, err := scaleFromStatefulSet(old.(*apps.StatefulSet))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return f(newScale, oldScale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// scaleFromStatefulSet returns a scale subresource for a statefulset.
|
// scaleFromStatefulSet returns a scale subresource for a statefulset.
|
||||||
func scaleFromStatefulSet(ss *apps.StatefulSet) (*autoscaling.Scale, error) {
|
func scaleFromStatefulSet(ss *apps.StatefulSet) (*autoscaling.Scale, error) {
|
||||||
selector, err := metav1.LabelSelectorAsSelector(ss.Spec.Selector)
|
selector, err := metav1.LabelSelectorAsSelector(ss.Spec.Selector)
|
||||||
|
@ -183,7 +183,15 @@ func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.Update
|
|||||||
|
|
||||||
rc.Spec.Replicas = scale.Spec.Replicas
|
rc.Spec.Replicas = scale.Spec.Replicas
|
||||||
rc.ResourceVersion = scale.ResourceVersion
|
rc.ResourceVersion = scale.ResourceVersion
|
||||||
obj, _, err = r.store.Update(ctx, rc.Name, rest.DefaultUpdatedObjectInfo(rc), createValidation, updateValidation, false, options)
|
obj, _, err = r.store.Update(
|
||||||
|
ctx,
|
||||||
|
rc.Name,
|
||||||
|
rest.DefaultUpdatedObjectInfo(rc),
|
||||||
|
toScaleCreateValidation(createValidation),
|
||||||
|
toScaleUpdateValidation(updateValidation),
|
||||||
|
false,
|
||||||
|
options,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
@ -191,6 +199,21 @@ func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.Update
|
|||||||
return scaleFromRC(rc), false, nil
|
return scaleFromRC(rc), false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toScaleCreateValidation(f rest.ValidateObjectFunc) rest.ValidateObjectFunc {
|
||||||
|
return func(obj runtime.Object) error {
|
||||||
|
return f(scaleFromRC(obj.(*api.ReplicationController)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toScaleUpdateValidation(f rest.ValidateObjectUpdateFunc) rest.ValidateObjectUpdateFunc {
|
||||||
|
return func(obj, old runtime.Object) error {
|
||||||
|
return f(
|
||||||
|
scaleFromRC(obj.(*api.ReplicationController)),
|
||||||
|
scaleFromRC(old.(*api.ReplicationController)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// scaleFromRC returns a scale subresource for a replication controller.
|
// scaleFromRC returns a scale subresource for a replication controller.
|
||||||
func scaleFromRC(rc *api.ReplicationController) *autoscaling.Scale {
|
func scaleFromRC(rc *api.ReplicationController) *autoscaling.Scale {
|
||||||
return &autoscaling.Scale{
|
return &autoscaling.Scale{
|
||||||
|
@ -95,7 +95,15 @@ func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.Update
|
|||||||
|
|
||||||
rc.Spec.Replicas = scale.Spec.Replicas
|
rc.Spec.Replicas = scale.Spec.Replicas
|
||||||
rc.ResourceVersion = scale.ResourceVersion
|
rc.ResourceVersion = scale.ResourceVersion
|
||||||
obj, _, err = r.store.Update(ctx, rc.Name, rest.DefaultUpdatedObjectInfo(rc), createValidation, updateValidation, false, options)
|
obj, _, err = r.store.Update(
|
||||||
|
ctx,
|
||||||
|
rc.Name,
|
||||||
|
rest.DefaultUpdatedObjectInfo(rc),
|
||||||
|
toScaleCreateValidation(createValidation),
|
||||||
|
toScaleUpdateValidation(updateValidation),
|
||||||
|
false,
|
||||||
|
options,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, errors.NewConflict(extensions.Resource("replicationcontrollers/scale"), scale.Name, err)
|
return nil, false, errors.NewConflict(extensions.Resource("replicationcontrollers/scale"), scale.Name, err)
|
||||||
}
|
}
|
||||||
@ -103,6 +111,21 @@ func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.Update
|
|||||||
return scaleFromRC(rc), false, nil
|
return scaleFromRC(rc), false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toScaleCreateValidation(f rest.ValidateObjectFunc) rest.ValidateObjectFunc {
|
||||||
|
return func(obj runtime.Object) error {
|
||||||
|
return f(scaleFromRC(obj.(*api.ReplicationController)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toScaleUpdateValidation(f rest.ValidateObjectUpdateFunc) rest.ValidateObjectUpdateFunc {
|
||||||
|
return func(obj, old runtime.Object) error {
|
||||||
|
return f(
|
||||||
|
scaleFromRC(obj.(*api.ReplicationController)),
|
||||||
|
scaleFromRC(old.(*api.ReplicationController)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// scaleFromRC returns a scale subresource for a replication controller.
|
// scaleFromRC returns a scale subresource for a replication controller.
|
||||||
func scaleFromRC(rc *api.ReplicationController) *autoscaling.Scale {
|
func scaleFromRC(rc *api.ReplicationController) *autoscaling.Scale {
|
||||||
return &autoscaling.Scale{
|
return &autoscaling.Scale{
|
||||||
|
@ -12,6 +12,7 @@ go_library(
|
|||||||
importpath = "k8s.io/apiextensions-apiserver/pkg/apiserver/conversion",
|
importpath = "k8s.io/apiextensions-apiserver/pkg/apiserver/conversion",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//staging/src/k8s.io/api/autoscaling/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library",
|
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library",
|
||||||
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library",
|
"//staging/src/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library",
|
||||||
"//staging/src/k8s.io/apiextensions-apiserver/pkg/features:go_default_library",
|
"//staging/src/k8s.io/apiextensions-apiserver/pkg/features:go_default_library",
|
||||||
@ -22,6 +23,7 @@ go_library(
|
|||||||
"//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/util/webhook:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/util/webhook:go_default_library",
|
||||||
|
"//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library",
|
||||||
"//staging/src/k8s.io/client-go/rest:go_default_library",
|
"//staging/src/k8s.io/client-go/rest:go_default_library",
|
||||||
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
||||||
],
|
],
|
||||||
|
@ -19,6 +19,7 @@ package conversion
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
autoscalingv1 "k8s.io/api/autoscaling/v1"
|
||||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||||
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
|
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
@ -26,6 +27,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/apiserver/pkg/util/webhook"
|
"k8s.io/apiserver/pkg/util/webhook"
|
||||||
|
typedscheme "k8s.io/client-go/kubernetes/scheme"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CRConverterFactory is the factory for all CR converters.
|
// CRConverterFactory is the factory for all CR converters.
|
||||||
@ -77,7 +79,20 @@ func (m *CRConverterFactory) NewConverter(crd *apiextensions.CustomResourceDefin
|
|||||||
default:
|
default:
|
||||||
return nil, nil, fmt.Errorf("unknown conversion strategy %q for CRD %s", crd.Spec.Conversion.Strategy, crd.Name)
|
return nil, nil, fmt.Errorf("unknown conversion strategy %q for CRD %s", crd.Spec.Conversion.Strategy, crd.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine whether we should expect to be asked to "convert" autoscaling/v1 Scale types
|
||||||
|
convertScale := false
|
||||||
|
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) {
|
||||||
|
convertScale = crd.Spec.Subresources != nil && crd.Spec.Subresources.Scale != nil
|
||||||
|
for _, version := range crd.Spec.Versions {
|
||||||
|
if version.Subresources != nil && version.Subresources.Scale != nil {
|
||||||
|
convertScale = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe = &crConverter{
|
unsafe = &crConverter{
|
||||||
|
convertScale: convertScale,
|
||||||
validVersions: validVersions,
|
validVersions: validVersions,
|
||||||
clusterScoped: crd.Spec.Scope == apiextensions.ClusterScoped,
|
clusterScoped: crd.Spec.Scope == apiextensions.ClusterScoped,
|
||||||
converter: converter,
|
converter: converter,
|
||||||
@ -96,6 +111,7 @@ type crConverterInterface interface {
|
|||||||
// crConverter extends the delegate converter with generic CR conversion behaviour. The delegate will implement the
|
// crConverter extends the delegate converter with generic CR conversion behaviour. The delegate will implement the
|
||||||
// user defined conversion strategy given in the CustomResourceDefinition.
|
// user defined conversion strategy given in the CustomResourceDefinition.
|
||||||
type crConverter struct {
|
type crConverter struct {
|
||||||
|
convertScale bool
|
||||||
converter crConverterInterface
|
converter crConverterInterface
|
||||||
validVersions map[schema.GroupVersion]bool
|
validVersions map[schema.GroupVersion]bool
|
||||||
clusterScoped bool
|
clusterScoped bool
|
||||||
@ -114,14 +130,23 @@ func (c *crConverter) ConvertFieldLabel(gvk schema.GroupVersionKind, label, valu
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *crConverter) Convert(in, out, context interface{}) error {
|
func (c *crConverter) Convert(in, out, context interface{}) error {
|
||||||
|
// Special-case typed scale conversion if this custom resource supports a scale endpoint
|
||||||
|
if c.convertScale {
|
||||||
|
_, isInScale := in.(*autoscalingv1.Scale)
|
||||||
|
_, isOutScale := out.(*autoscalingv1.Scale)
|
||||||
|
if isInScale || isOutScale {
|
||||||
|
return typedscheme.Scheme.Convert(in, out, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unstructIn, ok := in.(*unstructured.Unstructured)
|
unstructIn, ok := in.(*unstructured.Unstructured)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("input type %T in not valid for unstructured conversion", in)
|
return fmt.Errorf("input type %T in not valid for unstructured conversion to %T", in, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
unstructOut, ok := out.(*unstructured.Unstructured)
|
unstructOut, ok := out.(*unstructured.Unstructured)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("output type %T in not valid for unstructured conversion", out)
|
return fmt.Errorf("output type %T in not valid for unstructured conversion from %T", out, in)
|
||||||
}
|
}
|
||||||
|
|
||||||
outGVK := unstructOut.GroupVersionKind()
|
outGVK := unstructOut.GroupVersionKind()
|
||||||
|
@ -268,7 +268,15 @@ func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.Update
|
|||||||
}
|
}
|
||||||
cr.SetResourceVersion(scale.ResourceVersion)
|
cr.SetResourceVersion(scale.ResourceVersion)
|
||||||
|
|
||||||
obj, _, err = r.store.Update(ctx, cr.GetName(), rest.DefaultUpdatedObjectInfo(cr), createValidation, updateValidation, false, options)
|
obj, _, err = r.store.Update(
|
||||||
|
ctx,
|
||||||
|
cr.GetName(),
|
||||||
|
rest.DefaultUpdatedObjectInfo(cr),
|
||||||
|
toScaleCreateValidation(createValidation, r.specReplicasPath, r.statusReplicasPath, r.labelSelectorPath),
|
||||||
|
toScaleUpdateValidation(updateValidation, r.specReplicasPath, r.statusReplicasPath, r.labelSelectorPath),
|
||||||
|
false,
|
||||||
|
options,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
@ -281,6 +289,30 @@ func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.Update
|
|||||||
return newScale, false, err
|
return newScale, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toScaleCreateValidation(f rest.ValidateObjectFunc, specReplicasPath, statusReplicasPath, labelSelectorPath string) rest.ValidateObjectFunc {
|
||||||
|
return func(obj runtime.Object) error {
|
||||||
|
scale, _, err := scaleFromCustomResource(obj.(*unstructured.Unstructured), specReplicasPath, statusReplicasPath, labelSelectorPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return f(scale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toScaleUpdateValidation(f rest.ValidateObjectUpdateFunc, specReplicasPath, statusReplicasPath, labelSelectorPath string) rest.ValidateObjectUpdateFunc {
|
||||||
|
return func(obj, old runtime.Object) error {
|
||||||
|
newScale, _, err := scaleFromCustomResource(obj.(*unstructured.Unstructured), specReplicasPath, statusReplicasPath, labelSelectorPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
oldScale, _, err := scaleFromCustomResource(old.(*unstructured.Unstructured), specReplicasPath, statusReplicasPath, labelSelectorPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return f(newScale, oldScale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// scaleFromCustomResource returns a scale subresource for a customresource and a bool signalling wether
|
// scaleFromCustomResource returns a scale subresource for a customresource and a bool signalling wether
|
||||||
// the specReplicas value was found.
|
// the specReplicas value was found.
|
||||||
func scaleFromCustomResource(cr *unstructured.Unstructured, specReplicasPath, statusReplicasPath, labelSelectorPath string) (*autoscalingv1.Scale, bool, error) {
|
func scaleFromCustomResource(cr *unstructured.Unstructured, specReplicasPath, statusReplicasPath, labelSelectorPath string) (*autoscalingv1.Scale, bool, error) {
|
||||||
@ -310,6 +342,11 @@ func scaleFromCustomResource(cr *unstructured.Unstructured, specReplicasPath, st
|
|||||||
}
|
}
|
||||||
|
|
||||||
scale := &autoscalingv1.Scale{
|
scale := &autoscalingv1.Scale{
|
||||||
|
// Populate apiVersion and kind so conversion recognizes we are already in the desired GVK and doesn't try to convert
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
APIVersion: "autoscaling/v1",
|
||||||
|
Kind: "Scale",
|
||||||
|
},
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: cr.GetName(),
|
Name: cr.GetName(),
|
||||||
Namespace: cr.GetNamespace(),
|
Namespace: cr.GetNamespace(),
|
||||||
|
@ -381,6 +381,10 @@ func TestScaleGet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
want := &autoscalingv1.Scale{
|
want := &autoscalingv1.Scale{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
Kind: "Scale",
|
||||||
|
APIVersion: "autoscaling/v1",
|
||||||
|
},
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: cr.GetName(),
|
Name: cr.GetName(),
|
||||||
Namespace: metav1.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
|
Loading…
Reference in New Issue
Block a user