Skip to content
This repository has been archived by the owner on Sep 28, 2020. It is now read-only.

WIP: Build master with habitat #453

Open
wants to merge 22 commits into
base: master
Choose a base branch
from

Conversation

themightychris
Copy link

@themightychris themightychris commented Jul 28, 2017

On any Linux machine or Mac w/ Docker installed:

First-time setup

# install habitat
curl https://raw.githubusercontent.com/habitat-sh/habitat/master/components/hab/install.sh | sudo bash

# initialize habitat configuration
hab cli setup

# clone habitat branch of DistrictBuilder
git clone -b habitat [email protected]:themightychris/DistrictBuilder.git

# change into repository
cd DistrictBuilder

Enter studio and build package

# erase any existing studio to start completely fresh
hab studio rm

# enter habitat studio (a cleanroom for building with only explicit dependencies)
hab studio enter

# execute build. Type "return" to continue when debugger pauses at attach points
build

Setup app within studio after a successful build or install

# activate virtualenv within built package
source "`hab pkg path $HAB_ORIGIN/DistrictBuilder`/bin/activate"

# create sample config file
cp /src/docs/config.dist.xml /src/docs/config.xml

# setup app
cd "`hab pkg path $HAB_ORIGIN/DistrictBuilder`/django/publicmapping"
python setup.py /src/docs/config.{xsd,xml}

@themightychris themightychris changed the title Build with habitat WIP: Build with habitat Jul 28, 2017
@themightychris
Copy link
Author

pip install -r requirements.txt is currently failing, I've made some progress in ae9d561but I'm not sure to what extent it's app configuration issues to fix at the python/django layer or environmental issues to be fixed at the habitat level ye

@mcdisc
Copy link

mcdisc commented Jul 28, 2017 via email

@themightychris
Copy link
Author

Thanks @mcdisc ! I'm aware of the efforts on that front, I was hoping to help get the old version bare-bones deployable on current systems. I'm pretty familiar with tools to provide an exact environment to the application, even with old/unsupported dependencies being needed. I'm not too familiar with the python/django stack though so I'm pretty ignorant of how big the tech debt mountain may be within the app.

If anyone can help me get past pip install -r requirements completing though I'm more confident about being able to handle the rest of the process. My hope is this work might inspire some developers to play around as a contingency to funding coming through in a timely manner, and maybe it can provide a head start if/when it does.

@mcdisc
Copy link

mcdisc commented Jul 28, 2017 via email

@themightychris
Copy link
Author

Progress! pip install -r requirements.txt completes successfully now.

I've added a line to the main description that activates the created virtualenv post-build now. More stuff should probably still get done in the build phase, including copying whatever parts of this repo are needed at runtime into $pkg_prefix somewhere, but this gets us to a point where setup can continue I think.

@themightychris
Copy link
Author

Currently, python setup.py ../../docs/config.{xsd,xml} fails with:

ImportError: No module named lxml.etree

Running pip install lxml seems to fix that, does that need to be added to requirements.txt? Then the next failure is:

ImportError: Could not import settings 'publicmapping.settings' (Is it on sys.path?): cannot import name _uuid_generate_random

@themightychris
Copy link
Author

The settings issue got sorted out by bumping celery to a newer version, working on a timezone issue that's probably habitat's doing now

@themightychris themightychris changed the title WIP: Build with habitat WIP: Build master with habitat Jul 29, 2017
@hectcastro
Copy link
Contributor

Hey Chris,

We sincerely appreciate your efforts here. It is likely that a fair bit of your work will carry over into the technical debt reduction work referenced above. We're a bit resource constrained right now, but would like to lend a hand where we can.

With regard to Habitat, we're a bit unfamiliar with it as an organization. From an ongoing maintenance perspective, it is likely that we'd gravitate toward a more vanilla Docker based packaging approach that builds on top of our generic Django container image (at least for the Django/Celery bits). The other supporting services would use official container images (Redis, PostgreSQL, etc.) locally, but then Amazon Web Services equivalents (ElastiCache, RDS) when deployed to a staging/production environment.

Not sure how that overlaps with your efforts here, but I just wanted to put that point out there for discussion as early as possible.

@themightychris
Copy link
Author

themightychris commented Aug 3, 2017

@hectcastro thanks for the note, I'll keep pecking away at this here and there and appreciate any materials you have I might get some clues from. DistrictBuilder is a project I believe is really important, and habitat is a bit of an academic interest for me right now so I want to see if I can bring them together and show what they can do, even if ultimately your team keeps your current direction (totally understandable!)

Habitat is a new project from the Chef team, and it's essentially package and application lifecycle management reimagined for the container age. It's well-supported and has been aggressively developed. What's great about it is that it completely uncouples the application from the host environment and deployment topology. Traditional docker tools give you containers that are still anchored to specific operating system distributions, leaving you with a time bomb to defuse as distributions turn over. An application packaged with habitat can be exported to a docker container image, or run on a VM or bare metal just the same... and in every case, on every operating system, for all time the entire stack of code down to the ELF interpreter will be the exactly same until the application gets rebuilt or its plan gets changed. It provides very precise control of the entire dependency chain and gives you both community support for maintaining updates to dependencies and a seamless path to publish arbitrary updates/builds of deps if you need to--no more mixing in random software sources when the official distro builds are missing a bug fix or version bump you need. All build processes as well get automated in an application-centric way that runs in a clean-room guaranteed to be consistent across development environments

I'd encourage you to give the commands I listed in the PR description a try and see what it gets you, it will take just a couple minutes

@themightychris
Copy link
Author

FYI I switched to working on a branch based on the v2.0 tag in an attempt to find more sanity: https://github.com/themightychris/DistrictBuilder/tree/habitat-v2.0

@msarahan
Copy link

@themightychris advised me on the codeforphilly slack channel on getting this setup. He's missing a tiny bit in the setup instructions up top. Before hab studio enter, you should run hab cli setup and enter the profile name as codeforphilly, and also allow it to create the signing key. The rest doesn't matter. With that, the next error is

Traceback (most recent call last):
  File "setup.py", line 180, in <module>
    main()
  File "setup.py", line 138, in main
    management.call_command('syncdb', verbosity=options.verbosity, interactive=False)
  File "/hab/pkgs/codeforphilly/DistrictBuilder/2.0+114#ca42696/20170825012557/lib/python2.7/site-packages/django/core/management/__init__.py", line 134, in call_command
    klass = load_command_class(app_name, name)
  File "/hab/pkgs/codeforphilly/DistrictBuilder/2.0+114#ca42696/20170825012557/lib/python2.7/site-packages/django/core/management/__init__.py", line 69, in load_command_class
    module = import_module('%s.management.commands.%s' % (app_name, name))
  File "/hab/pkgs/codeforphilly/DistrictBuilder/2.0+114#ca42696/20170825012557/lib/python2.7/site-packages/django/utils/importlib.py", line 35, in import_module
    __import__(name)
  File "/hab/pkgs/codeforphilly/DistrictBuilder/2.0+114#ca42696/20170825012557/lib/python2.7/site-packages/django/core/management/commands/syncdb.py", line 8, in <module>
    from django.core.management.sql import custom_sql_for_model, emit_post_sync_signal
  File "/hab/pkgs/codeforphilly/DistrictBuilder/2.0+114#ca42696/20170825012557/lib/python2.7/site-packages/django/core/management/sql.py", line 6, in <module>
    from django.db import models
  File "/hab/pkgs/codeforphilly/DistrictBuilder/2.0+114#ca42696/20170825012557/lib/python2.7/site-packages/django/db/__init__.py", line 40, in <module>
    backend = load_backend(connection.settings_dict['ENGINE'])
  File "/hab/pkgs/codeforphilly/DistrictBuilder/2.0+114#ca42696/20170825012557/lib/python2.7/site-packages/django/db/__init__.py", line 34, in __getattr__
    return getattr(connections[DEFAULT_DB_ALIAS], item)
  File "/hab/pkgs/codeforphilly/DistrictBuilder/2.0+114#ca42696/20170825012557/lib/python2.7/site-packages/django/db/utils.py", line 92, in __getitem__
    backend = load_backend(db['ENGINE'])
  File "/hab/pkgs/codeforphilly/DistrictBuilder/2.0+114#ca42696/20170825012557/lib/python2.7/site-packages/django/db/utils.py", line 24, in load_backend
    return import_module('.base', backend_name)
  File "/hab/pkgs/codeforphilly/DistrictBuilder/2.0+114#ca42696/20170825012557/lib/python2.7/site-packages/django/utils/importlib.py", line 35, in import_module
    __import__(name)
  File "/hab/pkgs/codeforphilly/DistrictBuilder/2.0+114#ca42696/20170825012557/lib/python2.7/site-packages/django/contrib/gis/db/backends/postgis/base.py", line 5, in <module>
    from django.contrib.gis.db.backends.postgis.operations import PostGISOperations
  File "/hab/pkgs/codeforphilly/DistrictBuilder/2.0+114#ca42696/20170825012557/lib/python2.7/site-packages/django/contrib/gis/db/backends/postgis/operations.py", line 8, in <module>
    from django.contrib.gis.geometry.backend import Geometry
  File "/hab/pkgs/codeforphilly/DistrictBuilder/2.0+114#ca42696/20170825012557/lib/python2.7/site-packages/django/contrib/gis/geometry/backend/__init__.py", line 11, in <module>
    module = import_module(geom_backend)
  File "/hab/pkgs/codeforphilly/DistrictBuilder/2.0+114#ca42696/20170825012557/lib/python2.7/site-packages/django/utils/importlib.py", line 35, in import_module
    __import__(name)
  File "/hab/pkgs/codeforphilly/DistrictBuilder/2.0+114#ca42696/20170825012557/lib/python2.7/site-packages/geos/__init__.py", line 4, in <module>
    import geos.server
  File "/hab/pkgs/codeforphilly/DistrictBuilder/2.0+114#ca42696/20170825012557/lib/python2.7/site-packages/geos/server.py", line 3
    from geos.print import print_map
                  ^
