dcos package install with universe v2

This commit is contained in:
Tamar Ben-Shachar
2015-12-01 15:33:43 -08:00
parent 237f728dc3
commit 858e8fc37c
13 changed files with 127 additions and 58 deletions

View File

@@ -364,7 +364,8 @@ def _install(package_name, package_version, options_path, app_id, cli, app,
revision_map = pkg.package_revisions_map() revision_map = pkg.package_revisions_map()
package_version = revision_map.get(pkg_revision) package_version = revision_map.get(pkg_revision)
if app and pkg.has_marathon_definition(pkg_revision): if app and (pkg.has_marathon_definition(pkg_revision) or
pkg.has_marathon_mustache_definition(pkg_revision)):
# Install in Marathon # Install in Marathon
msg = 'Installing Marathon app for package [{}] version [{}]'.format( msg = 'Installing Marathon app for package [{}] version [{}]'.format(
pkg.name(), package_version) pkg.name(), package_version)

View File

@@ -5,5 +5,5 @@ timeout = 5
ssl_verify = "false" ssl_verify = "false"
dcos_url = "http://dcos.snakeoil.mesosphere.com" dcos_url = "http://dcos.snakeoil.mesosphere.com"
[package] [package]
sources = [ "https://github.com/mesosphere/universe/archive/cli-test-2.zip",] sources = [ "https://github.com/mesosphere/universe/archive/cli-test-3.zip",]
cache = "tmp/cache" cache = "tmp/cache"

View File

@@ -14,8 +14,8 @@
0 0
], ],
"uris": [ "uris": [
"https://downloads.mesosphere.io/cassandra-mesos/artifacts/0.2.0-1/cassandra-mesos-0.2.0-1.tar.gz", "{{resource.assets.uris.cassandra-mesos-tar-gz}}",
"https://downloads.mesosphere.io/java/jre-7u76-linux-x64.tar.gz" "{{resource.assets.uris.jre-7u76-linux-x64}}"
], ],
"healthChecks": [ "healthChecks": [
{ {

View File

@@ -35,9 +35,9 @@
"DCOS_PACKAGE_IS_FRAMEWORK": "true", "DCOS_PACKAGE_IS_FRAMEWORK": "true",
"DCOS_PACKAGE_METADATA": "eyJkZXNjcmlwdGlvbiI6ICJBIGNsdXN0ZXItd2lkZSBpbml0IGFuZCBjb250cm9sIHN5c3RlbSBmb3Igc2VydmljZXMgaW4gY2dyb3VwcyBvciBEb2NrZXIgY29udGFpbmVycy4iLCAiZnJhbWV3b3JrIjogdHJ1ZSwgImltYWdlcyI6IHsiaWNvbi1sYXJnZSI6ICJodHRwczovL2Rvd25sb2Fkcy5tZXNvc3BoZXJlLmlvL21hcmF0aG9uL2Fzc2V0cy9pY29uLXNlcnZpY2UtbWFyYXRob24tbGFyZ2UucG5nIiwgImljb24tbWVkaXVtIjogImh0dHBzOi8vZG93bmxvYWRzLm1lc29zcGhlcmUuaW8vbWFyYXRob24vYXNzZXRzL2ljb24tc2VydmljZS1tYXJhdGhvbi1tZWRpdW0ucG5nIiwgImljb24tc21hbGwiOiAiaHR0cHM6Ly9kb3dubG9hZHMubWVzb3NwaGVyZS5pby9tYXJhdGhvbi9hc3NldHMvaWNvbi1zZXJ2aWNlLW1hcmF0aG9uLXNtYWxsLnBuZyJ9LCAibGljZW5zZXMiOiBbeyJuYW1lIjogIkFwYWNoZSBMaWNlbnNlIFZlcnNpb24gMi4wIiwgInVybCI6ICJodHRwczovL2dpdGh1Yi5jb20vbWVzb3NwaGVyZS9tYXJhdGhvbi9ibG9iL21hc3Rlci9MSUNFTlNFIn1dLCAibWFpbnRhaW5lciI6ICJzdXBwb3J0QG1lc29zcGhlcmUuaW8iLCAibmFtZSI6ICJtYXJhdGhvbiIsICJwb3N0SW5zdGFsbE5vdGVzIjogIk1hcmF0aG9uIERDT1MgU2VydmljZSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgaW5zdGFsbGVkIVxuXG5cdERvY3VtZW50YXRpb246IGh0dHBzOi8vbWVzb3NwaGVyZS5naXRodWIuaW8vbWFyYXRob25cblx0SXNzdWVzOiBodHRwczovZ2l0aHViLmNvbS9tZXNvc3BoZXJlL21hcmF0aG9uL2lzc3Vlc1xuIiwgInBvc3RVbmluc3RhbGxOb3RlcyI6ICJUaGUgTWFyYXRob24gRENPUyBTZXJ2aWNlIGhhcyBiZWVuIHVuaW5zdGFsbGVkIGFuZCB3aWxsIG5vIGxvbmdlciBydW4uXG5QbGVhc2UgZm9sbG93IHRoZSBpbnN0cnVjdGlvbnMgYXQgaHR0cDovL2RvY3MubWVzb3NwaGVyZS5jb20vc2VydmljZXMvbWFyYXRob24vI3VuaW5zdGFsbCB0byBjbGVhbiB1cCBhbnkgcGVyc2lzdGVkIHN0YXRlIiwgInByZUluc3RhbGxOb3RlcyI6ICJXZSByZWNvbW1lbmQgYSBtaW5pbXVtIG9mIG9uZSBub2RlIHdpdGggYXQgbGVhc3QgMiBDUFUncyBhbmQgMUdCIG9mIFJBTSBhdmFpbGFibGUgZm9yIHRoZSBNYXJhdGhvbiBTZXJ2aWNlLiIsICJzY20iOiAiaHR0cHM6Ly9naXRodWIuY29tL21lc29zcGhlcmUvbWFyYXRob24uZ2l0IiwgInRhZ3MiOiBbImluaXQiLCAibG9uZy1ydW5uaW5nIl0sICJ2ZXJzaW9uIjogIjAuMTEuMSJ9", "DCOS_PACKAGE_METADATA": "eyJkZXNjcmlwdGlvbiI6ICJBIGNsdXN0ZXItd2lkZSBpbml0IGFuZCBjb250cm9sIHN5c3RlbSBmb3Igc2VydmljZXMgaW4gY2dyb3VwcyBvciBEb2NrZXIgY29udGFpbmVycy4iLCAiZnJhbWV3b3JrIjogdHJ1ZSwgImltYWdlcyI6IHsiaWNvbi1sYXJnZSI6ICJodHRwczovL2Rvd25sb2Fkcy5tZXNvc3BoZXJlLmlvL21hcmF0aG9uL2Fzc2V0cy9pY29uLXNlcnZpY2UtbWFyYXRob24tbGFyZ2UucG5nIiwgImljb24tbWVkaXVtIjogImh0dHBzOi8vZG93bmxvYWRzLm1lc29zcGhlcmUuaW8vbWFyYXRob24vYXNzZXRzL2ljb24tc2VydmljZS1tYXJhdGhvbi1tZWRpdW0ucG5nIiwgImljb24tc21hbGwiOiAiaHR0cHM6Ly9kb3dubG9hZHMubWVzb3NwaGVyZS5pby9tYXJhdGhvbi9hc3NldHMvaWNvbi1zZXJ2aWNlLW1hcmF0aG9uLXNtYWxsLnBuZyJ9LCAibGljZW5zZXMiOiBbeyJuYW1lIjogIkFwYWNoZSBMaWNlbnNlIFZlcnNpb24gMi4wIiwgInVybCI6ICJodHRwczovL2dpdGh1Yi5jb20vbWVzb3NwaGVyZS9tYXJhdGhvbi9ibG9iL21hc3Rlci9MSUNFTlNFIn1dLCAibWFpbnRhaW5lciI6ICJzdXBwb3J0QG1lc29zcGhlcmUuaW8iLCAibmFtZSI6ICJtYXJhdGhvbiIsICJwb3N0SW5zdGFsbE5vdGVzIjogIk1hcmF0aG9uIERDT1MgU2VydmljZSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgaW5zdGFsbGVkIVxuXG5cdERvY3VtZW50YXRpb246IGh0dHBzOi8vbWVzb3NwaGVyZS5naXRodWIuaW8vbWFyYXRob25cblx0SXNzdWVzOiBodHRwczovZ2l0aHViLmNvbS9tZXNvc3BoZXJlL21hcmF0aG9uL2lzc3Vlc1xuIiwgInBvc3RVbmluc3RhbGxOb3RlcyI6ICJUaGUgTWFyYXRob24gRENPUyBTZXJ2aWNlIGhhcyBiZWVuIHVuaW5zdGFsbGVkIGFuZCB3aWxsIG5vIGxvbmdlciBydW4uXG5QbGVhc2UgZm9sbG93IHRoZSBpbnN0cnVjdGlvbnMgYXQgaHR0cDovL2RvY3MubWVzb3NwaGVyZS5jb20vc2VydmljZXMvbWFyYXRob24vI3VuaW5zdGFsbCB0byBjbGVhbiB1cCBhbnkgcGVyc2lzdGVkIHN0YXRlIiwgInByZUluc3RhbGxOb3RlcyI6ICJXZSByZWNvbW1lbmQgYSBtaW5pbXVtIG9mIG9uZSBub2RlIHdpdGggYXQgbGVhc3QgMiBDUFUncyBhbmQgMUdCIG9mIFJBTSBhdmFpbGFibGUgZm9yIHRoZSBNYXJhdGhvbiBTZXJ2aWNlLiIsICJzY20iOiAiaHR0cHM6Ly9naXRodWIuY29tL21lc29zcGhlcmUvbWFyYXRob24uZ2l0IiwgInRhZ3MiOiBbImluaXQiLCAibG9uZy1ydW5uaW5nIl0sICJ2ZXJzaW9uIjogIjAuMTEuMSJ9",
"DCOS_PACKAGE_NAME": "marathon", "DCOS_PACKAGE_NAME": "marathon",
"DCOS_PACKAGE_REGISTRY_VERSION": "1.0.0-rc1", "DCOS_PACKAGE_REGISTRY_VERSION": "2.0.0-rc1",
"DCOS_PACKAGE_RELEASE": "6", "DCOS_PACKAGE_RELEASE": "6",
"DCOS_PACKAGE_SOURCE": "https://github.com/mesosphere/universe/archive/cli-test-2.zip", "DCOS_PACKAGE_SOURCE": "https://github.com/mesosphere/universe/archive/cli-test-3.zip",
"DCOS_PACKAGE_VERSION": "0.11.1" "DCOS_PACKAGE_VERSION": "0.11.1"
}, },
"mem": 1024.0, "mem": 1024.0,

View File

@@ -35,9 +35,9 @@
"DCOS_PACKAGE_IS_FRAMEWORK": "true", "DCOS_PACKAGE_IS_FRAMEWORK": "true",
"DCOS_PACKAGE_METADATA": "eyJkZXNjcmlwdGlvbiI6ICJBIGNsdXN0ZXItd2lkZSBpbml0IGFuZCBjb250cm9sIHN5c3RlbSBmb3Igc2VydmljZXMgaW4gY2dyb3VwcyBvciBEb2NrZXIgY29udGFpbmVycy4iLCAiZnJhbWV3b3JrIjogdHJ1ZSwgImltYWdlcyI6IHsiaWNvbi1sYXJnZSI6ICJodHRwczovL2Rvd25sb2Fkcy5tZXNvc3BoZXJlLmlvL21hcmF0aG9uL2Fzc2V0cy9pY29uLXNlcnZpY2UtbWFyYXRob24tbGFyZ2UucG5nIiwgImljb24tbWVkaXVtIjogImh0dHBzOi8vZG93bmxvYWRzLm1lc29zcGhlcmUuaW8vbWFyYXRob24vYXNzZXRzL2ljb24tc2VydmljZS1tYXJhdGhvbi1tZWRpdW0ucG5nIiwgImljb24tc21hbGwiOiAiaHR0cHM6Ly9kb3dubG9hZHMubWVzb3NwaGVyZS5pby9tYXJhdGhvbi9hc3NldHMvaWNvbi1zZXJ2aWNlLW1hcmF0aG9uLXNtYWxsLnBuZyJ9LCAibGljZW5zZXMiOiBbeyJuYW1lIjogIkFwYWNoZSBMaWNlbnNlIFZlcnNpb24gMi4wIiwgInVybCI6ICJodHRwczovL2dpdGh1Yi5jb20vbWVzb3NwaGVyZS9tYXJhdGhvbi9ibG9iL21hc3Rlci9MSUNFTlNFIn1dLCAibWFpbnRhaW5lciI6ICJzdXBwb3J0QG1lc29zcGhlcmUuaW8iLCAibmFtZSI6ICJtYXJhdGhvbiIsICJwb3N0SW5zdGFsbE5vdGVzIjogIk1hcmF0aG9uIERDT1MgU2VydmljZSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgaW5zdGFsbGVkIVxuXG5cdERvY3VtZW50YXRpb246IGh0dHBzOi8vbWVzb3NwaGVyZS5naXRodWIuaW8vbWFyYXRob25cblx0SXNzdWVzOiBodHRwczovZ2l0aHViLmNvbS9tZXNvc3BoZXJlL21hcmF0aG9uL2lzc3Vlc1xuIiwgInBvc3RVbmluc3RhbGxOb3RlcyI6ICJUaGUgTWFyYXRob24gRENPUyBTZXJ2aWNlIGhhcyBiZWVuIHVuaW5zdGFsbGVkIGFuZCB3aWxsIG5vIGxvbmdlciBydW4uXG5QbGVhc2UgZm9sbG93IHRoZSBpbnN0cnVjdGlvbnMgYXQgaHR0cDovL2RvY3MubWVzb3NwaGVyZS5jb20vc2VydmljZXMvbWFyYXRob24vI3VuaW5zdGFsbCB0byBjbGVhbiB1cCBhbnkgcGVyc2lzdGVkIHN0YXRlIiwgInByZUluc3RhbGxOb3RlcyI6ICJXZSByZWNvbW1lbmQgYSBtaW5pbXVtIG9mIG9uZSBub2RlIHdpdGggYXQgbGVhc3QgMiBDUFUncyBhbmQgMUdCIG9mIFJBTSBhdmFpbGFibGUgZm9yIHRoZSBNYXJhdGhvbiBTZXJ2aWNlLiIsICJzY20iOiAiaHR0cHM6Ly9naXRodWIuY29tL21lc29zcGhlcmUvbWFyYXRob24uZ2l0IiwgInRhZ3MiOiBbImluaXQiLCAibG9uZy1ydW5uaW5nIl0sICJ2ZXJzaW9uIjogIjAuMTEuMSJ9", "DCOS_PACKAGE_METADATA": "eyJkZXNjcmlwdGlvbiI6ICJBIGNsdXN0ZXItd2lkZSBpbml0IGFuZCBjb250cm9sIHN5c3RlbSBmb3Igc2VydmljZXMgaW4gY2dyb3VwcyBvciBEb2NrZXIgY29udGFpbmVycy4iLCAiZnJhbWV3b3JrIjogdHJ1ZSwgImltYWdlcyI6IHsiaWNvbi1sYXJnZSI6ICJodHRwczovL2Rvd25sb2Fkcy5tZXNvc3BoZXJlLmlvL21hcmF0aG9uL2Fzc2V0cy9pY29uLXNlcnZpY2UtbWFyYXRob24tbGFyZ2UucG5nIiwgImljb24tbWVkaXVtIjogImh0dHBzOi8vZG93bmxvYWRzLm1lc29zcGhlcmUuaW8vbWFyYXRob24vYXNzZXRzL2ljb24tc2VydmljZS1tYXJhdGhvbi1tZWRpdW0ucG5nIiwgImljb24tc21hbGwiOiAiaHR0cHM6Ly9kb3dubG9hZHMubWVzb3NwaGVyZS5pby9tYXJhdGhvbi9hc3NldHMvaWNvbi1zZXJ2aWNlLW1hcmF0aG9uLXNtYWxsLnBuZyJ9LCAibGljZW5zZXMiOiBbeyJuYW1lIjogIkFwYWNoZSBMaWNlbnNlIFZlcnNpb24gMi4wIiwgInVybCI6ICJodHRwczovL2dpdGh1Yi5jb20vbWVzb3NwaGVyZS9tYXJhdGhvbi9ibG9iL21hc3Rlci9MSUNFTlNFIn1dLCAibWFpbnRhaW5lciI6ICJzdXBwb3J0QG1lc29zcGhlcmUuaW8iLCAibmFtZSI6ICJtYXJhdGhvbiIsICJwb3N0SW5zdGFsbE5vdGVzIjogIk1hcmF0aG9uIERDT1MgU2VydmljZSBoYXMgYmVlbiBzdWNjZXNzZnVsbHkgaW5zdGFsbGVkIVxuXG5cdERvY3VtZW50YXRpb246IGh0dHBzOi8vbWVzb3NwaGVyZS5naXRodWIuaW8vbWFyYXRob25cblx0SXNzdWVzOiBodHRwczovZ2l0aHViLmNvbS9tZXNvc3BoZXJlL21hcmF0aG9uL2lzc3Vlc1xuIiwgInBvc3RVbmluc3RhbGxOb3RlcyI6ICJUaGUgTWFyYXRob24gRENPUyBTZXJ2aWNlIGhhcyBiZWVuIHVuaW5zdGFsbGVkIGFuZCB3aWxsIG5vIGxvbmdlciBydW4uXG5QbGVhc2UgZm9sbG93IHRoZSBpbnN0cnVjdGlvbnMgYXQgaHR0cDovL2RvY3MubWVzb3NwaGVyZS5jb20vc2VydmljZXMvbWFyYXRob24vI3VuaW5zdGFsbCB0byBjbGVhbiB1cCBhbnkgcGVyc2lzdGVkIHN0YXRlIiwgInByZUluc3RhbGxOb3RlcyI6ICJXZSByZWNvbW1lbmQgYSBtaW5pbXVtIG9mIG9uZSBub2RlIHdpdGggYXQgbGVhc3QgMiBDUFUncyBhbmQgMUdCIG9mIFJBTSBhdmFpbGFibGUgZm9yIHRoZSBNYXJhdGhvbiBTZXJ2aWNlLiIsICJzY20iOiAiaHR0cHM6Ly9naXRodWIuY29tL21lc29zcGhlcmUvbWFyYXRob24uZ2l0IiwgInRhZ3MiOiBbImluaXQiLCAibG9uZy1ydW5uaW5nIl0sICJ2ZXJzaW9uIjogIjAuMTEuMSJ9",
"DCOS_PACKAGE_NAME": "marathon", "DCOS_PACKAGE_NAME": "marathon",
"DCOS_PACKAGE_REGISTRY_VERSION": "1.0.0-rc1", "DCOS_PACKAGE_REGISTRY_VERSION": "2.0.0-rc1",
"DCOS_PACKAGE_RELEASE": "6", "DCOS_PACKAGE_RELEASE": "6",
"DCOS_PACKAGE_SOURCE": "https://github.com/mesosphere/universe/archive/cli-test-2.zip", "DCOS_PACKAGE_SOURCE": "https://github.com/mesosphere/universe/archive/cli-test-3.zip",
"DCOS_PACKAGE_VERSION": "0.11.1" "DCOS_PACKAGE_VERSION": "0.11.1"
}, },
"mem": 1024.0, "mem": 1024.0,

