Repository: jupyterhub/zero-to-jupyterhub-k8s

Issue:
traitlets.traitlets.TraitError: The 'extra_resource_limits' trait of a KubeSpawner instance must be a dict
I just tried to deploy `v0.7-0fdbfb5` and I'm getting an error immediately after login.

Hub logs:
```
[D 2018-08-01 09:28:25.829 JupyterHub user:190] Creating <class 'kubespawner.spawner.KubeSpawner'> for XXXX:
[E 2018-08-01 09:28:25.831 JupyterHub web:1670] Uncaught exception GET /jupyterhub-internal/hub/user/XXXX/ (XXXX)
    HTTPServerRequest(protocol='https', host='XXXX', method='GET', uri='/jupyterhub-internal/hub/user/XXXX/', version='HTTP/1.1', remote_ip='XXXX')
    Traceback (most recent call last):
      File "/usr/local/lib/python3.6/dist-packages/tornado/web.py", line 1592, in _execute
        result = yield result
      File "/usr/local/lib/python3.6/dist-packages/jupyterhub/handlers/base.py", line 947, in get
        spawner = user.spawner
      File "/usr/local/lib/python3.6/dist-packages/jupyterhub/user.py", line 228, in spawner
        return self.spawners['']
      File "/usr/local/lib/python3.6/dist-packages/jupyterhub/user.py", line 125, in __getitem__
        self[key] = self.spawner_factory(key)
      File "/usr/local/lib/python3.6/dist-packages/jupyterhub/user.py", line 221, in _new_spawner
        spawner = spawner_class(**spawn_kwargs)
      File "/usr/local/lib/python3.6/dist-packages/kubespawner/spawner.py", line 77, in __init__
        super().__init__(*args, **kwargs)
      File "/usr/local/lib/python3.6/dist-packages/traitlets/config/configurable.py", line 84, in __init__
        self.config = config
      File "/usr/local/lib/python3.6/dist-packages/traitlets/traitlets.py", line 585, in __set__
        self.set(obj, value)
      File "/usr/local/lib/python3.6/dist-packages/traitlets/traitlets.py", line 574, in set
        obj._notify_trait(self.name, old_value, new_value)
      File "/usr/local/lib/python3.6/dist-packages/traitlets/traitlets.py", line 1139, in _notify_trait
        type='change',
      File "/usr/local/lib/python3.6/dist-packages/traitlets/traitlets.py", line 1176, in notify_change
        c(change)
      File "/usr/local/lib/python3.6/dist-packages/traitlets/traitlets.py", line 819, in compatible_observer
        return func(self, change)
      File "/usr/local/lib/python3.6/dist-packages/traitlets/config/configurable.py", line 186, in _config_changed
        self._load_config(change.new, traits=traits, section_names=section_names)
      File "/usr/local/lib/python3.6/dist-packages/traitlets/config/configurable.py", line 153, in _load_config
        setattr(self, name, deepcopy(config_value))
      File "/usr/local/lib/python3.6/dist-packages/traitlets/traitlets.py", line 585, in __set__
        self.set(obj, value)
      File "/usr/local/lib/python3.6/dist-packages/traitlets/traitlets.py", line 559, in set
        new_value = self._validate(obj, value)
      File "/usr/local/lib/python3.6/dist-packages/traitlets/traitlets.py", line 591, in _validate
        value = self.validate(obj, value)
      File "/usr/local/lib/python3.6/dist-packages/traitlets/traitlets.py", line 2529, in validate
        value = super(Dict, self).validate(obj, value)
      File "/usr/local/lib/python3.6/dist-packages/traitlets/traitlets.py", line 1677, in validate
        self.error(obj, value)
      File "/usr/local/lib/python3.6/dist-packages/traitlets/traitlets.py", line 1524, in error
        raise TraitError(e)
    traitlets.traitlets.TraitError: The 'extra_resource_limits' trait of a KubeSpawner instance must be a dict, but a value of class 'NoneType' (i.e. None) was specified.

[D 2018-08-01 09:28:25.832 JupyterHub base:845] No template for 500
[D 2018-08-01 09:28:25.833 JupyterHub user:190] Creating <class 'kubespawner.spawner.KubeSpawner'> for XXXX:
...
[E 2018-08-01 09:28:25.836 JupyterHub log:158] 500 GET /jupyterhub-internal/hub/user/XXXX/ (XXXX@XXXX) 9.21ms
```
I suspect the problem might be https://github.com/jupyterhub/zero-to-jupyterhub-k8s/pull/793/files#diff-04b8604ebdfab5084aa24cb21f0d1deaR128 defaulting to `None` instead of `{}`. I'll try this and open a PR if so.


Discussion:
Note the hub appears to run fine, the error only occurs when spawning so it wasn't picked up by the current CI test.
Thanks for writing this up @manics! Better CI is a priority and having a user being spawned seems like a very good thing to test for.

Resolving patch:
diff --git a/images/hub/jupyterhub_config.py b/images/hub/jupyterhub_config.py
--- a/images/hub/jupyterhub_config.py
+++ b/images/hub/jupyterhub_config.py
@@ -126,8 +126,8 @@
 c.KubeSpawner.mem_guarantee = get_config('singleuser.memory.guarantee')
 c.KubeSpawner.cpu_limit = get_config('singleuser.cpu.limit')
 c.KubeSpawner.cpu_guarantee = get_config('singleuser.cpu.guarantee')
-c.KubeSpawner.extra_resource_limits = get_config('singleuser.extra_resource.limits')
-c.KubeSpawner.extra_resource_guarantees = get_config('singleuser.extra_resource.guarantees')
+c.KubeSpawner.extra_resource_limits = get_config('singleuser.extra-resource.limits', {})
+c.KubeSpawner.extra_resource_guarantees = get_config('singleuser.extra-resource.guarantees', {})
 
 # Allow switching authenticators easily
 auth_type = get_config('auth.type')


Test patch: