github.com/blystad/deis@v0.11.0/controller/api/tests/test_config.py (about)

     1  """
     2  Unit tests for the Deis api app.
     3  
     4  Run the tests with "./manage.py test api"
     5  """
     6  
     7  from __future__ import unicode_literals
     8  
     9  import json
    10  import mock
    11  import requests
    12  
    13  from django.test import TransactionTestCase
    14  from django.test.utils import override_settings
    15  
    16  from api.models import Config
    17  
    18  
    19  def mock_import_repository_task(*args, **kwargs):
    20      resp = requests.Response()
    21      resp.status_code = 200
    22      resp._content_consumed = True
    23      return resp
    24  
    25  
    26  @override_settings(CELERY_ALWAYS_EAGER=True)
    27  class ConfigTest(TransactionTestCase):
    28  
    29      """Tests setting and updating config values"""
    30  
    31      fixtures = ['tests.json']
    32  
    33      def setUp(self):
    34          self.assertTrue(
    35              self.client.login(username='autotest', password='password'))
    36          body = {'id': 'autotest', 'domain': 'autotest.local', 'type': 'mock',
    37                  'hosts': 'host1,host2', 'auth': 'base64string', 'options': {}}
    38          response = self.client.post('/api/clusters', json.dumps(body),
    39                                      content_type='application/json')
    40          self.assertEqual(response.status_code, 201)
    41  
    42      @mock.patch('requests.post', mock_import_repository_task)
    43      def test_config(self):
    44          """
    45          Test that config is auto-created for a new app and that
    46          config can be updated using a PATCH
    47          """
    48          url = '/api/apps'
    49          body = {'cluster': 'autotest'}
    50          response = self.client.post(url, json.dumps(body), content_type='application/json')
    51          self.assertEqual(response.status_code, 201)
    52          app_id = response.data['id']
    53          # check to see that an initial/empty config was created
    54          url = "/api/apps/{app_id}/config".format(**locals())
    55          response = self.client.get(url)
    56          self.assertEqual(response.status_code, 200)
    57          self.assertIn('values', response.data)
    58          self.assertEqual(response.data['values'], json.dumps({}))
    59          config1 = response.data
    60          # set an initial config value
    61          body = {'values': json.dumps({'NEW_URL1': 'http://localhost:8080/'})}
    62          response = self.client.post(url, json.dumps(body), content_type='application/json')
    63          self.assertEqual(response.status_code, 201)
    64          self.assertIn('x-deis-release', response._headers)
    65          config2 = response.data
    66          self.assertNotEqual(config1['uuid'], config2['uuid'])
    67          self.assertIn('NEW_URL1', json.loads(response.data['values']))
    68          # read the config
    69          response = self.client.get(url)
    70          self.assertEqual(response.status_code, 200)
    71          config3 = response.data
    72          self.assertEqual(config2, config3)
    73          self.assertIn('NEW_URL1', json.loads(response.data['values']))
    74          # set an additional config value
    75          body = {'values': json.dumps({'NEW_URL2': 'http://localhost:8080/'})}
    76          response = self.client.post(url, json.dumps(body), content_type='application/json')
    77          self.assertEqual(response.status_code, 201)
    78          config3 = response.data
    79          self.assertNotEqual(config2['uuid'], config3['uuid'])
    80          self.assertIn('NEW_URL1', json.loads(response.data['values']))
    81          self.assertIn('NEW_URL2', json.loads(response.data['values']))
    82          # read the config again
    83          response = self.client.get(url)
    84          self.assertEqual(response.status_code, 200)
    85          config4 = response.data
    86          self.assertEqual(config3, config4)
    87          self.assertIn('NEW_URL1', json.loads(response.data['values']))
    88          self.assertIn('NEW_URL2', json.loads(response.data['values']))
    89          # unset a config value
    90          body = {'values': json.dumps({'NEW_URL2': None})}
    91          response = self.client.post(url, json.dumps(body), content_type='application/json')
    92          self.assertEqual(response.status_code, 201)
    93          config5 = response.data
    94          self.assertNotEqual(config4['uuid'], config5['uuid'])
    95          self.assertNotIn('NEW_URL2', json.dumps(response.data['values']))
    96          # unset all config values
    97          body = {'values': json.dumps({'NEW_URL1': None})}
    98          response = self.client.post(url, json.dumps(body), content_type='application/json')
    99          self.assertEqual(response.status_code, 201)
   100          self.assertNotIn('NEW_URL1', json.dumps(response.data['values']))
   101          # disallow put/patch/delete
   102          self.assertEqual(self.client.put(url).status_code, 405)
   103          self.assertEqual(self.client.patch(url).status_code, 405)
   104          self.assertEqual(self.client.delete(url).status_code, 405)
   105          return config5
   106  
   107      @mock.patch('requests.post', mock_import_repository_task)
   108      def test_config_set_same_key(self):
   109          """
   110          Test that config sets on the same key function properly
   111          """
   112          url = '/api/apps'
   113          body = {'cluster': 'autotest'}
   114          response = self.client.post(url, json.dumps(body), content_type='application/json')
   115          self.assertEqual(response.status_code, 201)
   116          app_id = response.data['id']
   117          url = "/api/apps/{app_id}/config".format(**locals())
   118          # set an initial config value
   119          body = {'values': json.dumps({'PORT': '5000'})}
   120          response = self.client.post(url, json.dumps(body), content_type='application/json')
   121          self.assertEqual(response.status_code, 201)
   122          self.assertIn('PORT', json.loads(response.data['values']))
   123          # reset same config value
   124          body = {'values': json.dumps({'PORT': '5001'})}
   125          response = self.client.post(url, json.dumps(body), content_type='application/json')
   126          self.assertEqual(response.status_code, 201)
   127          self.assertIn('PORT', json.loads(response.data['values']))
   128          self.assertEqual(json.loads(response.data['values'])['PORT'], '5001')
   129  
   130      @mock.patch('requests.post', mock_import_repository_task)
   131      def test_config_str(self):
   132          """Test the text representation of a node."""
   133          config5 = self.test_config()
   134          config = Config.objects.get(uuid=config5['uuid'])
   135          self.assertEqual(str(config), "{}-{}".format(config5['app'], config5['uuid'][:7]))
   136  
   137      @mock.patch('requests.post', mock_import_repository_task)
   138      def test_limit_memory(self):
   139          """
   140          Test that limit is auto-created for a new app and that
   141          limits can be updated using a PATCH
   142          """
   143          url = '/api/apps'
   144          body = {'cluster': 'autotest'}
   145          response = self.client.post(url, json.dumps(body), content_type='application/json')
   146          self.assertEqual(response.status_code, 201)
   147          app_id = response.data['id']
   148          url = '/api/apps/{app_id}/config'.format(**locals())
   149          # check default limit
   150          response = self.client.get(url, content_type='application/json')
   151          self.assertEqual(response.status_code, 200)
   152          self.assertIn('memory', response.data)
   153          self.assertEqual(json.loads(response.data['memory']), {})
   154          # regression test for https://github.com/deis/deis/issues/1563
   155          self.assertNotIn('"', response.data['memory'])
   156          # set an initial limit
   157          mem = {'web': '1G'}
   158          body = {'memory': json.dumps(mem)}
   159          response = self.client.post(url, json.dumps(body), content_type='application/json')
   160          self.assertEqual(response.status_code, 201)
   161          self.assertIn('x-deis-release', response._headers)
   162          limit1 = response.data
   163          # check memory limits
   164          response = self.client.get(url, content_type='application/json')
   165          self.assertEqual(response.status_code, 200)
   166          self.assertIn('memory', response.data)
   167          memory = json.loads(response.data['memory'])
   168          self.assertIn('web', memory)
   169          self.assertEqual(memory['web'], '1G')
   170          # set an additional value
   171          body = {'memory': json.dumps({'worker': '512M'})}
   172          response = self.client.post(url, json.dumps(body), content_type='application/json')
   173          self.assertEqual(response.status_code, 201)
   174          limit2 = response.data
   175          self.assertNotEqual(limit1['uuid'], limit2['uuid'])
   176          memory = json.loads(response.data['memory'])
   177          self.assertIn('worker', memory)
   178          self.assertEqual(memory['worker'], '512M')
   179          self.assertIn('web', memory)
   180          self.assertEqual(memory['web'], '1G')
   181          # read the limit again
   182          response = self.client.get(url)
   183          self.assertEqual(response.status_code, 200)
   184          limit3 = response.data
   185          self.assertEqual(limit2, limit3)
   186          memory = json.loads(response.data['memory'])
   187          self.assertIn('worker', memory)
   188          self.assertEqual(memory['worker'], '512M')
   189          self.assertIn('web', memory)
   190          self.assertEqual(memory['web'], '1G')
   191          # regression test for https://github.com/deis/deis/issues/1613
   192          # ensure that config:set doesn't wipe out previous limits
   193          body = {'values': json.dumps({'NEW_URL2': 'http://localhost:8080/'})}
   194          response = self.client.post(url, json.dumps(body), content_type='application/json')
   195          self.assertEqual(response.status_code, 201)
   196          self.assertIn('NEW_URL2', json.loads(response.data['values']))
   197          # read the limit again
   198          response = self.client.get(url)
   199          self.assertEqual(response.status_code, 200)
   200          memory = json.loads(response.data['memory'])
   201          self.assertIn('worker', memory)
   202          self.assertEqual(memory['worker'], '512M')
   203          self.assertIn('web', memory)
   204          self.assertEqual(memory['web'], '1G')
   205          # unset a value
   206          body = {'memory': json.dumps({'worker': None})}
   207          response = self.client.post(url, json.dumps(body), content_type='application/json')
   208          self.assertEqual(response.status_code, 201)
   209          limit4 = response.data
   210          self.assertNotEqual(limit3['uuid'], limit4['uuid'])
   211          self.assertNotIn('worker', json.dumps(response.data['memory']))
   212          # disallow put/patch/delete
   213          self.assertEqual(self.client.put(url).status_code, 405)
   214          self.assertEqual(self.client.patch(url).status_code, 405)
   215          self.assertEqual(self.client.delete(url).status_code, 405)
   216          return limit4
   217  
   218      @mock.patch('requests.post', mock_import_repository_task)
   219      def test_limit_cpu(self):
   220          """
   221          Test that CPU limits can be set
   222          """
   223          url = '/api/apps'
   224          body = {'cluster': 'autotest'}
   225          response = self.client.post(url, json.dumps(body), content_type='application/json')
   226          self.assertEqual(response.status_code, 201)
   227          app_id = response.data['id']
   228          url = '/api/apps/{app_id}/config'.format(**locals())
   229          # check default limit
   230          response = self.client.get(url, content_type='application/json')
   231          self.assertEqual(response.status_code, 200)
   232          self.assertIn('cpu', response.data)
   233          self.assertEqual(json.loads(response.data['cpu']), {})
   234          # regression test for https://github.com/deis/deis/issues/1563
   235          self.assertNotIn('"', response.data['cpu'])
   236          # set an initial limit
   237          body = {'cpu': json.dumps({'web': '1024'})}
   238          response = self.client.post(url, json.dumps(body), content_type='application/json')
   239          self.assertEqual(response.status_code, 201)
   240          self.assertIn('x-deis-release', response._headers)
   241          limit1 = response.data
   242          # check memory limits
   243          response = self.client.get(url, content_type='application/json')
   244          self.assertEqual(response.status_code, 200)
   245          self.assertIn('cpu', response.data)
   246          cpu = json.loads(response.data['cpu'])
   247          self.assertIn('web', cpu)
   248          self.assertEqual(cpu['web'], '1024')
   249          # set an additional value
   250          body = {'cpu': json.dumps({'worker': '512'})}
   251          response = self.client.post(url, json.dumps(body), content_type='application/json')
   252          self.assertEqual(response.status_code, 201)
   253          limit2 = response.data
   254          self.assertNotEqual(limit1['uuid'], limit2['uuid'])
   255          cpu = json.loads(response.data['cpu'])
   256          self.assertIn('worker', cpu)
   257          self.assertEqual(cpu['worker'], '512')
   258          self.assertIn('web', cpu)
   259          self.assertEqual(cpu['web'], '1024')
   260          # read the limit again
   261          response = self.client.get(url)
   262          self.assertEqual(response.status_code, 200)
   263          limit3 = response.data
   264          self.assertEqual(limit2, limit3)
   265          cpu = json.loads(response.data['cpu'])
   266          self.assertIn('worker', cpu)
   267          self.assertEqual(cpu['worker'], '512')
   268          self.assertIn('web', cpu)
   269          self.assertEqual(cpu['web'], '1024')
   270          # unset a value
   271          body = {'memory': json.dumps({'worker': None})}
   272          response = self.client.post(url, json.dumps(body), content_type='application/json')
   273          self.assertEqual(response.status_code, 201)
   274          limit4 = response.data
   275          self.assertNotEqual(limit3['uuid'], limit4['uuid'])
   276          self.assertNotIn('worker', json.dumps(response.data['memory']))
   277          # disallow put/patch/delete
   278          self.assertEqual(self.client.put(url).status_code, 405)
   279          self.assertEqual(self.client.patch(url).status_code, 405)
   280          self.assertEqual(self.client.delete(url).status_code, 405)
   281          return limit4
   282  
   283      @mock.patch('requests.post', mock_import_repository_task)
   284      def test_tags(self):
   285          """
   286          Test that tags can be set on an application
   287          """
   288          url = '/api/apps'
   289          body = {'cluster': 'autotest'}
   290          response = self.client.post(url, json.dumps(body), content_type='application/json')
   291          self.assertEqual(response.status_code, 201)
   292          app_id = response.data['id']
   293          url = '/api/apps/{app_id}/config'.format(**locals())
   294          # check default
   295          response = self.client.get(url, content_type='application/json')
   296          self.assertEqual(response.status_code, 200)
   297          self.assertIn('tags', response.data)
   298          self.assertEqual(json.loads(response.data['tags']), {})
   299          # set some tags
   300          body = {'tags': json.dumps({'environ': 'dev'})}
   301          response = self.client.post(url, json.dumps(body), content_type='application/json')
   302          self.assertEqual(response.status_code, 201)
   303          self.assertIn('x-deis-release', response._headers)
   304          tags1 = response.data
   305          # check tags again
   306          response = self.client.get(url, content_type='application/json')
   307          self.assertEqual(response.status_code, 200)
   308          self.assertIn('tags', response.data)
   309          tags = json.loads(response.data['tags'])
   310          self.assertIn('environ', tags)
   311          self.assertEqual(tags['environ'], 'dev')
   312          # set an additional value
   313          body = {'tags': json.dumps({'rack': '1'})}
   314          response = self.client.post(url, json.dumps(body), content_type='application/json')
   315          self.assertEqual(response.status_code, 201)
   316          tags2 = response.data
   317          self.assertNotEqual(tags1['uuid'], tags2['uuid'])
   318          tags = json.loads(response.data['tags'])
   319          self.assertIn('rack', tags)
   320          self.assertEqual(tags['rack'], '1')
   321          self.assertIn('environ', tags)
   322          self.assertEqual(tags['environ'], 'dev')
   323          # read the limit again
   324          response = self.client.get(url)
   325          self.assertEqual(response.status_code, 200)
   326          tags3 = response.data
   327          self.assertEqual(tags2, tags3)
   328          tags = json.loads(response.data['tags'])
   329          self.assertIn('rack', tags)
   330          self.assertEqual(tags['rack'], '1')
   331          self.assertIn('environ', tags)
   332          self.assertEqual(tags['environ'], 'dev')
   333          # unset a value
   334          body = {'tags': json.dumps({'rack': None})}
   335          response = self.client.post(url, json.dumps(body), content_type='application/json')
   336          self.assertEqual(response.status_code, 201)
   337          tags4 = response.data
   338          self.assertNotEqual(tags3['uuid'], tags4['uuid'])
   339          self.assertNotIn('rack', json.dumps(response.data['tags']))
   340          # set invalid values
   341          body = {'tags': json.dumps({'valid': 'in\nvalid'})}
   342          response = self.client.post(url, json.dumps(body), content_type='application/json')
   343          self.assertEqual(response.status_code, 400)
   344          body = {'tags': json.dumps({'in.valid': 'valid'})}
   345          response = self.client.post(url, json.dumps(body), content_type='application/json')
   346          self.assertEqual(response.status_code, 400)
   347          # disallow put/patch/delete
   348          self.assertEqual(self.client.put(url).status_code, 405)
   349          self.assertEqual(self.client.patch(url).status_code, 405)
   350          self.assertEqual(self.client.delete(url).status_code, 405)
   351          return tags4