Make deployments work.

This commit is contained in:
Madhusudan.C.S 2016-02-05 18:43:02 -08:00
parent 518f08aa7c
commit ed7ad6dcf3
28 changed files with 485 additions and 385 deletions

View File

@ -943,6 +943,7 @@ __EOF__
kubectl scale --replicas=2 -f examples/guestbook/frontend-controller.yaml "${kube_flags[@]}"
# Post-condition: 2 replicas
kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '2'
kubectl delete rc frontend "${kube_flags[@]}"
### Scale multiple replication controllers
kubectl create -f examples/guestbook/redis-master-controller.yaml "${kube_flags[@]}"
@ -963,16 +964,16 @@ __EOF__
kube::test::get_object_assert 'job pi' "{{$job_parallelism_field}}" '2'
# Clean-up
kubectl delete job/pi "${kube_flags[@]}"
### Scale a deployment
kubectl create -f examples/extensions/deployment.yaml "${kube_flags[@]}"
# Command
kubectl scale --current-replicas=3 --replicas=1 deployment/nginx-deployment
# Post-condition: 1 replica for nginx-deployment
kube::test::get_object_assert 'deployment nginx-deployment' "{{$deployment_replicas}}" '1'
# Clean-up
kubectl delete deployment/nginx-deployment "${kube_flags[@]}"
# TODO: Remove once deployment reaping is implemented
kubectl delete rc --all "${kube_flags[@]}"
# ### Scale a deployment
# kubectl create -f examples/extensions/deployment.yaml "${kube_flags[@]}"
# # Command
# kubectl scale --current-replicas=3 --replicas=1 deployment/nginx-deployment
# # Post-condition: 1 replica for nginx-deployment
# kube::test::get_object_assert 'deployment nginx-deployment' "{{$deployment_replicas}}" '1'
# # Clean-up
# kubectl delete deployment/nginx-deployment "${kube_flags[@]}"
# # TODO: Remove once deployment reaping is implemented
# kubectl delete rs --all "${kube_flags[@]}"
### Expose a deployment as a service
kubectl create -f examples/extensions/deployment.yaml "${kube_flags[@]}"
@ -985,7 +986,7 @@ __EOF__
# Clean-up
kubectl delete deployment/nginx-deployment service/nginx-deployment "${kube_flags[@]}"
# TODO: Remove once deployment reaping is implemented
kubectl delete rc --all "${kube_flags[@]}"
kubectl delete rs --all "${kube_flags[@]}"
### Expose replication controller as service
kubectl create -f examples/guestbook/frontend-controller.yaml "${kube_flags[@]}"
@ -1102,7 +1103,7 @@ __EOF__
# Clean up
kubectl delete hpa nginx-deployment "${kube_flags[@]}"
kubectl delete deployment nginx-deployment "${kube_flags[@]}"
kubectl delete rc -l pod-template-hash "${kube_flags[@]}"
kubectl delete rs -l pod-template-hash "${kube_flags[@]}"
### Rollback a deployment
# Pre-condition: no deployment exists
@ -1131,7 +1132,7 @@ __EOF__
kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" 'nginx:latest:'
# Clean up
kubectl delete deployment nginx-deployment "${kube_flags[@]}"
kubectl delete rc -l pod-template-hash "${kube_flags[@]}"
kubectl delete rs -l pod-template-hash "${kube_flags[@]}"
######################
# ConfigMap #

View File

@ -7,7 +7,8 @@ metadata:
spec:
replicas: 3
selector:
name: nginx
matchLabels:
name: nginx
template:
metadata:
labels:

View File

@ -16,29 +16,32 @@ limitations under the License.
package extensions
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
)
// TODO(madhusudancs): Fix this when Scale group issues are resolved.
// import (
// "fmt"
// ScaleFromDeployment returns a scale subresource for a deployment.
func ScaleFromDeployment(deployment *Deployment) (*Scale, error) {
selector, err := unversioned.LabelSelectorAsSelector(deployment.Spec.Selector)
if err != nil {
return nil, fmt.Errorf("failed to convert label selector to selector: %v", err)
}
return &Scale{
ObjectMeta: api.ObjectMeta{
Name: deployment.Name,
Namespace: deployment.Namespace,
CreationTimestamp: deployment.CreationTimestamp,
},
Spec: ScaleSpec{
Replicas: deployment.Spec.Replicas,
},
Status: ScaleStatus{
Replicas: deployment.Status.Replicas,
Selector: selector.String(),
},
}, nil
}
// "k8s.io/kubernetes/pkg/api"
// "k8s.io/kubernetes/pkg/api/unversioned"
// )
// // ScaleFromDeployment returns a scale subresource for a deployment.
// func ScaleFromDeployment(deployment *Deployment) (*Scale, error) {
// selector, err := unversioned.LabelSelectorAsSelector(deployment.Spec.Selector)
// if err != nil {
// return nil, fmt.Errorf("failed to convert label selector to selector: %v", err)
// }
// return &Scale{
// ObjectMeta: api.ObjectMeta{
// Name: deployment.Name,
// Namespace: deployment.Namespace,
// CreationTimestamp: deployment.CreationTimestamp,
// },
// Spec: ScaleSpec{
// Replicas: deployment.Spec.Replicas,
// },
// Status: ScaleStatus{
// Replicas: deployment.Status.Replicas,
// Selector: selector.String(),
// },
// }, nil
// }

View File

