Repository: deis/deis

Issue:
Do not automatically scale up to 1 after a deploy
If a user has 0 containers of an app running and publishes a new release, we should confirm that Deis doesn't automatically scale up to 1. 

**Example:**
I have an app that defines two proctypes, **web** and **foo**. I keep my **web** scaled to 0, and only want **foo** to be running most of the time. If I deploy my app again, will Deis scale **web** back to 1?



Discussion:
I couldn't find any relevant unit tests that cover this, sadly, so a unit test (even if it is skipped for now) would be appreciated.


Resolving patch:
diff --git a/controller/api/models.py b/controller/api/models.py
--- a/controller/api/models.py
+++ b/controller/api/models.py
@@ -275,7 +275,9 @@ def scale(self, user, structure):  # noqa
         # save new structure to the database
         vals = self.container_set.exclude(type='run').values(
             'type').annotate(Count('pk')).order_by()
-        self.structure = {v['type']: v['pk__count'] for v in vals}
+        new_structure = structure.copy()
+        new_structure.update({v['type']: v['pk__count'] for v in vals})
+        self.structure = new_structure
         self.save()
         return changed
 


Test patch:
diff --git a/controller/api/tests/test_build.py b/controller/api/tests/test_build.py
--- a/controller/api/tests/test_build.py
+++ b/controller/api/tests/test_build.py
@@ -253,3 +253,48 @@ def test_unauthorized_user_cannot_modify_build(self):
         response = self.client.post(url, json.dumps(body), content_type='application/json',
                                     HTTP_AUTHORIZATION='token {}'.format(unauthorized_token))
         self.assertEqual(response.status_code, 403)
+
+    @mock.patch('requests.post', mock_import_repository_task)
+    def test_new_build_does_not_scale_up_automatically(self):
+        """
+        After the first initial deploy, if the containers are scaled down to zero,
+        they should stay that way on a new release.
+        """
+        url = '/v1/apps'
+        response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token))
+        self.assertEqual(response.status_code, 201)
+        app_id = response.data['id']
+        # post a new build
+        url = "/v1/apps/{app_id}/builds".format(**locals())
+        body = {'image': 'autotest/example',
+                'sha': 'a'*40,
+                'procfile': json.dumps({'web': 'node server.js',
+                                        'worker': 'node worker.js'})}
+        response = self.client.post(url, json.dumps(body), content_type='application/json',
+                                    HTTP_AUTHORIZATION='token {}'.format(self.token))
+        self.assertEqual(response.status_code, 201)
+        url = "/v1/apps/{app_id}/containers/web".format(**locals())
+        response = self.client.get(url,
+                                   HTTP_AUTHORIZATION='token {}'.format(self.token))
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(len(response.data['results']), 1)
+        # scale to zero
+        url = "/v1/apps/{app_id}/scale".format(**locals())
+        body = {'web': 0}
+        response = self.client.post(url, json.dumps(body), content_type='application/json',
+                                    HTTP_AUTHORIZATION='token {}'.format(self.token))
+        self.assertEqual(response.status_code, 204)
+        # post another build
+        url = "/v1/apps/{app_id}/builds".format(**locals())
+        body = {'image': 'autotest/example',
+                'sha': 'a'*40,
+                'procfile': json.dumps({'web': 'node server.js',
+                                        'worker': 'node worker.js'})}
+        response = self.client.post(url, json.dumps(body), content_type='application/json',
+                                    HTTP_AUTHORIZATION='token {}'.format(self.token))
+        self.assertEqual(response.status_code, 201)
+        url = "/v1/apps/{app_id}/containers/web".format(**locals())
+        response = self.client.get(url,
+                                   HTTP_AUTHORIZATION='token {}'.format(self.token))
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(len(response.data['results']), 0)