Skip to content

Commit

Permalink
Merge pull request #128 from engineyard/fix/deploy-set-current-replicas
Browse files Browse the repository at this point in the history
fix(controller): Set replicas to the current value of the deployment.
  • Loading branch information
Cryptophobia authored Jun 25, 2020
2 parents c0294a3 + 30745ca commit 523ef79
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 53 deletions.
5 changes: 5 additions & 0 deletions rootfs/scheduler/resources/deployment.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@ def create(self, namespace, name, image, entrypoint, command, spec_annotations,
return response

def update(self, namespace, name, image, entrypoint, command, spec_annotations, **kwargs):
# Set the replicas value to the current replicas of the deployment.
# This avoids resetting the replicas which causes disruptions during the deployment.
deployment = self.deployment.get(namespace, name).json()
current_replicas = int(deployment['spec']['replicas'])
kwargs['replicas'] = current_replicas
manifest = self.manifest(namespace, name, image,
entrypoint, command, spec_annotations, **kwargs)

Expand Down
28 changes: 15 additions & 13 deletions rootfs/scheduler/tests/test_deployments.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,12 @@ def test_deployment_api_version_1_9_and_up(self):
deployment.version = mock.MagicMock(return_value=parse(canonical))
actual = deployment.api_version
self.assertEqual(
expected,
actual,
"{} breaks - expected {}, got {}".format(
canonical,
expected,
actual,
"{} breaks - expected {}, got {}".format(
canonical,
expected,
actual))
actual))

def test_deployment_api_version_1_8_and_lower(self):
cases = ['1.8', '1.7', '1.6', '1.5', '1.4', '1.3', '1.2']
Expand All @@ -120,12 +120,12 @@ def test_deployment_api_version_1_8_and_lower(self):
deployment.version = mock.MagicMock(return_value=parse(canonical))
actual = deployment.api_version
self.assertEqual(
expected,
actual,
"{} breaks - expected {}, got {}".format(
canonical,
expected,
actual,
"{} breaks - expected {}, got {}".format(
canonical,
expected,
actual))
actual))

def test_create_failure(self):
with self.assertRaises(
Expand Down Expand Up @@ -158,11 +158,13 @@ def test_update(self):
deployment = self.scheduler.deployment.get(self.namespace, name).json()
self.assertEqual(deployment['spec']['replicas'], 4, deployment)

# emulate scale without calling scale
self.update(self.namespace, name, replicas=2)
# update the version
new_version = 'v1024'
self.update(self.namespace, name, version=new_version)

deployment = self.scheduler.deployment.get(self.namespace, name).json()
self.assertEqual(deployment['spec']['replicas'], 2, deployment)
self.assertEqual(deployment['spec']['template']['metadata']['labels']['version'],
new_version, deployment)

def test_delete_failure(self):
# test failure
Expand Down
27 changes: 7 additions & 20 deletions rootfs/scheduler/tests/test_horizontalpodautoscaler.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,27 +62,14 @@ def update(self, namespace=None, name=generate_random_name(), **kwargs):
self.assertEqual(horizontalpodautoscaler.status_code, 200, horizontalpodautoscaler.json()) # noqa
return name

def update_deployment(self, namespace=None, name=generate_random_name(), **kwargs):
def scale_deployment(self, namespace=None, name=generate_random_name(), replicas=1):
"""
Helper function to update and verify a deployment on the namespace
Helper function to scale the replicas of a deployment
"""
namespace = self.namespace if namespace is None else namespace
# these are all required even if it is kwargs...
d_kwargs = {
'app_type': kwargs.get('app_type', 'web'),
'version': kwargs.get('version', 'v99'),
'replicas': kwargs.get('replicas', 4),
'pod_termination_grace_period_seconds': 2,
'image': 'quay.io/fake/image',
'entrypoint': 'sh',
'command': 'start',
'spec_annotations': kwargs.get('spec_annotations', {}),
}

deployment = self.scheduler.deployment.update(namespace, name, **d_kwargs)
data = deployment.json()
self.assertEqual(deployment.status_code, 200, data)
return name
self.scheduler.deployment.scale(namespace, name, image=None,
entrypoint=None, command=None,
replicas=replicas)

def test_create_failure(self):
with self.assertRaises(
Expand Down Expand Up @@ -147,7 +134,7 @@ def test_update(self):
self.assertEqual(deployment['status']['availableReplicas'], 3)

# scale deployment to 1 (should go back to 3)
self.update_deployment(self.namespace, name, replicas=1)
self.scale_deployment(self.namespace, name, replicas=1)

# check the deployment object
deployment = self.scheduler.deployment.get(self.namespace, name).json()
Expand All @@ -158,7 +145,7 @@ def test_update(self):
self.assertEqual(deployment['status']['availableReplicas'], 3)

# scale deployment to 6 (should go back to 4)
self.update_deployment(self.namespace, name, replicas=6)
self.scale_deployment(self.namespace, name, replicas=6)

# check the deployment object
deployment = self.scheduler.deployment.get(self.namespace, name).json()
Expand Down
27 changes: 7 additions & 20 deletions rootfs/scheduler/tests/test_horizontalpodautoscaler_12_lower.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,27 +66,14 @@ def update(self, namespace=None, name=generate_random_name(), **kwargs):
self.assertEqual(horizontalpodautoscaler.status_code, 200, horizontalpodautoscaler.json()) # noqa
return name

def update_deployment(self, namespace=None, name=generate_random_name(), **kwargs):
def scale_deployment(self, namespace=None, name=generate_random_name(), replicas=1):
"""
Helper function to update and verify a deployment on the namespace
Helper function to scale the replicas of a deployment
"""
namespace = self.namespace if namespace is None else namespace
# these are all required even if it is kwargs...
kwargs = {
'app_type': kwargs.get('app_type', 'web'),
'version': kwargs.get('version', 'v99'),
'replicas': kwargs.get('replicas', 4),
'pod_termination_grace_period_seconds': 2,
'image': 'quay.io/fake/image',
'entrypoint': 'sh',
'command': 'start',
'spec_annotations': kwargs.get('spec_annotations', {}),
}

deployment = self.scheduler.deployment.update(namespace, name, **kwargs)
data = deployment.json()
self.assertEqual(deployment.status_code, 200, data)
return name
self.scheduler.deployment.scale(namespace, name, image=None,
entrypoint=None, command=None,
replicas=replicas)

def test_create_failure(self):
with self.assertRaises(
Expand Down Expand Up @@ -151,7 +138,7 @@ def test_update(self):
self.assertEqual(deployment['status']['availableReplicas'], 3)

# scale deployment to 1 (should go back to 3)
self.update_deployment(self.namespace, name, replicas=1)
self.scale_deployment(self.namespace, name, replicas=1)

# check the deployment object
deployment = self.scheduler.deployment.get(self.namespace, name).json()
Expand All @@ -162,7 +149,7 @@ def test_update(self):
self.assertEqual(deployment['status']['availableReplicas'], 3)

# scale deployment to 6 (should go back to 4)
self.update_deployment(self.namespace, name, replicas=6)
self.scale_deployment(self.namespace, name, replicas=6)

# check the deployment object
deployment = self.scheduler.deployment.get(self.namespace, name).json()
Expand Down

0 comments on commit 523ef79

Please sign in to comment.