| /* |
| Copyright 2014 The Kubernetes 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 storage |
| |
| import ( |
| "context" |
| "fmt" |
| |
| "k8s.io/apimachinery/pkg/api/errors" |
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
| "k8s.io/apimachinery/pkg/labels" |
| "k8s.io/apimachinery/pkg/runtime" |
| "k8s.io/apiserver/pkg/registry/generic" |
| genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" |
| "k8s.io/apiserver/pkg/registry/rest" |
| "k8s.io/kubernetes/pkg/apis/autoscaling" |
| autoscalingvalidation "k8s.io/kubernetes/pkg/apis/autoscaling/validation" |
| api "k8s.io/kubernetes/pkg/apis/core" |
| "k8s.io/kubernetes/pkg/apis/extensions" |
| controllerstore "k8s.io/kubernetes/pkg/registry/core/replicationcontroller/storage" |
| ) |
| |
| // Container includes dummy storage for RC pods and experimental storage for Scale. |
| type ContainerStorage struct { |
| ReplicationController *RcREST |
| Scale *ScaleREST |
| } |
| |
| func NewStorage(optsGetter generic.RESTOptionsGetter) ContainerStorage { |
| // scale does not set status, only updates spec so we ignore the status |
| controllerREST, _ := controllerstore.NewREST(optsGetter) |
| |
| return ContainerStorage{ |
| ReplicationController: &RcREST{}, |
| Scale: &ScaleREST{store: controllerREST.Store}, |
| } |
| } |
| |
| type ScaleREST struct { |
| store *genericregistry.Store |
| } |
| |
| // ScaleREST implements Patcher |
| var _ = rest.Patcher(&ScaleREST{}) |
| |
| // New creates a new Scale object |
| func (r *ScaleREST) New() runtime.Object { |
| return &autoscaling.Scale{} |
| } |
| |
| func (r *ScaleREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) { |
| obj, err := r.store.Get(ctx, name, options) |
| if err != nil { |
| return nil, errors.NewNotFound(extensions.Resource("replicationcontrollers/scale"), name) |
| } |
| rc := obj.(*api.ReplicationController) |
| return scaleFromRC(rc), nil |
| } |
| |
| func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) { |
| obj, err := r.store.Get(ctx, name, &metav1.GetOptions{}) |
| if err != nil { |
| return nil, false, errors.NewNotFound(extensions.Resource("replicationcontrollers/scale"), name) |
| } |
| rc := obj.(*api.ReplicationController) |
| oldScale := scaleFromRC(rc) |
| |
| obj, err = objInfo.UpdatedObject(ctx, oldScale) |
| |
| if obj == nil { |
| return nil, false, errors.NewBadRequest(fmt.Sprintf("nil update passed to Scale")) |
| } |
| scale, ok := obj.(*autoscaling.Scale) |
| if !ok { |
| return nil, false, errors.NewBadRequest(fmt.Sprintf("wrong object passed to Scale update: %v", obj)) |
| } |
| |
| if errs := autoscalingvalidation.ValidateScale(scale); len(errs) > 0 { |
| return nil, false, errors.NewInvalid(extensions.Kind("Scale"), scale.Name, errs) |
| } |
| |
| rc.Spec.Replicas = scale.Spec.Replicas |
| rc.ResourceVersion = scale.ResourceVersion |
| obj, _, err = r.store.Update(ctx, rc.Name, rest.DefaultUpdatedObjectInfo(rc), createValidation, updateValidation, false, options) |
| if err != nil { |
| return nil, false, errors.NewConflict(extensions.Resource("replicationcontrollers/scale"), scale.Name, err) |
| } |
| rc = obj.(*api.ReplicationController) |
| return scaleFromRC(rc), false, nil |
| } |
| |
| // scaleFromRC returns a scale subresource for a replication controller. |
| func scaleFromRC(rc *api.ReplicationController) *autoscaling.Scale { |
| return &autoscaling.Scale{ |
| ObjectMeta: metav1.ObjectMeta{ |
| Name: rc.Name, |
| Namespace: rc.Namespace, |
| UID: rc.UID, |
| ResourceVersion: rc.ResourceVersion, |
| CreationTimestamp: rc.CreationTimestamp, |
| }, |
| Spec: autoscaling.ScaleSpec{ |
| Replicas: rc.Spec.Replicas, |
| }, |
| Status: autoscaling.ScaleStatus{ |
| Replicas: rc.Status.Replicas, |
| Selector: labels.SelectorFromSet(labels.Set(rc.Spec.Selector)).String(), |
| }, |
| } |
| } |
| |
| // Dummy implementation |
| type RcREST struct{} |
| |
| func (r *RcREST) NamespaceScoped() bool { |
| return true |
| } |
| |
| func (r *RcREST) New() runtime.Object { |
| return &extensions.ReplicationControllerDummy{} |
| } |