@ -235,7 +235,7 @@ type DeploymentSpec struct {
// Label selector for pods. Existing ReplicaSets whose pods are
// selected by this will be the ones affected by this deployment.
Selector *LabelSelector `json:"selector,omitempty"`
Selector *unversioned.LabelSelector `json:"selector,omitempty"`
// Template describes the pods that will be created.
Template api.PodTemplateSpec `json:"template"`

View File

@ -105,7 +105,7 @@ func Convert_extensions_DeploymentSpec_To_v1beta1_DeploymentSpec(in *extensions.
*out.Replicas = int32(in.Replicas)
if in.Selector != nil {
out.Selector = new(LabelSelector)
if err := Convert_extensions_LabelSelector_To_v1beta1_LabelSelector(in.Selector, out.Selector, s); err != nil {
if err := Convert_unversioned_LabelSelector_To_v1beta1_LabelSelector(in.Selector, out.Selector, s); err != nil {
return err
}
} else {
@ -141,8 +141,8 @@ func Convert_v1beta1_DeploymentSpec_To_extensions_DeploymentSpec(in *DeploymentS
}
if in.Selector != nil {
out.Selector = new(extensions.LabelSelector)
if err := Convert_v1beta1_LabelSelector_To_extensions_LabelSelector(in.Selector, out.Selector, s); err != nil {
out.Selector = new(unversioned.LabelSelector)
if err := Convert_v1beta1_LabelSelector_To_unversioned_LabelSelector(in.Selector, out.Selector, s); err != nil {
return err
}
} else {

View File

@ -351,13 +351,13 @@ func ValidateDeploymentSpec(spec *extensions.DeploymentSpec, fldPath *field.Path
if spec.Selector == nil {
allErrs = append(allErrs, field.Required(fldPath.Child("selector"), ""))
} else {
allErrs = append(allErrs, ValidateLabelSelector(spec.Selector, fldPath.Child("selector"))...)
allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(spec.Selector, fldPath.Child("selector"))...)
if len(spec.Selector.MatchLabels)+len(spec.Selector.MatchExpressions) == 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "empty selector is not valid for deployment."))
}
}
selector, err := extensions.LabelSelectorAsSelector(spec.Selector)
selector, err := unversioned.LabelSelectorAsSelector(spec.Selector)
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "failed to convert LabelSelector to Selector."))
} else {

View File

@ -952,7 +952,7 @@ func validDeployment() *extensions.Deployment {
Namespace: api.NamespaceDefault,
},
Spec: extensions.DeploymentSpec{
Selector: &extensions.LabelSelector{
Selector: &unversioned.LabelSelector{
MatchLabels: map[string]string{
"name": "abc",
},
@ -1002,7 +1002,7 @@ func TestValidateDeployment(t *testing.T) {
}
// selector should match the labels in pod template.
invalidSelectorDeployment := validDeployment()
invalidSelectorDeployment.Spec.Selector = &extensions.LabelSelector{
invalidSelectorDeployment.Spec.Selector = &unversioned.LabelSelector{
MatchLabels: map[string]string{
"name": "def",
},

View File

@ -252,7 +252,7 @@ func (s *StoreToDeploymentLister) GetDeploymentsForReplicaSet(rs *extensions.Rep
continue
}
selector, err := extensions.LabelSelectorAsSelector(rs.Spec.Selector)
selector, err := unversioned.LabelSelectorAsSelector(rs.Spec.Selector)
if err != nil {
return nil, fmt.Errorf("failed to convert LabelSelector to Selector: %v", err)
}
@ -291,6 +291,27 @@ func (s *StoreToReplicaSetLister) List() (rss []extensions.ReplicaSet, err error
return rss, nil
}
type storeReplicaSetsNamespacer struct {
store Store
namespace string
}
func (s storeReplicaSetsNamespacer) List(selector labels.Selector) (rss []extensions.ReplicaSet, err error) {
for _, c := range s.store.List() {
rs := *(c.(*extensions.ReplicaSet))
if s.namespace == api.NamespaceAll || s.namespace == rs.Namespace {
if selector.Matches(labels.Set(rs.Labels)) {
rss = append(rss, rs)
}
}
}
return
}
func (s *StoreToReplicaSetLister) ReplicaSets(namespace string) storeReplicaSetsNamespacer {
return storeReplicaSetsNamespacer{s.Store, namespace}
}
// GetPodReplicaSets returns a list of ReplicaSets managing a pod. Returns an error only if no matching ReplicaSets are found.
func (s *StoreToReplicaSetLister) GetPodReplicaSets(pod *api.Pod) (rss []extensions.ReplicaSet, err error) {
var selector labels.Selector

View File

@ -26,6 +26,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/client/cache"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/record"
@ -477,3 +478,16 @@ func (o ControllersByCreationTimestamp) Less(i, j int) bool {
}
return o[i].CreationTimestamp.Before(o[j].CreationTimestamp)
}
// ReplicaSetsByCreationTimestamp sorts a list of ReplicationSets by creation timestamp, using their names as a tie breaker.
type ReplicaSetsByCreationTimestamp []*extensions.ReplicaSet
func (o ReplicaSetsByCreationTimestamp) Len() int { return len(o) }
func (o ReplicaSetsByCreationTimestamp) Swap(i, j int) { o[i], o[j] = o[j], o[i] }
func (o ReplicaSetsByCreationTimestamp) Less(i, j int) bool {
if o[i].CreationTimestamp.Equal(o[j].CreationTimestamp) {
return o[i].Name < o[j].Name
}
return o[i].CreationTimestamp.Before(o[j].CreationTimestamp)
}

View File

@ -1020,14 +1020,14 @@ func (dc *DeploymentController) cleanupOldReplicaSets(oldRSs []*extensions.Repli
return nil
}
sort.Sort(controller.ControllersByCreationTimestamp(oldRSs))
sort.Sort(controller.ReplicaSetsByCreationTimestamp(oldRSs))
var errList []error
// TODO: This should be parallelized.
for i := 0; i < diff; i++ {
controller := oldRSs[i]
rs := oldRSs[i]
// Avoid delete replica set with non-zero replica counts
if controller.Spec.Replicas != 0 || controller.Generation > controller.Status.ObservedGeneration {
if rs.Spec.Replicas != 0 || rs.Generation > rs.Status.ObservedGeneration {
continue
}
if err := dc.client.Extensions().ReplicaSets(rs.Namespace).Delete(rs.Name, nil); err != nil && !errors.IsNotFound(err) {
@ -1076,7 +1076,7 @@ func (dc *DeploymentController) scaleReplicaSetAndRecordEvent(rs *extensions.Rep
}
newRS, err := dc.scaleReplicaSet(rs, newScale)
if err == nil {
dc.eventRecorder.Eventf(&deployment, api.EventTypeNormal, "ScalingReplicaSet", "Scaled %s ReplicaSet %s to %d", scalingOperation, rs.Name, newScale)
dc.eventRecorder.Eventf(&deployment, api.EventTypeNormal, "ScalingReplicaSet", "Scaled %s replica set %s to %d", scalingOperation, rs.Name, newScale)
}
return newRS, err
}

View File

@ -89,12 +89,11 @@ func TestDeploymentController_reconcileNewReplicaSet(t *testing.T) {
t.Logf("executing scenario %d", i)
newRS := rs("foo-v2", test.newReplicas, nil)
oldRS := rs("foo-v2", test.oldReplicas, nil)
allRSs := []*extensions.ReplicaSet{newRS, oldRS}
allRSs := []*exp.ReplicaSet{newRS, oldRS}
deployment := deployment("foo", test.deploymentReplicas, test.maxSurge, intstr.FromInt(0))
fake := fake.Clientset{}
controller := &DeploymentController{
client: &fake,
expClient: fake.Extensions(),
eventRecorder: &record.FakeRecorder{},
}
scaled, err := controller.reconcileNewReplicaSet(allRSs, newRS, deployment)
@ -430,8 +429,8 @@ func TestDeploymentController_scaleDownOldReplicaSetsForRollingUpdate(t *testing
for i, test := range tests {
t.Logf("executing scenario %d", i)
oldRS := rs("foo-v2", test.oldReplicas, nil)
allRSs := []*extensions.ReplicaSet{oldRS}
oldRSs := []*extensions.ReplicaSet{oldRS}
allRSs := []*exp.ReplicaSet{oldRS}
oldRSs := []*exp.ReplicaSet{oldRS}
deployment := deployment("foo", test.deploymentReplicas, intstr.FromInt(0), test.maxUnavailable)
fakeClientset := fake.Clientset{}
fakeClientset.AddReactor("list", "pods", func(action core.Action) (handled bool, ret runtime.Object, err error) {
@ -460,7 +459,6 @@ func TestDeploymentController_scaleDownOldReplicaSetsForRollingUpdate(t *testing
})
controller := &DeploymentController{
client: &fakeClientset,
expClient: fake.Extensions(),
eventRecorder: &record.FakeRecorder{},
}
scaled, err := controller.scaleDownOldReplicaSetsForRollingUpdate(allRSs, oldRSs, deployment)
@ -506,12 +504,12 @@ func TestDeploymentController_cleanupOldReplicaSets(t *testing.T) {
selector := map[string]string{"foo": "bar"}
tests := []struct {
oldRSs []*extensions.ReplicaSet
oldRSs []*exp.ReplicaSet
revisionHistoryLimit int
expectedDeletions int
}{
{
oldRSs: []*extensions.ReplicaSet{
oldRSs: []*exp.ReplicaSet{
rs("foo-1", 0, selector),
rs("foo-2", 0, selector),
rs("foo-3", 0, selector),
@ -520,7 +518,7 @@ func TestDeploymentController_cleanupOldReplicaSets(t *testing.T) {
expectedDeletions: 2,
},
{
oldRSs: []*extensions.ReplicaSet{
oldRSs: []*exp.ReplicaSet{
rs("foo-1", 0, selector),
rs("foo-2", 0, selector),
},
@ -528,7 +526,7 @@ func TestDeploymentController_cleanupOldReplicaSets(t *testing.T) {
expectedDeletions: 2,
},
{
oldRSs: []*extensions.ReplicaSet{
oldRSs: []*exp.ReplicaSet{
rs("foo-1", 1, selector),
rs("foo-2", 1, selector),
},
@ -564,14 +562,14 @@ func TestDeploymentController_cleanupOldReplicaSets(t *testing.T) {
}
}
func rs(name string, replicas int, selector map[string]string) *extensions.ReplicaSet {
return &extensions.ReplicaSet{
func rs(name string, replicas int, selector map[string]string) *exp.ReplicaSet {
return &exp.ReplicaSet{
ObjectMeta: api.ObjectMeta{
Name: name,
},
Spec: exp.ReplicaSetSpec{
Replicas: replicas,
Selector: &exp.LabelSelector{MatchLabels: selector},
Selector: &unversioned.LabelSelector{MatchLabels: selector},
Template: &api.PodTemplateSpec{},
},
}
@ -612,7 +610,7 @@ func newDeployment(replicas int, revisionHistoryLimit *int) *exp.Deployment {
RollingUpdate: &exp.RollingUpdateDeployment{},
},
Replicas: replicas,
Selector: &exp.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
Template: api.PodTemplateSpec{
ObjectMeta: api.ObjectMeta{
Labels: map[string]string{
@ -681,12 +679,12 @@ func (f *fixture) expectUpdateDeploymentAction(d *exp.Deployment) {
f.objects.Items = append(f.objects.Items, d)
}
func (f *fixture) expectCreateRSAction(rs *extensions.ReplicaSet) {
func (f *fixture) expectCreateRSAction(rs *exp.ReplicaSet) {
f.actions = append(f.actions, core.NewCreateAction("replicasets", rs.Namespace, rs))
f.objects.Items = append(f.objects.Items, rs)
}
func (f *fixture) expectUpdateRSAction(rs *extensions.ReplicaSet) {
func (f *fixture) expectUpdateRSAction(rs *exp.ReplicaSet) {
f.actions = append(f.actions, core.NewUpdateAction("replicasets", rs.Namespace, rs))
f.objects.Items = append(f.objects.Items, rs)
}

View File

@ -291,6 +291,7 @@ func NewAPIFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) {
}
rf := cmdutil.NewFactory(nil)
f.PodSelectorForObject = rf.PodSelectorForObject
f.MapBasedSelectorForObject = rf.MapBasedSelectorForObject
f.PortsForObject = rf.PortsForObject
f.LabelsForObject = rf.LabelsForObject
f.CanBeExposed = rf.CanBeExposed

View File

@ -149,9 +149,9 @@ func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
// For objects that need a pod selector, derive it from the exposed object in case a user
// didn't explicitly specify one via --selector
if s, found := params["selector"]; found && kubectl.IsZero(s) {
s, err := f.PodSelectorForObject(inputObject)
s, err := f.MapBasedSelectorForObject(inputObject)
if err != nil {
return cmdutil.UsageError(cmd, fmt.Sprintf("couldn't find selectors via --selector flag or introspection: %s", err))
return cmdutil.UsageError(cmd, fmt.Sprintf("couldn't retrieve selectors via --selector flag or introspection: %s", err))
}
params["selector"] = s
}

View File

@ -94,6 +94,10 @@ type Factory struct {
Rollbacker func(mapping *meta.RESTMapping) (kubectl.Rollbacker, error)
// PodSelectorForObject returns the pod selector associated with the provided object
PodSelectorForObject func(object runtime.Object) (string, error)
// MapBasedSelectorForObject returns the map-based selector associated with the provided object. If a
// new set-based selector is provided, an error is returned if the selector cannot be converted to a
// map-based selector
MapBasedSelectorForObject func(object runtime.Object) (string, error)
// PortsForObject returns the ports associated with the provided object
PortsForObject func(object runtime.Object) ([]string, error)
// LabelsForObject returns the labels associated with the provided object
@ -257,7 +261,41 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
}
return kubectl.MakeLabels(t.Spec.Selector), nil
case *extensions.Deployment:
selector, err := unversioned.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", fmt.Errorf("failed to convert label selector to selector: %v", err)
}
return selector.String(), nil
default:
gvk, err := api.Scheme.ObjectKind(object)
if err != nil {
return "", err
}
return "", fmt.Errorf("cannot extract pod selector from %v", gvk)
}
},
MapBasedSelectorForObject: func(object runtime.Object) (string, error) {
// TODO: replace with a swagger schema based approach (identify pod selector via schema introspection)
switch t := object.(type) {
case *api.ReplicationController:
return kubectl.MakeLabels(t.Spec.Selector), nil
case *api.Pod:
if len(t.Labels) == 0 {
return "", fmt.Errorf("the pod has no labels and cannot be exposed")
}
return kubectl.MakeLabels(t.Labels), nil
case *api.Service:
if t.Spec.Selector == nil {
return "", fmt.Errorf("the service has no pod selector set")
}
return kubectl.MakeLabels(t.Spec.Selector), nil
case *extensions.Deployment:
// TODO(madhusudancs): Make this smarter by admitting MatchExpressions with Equals
// operator, DoubleEquals operator and In operator with only one element in the set.
if len(t.Spec.Selector.MatchExpressions) > 0 {
return "", fmt.Errorf("couldn't convert expressions - \"%+v\" to map-based selector format")
}
return kubectl.MakeLabels(t.Spec.Selector.MatchLabels), nil
default:
gvk, err := api.Scheme.ObjectKind(object)
if err != nil {
@ -450,13 +488,13 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
selector := labels.SelectorFromSet(t.Spec.Selector)
return GetFirstPod(client, t.Namespace, selector)
case *extensions.Deployment:
selector, err := extensions.LabelSelectorAsSelector(t.Spec.Selector)
selector, err := unversioned.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return nil, fmt.Errorf("failed to convert label selector to selector: %v", err)
}
return GetFirstPod(client, t.Namespace, selector)
case *extensions.Job:
selector, err := extensions.LabelSelectorAsSelector(t.Spec.Selector)
selector, err := unversioned.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return nil, fmt.Errorf("failed to convert label selector to selector: %v", err)
}

View File

@ -67,11 +67,11 @@ func (h *DeploymentHistoryViewer) History(namespace, name string) (HistoryInfo,
if err != nil {
return historyInfo, fmt.Errorf("failed to retrieve deployment %s: %v", name, err)
}
_, allOldRCs, err := deploymentutil.GetOldRCs(*deployment, h.c)
_, allOldRCs, err := deploymentutil.GetOldReplicaSets(*deployment, h.c)
if err != nil {
return historyInfo, fmt.Errorf("failed to retrieve old RCs from deployment %s: %v", name, err)
}
newRC, err := deploymentutil.GetNewRC(*deployment, h.c)
newRC, err := deploymentutil.GetNewReplicaSet(*deployment, h.c)
if err != nil {
return historyInfo, fmt.Errorf("failed to retrieve new RC from deployment %s: %v", name, err)
}

View File

@ -103,7 +103,7 @@ func (DeploymentV1Beta1) Generate(genericParams map[string]interface{}) (runtime
},
Spec: extensions.DeploymentSpec{
Replicas: count,
Selector: &extensions.LabelSelector{MatchLabels: labels},
Selector: &unversioned.LabelSelector{MatchLabels: labels},
Template: api.PodTemplateSpec{
ObjectMeta: api.ObjectMeta{
Labels: labels,

View File

@ -656,7 +656,7 @@ func TestGenerateDeployment(t *testing.T) {
},
Spec: extensions.DeploymentSpec{
Replicas: 3,
Selector: &extensions.LabelSelector{MatchLabels: map[string]string{"foo": "bar", "baz": "blah"}},
Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar", "baz": "blah"}},
Template: api.PodTemplateSpec{
ObjectMeta: api.ObjectMeta{
Labels: map[string]string{"foo": "bar", "baz": "blah"},

View File

@ -48,8 +48,9 @@ func ScalerFor(kind unversioned.GroupKind, c client.Interface) (Scaler, error) {
return &ReplicaSetScaler{c.Extensions()}, nil
case extensions.Kind("Job"):
return &JobScaler{c.Extensions()}, nil
case extensions.Kind("Deployment"):
return &DeploymentScaler{c.Extensions()}, nil
// TODO(madhusudancs): Fix this when Scale group issues are resolved.
// case extensions.Kind("Deployment"):
// return &DeploymentScaler{c.Extensions()}, nil
}
return nil, fmt.Errorf("no scaler has been implemented for %q", kind)
}
@ -327,56 +328,57 @@ func (precondition *ScalePrecondition) ValidateDeployment(deployment *extensions
return nil
}
type DeploymentScaler struct {
c client.ExtensionsInterface
}
// TODO(madhusudancs): Fix this when Scale group issues are resolved.
// type DeploymentScaler struct {
// c client.ExtensionsInterface
// }
// ScaleSimple is responsible for updating a deployment's desired replicas count.
func (scaler *DeploymentScaler) ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint) error {
deployment, err := scaler.c.Deployments(namespace).Get(name)
if err != nil {
return ScaleError{ScaleGetFailure, "Unknown", err}
}
if preconditions != nil {
if err := preconditions.ValidateDeployment(deployment); err != nil {
return err
}
}
scale, err := extensions.ScaleFromDeployment(deployment)
if err != nil {
return ScaleError{ScaleUpdateFailure, deployment.ResourceVersion, err}
}
scale.Spec.Replicas = int(newSize)
if _, err := scaler.c.Scales(namespace).Update("Deployment", scale); err != nil {
if errors.IsInvalid(err) {
return ScaleError{ScaleUpdateInvalidFailure, deployment.ResourceVersion, err}
}
return ScaleError{ScaleUpdateFailure, deployment.ResourceVersion, err}
}
return nil
}
// // ScaleSimple is responsible for updating a deployment's desired replicas count.
// func (scaler *DeploymentScaler) ScaleSimple(namespace, name string, preconditions *ScalePrecondition, newSize uint) error {
// deployment, err := scaler.c.Deployments(namespace).Get(name)
// if err != nil {
// return ScaleError{ScaleGetFailure, "Unknown", err}
// }
// if preconditions != nil {
// if err := preconditions.ValidateDeployment(deployment); err != nil {
// return err
// }
// }
// scale, err := extensions.ScaleFromDeployment(deployment)
// if err != nil {
// return ScaleError{ScaleUpdateFailure, deployment.ResourceVersion, err}
// }
// scale.Spec.Replicas = int(newSize)
// if _, err := scaler.c.Scales(namespace).Update("Deployment", scale); err != nil {
// if errors.IsInvalid(err) {
// return ScaleError{ScaleUpdateInvalidFailure, deployment.ResourceVersion, err}
// }
// return ScaleError{ScaleUpdateFailure, deployment.ResourceVersion, err}
// }
// return nil
// }
// Scale updates a deployment to a new size, with optional precondition check (if preconditions is not nil),
// optional retries (if retry is not nil), and then optionally waits for the status to reach desired count.
func (scaler *DeploymentScaler) Scale(namespace, name string, newSize uint, preconditions *ScalePrecondition, retry, waitForReplicas *RetryParams) error {
if preconditions == nil {
preconditions = &ScalePrecondition{-1, ""}
}
if retry == nil {
// Make it try only once, immediately
retry = &RetryParams{Interval: time.Millisecond, Timeout: time.Millisecond}
}
cond := ScaleCondition(scaler, preconditions, namespace, name, newSize)
if err := wait.Poll(retry.Interval, retry.Timeout, cond); err != nil {
return err
}
if waitForReplicas != nil {
deployment, err := scaler.c.Deployments(namespace).Get(name)
if err != nil {
return err
}
return wait.Poll(waitForReplicas.Interval, waitForReplicas.Timeout,
client.DeploymentHasDesiredReplicas(scaler.c, deployment))
}
return nil
}
// // Scale updates a deployment to a new size, with optional precondition check (if preconditions is not nil),
// // optional retries (if retry is not nil), and then optionally waits for the status to reach desired count.
// func (scaler *DeploymentScaler) Scale(namespace, name string, newSize uint, preconditions *ScalePrecondition, retry, waitForReplicas *RetryParams) error {
// if preconditions == nil {
// preconditions = &ScalePrecondition{-1, ""}
// }
// if retry == nil {
// // Make it try only once, immediately
// retry = &RetryParams{Interval: time.Millisecond, Timeout: time.Millisecond}
// }
// cond := ScaleCondition(scaler, preconditions, namespace, name, newSize)
// if err := wait.Poll(retry.Interval, retry.Timeout, cond); err != nil {
// return err
// }
// if waitForReplicas != nil {
// deployment, err := scaler.c.Deployments(namespace).Get(name)
// if err != nil {
// return err
// }
// return wait.Poll(waitForReplicas.Interval, waitForReplicas.Timeout,
// client.DeploymentHasDesiredReplicas(scaler.c, deployment))
// }
// return nil
// }

View File

@ -488,143 +488,145 @@ func TestValidateJob(t *testing.T) {
}
}
type ErrorScales struct {
testclient.FakeScales
invalid bool
}
// TODO(madhusudancs): Fix this when Scale group issues are resolved.
func (c *ErrorScales) Update(kind string, scale *extensions.Scale) (*extensions.Scale, error) {
if c.invalid {
return nil, kerrors.NewInvalid(extensions.Kind(scale.Kind), scale.Name, nil)
}
return nil, errors.New("scale update failure")
}
// type ErrorScales struct {
// testclient.FakeScales
// invalid bool
// }
func (c *ErrorScales) Get(kind, name string) (*extensions.Scale, error) {
return &extensions.Scale{
Spec: extensions.ScaleSpec{
Replicas: 0,
},
}, nil
}
// func (c *ErrorScales) Update(kind string, scale *extensions.Scale) (*extensions.Scale, error) {
// if c.invalid {
// return nil, kerrors.NewInvalid(extensions.Kind(scale.Kind), scale.Name, nil)
// }
// return nil, errors.New("scale update failure")
// }
type ErrorDeployments struct {
testclient.FakeDeployments
invalid bool
}
// func (c *ErrorScales) Get(kind, name string) (*extensions.Scale, error) {
// return &extensions.Scale{
// Spec: extensions.ScaleSpec{
// Replicas: 0,
// },
// }, nil
// }
func (c *ErrorDeployments) Update(deployment *extensions.Deployment) (*extensions.Deployment, error) {
if c.invalid {
return nil, kerrors.NewInvalid(extensions.Kind(deployment.Kind), deployment.Name, nil)
}
return nil, errors.New("deployment update failure")
}
// type ErrorDeployments struct {
// testclient.FakeDeployments
// invalid bool
// }
func (c *ErrorDeployments) Get(name string) (*extensions.Deployment, error) {
return &extensions.Deployment{
Spec: extensions.DeploymentSpec{
Replicas: 0,
},
}, nil
}
// func (c *ErrorDeployments) Update(deployment *extensions.Deployment) (*extensions.Deployment, error) {
// if c.invalid {
// return nil, kerrors.NewInvalid(extensions.Kind(deployment.Kind), deployment.Name, nil)
// }
// return nil, errors.New("deployment update failure")
// }
type ErrorDeploymentClient struct {
testclient.FakeExperimental
invalid bool
}
// func (c *ErrorDeployments) Get(name string) (*extensions.Deployment, error) {
// return &extensions.Deployment{
// Spec: extensions.DeploymentSpec{
// Replicas: 0,
// },
// }, nil
// }
func (c *ErrorDeploymentClient) Deployments(namespace string) client.DeploymentInterface {
return &ErrorDeployments{testclient.FakeDeployments{Fake: &c.FakeExperimental, Namespace: namespace}, c.invalid}
}
// type ErrorDeploymentClient struct {
// testclient.FakeExperimental
// invalid bool
// }
func (c *ErrorDeploymentClient) Scales(namespace string) client.ScaleInterface {
return &ErrorScales{testclient.FakeScales{Fake: &c.FakeExperimental, Namespace: namespace}, c.invalid}
}
// func (c *ErrorDeploymentClient) Deployments(namespace string) client.DeploymentInterface {
// return &ErrorDeployments{testclient.FakeDeployments{Fake: &c.FakeExperimental, Namespace: namespace}, c.invalid}
// }
func TestDeploymentScaleRetry(t *testing.T) {
fake := &ErrorDeploymentClient{FakeExperimental: testclient.FakeExperimental{Fake: &testclient.Fake{}}, invalid: false}
scaler := &DeploymentScaler{fake}
preconditions := &ScalePrecondition{-1, ""}
count := uint(3)
name := "foo"
namespace := "default"
// func (c *ErrorDeploymentClient) Scales(namespace string) client.ScaleInterface {
// return &ErrorScales{testclient.FakeScales{Fake: &c.FakeExperimental, Namespace: namespace}, c.invalid}
// }
scaleFunc := ScaleCondition(scaler, preconditions, namespace, name, count)
pass, err := scaleFunc()
if pass != false {
t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass)
}
if err != nil {
t.Errorf("Did not expect an error on update failure, got %v", err)
}
preconditions = &ScalePrecondition{3, ""}
scaleFunc = ScaleCondition(scaler, preconditions, namespace, name, count)
pass, err = scaleFunc()
if err == nil {
t.Errorf("Expected error on precondition failure")
}
}
// func TestDeploymentScaleRetry(t *testing.T) {
// fake := &ErrorDeploymentClient{FakeExperimental: testclient.FakeExperimental{Fake: &testclient.Fake{}}, invalid: false}
// scaler := &DeploymentScaler{fake}
// preconditions := &ScalePrecondition{-1, ""}
// count := uint(3)
// name := "foo"
// namespace := "default"
func TestDeploymentScale(t *testing.T) {
fake := &testclient.FakeExperimental{Fake: &testclient.Fake{}}
scaler := DeploymentScaler{fake}
preconditions := ScalePrecondition{-1, ""}
count := uint(3)
name := "foo"
scaler.Scale("default", name, count, &preconditions, nil, nil)
// scaleFunc := ScaleCondition(scaler, preconditions, namespace, name, count)
// pass, err := scaleFunc()
// if pass != false {
// t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass)
// }
// if err != nil {
// t.Errorf("Did not expect an error on update failure, got %v", err)
// }
// preconditions = &ScalePrecondition{3, ""}
// scaleFunc = ScaleCondition(scaler, preconditions, namespace, name, count)
// pass, err = scaleFunc()
// if err == nil {
// t.Errorf("Expected error on precondition failure")
// }
// }
actions := fake.Actions()
if len(actions) != 2 {
t.Errorf("unexpected actions: %v, expected 2 actions (get, update)", actions)
}
if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "deployments" || action.GetName() != name {
t.Errorf("unexpected action: %v, expected get-replicationController %s", actions[0], name)
}
// TODO: The testclient needs to support subresources
if action, ok := actions[1].(testclient.UpdateAction); !ok || action.GetResource() != "Deployment" || action.GetObject().(*extensions.Scale).Spec.Replicas != int(count) {
t.Errorf("unexpected action %v, expected update-deployment-scale with replicas = %d", actions[1], count)
}
}
// func TestDeploymentScale(t *testing.T) {
// fake := &testclient.FakeExperimental{Fake: &testclient.Fake{}}
// scaler := DeploymentScaler{fake}
// preconditions := ScalePrecondition{-1, ""}
// count := uint(3)
// name := "foo"
// scaler.Scale("default", name, count, &preconditions, nil, nil)
func TestDeploymentScaleInvalid(t *testing.T) {
fake := &ErrorDeploymentClient{FakeExperimental: testclient.FakeExperimental{Fake: &testclient.Fake{}}, invalid: true}
scaler := DeploymentScaler{fake}
preconditions := ScalePrecondition{-1, ""}
count := uint(3)
name := "foo"
namespace := "default"
// actions := fake.Actions()
// if len(actions) != 2 {
// t.Errorf("unexpected actions: %v, expected 2 actions (get, update)", actions)
// }
// if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "deployments" || action.GetName() != name {
// t.Errorf("unexpected action: %v, expected get-replicationController %s", actions[0], name)
// }
// // TODO: The testclient needs to support subresources
// if action, ok := actions[1].(testclient.UpdateAction); !ok || action.GetResource() != "Deployment" || action.GetObject().(*extensions.Scale).Spec.Replicas != int(count) {
// t.Errorf("unexpected action %v, expected update-deployment-scale with replicas = %d", actions[1], count)
// }
// }
scaleFunc := ScaleCondition(&scaler, &preconditions, namespace, name, count)
pass, err := scaleFunc()
if pass {
t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass)
}
e, ok := err.(ScaleError)
if err == nil || !ok || e.FailureType != ScaleUpdateInvalidFailure {
t.Errorf("Expected error on invalid update failure, got %v", err)
}
}
// func TestDeploymentScaleInvalid(t *testing.T) {
// fake := &ErrorDeploymentClient{FakeExperimental: testclient.FakeExperimental{Fake: &testclient.Fake{}}, invalid: true}
// scaler := DeploymentScaler{fake}
// preconditions := ScalePrecondition{-1, ""}
// count := uint(3)
// name := "foo"
// namespace := "default"
func TestDeploymentScaleFailsPreconditions(t *testing.T) {
fake := testclient.NewSimpleFake(&extensions.Deployment{
Spec: extensions.DeploymentSpec{
Replicas: 10,
},
})
scaler := DeploymentScaler{&testclient.FakeExperimental{fake}}
preconditions := ScalePrecondition{2, ""}
count := uint(3)
name := "foo"
scaler.Scale("default", name, count, &preconditions, nil, nil)
// scaleFunc := ScaleCondition(&scaler, &preconditions, namespace, name, count)
// pass, err := scaleFunc()
// if pass {
// t.Errorf("Expected an update failure to return pass = false, got pass = %v", pass)
// }
// e, ok := err.(ScaleError)
// if err == nil || !ok || e.FailureType != ScaleUpdateInvalidFailure {
// t.Errorf("Expected error on invalid update failure, got %v", err)
// }
// }
actions := fake.Actions()
if len(actions) != 1 {
t.Errorf("unexpected actions: %v, expected 1 actions (get)", actions)
}
if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "deployments" || action.GetName() != name {
t.Errorf("unexpected action: %v, expected get-deployment %s", actions[0], name)
}
}
// func TestDeploymentScaleFailsPreconditions(t *testing.T) {
// fake := testclient.NewSimpleFake(&extensions.Deployment{
// Spec: extensions.DeploymentSpec{
// Replicas: 10,
// },
// })
// scaler := DeploymentScaler{&testclient.FakeExperimental{fake}}
// preconditions := ScalePrecondition{2, ""}
// count := uint(3)
// name := "foo"
// scaler.Scale("default", name, count, &preconditions, nil, nil)
// actions := fake.Actions()
// if len(actions) != 1 {
// t.Errorf("unexpected actions: %v, expected 1 actions (get)", actions)
// }
// if action, ok := actions[0].(testclient.GetAction); !ok || action.GetResource() != "deployments" || action.GetName() != name {
// t.Errorf("unexpected action: %v, expected get-deployment %s", actions[0], name)
// }
// }
func TestValidateDeployment(t *testing.T) {
zero, ten, twenty := 0, 10, 20

View File

@ -624,7 +624,8 @@ func (m *Master) getExtensionResources(c *Config) map[string]rest.Storage {
deploymentStorage := deploymentetcd.NewStorage(dbClient("deployments"), storageDecorator)
storage["deployments"] = deploymentStorage.Deployment
storage["deployments/status"] = deploymentStorage.Status
storage["deployments/scale"] = deploymentStorage.Scale
// TODO(madhusudancs): Install scale when Scale group issues are fixed.
// storage["deployments/scale"] = deploymentStorage.Scale
storage["deployments/rollback"] = deploymentStorage.Rollback
}
if isEnabled("jobs") {

View File

@ -183,51 +183,53 @@ type ScaleREST struct {
registry *deployment.Registry
}
// ScaleREST implements Patcher
var _ = rest.Patcher(&ScaleREST{})
// TODO(madhusudancs): Fix this when Scale group issues are resolved.
// New creates a new Scale object
func (r *ScaleREST) New() runtime.Object {
return &extensions.Scale{}
}
// // ScaleREST implements Patcher
// var _ = rest.Patcher(&ScaleREST{})
func (r *ScaleREST) Get(ctx api.Context, name string) (runtime.Object, error) {
deployment, err := (*r.registry).GetDeployment(ctx, name)
if err != nil {
return nil, errors.NewNotFound(extensions.Resource("deployments/scale"), name)
}
scale, err := extensions.ScaleFromDeployment(deployment)
if err != nil {
return nil, errors.NewBadRequest(fmt.Sprintf("%v", err))
}
return scale, nil
}
// // New creates a new Scale object
// func (r *ScaleREST) New() runtime.Object {
// return &extensions.Scale{}
// }
func (r *ScaleREST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) {
if obj == nil {
return nil, false, errors.NewBadRequest(fmt.Sprintf("nil update passed to Scale"))
}
scale, ok := obj.(*extensions.Scale)
if !ok {
return nil, false, errors.NewBadRequest(fmt.Sprintf("wrong object passed to Scale update: %v", obj))
}
// func (r *ScaleREST) Get(ctx api.Context, name string) (runtime.Object, error) {
// deployment, err := (*r.registry).GetDeployment(ctx, name)
// if err != nil {
// return nil, errors.NewNotFound(extensions.Resource("deployments/scale"), name)
// }
// scale, err := extensions.ScaleFromDeployment(deployment)
// if err != nil {
// return nil, errors.NewBadRequest(fmt.Sprintf("%v", err))
// }
// return scale, nil
// }
if errs := extvalidation.ValidateScale(scale); len(errs) > 0 {
return nil, false, errors.NewInvalid(extensions.Kind("Scale"), scale.Name, errs)
}
// func (r *ScaleREST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) {
// if obj == nil {
// return nil, false, errors.NewBadRequest(fmt.Sprintf("nil update passed to Scale"))
// }
// scale, ok := obj.(*extensions.Scale)
// if !ok {
// return nil, false, errors.NewBadRequest(fmt.Sprintf("wrong object passed to Scale update: %v", obj))
// }
deployment, err := (*r.registry).GetDeployment(ctx, scale.Name)
if err != nil {
return nil, false, errors.NewNotFound(extensions.Resource("deployments/scale"), scale.Name)
}
deployment.Spec.Replicas = scale.Spec.Replicas
deployment, err = (*r.registry).UpdateDeployment(ctx, deployment)
if err != nil {
return nil, false, errors.NewConflict(extensions.Resource("deployments/scale"), scale.Name, err)
}
newScale, err := extensions.ScaleFromDeployment(deployment)
if err != nil {
return nil, false, errors.NewBadRequest(fmt.Sprintf("%v", err))
}
return newScale, false, nil
}
// if errs := extvalidation.ValidateScale(scale); len(errs) > 0 {
// return nil, false, errors.NewInvalid(extensions.Kind("Scale"), scale.Name, errs)
// }
// deployment, err := (*r.registry).GetDeployment(ctx, scale.Name)
// if err != nil {
// return nil, false, errors.NewNotFound(extensions.Resource("deployments/scale"), scale.Name)
// }
// deployment.Spec.Replicas = scale.Spec.Replicas
// deployment, err = (*r.registry).UpdateDeployment(ctx, deployment)
// if err != nil {
// return nil, false, errors.NewConflict(extensions.Resource("deployments/scale"), scale.Name, err)
// }
// newScale, err := extensions.ScaleFromDeployment(deployment)
// if err != nil {
// return nil, false, errors.NewBadRequest(fmt.Sprintf("%v", err))
// }
// return newScale, false, nil
// }

View File

@ -23,6 +23,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
etcderrors "k8s.io/kubernetes/pkg/api/errors/etcd"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
@ -31,7 +32,6 @@ import (
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/storage/etcd/etcdtest"
etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing"
"k8s.io/kubernetes/pkg/util"
)
func newStorage(t *testing.T) (*DeploymentStorage, *etcdtesting.EtcdTestServer) {
@ -50,7 +50,7 @@ func validNewDeployment() *extensions.Deployment {
Namespace: namespace,
},
Spec: extensions.DeploymentSpec{
Selector: &extensions.LabelSelector{MatchLabels: map[string]string{"a": "b"}},
Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"a": "b"}},
Template: api.PodTemplateSpec{
ObjectMeta: api.ObjectMeta{
Labels: map[string]string{"a": "b"},
@ -89,7 +89,7 @@ func TestCreate(t *testing.T) {
// invalid (invalid selector)
&extensions.Deployment{
Spec: extensions.DeploymentSpec{
Selector: &extensions.LabelSelector{MatchLabels: map[string]string{}},
Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{}},
Template: validDeployment.Spec.Template,
},
},
@ -127,7 +127,7 @@ func TestUpdate(t *testing.T) {
},
func(obj runtime.Object) runtime.Object {
object := obj.(*extensions.Deployment)
object.Spec.Selector = &extensions.LabelSelector{MatchLabels: map[string]string{}}
object.Spec.Selector = &unversioned.LabelSelector{MatchLabels: map[string]string{}}
return object
},
)
@ -179,71 +179,73 @@ func TestWatch(t *testing.T) {
)
}
func validNewScale() *extensions.Scale {
return &extensions.Scale{
ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespace},
Spec: extensions.ScaleSpec{
Replicas: validDeployment.Spec.Replicas,
},
Status: extensions.ScaleStatus{
Replicas: validDeployment.Status.Replicas,
Selector: validDeployment.Spec.Template.Labels,
},
}
}
// TODO(madhusudancs): Fix this when Scale group issues are resolved.
var validScale = *validNewScale()
// func validNewScale() *extensions.Scale {
// return &extensions.Scale{
// ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespace},
// Spec: extensions.ScaleSpec{
// Replicas: validDeployment.Spec.Replicas,
// },
// Status: extensions.ScaleStatus{
// Replicas: validDeployment.Status.Replicas,
// Selector: validDeployment.Spec.Template.Labels,
// },
// }
// }
func TestScaleGet(t *testing.T) {
storage, server := newStorage(t)
defer server.Terminate(t)
// var validScale = *validNewScale()
ctx := api.WithNamespace(api.NewContext(), namespace)
key := etcdtest.AddPrefix("/deployments/" + namespace + "/" + name)
if err := storage.Deployment.Storage.Set(ctx, key, &validDeployment, nil, 0); err != nil {
t.Fatalf("unexpected error: %v", err)
}
// func TestScaleGet(t *testing.T) {
// storage, server := newStorage(t)
// defer server.Terminate(t)
expect := &validScale
obj, err := storage.Scale.Get(ctx, name)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
scale := obj.(*extensions.Scale)
if e, a := expect, scale; !api.Semantic.DeepDerivative(e, a) {
t.Errorf("unexpected scale: %s", util.ObjectDiff(e, a))
}
}
// ctx := api.WithNamespace(api.NewContext(), namespace)
// key := etcdtest.AddPrefix("/deployments/" + namespace + "/" + name)
// if err := storage.Deployment.Storage.Set(ctx, key, &validDeployment, nil, 0); err != nil {
// t.Fatalf("unexpected error: %v", err)
// }
func TestScaleUpdate(t *testing.T) {
storage, server := newStorage(t)
defer server.Terminate(t)
// expect := &validScale
// obj, err := storage.Scale.Get(ctx, name)
// if err != nil {
// t.Fatalf("unexpected error: %v", err)
// }
// scale := obj.(*extensions.Scale)
// if e, a := expect, scale; !api.Semantic.DeepDerivative(e, a) {
// t.Errorf("unexpected scale: %s", util.ObjectDiff(e, a))
// }
// }
ctx := api.WithNamespace(api.NewContext(), namespace)
key := etcdtest.AddPrefix("/deployments/" + namespace + "/" + name)
if err := storage.Deployment.Storage.Set(ctx, key, &validDeployment, nil, 0); err != nil {
t.Fatalf("unexpected error: %v", err)
}
replicas := 12
update := extensions.Scale{
ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespace},
Spec: extensions.ScaleSpec{
Replicas: replicas,
},
}
// func TestScaleUpdate(t *testing.T) {
// storage, server := newStorage(t)
// defer server.Terminate(t)
if _, _, err := storage.Scale.Update(ctx, &update); err != nil {
t.Fatalf("unexpected error: %v", err)
}
obj, err := storage.Deployment.Get(ctx, name)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
deployment := obj.(*extensions.Deployment)
if deployment.Spec.Replicas != replicas {
t.Errorf("wrong replicas count expected: %d got: %d", replicas, deployment.Spec.Replicas)
}
}
// ctx := api.WithNamespace(api.NewContext(), namespace)
// key := etcdtest.AddPrefix("/deployments/" + namespace + "/" + name)
// if err := storage.Deployment.Storage.Set(ctx, key, &validDeployment, nil, 0); err != nil {
// t.Fatalf("unexpected error: %v", err)
// }
// replicas := 12
// update := extensions.Scale{
// ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespace},
// Spec: extensions.ScaleSpec{
// Replicas: replicas,
// },
// }
// if _, _, err := storage.Scale.Update(ctx, &update); err != nil {
// t.Fatalf("unexpected error: %v", err)
// }
// obj, err := storage.Deployment.Get(ctx, name)
// if err != nil {
// t.Fatalf("unexpected error: %v", err)
// }
// deployment := obj.(*extensions.Deployment)
// if deployment.Spec.Replicas != replicas {
// t.Errorf("wrong replicas count expected: %d got: %d", replicas, deployment.Spec.Replicas)
// }
// }
func TestStatusUpdate(t *testing.T) {
storage, server := newStorage(t)

View File

@ -22,6 +22,7 @@ import (
"time"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/extensions"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/labels"
@ -56,9 +57,9 @@ func GetOldReplicaSets(deployment extensions.Deployment, c clientset.Interface)
// Note that the first set of old replica sets doesn't include the ones with no pods, and the second set of old replica sets include all old replica sets.
func GetOldReplicaSetsFromLists(deployment extensions.Deployment, c clientset.Interface, getPodList func(string, api.ListOptions) (*api.PodList, error), getRcList func(string, api.ListOptions) ([]extensions.ReplicaSet, error)) ([]*extensions.ReplicaSet, []*extensions.ReplicaSet, error) {
namespace := deployment.ObjectMeta.Namespace
selector, err := extensions.LabelSelectorAsSelector(deployment.Spec.Selector)
selector, err := unversioned.LabelSelectorAsSelector(deployment.Spec.Selector)
if err != nil {
return nil, fmt.Errorf("failed to convert LabelSelector to Selector: %v", err)
return nil, nil, fmt.Errorf("failed to convert LabelSelector to Selector: %v", err)
}
// 1. Find all pods whose labels match deployment.Spec.Selector
@ -79,7 +80,10 @@ func GetOldReplicaSetsFromLists(deployment extensions.Deployment, c clientset.In
for _, pod := range podList.Items {
podLabelsSelector := labels.Set(pod.ObjectMeta.Labels)
for _, rs := range rsList {
rsLabelsSelector := labels.SelectorFromSet(rs.Spec.Selector)
rsLabelsSelector, err := unversioned.LabelSelectorAsSelector(rs.Spec.Selector)
if err != nil {
return nil, nil, fmt.Errorf("failed to convert LabelSelector to Selector: %v", err)
}
// Filter out replica set that has the same pod template spec as the deployment - that is the new replica set.
if api.Semantic.DeepEqual(rs.Spec.Template, &newRSTemplate) {
continue
@ -117,7 +121,12 @@ func GetNewReplicaSet(deployment extensions.Deployment, c clientset.Interface) (
// Returns nil if the new replica set doesnt exist yet.
func GetNewReplicaSetFromList(deployment extensions.Deployment, c clientset.Interface, getRcList func(string, api.ListOptions) ([]extensions.ReplicaSet, error)) (*extensions.ReplicaSet, error) {
namespace := deployment.ObjectMeta.Namespace
rsList, err := getRcList(namespace, api.ListOptions{LabelSelector: labels.SelectorFromSet(deployment.Spec.Selector)})
selector, err := unversioned.LabelSelectorAsSelector(deployment.Spec.Selector)
if err != nil {
return nil, fmt.Errorf("failed to convert LabelSelector to Selector: %v", err)
}
rsList, err := getRcList(namespace, api.ListOptions{LabelSelector: selector})
if err != nil {
return nil, fmt.Errorf("error listing ReplicaSets: %v", err)
}
@ -158,7 +167,7 @@ func SetFromReplicaSetTemplate(deployment *extensions.Deployment, template api.P
}
// Returns the sum of Replicas of the given replica sets.
func GetReplicaCountForReplicaSets(replicationControllers []*extensions.ReplicaSet) int {
func GetReplicaCountForReplicaSets(replicaSets []*extensions.ReplicaSet) int {
totalReplicaCount := 0
for _, rs := range replicaSets {
totalReplicaCount += rs.Spec.Replicas
@ -199,10 +208,10 @@ func getReadyPodsCount(pods []api.Pod, minReadySeconds int) int {
return readyPodCount
}
func getPodsForReplicaSets(c clientset.Interface, replicationControllers []*extensions.ReplicaSet) ([]api.Pod, error) {
func getPodsForReplicaSets(c clientset.Interface, replicaSets []*extensions.ReplicaSet) ([]api.Pod, error) {
allPods := []api.Pod{}
for _, rs := range replicaSets {
selector, err := extensions.LabelSelectorAsSelector(rs.Spec.Selector)
selector, err := unversioned.LabelSelectorAsSelector(rs.Spec.Selector)
if err != nil {
return nil, fmt.Errorf("failed to convert LabelSelector to Selector: %v", err)
}

View File

@ -118,7 +118,7 @@ func generateRSWithLabel(labels map[string]string, image string) extensions.Repl
},
Spec: extensions.ReplicaSetSpec{
Replicas: 1,
Selector: &extensions.LabelSelector{MatchLabels: labels},
Selector: &unversioned.LabelSelector{MatchLabels: labels},
Template: &api.PodTemplateSpec{
Spec: api.PodSpec{
Containers: []api.Container{
@ -145,7 +145,7 @@ func generateRS(deployment extensions.Deployment) extensions.ReplicaSet {
},
Spec: extensions.ReplicaSetSpec{
Template: &template,
Selector: &extensions.LabelSelector{MatchLabels: template.Labels},
Selector: &unversioned.LabelSelector{MatchLabels: template.Labels},
},
}
}
@ -160,7 +160,7 @@ func generateDeployment(image string) extensions.Deployment {
},
Spec: extensions.DeploymentSpec{
Replicas: 1,
Selector: &extensions.LabelSelector{MatchLabels: podLabels},
Selector: &unversioned.LabelSelector{MatchLabels: podLabels},
Template: api.PodTemplateSpec{
ObjectMeta: api.ObjectMeta{
Labels: podLabels,

View File

@ -19,7 +19,7 @@ package labels
import (
"fmt"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/api/unversioned"
)
// Clones the given map and returns a new map with the given key and value added.
@ -56,14 +56,14 @@ func CloneAndRemoveLabel(labels map[string]string, labelKey string) map[string]s
// Clones the given selector and returns a new selector with the given key and value added.
// Returns the given selector, if labelKey is empty.
func CloneSelectorAndAddLabel(selector *extensions.LabelSelector, labelKey string, labelValue uint32) *extensions.LabelSelector {
func CloneSelectorAndAddLabel(selector *unversioned.LabelSelector, labelKey string, labelValue uint32) *unversioned.LabelSelector {
if labelKey == "" {
// Dont need to add a label.
return selector
}
// Clone.
newSelector := new(extensions.LabelSelector)
newSelector := new(unversioned.LabelSelector)
// TODO(madhusudancs): Check if you can use deepCopy_extensions_LabelSelector here.
newSelector.MatchLabels = make(map[string]string)
@ -75,7 +75,7 @@ func CloneSelectorAndAddLabel(selector *extensions.LabelSelector, labelKey strin
newSelector.MatchLabels[labelKey] = fmt.Sprintf("%d", labelValue)
if selector.MatchExpressions != nil {
newMExps := make([]extensions.LabelSelectorRequirement, len(selector.MatchExpressions))
newMExps := make([]unversioned.LabelSelectorRequirement, len(selector.MatchExpressions))
for i, me := range selector.MatchExpressions {
newMExps[i].Key = me.Key
newMExps[i].Operator = me.Operator

View File

@ -21,10 +21,10 @@ import (
"time"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/extensions"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/labels"
deploymentutil "k8s.io/kubernetes/pkg/util/deployment"
"k8s.io/kubernetes/pkg/util/intstr"
@ -64,14 +64,14 @@ var _ = Describe("Deployment [Feature:Deployment]", func() {
})
})
func newReplicaSet(rsName string, replicas int, rsPodLabels map[string]string, imageName string, image string) *extensions.ReplicaSet {
func newRS(rsName string, replicas int, rsPodLabels map[string]string, imageName string, image string) *extensions.ReplicaSet {
return &extensions.ReplicaSet{
ObjectMeta: api.ObjectMeta{
Name: rsName,
},
Spec: extensions.ReplicaSetSpec{
Replicas: replicas,
Selector: &extensions.LabelSelector{MatchLabels: rsPodLabels},
Selector: &unversioned.LabelSelector{MatchLabels: rsPodLabels},
Template: &api.PodTemplateSpec{
ObjectMeta: api.ObjectMeta{
Labels: rsPodLabels,
@ -96,7 +96,7 @@ func newDeployment(deploymentName string, replicas int, podLabels map[string]str
},
Spec: extensions.DeploymentSpec{
Replicas: replicas,
Selector: &extensions.LabelSelector{MatchLabels: podLabels},
Selector: &unversioned.LabelSelector{MatchLabels: podLabels},
Strategy: extensions.DeploymentStrategy{
Type: strategyType,
},
@ -214,7 +214,7 @@ func testRollingUpdateDeployment(f *Framework) {
rsName := "nginx-controller"
replicas := 3
_, err := c.Extensions().ReplicaSets(ns).Create(newReplicaSet(rsName, replicas, rsPodLabels, "nginx", "nginx"))
_, err := c.Extensions().ReplicaSets(ns).Create(newRS(rsName, replicas, rsPodLabels, "nginx", "nginx"))
Expect(err).NotTo(HaveOccurred())
defer func() {
Logf("deleting replica set %s", rsName)
@ -557,7 +557,11 @@ func testPausedDeployment(f *Framework) {
deployment, err = c.Extensions().Deployments(ns).Update(deployment)
Expect(err).NotTo(HaveOccurred())
opts := api.ListOptions{LabelSelector: labels.Set(deployment.Spec.Selector).AsSelector()}
selector, err := unversioned.LabelSelectorAsSelector(deployment.Spec.Selector)
if err != nil {
Expect(err).NotTo(HaveOccurred())
}
opts := api.ListOptions{LabelSelector: selector}
w, err := c.Extensions().ReplicaSets(ns).Watch(opts)
Expect(err).NotTo(HaveOccurred())

View File

@ -41,15 +41,16 @@ var _ = Describe("Horizontal pod autoscaling (scale resource: CPU) [Serial] [Slo
titleUp := "Should scale from 1 pod to 3 pods and from 3 to 5"
titleDown := "Should scale from 5 pods to 3 pods and from 3 to 1"
Describe("Deployment [Feature:Deployment]", func() {
// CPU tests via deployments
It(titleUp, func() {
scaleUp("deployment", kindDeployment, rc, f)
})
It(titleDown, func() {
scaleDown("deployment", kindDeployment, rc, f)
})
})
// TODO(madhusudancs): Fix this when Scale group issues are resolved.
// Describe("Deployment [Feature:Deployment]", func() {
// // CPU tests via deployments
// It(titleUp, func() {
// scaleUp("deployment", kindDeployment, rc, f)
// })
// It(titleDown, func() {
// scaleDown("deployment", kindDeployment, rc, f)
// })
// })
Describe("ReplicationController", func() {
// CPU tests via replication controllers

View File

@ -1529,7 +1529,7 @@ func (config *DeploymentConfig) create() error {
},
Spec: extensions.DeploymentSpec{
Replicas: config.Replicas,
Selector: &extensions.LabelSelector{
Selector: &unversioned.LabelSelector{
MatchLabels: map[string]string{
"name": config.Name,
},