Fix CLI test against latest Cosmos (#665)

* latest Cosmos always includes the `framework` and `selected` properties.
This change fixes the `metadata` label to include those fields

* remove no longer defaulted Universe-1.7 repo

* update tasks test for new mesos version
This commit is contained in:
José Armando García Sancio
2016-07-25 19:32:37 -07:00
committed by tamarrow
parent b078e54db1
commit a6bf5fbc79
8 changed files with 26 additions and 33 deletions

View File

@@ -32,7 +32,7 @@
"instances": 1,
"labels": {
"DCOS_PACKAGE_IS_FRAMEWORK": "true",
"DCOS_PACKAGE_METADATA": "eyJsaWNlbnNlcyI6W3sibmFtZSI6IkFwYWNoZSBMaWNlbnNlIFZlcnNpb24gMi4wIiwidXJsIjoiaHR0cHM6Ly9naXRodWIuY29tL21lc29zcGhlcmUvbWFyYXRob24vYmxvYi9tYXN0ZXIvTElDRU5TRSJ9XSwibmFtZSI6Im1hcmF0aG9uIiwicG9zdEluc3RhbGxOb3RlcyI6Ik1hcmF0aG9uIERDT1MgU2VydmljZSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgaW5zdGFsbGVkIVxuXG5cdERvY3VtZW50YXRpb246IGh0dHBzOi8vbWVzb3NwaGVyZS5naXRodWIuaW8vbWFyYXRob25cblx0SXNzdWVzOiBodHRwczovZ2l0aHViLmNvbS9tZXNvc3BoZXJlL21hcmF0aG9uL2lzc3Vlc1xuIiwic2NtIjoiaHR0cHM6Ly9naXRodWIuY29tL21lc29zcGhlcmUvbWFyYXRob24uZ2l0IiwiZGVzY3JpcHRpb24iOiJBIGNsdXN0ZXItd2lkZSBpbml0IGFuZCBjb250cm9sIHN5c3RlbSBmb3Igc2VydmljZXMgaW4gY2dyb3VwcyBvciBEb2NrZXIgY29udGFpbmVycy4iLCJwYWNrYWdpbmdWZXJzaW9uIjoiMi4wIiwidGFncyI6WyJpbml0IiwibG9uZy1ydW5uaW5nIl0sInBvc3RVbmluc3RhbGxOb3RlcyI6IlRoZSBNYXJhdGhvbiBEQ09TIFNlcnZpY2UgaGFzIGJlZW4gdW5pbnN0YWxsZWQgYW5kIHdpbGwgbm8gbG9uZ2VyIHJ1bi5cblBsZWFzZSBmb2xsb3cgdGhlIGluc3RydWN0aW9ucyBhdCBodHRwOi8vZG9jcy5tZXNvc3BoZXJlLmNvbS9zZXJ2aWNlcy9tYXJhdGhvbi8jdW5pbnN0YWxsIHRvIGNsZWFuIHVwIGFueSBwZXJzaXN0ZWQgc3RhdGUiLCJtYWludGFpbmVyIjoic3VwcG9ydEBtZXNvc3BoZXJlLmlvIiwiZnJhbWV3b3JrIjp0cnVlLCJ2ZXJzaW9uIjoiMC4xMS4xIiwicHJlSW5zdGFsbE5vdGVzIjoiV2UgcmVjb21tZW5kIGEgbWluaW11bSBvZiBvbmUgbm9kZSB3aXRoIGF0IGxlYXN0IDIgQ1BVJ3MgYW5kIDFHQiBvZiBSQU0gYXZhaWxhYmxlIGZvciB0aGUgTWFyYXRob24gU2VydmljZS4iLCJpbWFnZXMiOnsiaWNvbi1zbWFsbCI6Imh0dHBzOi8vZG93bmxvYWRzLm1lc29zcGhlcmUuY29tL21hcmF0aG9uL2Fzc2V0cy9pY29uLXNlcnZpY2UtbWFyYXRob24tc21hbGwucG5nIiwiaWNvbi1tZWRpdW0iOiJodHRwczovL2Rvd25sb2Fkcy5tZXNvc3BoZXJlLmNvbS9tYXJhdGhvbi9hc3NldHMvaWNvbi1zZXJ2aWNlLW1hcmF0aG9uLW1lZGl1bS5wbmciLCJpY29uLWxhcmdlIjoiaHR0cHM6Ly9kb3dubG9hZHMubWVzb3NwaGVyZS5jb20vbWFyYXRob24vYXNzZXRzL2ljb24tc2VydmljZS1tYXJhdGhvbi1sYXJnZS5wbmciLCJzY3JlZW5zaG90cyI6bnVsbH19",
"DCOS_PACKAGE_METADATA": "eyJsaWNlbnNlcyI6W3sibmFtZSI6IkFwYWNoZSBMaWNlbnNlIFZlcnNpb24gMi4wIiwidXJsIjoiaHR0cHM6Ly9naXRodWIuY29tL21lc29zcGhlcmUvbWFyYXRob24vYmxvYi9tYXN0ZXIvTElDRU5TRSJ9XSwibmFtZSI6Im1hcmF0aG9uIiwicG9zdEluc3RhbGxOb3RlcyI6Ik1hcmF0aG9uIERDT1MgU2VydmljZSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgaW5zdGFsbGVkIVxuXG5cdERvY3VtZW50YXRpb246IGh0dHBzOi8vbWVzb3NwaGVyZS5naXRodWIuaW8vbWFyYXRob25cblx0SXNzdWVzOiBodHRwczovZ2l0aHViLmNvbS9tZXNvc3BoZXJlL21hcmF0aG9uL2lzc3Vlc1xuIiwic2NtIjoiaHR0cHM6Ly9naXRodWIuY29tL21lc29zcGhlcmUvbWFyYXRob24uZ2l0IiwiZGVzY3JpcHRpb24iOiJBIGNsdXN0ZXItd2lkZSBpbml0IGFuZCBjb250cm9sIHN5c3RlbSBmb3Igc2VydmljZXMgaW4gY2dyb3VwcyBvciBEb2NrZXIgY29udGFpbmVycy4iLCJwYWNrYWdpbmdWZXJzaW9uIjoiMi4wIiwidGFncyI6WyJpbml0IiwibG9uZy1ydW5uaW5nIl0sInBvc3RVbmluc3RhbGxOb3RlcyI6IlRoZSBNYXJhdGhvbiBEQ09TIFNlcnZpY2UgaGFzIGJlZW4gdW5pbnN0YWxsZWQgYW5kIHdpbGwgbm8gbG9uZ2VyIHJ1bi5cblBsZWFzZSBmb2xsb3cgdGhlIGluc3RydWN0aW9ucyBhdCBodHRwOi8vZG9jcy5tZXNvc3BoZXJlLmNvbS9zZXJ2aWNlcy9tYXJhdGhvbi8jdW5pbnN0YWxsIHRvIGNsZWFuIHVwIGFueSBwZXJzaXN0ZWQgc3RhdGUiLCJtYWludGFpbmVyIjoic3VwcG9ydEBtZXNvc3BoZXJlLmlvIiwic2VsZWN0ZWQiOmZhbHNlLCJmcmFtZXdvcmsiOnRydWUsInZlcnNpb24iOiIwLjExLjEiLCJwcmVJbnN0YWxsTm90ZXMiOiJXZSByZWNvbW1lbmQgYSBtaW5pbXVtIG9mIG9uZSBub2RlIHdpdGggYXQgbGVhc3QgMiBDUFUncyBhbmQgMUdCIG9mIFJBTSBhdmFpbGFibGUgZm9yIHRoZSBNYXJhdGhvbiBTZXJ2aWNlLiIsImltYWdlcyI6eyJpY29uLXNtYWxsIjoiaHR0cHM6Ly9kb3dubG9hZHMubWVzb3NwaGVyZS5jb20vbWFyYXRob24vYXNzZXRzL2ljb24tc2VydmljZS1tYXJhdGhvbi1zbWFsbC5wbmciLCJpY29uLW1lZGl1bSI6Imh0dHBzOi8vZG93bmxvYWRzLm1lc29zcGhlcmUuY29tL21hcmF0aG9uL2Fzc2V0cy9pY29uLXNlcnZpY2UtbWFyYXRob24tbWVkaXVtLnBuZyIsImljb24tbGFyZ2UiOiJodHRwczovL2Rvd25sb2Fkcy5tZXNvc3BoZXJlLmNvbS9tYXJhdGhvbi9hc3NldHMvaWNvbi1zZXJ2aWNlLW1hcmF0aG9uLWxhcmdlLnBuZyIsInNjcmVlbnNob3RzIjpudWxsfX0=",
"DCOS_PACKAGE_NAME": "marathon",
"DCOS_PACKAGE_REGISTRY_VERSION": "2.0",
"DCOS_PACKAGE_RELEASE": "0",

View File

@@ -32,7 +32,8 @@
"instances": 1,
"labels": {
"DCOS_PACKAGE_IS_FRAMEWORK": "true",
"DCOS_PACKAGE_METADATA": "eyJsaWNlbnNlcyI6W3sibmFtZSI6IkFwYWNoZSBMaWNlbnNlIFZlcnNpb24gMi4wIiwidXJsIjoiaHR0cHM6Ly9naXRodWIuY29tL21lc29zcGhlcmUvbWFyYXRob24vYmxvYi9tYXN0ZXIvTElDRU5TRSJ9XSwibmFtZSI6Im1hcmF0aG9uIiwicG9zdEluc3RhbGxOb3RlcyI6Ik1hcmF0aG9uIERDT1MgU2VydmljZSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgaW5zdGFsbGVkIVxuXG5cdERvY3VtZW50YXRpb246IGh0dHBzOi8vbWVzb3NwaGVyZS5naXRodWIuaW8vbWFyYXRob25cblx0SXNzdWVzOiBodHRwczovZ2l0aHViLmNvbS9tZXNvc3BoZXJlL21hcmF0aG9uL2lzc3Vlc1xuIiwic2NtIjoiaHR0cHM6Ly9naXRodWIuY29tL21lc29zcGhlcmUvbWFyYXRob24uZ2l0IiwiZGVzY3JpcHRpb24iOiJBIGNsdXN0ZXItd2lkZSBpbml0IGFuZCBjb250cm9sIHN5c3RlbSBmb3Igc2VydmljZXMgaW4gY2dyb3VwcyBvciBEb2NrZXIgY29udGFpbmVycy4iLCJwYWNrYWdpbmdWZXJzaW9uIjoiMi4wIiwidGFncyI6WyJpbml0IiwibG9uZy1ydW5uaW5nIl0sInBvc3RVbmluc3RhbGxOb3RlcyI6IlRoZSBNYXJhdGhvbiBEQ09TIFNlcnZpY2UgaGFzIGJlZW4gdW5pbnN0YWxsZWQgYW5kIHdpbGwgbm8gbG9uZ2VyIHJ1bi5cblBsZWFzZSBmb2xsb3cgdGhlIGluc3RydWN0aW9ucyBhdCBodHRwOi8vZG9jcy5tZXNvc3BoZXJlLmNvbS9zZXJ2aWNlcy9tYXJhdGhvbi8jdW5pbnN0YWxsIHRvIGNsZWFuIHVwIGFueSBwZXJzaXN0ZWQgc3RhdGUiLCJtYWludGFpbmVyIjoic3VwcG9ydEBtZXNvc3BoZXJlLmlvIiwiZnJhbWV3b3JrIjp0cnVlLCJ2ZXJzaW9uIjoiMC4xMS4xIiwicHJlSW5zdGFsbE5vdGVzIjoiV2UgcmVjb21tZW5kIGEgbWluaW11bSBvZiBvbmUgbm9kZSB3aXRoIGF0IGxlYXN0IDIgQ1BVJ3MgYW5kIDFHQiBvZiBSQU0gYXZhaWxhYmxlIGZvciB0aGUgTWFyYXRob24gU2VydmljZS4iLCJpbWFnZXMiOnsiaWNvbi1zbWFsbCI6Imh0dHBzOi8vZG93bmxvYWRzLm1lc29zcGhlcmUuY29tL21hcmF0aG9uL2Fzc2V0cy9pY29uLXNlcnZpY2UtbWFyYXRob24tc21hbGwucG5nIiwiaWNvbi1tZWRpdW0iOiJodHRwczovL2Rvd25sb2Fkcy5tZXNvc3BoZXJlLmNvbS9tYXJhdGhvbi9hc3NldHMvaWNvbi1zZXJ2aWNlLW1hcmF0aG9uLW1lZGl1bS5wbmciLCJpY29uLWxhcmdlIjoiaHR0cHM6Ly9kb3dubG9hZHMubWVzb3NwaGVyZS5jb20vbWFyYXRob24vYXNzZXRzL2ljb24tc2VydmljZS1tYXJhdGhvbi1sYXJnZS5wbmciLCJzY3JlZW5zaG90cyI6bnVsbH19",
"DCOS_PACKAGE_METADATA": "eyJsaWNlbnNlcyI6W3sibmFtZSI6IkFwYWNoZSBMaWNlbnNlIFZlcnNpb24gMi4wIiwidXJsIjoiaHR0cHM6Ly9naXRodWIuY29tL21lc29zcGhlcmUvbWFyYXRob24vYmxvYi9tYXN0ZXIvTElDRU5TRSJ9XSwibmFtZSI6Im1hcmF0aG9uIiwicG9zdEluc3RhbGxOb3RlcyI6Ik1hcmF0aG9uIERDT1MgU2VydmljZSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgaW5zdGFsbGVkIVxuXG5cdERvY3VtZW50YXRpb246IGh0dHBzOi8vbWVzb3NwaGVyZS5naXRodWIuaW8vbWFyYXRob25cblx0SXNzdWVzOiBodHRwczovZ2l0aHViLmNvbS9tZXNvc3BoZXJlL21hcmF0aG9uL2lzc3Vlc1xuIiwic2NtIjoiaHR0cHM6Ly9naXRodWIuY29tL21lc29zcGhlcmUvbWFyYXRob24uZ2l0IiwiZGVzY3JpcHRpb24iOiJBIGNsdXN0ZXItd2lkZSBpbml0IGFuZCBjb250cm9sIHN5c3RlbSBmb3Igc2VydmljZXMgaW4gY2dyb3VwcyBvciBEb2NrZXIgY29udGFpbmVycy4iLCJwYWNrYWdpbmdWZXJzaW9uIjoiMi4wIiwidGFncyI6WyJpbml0IiwibG9uZy1ydW5uaW5nIl0sInBvc3RVbmluc3RhbGxOb3RlcyI6IlRoZSBNYXJhdGhvbiBEQ09TIFNlcnZpY2UgaGFzIGJlZW4gdW5pbnN0YWxsZWQgYW5kIHdpbGwgbm8gbG9uZ2VyIHJ1bi5cblBsZWFzZSBmb2xsb3cgdGhlIGluc3RydWN0aW9ucyBhdCBodHRwOi8vZG9jcy5tZXNvc3BoZXJlLmNvbS9zZXJ2aWNlcy9tYXJhdGhvbi8jdW5pbnN0YWxsIHRvIGNsZWFuIHVwIGFueSBwZXJzaXN0ZWQgc3RhdGUiLCJtYWludGFpbmVyIjoic3VwcG9ydEBtZXNvc3BoZXJlLmlvIiwic2VsZWN0ZWQiOmZhbHNlLCJmcmFtZXdvcmsiOnRydWUsInZlcnNpb24iOiIwLjExLjEiLCJwcmVJbnN0YWxsTm90ZXMiOiJXZSByZWNvbW1lbmQgYSBtaW5pbXVtIG9mIG9uZSBub2RlIHdpdGggYXQgbGVhc3QgMiBDUFUncyBhbmQgMUdCIG9mIFJBTSBhdmFpbGFibGUgZm9yIHRoZSBNYXJhdGhvbiBTZXJ2aWNlLiIsImltYWdlcyI6eyJpY29uLXNtYWxsIjoiaHR0cHM6Ly9kb3dubG9hZHMubWVzb3NwaGVyZS5jb20vbWFyYXRob24vYXNzZXRzL2ljb24tc2VydmljZS1tYXJhdGhvbi1zbWFsbC5wbmciLCJpY29uLW1lZGl1bSI6Imh0dHBzOi8vZG93bmxvYWRzLm1lc29zcGhlcmUuY29tL21hcmF0aG9uL2Fzc2V0cy9pY29uLXNlcnZpY2UtbWFyYXRob24tbWVkaXVtLnBuZyIsImljb24tbGFyZ2UiOiJodHRwczovL2Rvd25sb2Fkcy5tZXNvc3BoZXJlLmNvbS9tYXJhdGhvbi9hc3NldHMvaWNvbi1zZXJ2aWNlLW1hcmF0aG9uLWxhcmdlLnBuZyIsInNjcmVlbnNob3RzIjpudWxsfX0=",
"DCOS_PACKAGE_NAME": "marathon",
"DCOS_PACKAGE_REGISTRY_VERSION": "2.0",
"DCOS_PACKAGE_RELEASE": "0",

View File

@@ -26,7 +26,6 @@ def task_fixture():
"container_status": {
"network_infos": [
{
"ip_address": "172.17.8.12",
"ip_addresses": [
{
"ip_address": "127.17.8.12"

View File

@@ -212,21 +212,17 @@ def _node_ssh(args, expected_returncode=None, expected_stdout=None):
def _get_schema(slave):
schema = create_schema(slave)
schema['additionalProperties'] = True
schema = create_schema(slave, True)
schema['required'].remove('reregistered_time')
schema['required'].remove('reserved_resources')
schema['properties']['reserved_resources']['required'] = []
schema['properties']['reserved_resources']['additionalProperties'] = True
schema['required'].remove('unreserved_resources')
schema['properties']['unreserved_resources']['required'] = []
schema['properties']['unreserved_resources']['additionalProperties'] = True
schema['properties']['used_resources']['required'].remove('ports')
schema['properties']['offered_resources']['required'].remove('ports')
schema['properties']['attributes']['additionalProperties'] = True
schema['required'].remove('version')
return schema

View File

@@ -15,8 +15,6 @@ from .common import (assert_command, assert_lines, delete_zk_node,
def setup_module(module):
assert_command(
['dcos', 'package', 'repo', 'remove', 'Universe-1.7'])
assert_command(
['dcos', 'package', 'repo', 'remove', 'Universe'])
repo = "https://github.com/mesosphere/universe/archive/cli-test-4.zip"
@@ -26,8 +24,6 @@ def setup_module(module):
def teardown_module(module):
assert_command(
['dcos', 'package', 'repo', 'remove', 'test4'])
repo17 = "https://universe.mesosphere.com/repo-1.7"
assert_command(['dcos', 'package', 'repo', 'add', 'Universe-1.7', repo17])
repo = "https://universe.mesosphere.com/repo"
assert_command(['dcos', 'package', 'repo', 'add', 'Universe', repo])
@@ -388,13 +384,17 @@ def test_package_metadata():
_install_helloworld()
# test marathon labels
expected_metadata = b"""eyJ3ZWJzaXRlIjoiaHR0cHM6Ly9naXRodWIuY29tL21lc29zcG\
hlcmUvZGNvcy1oZWxsb3dvcmxkIiwibmFtZSI6ImhlbGxvd29ybGQiLCJwb3N0SW5zdGFsbE5vdGVz\
IjoiQSBzYW1wbGUgcG9zdC1pbnN0YWxsYXRpb24gbWVzc2FnZSIsImRlc2NyaXB0aW9uIjoiRXhhbX\
BsZSBEQ09TIGFwcGxpY2F0aW9uIHBhY2thZ2UiLCJwYWNrYWdpbmdWZXJzaW9uIjoiMi4wIiwidGFn\
cyI6WyJtZXNvc3BoZXJlIiwiZXhhbXBsZSIsInN1YmNvbW1hbmQiXSwibWFpbnRhaW5lciI6InN1cH\
BvcnRAbWVzb3NwaGVyZS5pbyIsInZlcnNpb24iOiIwLjEuMCIsInByZUluc3RhbGxOb3RlcyI6IkEg\
c2FtcGxlIHByZS1pbnN0YWxsYXRpb24gbWVzc2FnZSJ9"""
expected_metadata = (b'eyJ3ZWJzaXRlIjoiaHR0cHM6Ly9naXRodWIuY29tL21lc29zcG'
b'hlcmUvZGNvcy1oZWxsb3dvcmxkIiwibmFtZSI6ImhlbGxvd29y'
b'bGQiLCJwb3N0SW5zdGFsbE5vdGVzIjoiQSBzYW1wbGUgcG9zdC'
b'1pbnN0YWxsYXRpb24gbWVzc2FnZSIsImRlc2NyaXB0aW9uIjoi'
b'RXhhbXBsZSBEQ09TIGFwcGxpY2F0aW9uIHBhY2thZ2UiLCJwYW'
b'NrYWdpbmdWZXJzaW9uIjoiMi4wIiwidGFncyI6WyJtZXNvc3Bo'
b'ZXJlIiwiZXhhbXBsZSIsInN1YmNvbW1hbmQiXSwibWFpbnRhaW'
b'5lciI6InN1cHBvcnRAbWVzb3NwaGVyZS5pbyIsInNlbGVjdGVk'
b'IjpmYWxzZSwiZnJhbWV3b3JrIjpmYWxzZSwidmVyc2lvbiI6Ij'
b'AuMS4wIiwicHJlSW5zdGFsbE5vdGVzIjoiQSBzYW1wbGUgcHJl'
b'LWluc3RhbGxhdGlvbiBtZXNzYWdlIn0=')
expected_command = b"""eyJwaXAiOlsiZGNvczwxLjAiLCJnaXQraHR0cHM6Ly9naXRodWI\
uY29tL21lc29zcGhlcmUvZGNvcy1oZWxsb3dvcmxkLmdpdCNkY29zLWhlbGxvd29ybGQ9MC4xLjAiX\

View File

@@ -18,7 +18,6 @@ from .common import (assert_command, assert_lines, delete_zk_node,
def setup_module(module):
exec_command(['dcos', 'package', 'repo', 'remove', 'Universe-1.7'])
exec_command(
['dcos', 'package', 'repo', 'remove', 'Universe'])
repo = "https://github.com/mesosphere/universe/archive/cli-test-4.zip"
@@ -37,8 +36,6 @@ def teardown_module(module):
delete_zk_nodes()
assert_command(
['dcos', 'package', 'repo', 'remove', 'test4'])
repo17 = "https://universe.mesosphere.com/repo-1.7"
assert_command(['dcos', 'package', 'repo', 'add', 'Universe-1.7', repo17])
repo = "https://universe.mesosphere.com/repo"
assert_command(['dcos', 'package', 'repo', 'add', 'Universe', repo])
@@ -277,13 +274,12 @@ def test_log_no_apps():
def _get_schema(service):
schema = create_schema(service.dict())
schema = create_schema(service.dict(), True)
schema['required'].remove('reregistered_time')
schema['required'].remove('pid')
schema['required'].remove('executors')
schema['properties']['offered_resources']['required'].remove('ports')
schema['properties']['resources']['required'].remove('ports')
schema['properties']['used_resources']['required'].remove('ports')
schema['additionalProperties'] = True
return schema

View File

@@ -66,8 +66,7 @@ def test_task():
assert isinstance(tasks, collections.Sequence)
assert len(tasks) == NUM_TASKS
schema = create_schema(task_fixture().dict())
schema['additionalProperties'] = True
schema = create_schema(task_fixture().dict(), True)
schema['required'].remove('labels')
for task in tasks:
@@ -120,7 +119,7 @@ def test_log_single_file():
assert returncode == 0
assert stderr == b''
assert len(stdout.decode('utf-8').split('\n')) == 5
assert len(stdout.decode('utf-8').split('\n')) == 7
def test_log_missing_file():
@@ -179,9 +178,9 @@ def test_log_two_tasks():
assert stderr == b''
lines = stdout.decode('utf-8').split('\n')
assert len(lines) == 11
assert len(lines) == 15
assert re.match('===>.*<===', lines[0])
assert re.match('===>.*<===', lines[5])
assert re.match('===>.*<===', lines[7])
@pytest.mark.skipif(sys.platform == 'win32',

View File

@@ -360,11 +360,13 @@ def _format_validation_error(error):
return message
def create_schema(obj):
def create_schema(obj, add_properties=False):
""" Creates a basic json schema derived from `obj`.
:param obj: object for which to derive a schema
:type obj: str | int | float | dict | list
:param add_properties: whether to allow additional properties
:type add_properties: bool
:returns: json schema
:rtype: dict
"""
@@ -384,18 +386,18 @@ def create_schema(obj):
elif isinstance(obj, collections.Mapping):
schema = {'type': 'object',
'properties': {},
'additionalProperties': False,
'additionalProperties': add_properties,
'required': list(obj.keys())}
for key, val in obj.items():
schema['properties'][key] = create_schema(val)
schema['properties'][key] = create_schema(val, add_properties)
return schema
elif isinstance(obj, collections.Sequence):
schema = {'type': 'array'}
if obj:
schema['items'] = create_schema(obj[0])
schema['items'] = create_schema(obj[0], add_properties)
return schema
else: