-
Notifications
You must be signed in to change notification settings - Fork 116
Implement package build command #808
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Minor changes.
Can you please add example outputs from using this new command in the comments.
cli/dcoscli/data/help/package.txt
Outdated
|
||
Commands: | ||
bundle | ||
Bundle a package for dcos consumption. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would change this to "Bundle a package to install to DC/OS or share with Universe."
"description": "[Deprecated v3.x] An array of strings representing of the requirements file to use for installing the subcommand for Pip. Each item is interpreted as a line in the requirements file." | ||
} | ||
} | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to follow up on this but I would like to get rid of this. It will be hard to make packages self-contain if we support this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, @tamarrow what do you think about get rid of this? This means that we can never generate DC/OS Package that are have a Python CLI.
cli/dcoscli/package/main.py
Outdated
'{}-{}-{}.dcos'.format( | ||
package_resolved['name'], | ||
package_resolved['version'], | ||
sha256_file(temp_file.name))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We changed the algorithm to use MD5 so that the hash and filename is smaller.
cli/dcoscli/package/main.py
Outdated
|
||
|
||
def _resolve_local_references(package_json, package_directory): | ||
""" Resolves all local refereces in package json |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need a newline after this line. Our doc generator needs this.
cli/dcoscli/package/main.py
Outdated
""" | ||
bundle_schema_path = "data/schemas/bundle-schema.json" | ||
bundle_schema = util.load_jsons( | ||
pkg_resources.resource_string("dcoscli", bundle_schema_path).decode("utf-8")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of loading it from disk, I would pass the bundle_schema
in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean?
Where do I pass it in from? How do I get it to begin with?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a parameter to this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example you already constructed this value from the function that calls this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohhhh, I see what you mean.
cli/dcoscli/package/main.py
Outdated
:rtype: bool | ||
""" | ||
local_ref_pattern = re.compile("^@") | ||
return isinstance(item, str) and local_ref_pattern.match(item) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need to use regex. You just need to know that the string to start with @
.
|
||
# check that the output is correct | ||
assert return_code == 1 | ||
assert stderr == expected_error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would also assert that no files where created in the temp folder.
def test_package_missing_references(): | ||
_failure_test("tests/data/bundle/package_missing_references.json", | ||
b"Error opening file [/Users/mesosphere" | ||
b"/Work/dcos-cli/cli/tests/data/bundle/marathon.json]: No such file or directory\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Full path won't work in other environment like the CI.
_failure_test("tests/data/bundle/package_reference_does_not_match_schema.json", | ||
b"Error validating package: " | ||
b"[/Users/mesosphere/Work/dcos-cli/cli/tests/data/bundle/resource-bad.json] " | ||
b"does not conform to the specified schema\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Full path won't work in other environment like the CI.
with open(filename, 'rb') as f: | ||
for chunk in iter(lambda: f.read(4096), b''): | ||
hasher.update(chunk) | ||
return hasher.hexdigest() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We change the format to use MD5 because it is a smaller string in the filename.
@jsancio Which comments. The Github comments or the comments in the code? |
GitHub PR comment. For new commands it is nice for the reviewer to be able to see how the command works by seeing some examples. |
@cruhland Was this closed by accident? |
"type": "boolean", | ||
"description": "Flag indicating if the package is selected in search results", | ||
"default": false | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
selected
is not allowed.
"type": "boolean", | ||
"description": "Flag indicating if the package is selected in search results", | ||
"default": false | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
selected
is not allowed.
"type": "integer", | ||
"description": "Corresponds to the revision index from the universe directory structure", | ||
"minimum": 0 | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should remove this property from the bundle-schema
and the package-schema
. This is controlled by Universe and Cosmos.
"type": "boolean", | ||
"description": "Flag indicating if the package is selected in search results", | ||
"default": false | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
selected
is not allowed.
"type": "boolean", | ||
"description": "Flag indicating if the package is selected in search results", | ||
"default": false | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
selected
is not allowed.
"type": "integer", | ||
"description": "Corresponds to the revision index from the universe directory structure", | ||
"minimum": 0 | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should remove this property from the bundle-schema
and the package-schema
. This is controlled by Universe and Cosmos.
"packagingVersion", | ||
"name", | ||
"version", | ||
"releaseVersion", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should remove this property from the bundle-schema
and the package-schema
. This is controlled by Universe and Cosmos.
"type": "integer", | ||
"description": "Corresponds to the revision index from the universe directory structure", | ||
"minimum": 0 | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should remove this property from the bundle-schema
and the package-schema
. This is controlled by Universe and Cosmos.
"type": "integer", | ||
"description": "Corresponds to the revision index from the universe directory structure", | ||
"minimum": 0 | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should remove this property from the bundle-schema
and the package-schema
. This is controlled by Universe and Cosmos.
"packagingVersion", | ||
"name", | ||
"version", | ||
"releaseVersion", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should remove this property from the bundle-schema
and the package-schema
. This is controlled by Universe and Cosmos.
"packagingVersion": "3.0", | ||
"name": "bitbucket", | ||
"version": "4.5", | ||
"releaseVersion": 3, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should remove this property from the bundle-schema
and the package-schema
. This is controlled by Universe and Cosmos.
"packagingVersion": "3.0", | ||
"name": "bitbucket", | ||
"version": "4.5", | ||
"releaseVersion": 3, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should remove this property from the bundle-schema
and the package-schema
. This is controlled by Universe and Cosmos.
"packagingVersion": "3.0", | ||
"name": "bitbucket", | ||
"version": "4.5", | ||
"releaseVersion": 3, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should remove this property from the bundle-schema
and the package-schema
. This is controlled by Universe and Cosmos.
"packagingVersion": "3.0", | ||
"name": "bitbucket", | ||
"version": "4.5", | ||
"releaseVersion": 3, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should remove this property from the bundle-schema
and the package-schema
. This is controlled by Universe and Cosmos.
"packagingVersion": "3.0", | ||
"name": "bitbucket", | ||
"version": "4.5", | ||
"releaseVersion": 3, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should remove this property from the bundle-schema
and the package-schema
. This is controlled by Universe and Cosmos.
cli/dcoscli/package/main.py
Outdated
' specified schema'.format(location)) | ||
|
||
|
||
def _replace_marathon(bundle_schema, package_directory, package_json): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing pydoc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the _replace_X
methods are all very similar. lets use a shared method and call it for each different file or "ref"
cli/tests/data/dcos.toml
Outdated
@@ -1,5 +1,5 @@ | |||
[core] | |||
timeout = 5 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be reverted
cli/tests/data/help/package.txt
Outdated
|
||
Positional Arguments: | ||
<package-json> | ||
Path to the package json of the project. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is 'package-json'? Is this package.json
in universe or package manifest? We should link to a schema ref.
|
||
install_requires=[ | ||
'jsonschema==2.4', # pin the exact version, jsonschema 2.5 broke py3 | ||
'jsonschema>=2.5', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did we verify this on 2.7?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@larioj ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tamarrow working on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tamarrow Jose and I verified that it works.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
dcos/util.py
Outdated
|
||
|
||
def hash_file(filename): | ||
"""Calculates the sha256 of a file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dcos.subcommand
has a _hashfile
method for sha256. Looks like this is md5, we should name the function as such
|
||
|
||
def test_package_resource_only_reference(): | ||
_success_test("tests/data/bundle/package_resource_only_reference.json", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the data files for the tests are quite long. we should use simpler examples (only required fields) for easier debugging when a test fails
Note that we changed jsonschema version because we run into this bug: python-jsonschema/jsonschema#201 |
cli/dcoscli/package/main.py
Outdated
# get the path to the output directory | ||
if output_directory is None: | ||
package_json_dir = os.path.dirname(package_json_path) | ||
output_directory = os.path.join(package_json_dir, "target/") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: the trailing slash in target/
shouldn't be needed.
cli/dcoscli/package/main.py
Outdated
|
||
# create the directory if it does not exist | ||
if not (os.path.exists(output_directory)): | ||
os.makedirs(output_directory) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of checking for existence, just use the exist_ok
parameter:
# ensure the directory exists
os.makedirs(output_directory, exist_ok=True)
This avoids a race condition in the current code: if the directory is created by another process after the call to exists()
returns, then makedirs()
will raise an exception.
Added a test that will check for failure when references are formatted incorrectly
File paths have \ rather than /
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great @larioj. Some minor comments. 🎉
cli/dcoscli/data/help/package.txt
Outdated
Path to a JSON file that contains customized package installation options. | ||
--output-directory=<output-directory> | ||
Path to the directory where the data should be stored. | ||
Defaults to target/ underneath the directory of the DC/OS Package Build Definition. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@larioj What do you think of "... the directory of the file" instead of "... the directory of the DC/OS ..."?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
target is very scala-y. dcos node diagnostics
defaults to cwd if none specified. i would do the same here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tamarrow Can you please talk to @BenWhitehead regarding the target
directory and let us know what you guys decide?
@larioj Sounds good 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:( I'll still make my vote against it. It's not great that we are inconsistent with where we store files outputted by the CLI.
@@ -0,0 +1,472 @@ | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's name this file "metadata-schema.json"
"description": "[Deprecated v3.x] An array of strings representing of the requirements file to use for installing the subcommand for Pip. Each item is interpreted as a line in the requirements file." | ||
} | ||
} | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, @tamarrow what do you think about get rid of this? This means that we can never generate DC/OS Package that are have a Python CLI.
cli/dcoscli/package/main.py
Outdated
build_definition_resolved = build_definition_raw | ||
|
||
# validate resolved build definition | ||
package_schema_path = "data/schemas/package-schema.json" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use metadata-schema.json
instead. Would need to change all of the related variable names.
cli/dcoscli/package/main.py
Outdated
manifest = json.dumps(manifest_json, indent=2).encode() | ||
zip_file.writestr("manifest.json", manifest) | ||
|
||
try: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain why we are doing this outside of the ContextManager
for temp_file
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jsancio In windows, I can't open the file twice. I tried passing in the opened file to the hash function, but that was giving me incorrect hashes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@larioj and I talked offline. He is working on a solution.
@jsancio we can't get rid of that until spark cli is a binary :/ |
cli/dcoscli/package/main.py
Outdated
:type build_schema: dict | ||
""" | ||
ref = "marathon" | ||
tp = "v2AppMustacheTemplate" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is tp
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tamarrow tp stands for template, as in v2AppMustancheTemplate. It's just there so that I don't have to type long names.
What is it is { 'marathon': { 'v2AppMustacheTemplate': 'euhantoeuhsnaoh' }}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets use template
.
cli/dcoscli/package/main.py
Outdated
|
||
errs = util.validate_json(build_definition, build_schema) | ||
if errs: | ||
raise DCOSException('Error validating package: ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this message is used many times in this file. can we have a custom bundle error similarly to how we have a custom marathon error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
@jsancio when we merge we should mention the jsonschema version change so we can put it in the release notes :) |
* updated jsonschema to version 2.5.1
This PR is part of the new packaging workflow that is currently in development. Specifically this is to satisfy milestone 1 of the packaging flow. See document https://docs.google.com/document/d/1VEx2O28Aiiv-JgIBrdoWhD3gTAYfbz0D4JLUOhnwdPY/edit?usp=sharing for a more complete discussion of the new flow.
A quick rundown of what this PR will add to the CLI:
The CLI will resolve any local references found in build-definition.json to create the bundle.