Repository: deis/deis

Issue:
User should be able to modify flavor config
Users should be able to use `deis flavors:update` to modify:
- [ ] AMI ID
- [ ] Instance Size
- [ ] Region
- [ ] Zone (specify "all")

This is an extension of the work on #124.



Discussion:

Resolving patch:
diff --git a/client/deis.py b/client/deis.py
--- a/client/deis.py
+++ b/client/deis.py
@@ -626,6 +626,7 @@ def flavors(self, args):
         Valid commands for flavors:
 
         flavors:create        create a new node flavor
+        flavors:update        update an existing node flavor
         flavors:info          print information about a node flavor
         flavors:list          list available flavors
         flavors:delete        delete a node flavor
@@ -658,6 +659,30 @@ def flavors_create(self, args):
         else:
             print('Error!', response.text)
 
+    def flavors_update(self, args):
+        """
+        Create an existing node flavor
+
+        Usage: deis flavors:update <id> --params=<params> [options]
+
+        Options:
+
+        --params=PARAMS    provider-specific parameters (size, region, zone, etc.)
+        --init=INIT        override Ubuntu cloud-init with custom YAML
+        """
+        flavor = args.get('<id>')
+        body = {'id': flavor}
+        fields = ('params', 'init')
+        for fld in fields:
+            opt = args.get('--' + fld)
+            if opt:
+                body.update({fld: opt})
+        response = self._dispatch('patch', '/api/flavors/{}'.format(flavor), json.dumps(body))
+        if response.status_code == requests.codes.ok:  # @UndefinedVariable
+            print("{0[id]}".format(response.json()))
+        else:
+            print('Error!', response.text)
+
     def flavors_delete(self, args):
         """
         Delete a node flavor


Test patch:
diff --git a/api/tests/flavor.py b/api/tests/flavor.py
--- a/api/tests/flavor.py
+++ b/api/tests/flavor.py
@@ -69,3 +69,48 @@ def test_flavor_contents(self):
         self.assertEqual(params['zone'], 'any')
         self.assertEqual(params['size'], 'm1.medium')
         self.assertTrue(params['image'])
+
+    def test_flavor_update(self):
+        """Tests that flavors can be updated by the client."""
+        url = '/api/flavors'
+        params = {
+            'region': 'us-west-2',
+            'size': 't1.micro',
+        }
+        body = {'id': 'autotest', 'provider': 'autotest', 'params': json.dumps(params)}
+        response = self.client.post(url, json.dumps(body), content_type='application/json')
+        self.assertEqual(response.status_code, 201)
+        flavor_id = response.data['id']
+        response = self.client.get('/api/flavors')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(len(response.data['results']), 1)
+        url = "/api/flavors/{flavor_id}".format(**locals())
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, 200)
+        uuid = response.data['uuid']
+        self.assertRegexpMatches(uuid, r'^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$')
+        params = json.loads(response.data['params'])
+        self.assertEqual(params['region'], 'us-west-2')
+        self.assertEqual(params['zone'], 'any')
+        self.assertEqual(params['size'], 't1.micro')
+        self.assertTrue(params['image'])
+        params = {
+            'size': 'c1.xlarge',
+            'image': 'ami-c98d1bf9',
+        }
+        body = {'id': flavor_id, 'params': json.dumps(params)}
+        response = self.client.patch(url, json.dumps(body), content_type='application/json')
+        self.assertEqual(response.status_code, 200)
+        flavor_id = response.data['id']
+        response = self.client.get('/api/flavors')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(len(response.data['results']), 1)
+        url = "/api/flavors/{flavor_id}".format(**locals())
+        response = self.client.get(url)
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.data['uuid'], uuid)
+        params = json.loads(response.data['params'])
+        self.assertNotIn('region', params)
+        self.assertNotIn('zone', params)
+        self.assertEqual(params['size'], 'c1.xlarge')
+        self.assertEqual(params['image'], 'ami-c98d1bf9')