cloudfoundry / python-buildpack

Cloud Foundry buildpack for the Python Language
http://docs.cloudfoundry.org/buildpacks/
Apache License 2.0
121 stars 279 forks source link

Running bash scripts in deployment environment before buildpack? (.profile.d not working) #95

Closed ewmiller closed 6 years ago

ewmiller commented 6 years ago

Summary

Is there a way to run bash scripts on a deployment environment before the buildpack is executed and pip install is called? I am aware of the .profile.d functionality but it seems like those scripts are executed after pip install but before the app itself is started. I need to configure my environment before pip install because of an error I'm having with a specific dependency. Explanation follows:

Required Info

What version of Cloud Foundry and CF CLI are you using? (i.e. What is the output of running cf curl /v2/info && cf version?

{
   "name": "",
   "build": "",
   "support": "https://support.pivotal.io",
   "version": 0,
   "description": "",
   "min_cli_version": "6.23.0",
   "min_recommended_cli_version": "6.23.0",
   "api_version": "2.82.0",
...
}
cf.exe version 6.34.1+bbdf81482.2018-01-17

What version of the buildpack you are using? python buildpack version 13

If you were attempting to accomplish a task, what was it you were attempting to do? Deploy my application with vendored dependencies to a deployment environment which is behind a firewall (and thus can't access PyPi, so it needs the vendoring to work).

What did you expect to happen? I expected the application to install the vendored dependencies successfully and start.

What was the actual behavior? The app failed to deploy because one of its dependencies tried to reach out to PyPi anyway. The library in question, jsonschema, has a setup-time dependency of vcversioner. Unfortunately, the pip install --download vendor -r requirements.txt --no-binary :all: command does not work, because jsonschema has vcversioner as a dependency only in its setup.py script; it is not an install-time dependency. Thus, it does not download and vendor vcversioner like it's supposed to; it tries to pull it in at setup time, after the vendoring has already taken place.

In addition, requiring vcversioner explicitly during pip install seems to still not work. jsonschema's setup.py script uses easy_install instead of pip, and apparently even if vcversioner has been vendored by pip, easy_install still tries to pull it down from PyPi. This issue is documented here: https://github.com/Julian/jsonschema/issues/276

Potential Fix?

The fix would be to include a file in the home directory called ~/.pydistutils.cfg which tells easy_install to look for my company's internal python repository instead of calling out to PyPi (this is documented here). I have a bash script that can accomplish this; unfortunately I don't know how to run the script before the buildpack tries to install the python dependencies.

So to summarize, I'm just wondering if there's a way to run a bash script in the deployment environment before the python buildpack tries to perform pip install. I've tried including said script in the .profile.d/ directory in the root of my application, but it seems from the logs that the script never gets called.

Reproduce the Issue

To reproduce the issue, deploy a python app that has jsonschema listed in its requirements.txt to an environment which is cut off from the internet, following the PCF docs for vendoring dependencies.

Logs

Here is some log output of the error in question:

18-Jan-2018 12:48:11    2018-01-18T12:48.12-0500 [STG/0]      OUT        Collecting jsonschema>=2.5.1 (from flasgger->-r requirements.txt (line 24))
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT            Complete output from command python setup.py egg_info:
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT            Download error on https://pypi.python.org/simple/vcversioner/: [Errno -2] Name or service not known -- Some packages may not be found!
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT            Couldn't find index page for 'vcversioner' (maybe misspelled?)
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT                vcversioner={"version_module_paths" : ["jsonschema/_version.py"]},
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT              File "/tmp/contents733615508/deps/0/python/lib/python3.6/distutils/core.py", line 108, in setup
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT            No local packages or working download links found for vcversioner>=2.16.0.0
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT                _setup_distribution = dist = klass(attrs)
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT            Download error on https://pypi.python.org/simple/: [Errno -2] Name or service not known -- Some packages may not be found!
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT            Traceback (most recent call last):
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT              File "<string>", line 1, in <module>
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT              File "/tmp/pip-build-agv13y01/jsonschema/setup.py", line 42, in <module>
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT              File "/tmp/contents733615508/deps/0/python/lib/python3.6/site-packages/setuptools-32.1.0-py3.6.egg/setuptools/dist.py", line 316, in __init__
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT              File "/tmp/contents733615508/deps/0/python/lib/python3.6/site-packages/setuptools-32.1.0-py3.6.egg/pkg_resources/__init__.py", line 846, in resolve
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT              File "/tmp/contents733615508/deps/0/python/lib/python3.6/site-packages/setuptools-32.1.0-py3.6.egg/setuptools/dist.py", line 371, in fetch_build_eggs
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT              File "/tmp/contents733615508/deps/0/python/lib/python3.6/site-packages/setuptools-32.1.0-py3.6.egg/pkg_resources/__init__.py", line 1118, in best_match
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT              File "/tmp/contents733615508/deps/0/python/lib/python3.6/site-packages/setuptools-32.1.0-py3.6.egg/pkg_resources/__init__.py", line 1130, in obtain
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT              File "/tmp/contents733615508/deps/0/python/lib/python3.6/site-packages/setuptools-32.1.0-py3.6.egg/setuptools/dist.py", line 439, in fetch_build_egg
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT              File "/tmp/contents733615508/deps/0/python/lib/python3.6/site-packages/setuptools-32.1.0-py3.6.egg/setuptools/command/easy_install.py", line 659, in easy_install
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT            distutils.errors.DistutilsError: Could not find suitable distribution for Requirement.parse('vcversioner>=2.16.0.0')
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT            ----------------------------------------
18-Jan-2018 12:48:37    2018-01-18T12:48.38-0500 [STG/0]      OUT            
18-Jan-2018 12:48:38    2018-01-18T12:48.39-0500 [STG/0]      ERR Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-agv13y01/jsonschema/
18-Jan-2018 12:48:38    2018-01-18T12:48.39-0500 [STG/0]      ERR Failed to compile droplet: Failed to run all supply scripts: exit status 1
18-Jan-2018 12:48:38    2018-01-18T12:48.39-0500 [STG/0]      ERR Staging failed: STG: Exited with status 223
18-Jan-2018 12:48:38    2018-01-18T12:48.39-0500 [STG/0]      OUT Stopping instance 08727baf-e88e-49ac-a941-3a1756c54d32
18-Jan-2018 12:48:38    2018-01-18T12:48.39-0500 [STG/0]      OUT Exit status 223
18-Jan-2018 12:48:38    2018-01-18T12:48.39-0500 [STG/0]      OUT Destroying container
18-Jan-2018 12:48:39    2018-01-18T12:48.39-0500 [STG/0]      OUT Successfully destroyed container
18-Jan-2018 12:48:47    Starting application <app name>... FAILED: Application <app name> failed during staging
18-Jan-2018 12:48:47    Unable to push app: Application <app name> failed during staging
18-Jan-2018 12:48:47    Finished task 'Cloud Foundry Push' with result: Error

Please confirm where necessary:

cf-gitbot commented 6 years ago

We have created an issue in Pivotal Tracker to manage this:

https://www.pivotaltracker.com/story/show/154449468

The labels on this github issue will be updated when the story is started.

dgodd commented 6 years ago

From your linked documentation, it appears you could also create file setup.cfg in your app. Does that work?

ewmiller commented 6 years ago

I tried it and was unsuccessful. I saw the same thing and got my hopes up but then further down in the documentation it says this:

Notice that easy_install will use the setup.cfg from the current working directory only if it was triggered from setup.py through the install_requires option. The standalone command will not use that file.

That makes me think the local setup.cfg doesn't actually work most of the time. Especially in this case since jsonschema is using setup_requires instead of install_requires which is what the docs said. It's pretty confusing.

dgodd commented 6 years ago

@ewmiller if you can post a sample app which exhibits the behavior (and works on your machine) I'll try and get it going.

sclevine commented 6 years ago

Merging thread into #86.