View File

@@ -1,6 +1,6 @@
[package] [package]
cache = "tmp/cache" cache = "tmp/cache"
sources = [ "https://github.com/mesosphere/universe/archive/cli-test-2.zip",] sources = [ "https://github.com/mesosphere/universe/archive/cli-test-3.zip",]
[core] [core]
timeout = 5 timeout = 5
dcos_url = "https://dcos.snakeoil.mesosphere.com" dcos_url = "https://dcos.snakeoil.mesosphere.com"

View File

@@ -234,6 +234,13 @@ def add_app(app_path, wait=True):
watch_all_deployments() watch_all_deployments()
def remove_group(group_id):
assert_command(['dcos', 'marathon', 'group', 'remove', group_id])
# Let's make sure that we don't return until the deployment has finished
watch_all_deployments()
def remove_app(app_id): def remove_app(app_id):
""" Remove an app """ Remove an app

View File

@@ -59,7 +59,7 @@ core.ssl_verify=false
core.timeout=5 core.timeout=5
package.cache=tmp/cache package.cache=tmp/cache
package.sources=['https://github.com/mesosphere/universe/archive/\ package.sources=['https://github.com/mesosphere/universe/archive/\
cli-test-2.zip'] cli-test-3.zip']
""" """
assert_command(['dcos', 'config', 'show'], assert_command(['dcos', 'config', 'show'],
stdout=stdout, stdout=stdout,
@@ -157,11 +157,11 @@ def test_append_empty_list(env):
config_set('package.sources', '[]', env) config_set('package.sources', '[]', env)
_append_value( _append_value(
'package.sources', 'package.sources',
'https://github.com/mesosphere/universe/archive/cli-test-2.zip', 'https://github.com/mesosphere/universe/archive/cli-test-3.zip',
env) env)
_get_value( _get_value(
'package.sources', 'package.sources',
['https://github.com/mesosphere/universe/archive/cli-test-2.zip'], ['https://github.com/mesosphere/universe/archive/cli-test-3.zip'],
env) env)
@@ -169,11 +169,11 @@ def test_prepend_empty_list(env):
config_set('package.sources', '[]', env) config_set('package.sources', '[]', env)
_prepend_value( _prepend_value(
'package.sources', 'package.sources',
'https://github.com/mesosphere/universe/archive/cli-test-2.zip', 'https://github.com/mesosphere/universe/archive/cli-test-3.zip',
env) env)
_get_value( _get_value(
'package.sources', 'package.sources',
['https://github.com/mesosphere/universe/archive/cli-test-2.zip'], ['https://github.com/mesosphere/universe/archive/cli-test-3.zip'],
env) env)
@@ -184,7 +184,7 @@ def test_append_list(env):
env) env)
_get_value( _get_value(
'package.sources', 'package.sources',
['https://github.com/mesosphere/universe/archive/cli-test-2.zip', ['https://github.com/mesosphere/universe/archive/cli-test-3.zip',
'https://github.com/mesosphere/universe/archive/version-2.x.zip'], 'https://github.com/mesosphere/universe/archive/version-2.x.zip'],
env) env)
config_unset('package.sources', '1', env) config_unset('package.sources', '1', env)
@@ -198,7 +198,7 @@ def test_prepend_list(env):
_get_value( _get_value(
'package.sources', 'package.sources',
['https://github.com/mesosphere/universe/archive/version-2.x.zip', ['https://github.com/mesosphere/universe/archive/version-2.x.zip',
'https://github.com/mesosphere/universe/archive/cli-test-2.zip'], 'https://github.com/mesosphere/universe/archive/cli-test-3.zip'],
env) env)
config_unset('package.sources', '0', env) config_unset('package.sources', '0', env)
@@ -249,7 +249,7 @@ def test_unset_output(env):
def test_unset_index_output(env): def test_unset_index_output(env):
stdout = ( stdout = (
b"[package.sources]: removed element " b"[package.sources]: removed element "
b"'https://github.com/mesosphere/universe/archive/cli-test-2.zip' " b"'https://github.com/mesosphere/universe/archive/cli-test-3.zip' "
b"at index '0'\n" b"at index '0'\n"
) )
@@ -259,14 +259,14 @@ def test_unset_index_output(env):
_prepend_value( _prepend_value(
'package.sources', 'package.sources',
'https://github.com/mesosphere/universe/archive/cli-test-2.zip', 'https://github.com/mesosphere/universe/archive/cli-test-3.zip',
env) env)
def test_set_whole_list(env): def test_set_whole_list(env):
config_set( config_set(
'package.sources', 'package.sources',
'["https://github.com/mesosphere/universe/archive/cli-test-2.zip"]', '["https://github.com/mesosphere/universe/archive/cli-test-3.zip"]',
env) env)
@@ -293,7 +293,7 @@ def test_unset_list_index(env):
env) env)
_prepend_value( _prepend_value(
'package.sources', 'package.sources',
'https://github.com/mesosphere/universe/archive/cli-test-2.zip', 'https://github.com/mesosphere/universe/archive/cli-test-3.zip',
env) env)
@@ -337,7 +337,7 @@ def test_validate(env):
def test_validation_error(env): def test_validation_error(env):
source = ["https://github.com/mesosphere/universe/archive/cli-test-2.zip"] source = ["https://github.com/mesosphere/universe/archive/cli-test-3.zip"]
config_unset('package.sources', None, env) config_unset('package.sources', None, env)
stdout = b"Error: missing required property 'sources'.\n" stdout = b"Error: missing required property 'sources'.\n"
@@ -401,12 +401,12 @@ def test_url_validation(env):
def test_append_url_validation(env): def test_append_url_validation(env):
default_value = ('["https://github.com/mesosphere/universe/archive/' default_value = ('["https://github.com/mesosphere/universe/archive/'
'cli-test-2.zip"]') 'cli-test-3.zip"]')
config_set('package.sources', '[]', env) config_set('package.sources', '[]', env)
_append_value( _append_value(
'package.sources', 'package.sources',
'https://github.com/mesosphere/universe/archive/cli-test-2.zip', 'https://github.com/mesosphere/universe/archive/cli-test-3.zip',
env) env)
_append_value( _append_value(
'package.sources', 'package.sources',
@@ -429,12 +429,12 @@ def test_append_url_validation(env):
def test_prepend_url_validation(env): def test_prepend_url_validation(env):
default_value = ('["https://github.com/mesosphere/universe/archive/' default_value = ('["https://github.com/mesosphere/universe/archive/'
'cli-test-2.zip"]') 'cli-test-3.zip"]')
config_set('package.sources', '[]', env) config_set('package.sources', '[]', env)
_prepend_value( _prepend_value(
'package.sources', 'package.sources',
'https://github.com/mesosphere/universe/archive/cli-test-2.zip', 'https://github.com/mesosphere/universe/archive/cli-test-3.zip',
env) env)
_prepend_value( _prepend_value(
'package.sources', 'package.sources',

View File

@@ -1,15 +1,15 @@
import contextlib import contextlib
import json import json
from .common import (assert_command, assert_lines, exec_command, show_app, from .common import (assert_command, assert_lines, exec_command, remove_group,
watch_all_deployments) show_app, watch_all_deployments)
GOOD_GROUP = 'tests/data/marathon/groups/good.json' GOOD_GROUP = 'tests/data/marathon/groups/good.json'
def test_deploy_group(): def test_deploy_group():
_deploy_group(GOOD_GROUP) _deploy_group(GOOD_GROUP)
_remove_group('test-group') remove_group('test-group')
def test_group_list_table(): def test_group_list_table():
@@ -19,12 +19,12 @@ def test_group_list_table():
def test_validate_complicated_group_and_app(): def test_validate_complicated_group_and_app():
_deploy_group('tests/data/marathon/groups/complicated.json') _deploy_group('tests/data/marathon/groups/complicated.json')
_remove_group('test-group') remove_group('test-group')
def test_optional_deploy_group(): def test_optional_deploy_group():
_deploy_group(GOOD_GROUP, False) _deploy_group(GOOD_GROUP, False)
_remove_group('test-group') remove_group('test-group')
def test_add_existing_group(): def test_add_existing_group():
@@ -108,7 +108,7 @@ def test_scale_group():
res = json.loads(stdout.decode('utf-8')) res = json.loads(stdout.decode('utf-8'))
assert res['groups'][0]['apps'][0]['instances'] == 2 assert res['groups'][0]['apps'][0]['instances'] == 2
_remove_group('scale-group') remove_group('scale-group')
def test_scale_group_not_exist(): def test_scale_group_not_exist():
@@ -122,7 +122,7 @@ def test_scale_group_not_exist():
res = json.loads(stdout.decode('utf-8')) res = json.loads(stdout.decode('utf-8'))
assert len(res['apps']) == 0 assert len(res['apps']) == 0
_remove_group('scale-group') remove_group('scale-group')
def test_scale_group_when_scale_factor_negative(): def test_scale_group_when_scale_factor_negative():
@@ -132,7 +132,7 @@ def test_scale_group_when_scale_factor_negative():
assert b'Command not recognized' in stdout assert b'Command not recognized' in stdout
assert returncode == 1 assert returncode == 1
watch_all_deployments() watch_all_deployments()
_remove_group('scale-group') remove_group('scale-group')
def test_scale_group_when_scale_factor_not_float(): def test_scale_group_when_scale_factor_not_float():
@@ -142,14 +142,7 @@ def test_scale_group_when_scale_factor_not_float():
assert stderr == b'Error parsing string as float\n' assert stderr == b'Error parsing string as float\n'
assert returncode == 1 assert returncode == 1
watch_all_deployments() watch_all_deployments()
_remove_group('scale-group') remove_group('scale-group')
def _remove_group(group_id):
assert_command(['dcos', 'marathon', 'group', 'remove', group_id])
# Let's make sure that we don't return until the deployment has finished
watch_all_deployments()
def _deploy_group(file_path, stdin=True): def _deploy_group(file_path, stdin=True):
@@ -212,4 +205,4 @@ def _group(path, group_id):
try: try:
yield yield
finally: finally:
_remove_group(group_id) remove_group(group_id)

View File

@@ -51,7 +51,7 @@ def _chronos_description(app_ids):
"maintainer": "support@mesosphere.io", "maintainer": "support@mesosphere.io",
"name": "chronos", "name": "chronos",
"packageSource": "https://github.com/mesosphere/universe/archive/\ "packageSource": "https://github.com/mesosphere/universe/archive/\
cli-test-2.zip", cli-test-3.zip",
"postInstallNotes": "Chronos DCOS Service has been successfully " "postInstallNotes": "Chronos DCOS Service has been successfully "
"installed!\n\n\tDocumentation: http://mesos." "installed!\n\n\tDocumentation: http://mesos."
"github.io/chronos\n\tIssues: https://github.com/" "github.io/chronos\n\tIssues: https://github.com/"
@@ -97,8 +97,8 @@ def test_version():
def test_sources_list(): def test_sources_list():
stdout = b"1a9bef0c579dd0692af9c6ba22c3ec910fb03efc " + \ stdout = b"fd40db7f075490e0c92ec6fcd62ec1caa361b313 " + \
b"https://github.com/mesosphere/universe/archive/cli-test-2.zip\n" b"https://github.com/mesosphere/universe/archive/cli-test-3.zip\n"
assert_command(['dcos', 'package', 'sources'], assert_command(['dcos', 'package', 'sources'],
stdout=stdout) stdout=stdout)
@@ -324,12 +324,12 @@ b3NwaGVyZS9kY29zLWhlbGxvd29ybGQifQ=="""
CJdfQ==""" CJdfQ=="""
expected_source = b"""https://github.com/mesosphere/universe/archive/\ expected_source = b"""https://github.com/mesosphere/universe/archive/\
cli-test-2.zip""" cli-test-3.zip"""
expected_labels = { expected_labels = {
'DCOS_PACKAGE_METADATA': expected_metadata, 'DCOS_PACKAGE_METADATA': expected_metadata,
'DCOS_PACKAGE_COMMAND': expected_command, 'DCOS_PACKAGE_COMMAND': expected_command,
'DCOS_PACKAGE_REGISTRY_VERSION': b'1.0.0-rc1', 'DCOS_PACKAGE_REGISTRY_VERSION': b'2.0.0-rc1',
'DCOS_PACKAGE_NAME': b'helloworld', 'DCOS_PACKAGE_NAME': b'helloworld',
'DCOS_PACKAGE_VERSION': b'0.1.0', 'DCOS_PACKAGE_VERSION': b'0.1.0',
'DCOS_PACKAGE_SOURCE': expected_source, 'DCOS_PACKAGE_SOURCE': expected_source,
@@ -434,7 +434,7 @@ def test_uninstall_cli():
"maintainer": "support@mesosphere.io", "maintainer": "support@mesosphere.io",
"name": "helloworld", "name": "helloworld",
"packageSource": "https://github.com/mesosphere/universe/archive/\ "packageSource": "https://github.com/mesosphere/universe/archive/\
cli-test-2.zip", cli-test-3.zip",
"postInstallNotes": "A sample post-installation message", "postInstallNotes": "A sample post-installation message",
"preInstallNotes": "A sample pre-installation message", "preInstallNotes": "A sample pre-installation message",
"releaseVersion": "0", "releaseVersion": "0",
@@ -552,7 +552,7 @@ def test_list_cli():
"maintainer": "support@mesosphere.io", "maintainer": "support@mesosphere.io",
"name": "helloworld", "name": "helloworld",
"packageSource": "https://github.com/mesosphere/universe/archive/\ "packageSource": "https://github.com/mesosphere/universe/archive/\
cli-test-2.zip", cli-test-3.zip",
"postInstallNotes": "A sample post-installation message", "postInstallNotes": "A sample post-installation message",
"preInstallNotes": "A sample pre-installation message", "preInstallNotes": "A sample pre-installation message",
"releaseVersion": "0", "releaseVersion": "0",
@@ -586,7 +586,7 @@ cli-test-2.zip",
"maintainer": "support@mesosphere.io", "maintainer": "support@mesosphere.io",
"name": "helloworld", "name": "helloworld",
"packageSource": "https://github.com/mesosphere/universe/archive/\ "packageSource": "https://github.com/mesosphere/universe/archive/\
cli-test-2.zip", cli-test-3.zip",
"postInstallNotes": "A sample post-installation message", "postInstallNotes": "A sample post-installation message",
"preInstallNotes": "A sample pre-installation message", "preInstallNotes": "A sample pre-installation message",
"releaseVersion": "0", "releaseVersion": "0",
@@ -661,7 +661,7 @@ def test_search():
assert returncode == 0 assert returncode == 0
assert b'"packages": []' in stdout assert b'"packages": []' in stdout
assert b'"source": "https://github.com/mesosphere/universe/archive/\ assert b'"source": "https://github.com/mesosphere/universe/archive/\
cli-test-2.zip"' in stdout cli-test-3.zip"' in stdout
assert stderr == b'' assert stderr == b''
returncode, stdout, stderr = exec_command( returncode, stdout, stderr = exec_command(

View File

@@ -87,7 +87,7 @@ def _request(method,
logger.info('Received HTTP response [%r]: %r', logger.info('Received HTTP response [%r]: %r',
response.status_code, response.status_code,
response.text) response.headers)
return response return response

View File

@@ -242,6 +242,7 @@ def uninstall_app(app_name, remove_all, app_id, init_client, dcos_client):
package_json = _decode_and_add_context( package_json = _decode_and_add_context(
app['id'], app['id'],
app.get('labels', {})) app.get('labels', {}))
# First, remove the app from Marathon # First, remove the app from Marathon
init_client.remove_app(app['id'], force=True) init_client.remove_app(app['id'], force=True)
@@ -569,7 +570,7 @@ def _extract_default_values(config_schema):
return defaults return defaults
def _merge_options(first, second): def _merge_options(first, second, overrides=True):
"""Merges the :code:`second` dictionary into the :code:`first` dictionary. """Merges the :code:`second` dictionary into the :code:`first` dictionary.
If both dictionaries have the same key and both values are dictionaries If both dictionaries have the same key and both values are dictionaries
then it recursively merges those two dictionaries. then it recursively merges those two dictionaries.
@@ -578,6 +579,8 @@ def _merge_options(first, second):
:type first: dict :type first: dict
:param second: second dictionary :param second: second dictionary
:type second: dict :type second: dict
:param overrides: allow second to override first if both have same key
:type overrides: bool
:returns: merged dictionary :returns: merged dictionary
:rtype: dict :rtype: dict
""" """
@@ -590,6 +593,10 @@ def _merge_options(first, second):
if (isinstance(first_value, collections.Mapping) and if (isinstance(first_value, collections.Mapping) and
isinstance(second_value, collections.Mapping)): isinstance(second_value, collections.Mapping)):
result[key] = _merge_options(first_value, second_value) result[key] = _merge_options(first_value, second_value)
elif not overrides and first_value != second_value:
raise DCOSException(
"Trying to override package.json's key {} to {}".format(
key, second_value))
else: else:
result[key] = second_value result[key] = second_value
else: else:
@@ -761,7 +768,7 @@ def update_sources(config, validate=False):
# TODO(jsancio): move this to the validation when it is forced # TODO(jsancio): move this to the validation when it is forced
Registry(source, stage_dir).check_version( Registry(source, stage_dir).check_version(
LooseVersion('1.0'), LooseVersion('1.0'),
LooseVersion('2.0')) LooseVersion('3.0'))
# validate content # validate content
if validate: if validate:
@@ -1162,7 +1169,7 @@ class Registry():
raise DCOSException('Unable to parse [{}]'.format(index_path)) raise DCOSException('Unable to parse [{}]'.format(index_path))
def get_index(self): def get_index(self):
"""Retuprns the index of packages in this registry. """Returns the index of packages in this registry.
:rtype: dict :rtype: dict
""" """
@@ -1270,7 +1277,7 @@ class Package():
logger.info('Generated default options: %r', default_options) logger.info('Generated default options: %r', default_options)
# Merge option overrides # Merge option overrides, second argument takes precedence
options = _merge_options(default_options, user_options) options = _merge_options(default_options, user_options)
logger.info('Merged options: %r', options) logger.info('Merged options: %r', options)
@@ -1321,6 +1328,16 @@ class Package():
return self.has_definition(revision, 'command.json') return self.has_definition(revision, 'command.json')
def _has_resource_definition(self, revision):
"""Returns true if the package defines a resource; false otherwise.
:param revision: package revision
:type revision: str
:rtype: bool
"""
return self.has_definition(revision, 'resource.json')
def has_marathon_definition(self, revision): def has_marathon_definition(self, revision):
"""Returns true if the package defines a Marathon json. false otherwise. """Returns true if the package defines a Marathon json. false otherwise.
@@ -1331,6 +1348,32 @@ class Package():
return self.has_definition(revision, 'marathon.json') return self.has_definition(revision, 'marathon.json')
def has_marathon_mustache_definition(self, revision):
"""Returns true if the package defines a Marathon.json.mustache false
otherwise.
:param revision: package revision
:type revision: str
:rtype: bool
"""
return self.has_definition(revision, 'marathon.json.mustache')
def _get_marathon_json_file(self, revision):
"""Returns the file name of Marathon json
:param revision: package revision
:type revision: str
:returns: Marathon file name
:rtype: str
"""
if self.has_marathon_definition(revision):
return 'marathon.json'
elif self.has_marathon_mustache_definition(revision):
return 'marathon.json.mustache'
else:
raise DCOSException("Missing Marathon json definition of package")
def config_json(self, revision): def config_json(self, revision):
"""Returns the JSON content of the config.json file. """Returns the JSON content of the config.json file.
@@ -1353,6 +1396,17 @@ class Package():
return self._json(revision, 'package.json') return self._json(revision, 'package.json')
def _resource_json(self, revision):
"""Returns the JSON content of the resource.json file.
:param revision: the package revision
:type revision: str
:returns: Package data
:rtype: dict
"""
return self._json(revision, 'resource.json')
def marathon_json(self, revision, options): def marathon_json(self, revision, options):
"""Returns the JSON content of the marathon.json template, after """Returns the JSON content of the marathon.json template, after
rendering it with options. rendering it with options.
@@ -1364,8 +1418,13 @@ class Package():
:rtype: dict :rtype: dict
""" """
marathon_file = self._get_marathon_json_file(revision)
if self.has_marathon_mustache_definition(revision) and \
self._has_resource_definition(revision):
resources = {"resource": self._resource_json(revision)}
options = _merge_options(options, resources, False)
init_desc = self._render_template( init_desc = self._render_template(
'marathon.json', marathon_file,
revision, revision,
options) options)
@@ -1404,7 +1463,7 @@ class Package():
:returns: raw data from marathon.json :returns: raw data from marathon.json
:rtype: str :rtype: str
""" """
return self._data(revision, 'marathon.json') return self._data(revision, self._get_marathon_json_file(revision))
def command_template(self, revision): def command_template(self, revision):
""" Returns raw data from command.json """ Returns raw data from command.json

View File

@@ -31,11 +31,20 @@ MergeData = collections.namedtuple(
first={'b': {'a': 'a'}}, first={'b': {'a': 'a'}},
second={'b': {'c': 'c'}}, second={'b': {'c': 'c'}},
expected={'b': {'c': 'c', 'a': 'a'}}), expected={'b': {'c': 'c', 'a': 'a'}}),
MergeData(
first={'b': 'c'},
second={'b': 'd'},
expected={'b': 'd'}),
]) ])
def merge_data(request): def merge_data(request):
return request.param return request.param
def test_options_merge_wont_override():
with pytest.raises(DCOSException):
package._merge_options({'b': 'c'}, {'b': 'd'}, False)
def test_option_merge(merge_data): def test_option_merge(merge_data):
assert merge_data.expected == package._merge_options( assert merge_data.expected == package._merge_options(
merge_data.first, merge_data.first,