예제 #1
0
    def test_parse_site_media_map(self):
        here = path.abspath(path.split(__file__)[0])
        test_fixture_cfg = path.join(here, '../fixtures',
                                     'app', 'zoombuild.cfg')
        zcfg = utils.parse_zoombuild(test_fixture_cfg)

        input_text = zcfg["site_media_map"]

        self.assertEqual(len(input_text.splitlines()), 3)
        self.assertTrue("static static" in input_text)
        self.assertTrue("staticfiles staticfiles" in input_text)
        self.assertTrue("foo {SITE_PACKAGES}/foo" in input_text)

        smm = utils.parse_site_media_map(input_text)
        self.assertTrue(isinstance(smm, dict))

        # each url path should start and end with a single slash
        for url_path in smm.keys():
            self.assertTrue(url_path.startswith("/"))
            self.assertTrue(url_path.endswith("/"))
            self.assertFalse(url_path.startswith("//"))
            self.assertFalse(url_path.endswith("//"))

        self.assertEqual(smm["/foo/"], "{SITE_PACKAGES}/foo")
        self.assertEqual(smm["/static/"], "static")
        self.assertEqual(smm["/staticfiles/"], "staticfiles")
        self.assertEqual(len(smm), 3)
예제 #2
0
 def test_parse_zoombuild_string(self):
     here = path.abspath(path.split(__file__)[0])
     test_fixture_cfg = path.join(here, '../fixtures',
                                  'app', 'zoombuild.cfg')
     cfg_content = file(test_fixture_cfg).read()
     result = utils.parse_zoombuild_string(cfg_content)
     self.assertEqual(result["base_python_package"], "mysite")
     self.assertEqual(result, utils.parse_zoombuild(test_fixture_cfg))
예제 #3
0
    def test_parse_zoombuild(self):
        here = path.abspath(path.split(__file__)[0])
        test_fixture_cfg = path.join(here, '../fixtures',
                                     'app', 'zoombuild.cfg')

        result = utils.parse_zoombuild(test_fixture_cfg)

        self.assertEqual(result["base_python_package"], "mysite")
        self.assertEqual(result["database_type"], "postgresql-8.4")
예제 #4
0
def update_front_end_proxy(zoomdb, opts):
    """
    Generate config template for site, note location of app servers as proxy
    backend.  Reload nginx.

    Nginx examples for this are in the chef nginx recipe.

    When running locally in dev, you must make sure whatever user runs celeryd
    has write permission to /etc/nginx/sites-enabled
    $ sudo chgrp nateaune /etc/nginx/sites-enabled/
    $ sudo chmod g+w /etc/nginx/sites-enabled/
    """
    # (instance_id, node_name, host_ip, host_port) format
    appservers = opts["DEPLOYED_ADDRESSES"]

    virtual_hostnames = zoomdb.get_project_virtual_hosts()

    zcfg = utils.parse_zoombuild(os.path.join(opts["APP_DIR"],
                                              "zoombuild.cfg"))
    site_media_map = utils.parse_site_media_map(zcfg.get("site_media_map", ""))

    args = [zoomdb._job_id, opts["APP_ID"], opts["BUNDLE_NAME"],
            appservers, virtual_hostnames, site_media_map]

    remove_other_bundles = taskconfig.NGINX_REMOVE_OLD_BUNDLES_ON_UPDATE

    if opts["USE_SUBTASKS"]:
        res = nginx.update_proxy_conf.apply_async(args=args,
                                                  kwargs={
                                                      "remove_other_bundles":
                                                      remove_other_bundles})
        res.wait()
    else:
        nginx.update_proxy_conf(*args,
                                remove_other_bundles=remove_other_bundles)

    zoomdb.log("Updated proxy server configuration. Your project is now "
               "available from the following URLs: " +
               ", ".join(virtual_hostnames))
예제 #5
0
def bundle_app(app_id, force_bundle_name=None, return_ue=False,
               src_repo_type="git"):
    """
    Task: Bundle an app with ``app_id`` found in ``custdir``

    :param custdir: Absolute path to the base customer directory
    :param app_id: A path such that ``os.path.join(custdir, app_id)`` is a
        valid directory.
    :param force_bundle_name: Optional name for the bundle. If absent, name
        will be auto-generated based on the app name and current date/time.
    :param return_ue: If true, returns the UserEnv object used to build
        the bundle.

    :returns: (bundle_name, code_revision, userenv) if ``return_ue`` is True
        otherwise returns (bundle_name, code_revision)
    """

    appdir = os.path.join(taskconfig.NR_CUSTOMER_DIR, app_id)
    appsrcdir = os.path.join(appdir, "src")
    buildconfig = os.path.join(appdir, "zoombuild.cfg")

    assert os.path.isdir(taskconfig.NR_CUSTOMER_DIR),\
           "Expected custdir %r to be a directory, but it isn't." % (
        taskconfig.NR_CUSTOMER_DIR)

    err_msg = ("Expected to find customer source in directory %r," % appsrcdir,
               "but that isn't a directory.")
    assert os.path.isdir(appdir), err_msg

    assert os.path.isfile(buildconfig),\
           "Expected zoombuild.cfg file in %r, but no dice." % buildconfig

    # parse the zoombuild.cfg file
    buildconfig_info = utils.parse_zoombuild(buildconfig)

    err_msg = ("File %r doesn't look like a valid" % buildconfig,
               "zoombuild.cfg format file.")
    assert buildconfig_info, err_msg

    # generate a bundle name and directory
    if force_bundle_name:
        bundle_name = force_bundle_name
    else:
        bundle_name = "bundle_%s_%s" % (
            app_id,
            datetime.datetime.utcnow().strftime("%Y-%m-%d-%H.%M.%S"))

    bundle_dir = os.path.join(appdir, bundle_name)

    # make virtualenv
    utils.make_virtualenv(bundle_dir)

    # archive a copy of the build parameters
    shutil.copyfile(buildconfig,
                    os.path.join(bundle_dir,
                                 "zoombuild.cfg"))

    # Check what version of the code we've got
    vcs_h = vcs_handlers.get_handler(src_repo_type)
    code_revision = unicode(vcs_h.get_revision_info(appsrcdir), "utf8")

    # Copy in user code and add to pth
    to_src = os.path.join(bundle_dir, 'user-src')

    # if there is a base python package, copy user's code under there.
    if buildconfig_info["base_python_package"]:
        bpp_as_path = buildconfig_info["base_python_package"].replace(
            ".", "/")
        to_src = os.path.join(to_src, bpp_as_path)
    else:
        bpp_as_path = None

    # Add in a symlink pointing to the actual repo, so that we can
    # find static files later
    repo_link = os.path.join(bundle_dir, 'user-repo')
    if bpp_as_path:
        repo_link_src = os.path.join('user-src', bpp_as_path)
    else:
        repo_link_src = 'user-src'
    os.symlink(repo_link_src, repo_link)

    # Do the shutil.copytree inside a try/except block so that we can
    # identify bad symlinks. According to http://bugs.python.org/issue6547,
    # bad symlinks will cause an shutil.Error to be raised only at the
    # end of the copy process, so other files are copied correctly.
    # Therefore it is OK to simply warn about any bad links but otherwise
    # assume that things were copied over OK.
    try:
        shutil.copytree(appsrcdir, to_src, ignore=_ignore_vcs_files)
    except shutil.Error, e:
        for src, dst, error in e.args[0]:
            if not os.path.islink(src):
                raise
            else:
                linkto = os.readlink(src)
                if os.path.exists(linkto):
                    raise
                else:
                    ### TODO: communicate this warning to end-user via
                    ### zoomdb.log
                    print("*** Warning: invalid symlink found in " +
                          "project: %s -> %s, but %s doesn't exist." % (
                            src, linkto, linkto))