SyntaxError: invalid syntax

This doesn't make sense to me - the imports appear to be valid syntax, aside from the nasty from geos.kml import * It may be the module name conflicting with the built-in print statement, but surely that would have presented itself quite a while back.

Anyway, I will work this weekend to debug further.

@themightychris
Copy link
Author

@msarahan that's where my efforts went off the rails. IIRC that syntax seems to require python 3, and every version of geos uses it, but half the rest of the app melts if you switch from python2 to python3. So, I don't know how it ever worked, but I also have never built a python app and learned most of what I know about PIP trying to make this work

@msarahan
Copy link

It does not seem that conda will play as nicely as I had hoped with habitat. Our installer fails to run because of the way that habitat does glibc. It may be possible to patchelf it, but it's not going to be pretty.

Our installer is basically a bash script with a binary blob, consisting of many conda packages (each a .tar.bz2 with a particular folder structure). These appear to be getting extracted successfully. However, after they are extracted, the installer tries to run the python executable that it has just extracted to do some more stuff. That's where we bump into the glibc issue. So, we'd need to sort of intercept the installer mid-way to patchelf python. We'd probably also need to end up patchelf'ing any of the compiled libraries that conda provides. I think that's not worth the headache.

@themightychris sorry this was a wash. In looking at your requirements.txt file, it seems fragile to update all of the dependencies to the latest version. You may have more luck pinning to older versions for the time being, until DistrictBuilder can be refactored and modernized as necessary to use current versions.

@themightychris
Copy link
Author

@hectcastro @mcdisc does anyone know what the last commit of DistrictBuilder that is running online is? I've gotten past environmental issues I think and just gotten down to the list of python deps in master and the v2 tag just being unworkable. It's hard to see how either of those commits could ever get running

@mcdisc
Copy link

mcdisc commented Aug 29, 2017 via email

@hectcastro
Copy link
Contributor

Unfortunately, it is unclear what version was most recently used from our perspective (most people involved with those efforts have moved on). I started with master and created a branch to try and get the application up via Docker/Docker Compose. Progress on that is in the development-env branch.

Currently, the last RUN command is failing because psycopg2 cannot connect to the templated database endpoint. Next steps are probably to determine how to override that value so that it can try to connect to the commented out PostgreSQL configuration in docker-compose.yml (after links are established).

Hopefully that gives you a better path forward. I'll try to pick this up again when I have more time.

@themightychris
Copy link
Author

I wonder if this (new?) tool might help, just saw some talk of it in the habitat #python channel: https://github.com/ofek/hatch

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants