{ "info": { "author": "R\u00e9my Sanchez", "author_email": "remy.sanchez@hyperthese.net", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3 :: Only", "Topic :: Software Development :: Build Tools" ], "description": "LUH3417\n=======\n\nThis is a tool to help you implement a WordPress development workflow.\nIt has 3 main features:\n\n- **Snapshot** \u2014 Take snapshots of a running WordPress instance\n- **Restore** \u2014 Restore those snapshots in-place or to a different\n location\n- **Transfer** \u2014 Transfer one instance over another using automated\n backup, validation and configuration rules\n\nEverything can happen seamlessly in *local* or *through SSH*, allowing\nyou to work easily on remote servers from your local machine and to\ntransfer instances from one server to another.\n\nThanks to this, putting your code to production is as simple as:\n\n.. code:: bash\n\n python -m luh3417.transfer -g my_project.py local production \n\nWhile the ``snapshot`` and ``restore`` operations can be used\nindividually, it is not recommended to use them as the main tools.\nIndeed, ``restore`` can easily override an instance without any previous\nbackup. For this reason, it is better to use ``transfer`` whenever\npossible. It will ensure your safety within the workflow that you\ndefined.\n\nInstallation\n------------\n\n::\n\n pip install luh3417\n\nUsage\n-----\n\nLUH3417 is made to use with Python's ``-m`` option. This way, if you\nwant to invoke the ``snapshot`` feature, the base command will be\n``python -m luh3417.snapshot``.\n\nIf you prefer, there is also equivalent commands installed in the\n``bin`` directory, namely ``luh3417_snapshot``, ``luh3417_restore`` and\n``luh3417_transfer``.\n\nAll the locations can be in two formats:\n\n- ``SSH`` \u2014 ``user@server:/location/on/server``\n- ``Local`` \u2014 ``/location/on/current/machine``\n\nThis allows you to transfer data between remote servers and local\nmachine quite seamlessly.\n\n **NOTE** \u2014 You need to use an SSH agent in order for all the\n features to work. No password prompt will show up. Usually it's as\n simple as to type ``ssh-add`` in your terminal once during your\n session.\n\n``snapshot``\n~~~~~~~~~~~~\n\nCreates a snapshot of a running WordPress instance. A snapshot is an\narchive containing:\n\n- All PHP/theme/media/etc files\n- A DB dump\n- Meta information about how the snapshot was taken\n\nUsage syntax:\n\n::\n\n python -m luh3417.snapshot [-h] [-n SNAPSHOT_BASE_NAME] [-t FILE_NAME_TEMPLATE] source backup_dir\n\nExample:\n\n::\n\n python -m luh3417.snapshot root@prod-server.com:/var/www/html root@backup-server.com:/var/backups/wp\n\nAdditional options:\n\n- ``-n``/``--snapshot-base-name`` \u2014 Base name for your snapshot file.\n See the ``--file-name-template`` option to see how this name is used.\n The default name is the database's name.\n- ``-t``/``--file-name-template`` \u2014 This template will be used to\n generate the snapshot file name. By default it is\n ``{base}_{time}.tar.gz`` but you can put whatever you want.\n ``{base}`` and ``{time}`` will be replaced respectively by the base\n name (see ``--snapshot-base-name``) and the ISO 8601 UTC date.\n Independently of the name, the file will be placed in the\n ``backup_dir``.\n\n``restore``\n~~~~~~~~~~~\n\nRestores a snapshot either in-place to its original location using the\nembedded meta-data or to another location using a patch on the\nmeta-data.\n\nIn addition to just restoring the files and database, the patch can\ntrigger changes in ``wp-settings.php``, replace values in the database\nand much more.\n\n**``restore`` will essentially override an instance with the content of\na backup, so make sure to use it wisely in order not to loose data.\nAlso, see ``transfer``**.\n\nUsage:\n\n::\n\n python -m luh3417.restore [-p PATCH] [-a ALLOW_IN_PLACE] snapshot\n\nOptions:\n\n- ``-p``/``--patch`` \u2014 Location to the patch file (see below)\n- ``-a``/``--allow-in-place`` \u2014 Allows restoring the backup onto its\n original location. This flag is required because otherwise it would\n be way too easy to override\n\nRestore in-place\n^^^^^^^^^^^^^^^^\n\nIf you want to restore a backup to its original location, you just need\nto know the file's location and pass the ``-a`` flag.\n\n::\n\n python -m luh3417.restore -a root@backup-server.com:/path/to/snapshot.tar.gz\n\n **NOTE** \u2014 If the snapshot was made locally, it will always be\n restored locally because there is no way for LUH3417 to know the\n originating server so it assumes that the snapshot file was not\n transferred to another machine.\n\nRestore to another location\n^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nIn order to restore to another location, you need to use a patch file\n\n::\n\n python -m luh3417.restore -p patch.json root@backup-server.com:/path/to/snapshot.tar.gz\n\nHere is an example of patch file:\n\n.. code:: json\n\n {\n \"args\": {\n \"source\": \"root@new-server.com:/var/www/html\"\n },\n \"owner\": \"www-data:\"\n }\n\nSee below for detailed documentation of patch content\n\n``args.source``\n'''''''''''''''\n\nSet this one to define where to restore the archive.\n\n.. code:: json\n\n {\n \"args\": {\n \"source\": \"root@new-server.com:/var/www/html\"\n }\n }\n\n``wp_config``\n'''''''''''''\n\nDatabase configuration from the WordPress\n\n.. code:: json\n\n {\n \"wp_config\": {\n \"db_host\": \"localhost\",\n \"db_name\": \"xxx\",\n \"db_user\": \"xxx\",\n \"db_password\": \"xxx\"\n }\n }\n\n **NOTE** \u2014 You need to make sure you match those values in\n ``php_define`` unless you're using ``transfer`` which sets them\n automatically\n\n``owner``\n'''''''''\n\nThis changes the owner of the files to another one. This only works if:\n\n- When restoring locally, you run as ``root``\n- When restoring remotely, you login in as ``root``\n\n.. code:: json\n\n {\n \"owner\": \"www-data:\"\n }\n\n``git``\n'''''''\n\nReplaces some directories with a Git repository at a given version\n\n.. code:: json\n\n {\n \"git\": [\n {\n \"location\": \"wp-content/themes/jupiter-child\",\n \"repo\": \"git@gitlab.com:your_company/jupiter_child.git\",\n \"version\": \"master\"\n }\n ]\n }\n\n **NOTE** \u2014 ``.git`` directories are excluded from snapshots, so\n unless you specify this option there will be no git-enabled\n directories in the restored files. On the other hand, git\n repositories will be created at specified version, so it might not\n make sense to specify this option when restoring a backup in-place.\n\n``setup_queries``\n'''''''''''''''''\n\nA list of SQL queries to be run after the DB was restored\n\n.. code:: json\n\n {\n \"setup_queries\": [\n \"delete from wp_options where option_name = 'gtm4wp-options';\"\n ]\n }\n\n``php_define``\n''''''''''''''\n\nValues to be changed or added in ``wp-config.php``. Any\nJSON-serializable value can be used.\n\n.. code:: json\n\n {\n \"php_define\": {\n \"WP_CACHE\": false,\n \"WP_SENTRY_ENV\": \"new-env\"\n }\n }\n\n``replace_in_dump``\n'''''''''''''''''''\n\nA list of strings with their replacement to be changed in the dump\nbefore restoring it. This is mainly used to change the domain name of\nthe instance. As WordPress serializes its settings, a simple replace is\nnot possible. This will use a holistic heuristic which will try to keep\nPHP-serialized values correct even if quoted in a MySQL string.\n\n **NOTE** \u2014 PHP-serialized values are prefixed by their length, this\n is why a simple replace cannot be effective: if the length changes\n then the whole value gets corrupted.\n\n.. code:: json\n\n {\n \"replace_in_dump\": [\n {\n \"search\": \"https://old-domain.com\",\n \"replace\": \"https://new-domain.com\"\n }\n ]\n }\n\n``mysql_root``\n''''''''''''''\n\nIn order to create the database and set the user password, the script\nneeds a root access to MySQL. Today, the only supported method is\n``socket``, because it is password-less. However it only works when the\nserver is local and properly configured (it's the default behavior in\nDebian-based distros).\n\n.. code:: json\n\n {\n \"mysql_root\": {\n \"method\": \"socket\",\n \"options\": {\n \"sudo_user\": \"root\",\n \"mysql_user\": \"root\"\n }\n }\n }\n\nAbout the options:\n\n- ``sudo_user`` \u2014 don't set it if you don't need to sudo to use the\n socket, set it to ``root`` or whichever user is right otherwise.\n- ``mysql_user`` \u2014 name of the MySQL user to use\n\n``outer_files``\n'''''''''''''''\n\nCreates files on the server's file system. If the file name is relative\nthen the file is created relatively to the WordPress's root, otherwise\nit is created at the specified absolute location.\n\n.. code:: json\n\n {\n \"outer_files\": [\n {\n \"name\": \"robots.txt\",\n \"content\": \"User-agent: *\\nDisallow: /\\n\"\n },\n {\n \"name\": \"/etc/apache2/sites-available/my-host.conf\",\n \"content\": \" ...\"\n }\n ]\n }\n\n **NOTE** \u2014 There is not (yet) any form of privilege escalation to\n create those files, so the local/remote user must have the rights to\n create those files.\n\n``post_install``\n''''''''''''''''\n\nThose are shell scripts which run on the host server after the install\nis complete. Typically, you can enable your virtual host and reload\nApache.\n\n.. code:: json\n\n {\n \"post_install\": [\n \"a2ensite my-website.com\",\n \"systemctl reload apache2\"\n ]\n }\n\n``dns``\n'''''''\n\nYou might want to use your DNS provider's API in order to configure the\ndomain that is going to target your website. LUH3417 integrates with\n`libcloud `__ in\norder to provide an abstraction over the most popular cloud providers.\n\nHere is an example entry:\n\n.. code:: json\n\n {\n \"dns\": {\n \"providers\": [\n {\n \"domain\": \"my-corp.net\",\n \"provider\": \"digitalocean\",\n \"credentials\": {\n \"key\": \"xxxxxx\",\n }\n }\n ],\n \"entries\": [\n {\n \"type\": \"alias\",\n \"params\": {\n \"domain\": \"my-wp.my-corp.net\",\n \"target\": \"load-balancer.my-corp.net\"\n }\n },\n {\n \"type\": \"ips\",\n \"params\": {\n \"domain\": \"dns.my-corp.net\",\n \"ips\": [\n \"2606:4700:4700::1111\",\n \"2606:4700:4700::1001\",\n \"1.1.1.1\",\n \"1.0.0.1\"\n ]\n }\n }\n ]\n }\n }\n\nLet's break this down\n\n``providers``\n \n\nThat's a list of the providers, associated to a domain name. The\ndifferent keys are used like this:\n\n- ``domain`` \u2014 root domain name managed by this provider\n- ``provider`` \u2014 domain name provider (you can get the list\n `here `__,\n use the lower-case string value)\n- ``credentials`` \u2014 kwargs to be passed to the constructor of the\n provider\n\n``entries``\n \n\nEntries are either a single CNAME either a set of A/AAAA records for a\nsame domain name. LUH3417 will make sure that all records for this\n(sub-)domain match your specification and **will delete other records\nfor that sub-domain**.\n\nSuppose the following situation:\n\n- ``foo.my.org`` resolves to ``A 1.2.3.4``\n- But you want it to be a CNAME of ``bar.my.org``\n- The ``A 1.2.3.4`` entry will be deleted and a ``CNAME bar.my.org``\n will be created\n\nNow, let's dig into the options\n\n**``\"type\" = \"alias\"``**\n\nThat's when you want to create a CNAME.\n\n.. code:: json\n\n {\n \"type\": \"alias\",\n \"params\": {\n \"domain\": \"my-wp.my-corp.net\",\n \"target\": \"load-balancer.my-corp.net\"\n }\n }\n\nThe two params are:\n\n- ``domain`` \u2014 target (sub-)domain\n- ``target`` \u2014 target of the CNAME (aka the value of the record)\n\n**``\"type\" = \"ips\"``**\n\nThis will set your (sub-)domain to point on a set if IP addresses,\npreferably v6 but legacy systems like v4 are still supported.\n\n.. code:: json\n\n {\n \"type\": \"ips\",\n \"params\": {\n \"domain\": \"dns.my-corp.net\",\n \"ips\": [\n \"2606:4700:4700::1111\",\n \"2606:4700:4700::1001\",\n \"1.1.1.1\",\n \"1.0.0.1\"\n ]\n }\n }\n\n- ``domain`` \u2014 is the target (sub-)domain\n- ``ips`` \u2014 is a list of IP address that will be set to AAAA and A\n records\n\n``transfer``\n~~~~~~~~~~~~\n\nThe main goal of this package is to allow the setup of a custom workflow\nthat allows easy copy of WordPress instances from an environment from\nthe other.\n\nThe basic idea is the following:\n\n- You can specify an origin and target environment names\n- There is a *settings generator* Python file which will generate all\n the settings and patches appropriate for this transfer.\n\nIt's **your responsibility** to write an settings generator, however\nthere is an a documented example attached in this repository.\n\nUsage:\n\n::\n\n python -m luh3417.transfer [-h] -g SETTINGS_GENERATOR origin target\n\nExample:\n\n::\n\n python -m luh3417.transfer -g example/generator.py develop local\n\nTo see the content of the generator file, please refer to the\n`example/generator.py `__ file and especially the\n``allow_transfer()`` method's documentation which will explain the\nspirit of the file.\n\nFAQ\n---\n\n Why the name ``LUH3417``?\n\nIt's a character from THX1138. The author is not particularly fan of\nthis movie, however it expresses quite well the feeling of working with\nWordPress and especially setting up a professional workflow.\n\n Why using Python to code it?\n\nIt felt to the author that this language was more appropriate for this\ntask than PHP.\n\n Do I need to write Python to use the transfer feature?\n\nYes, fortunately it's pretty easy. The author started with `Dive Into\nPython `__.\n\n Why can't the transfer feature have a configuration file instead?\n\nA configuration file would mean imposing the skeleton of the author's\nworkflow onto all users. If such a workflow is suitable for your needs,\nexample code and tutorial are provided so just have to adapt the code\nfor yourself.\n\nLicense\n-------\n\nThis project is distributed under the terms of the\n`WTFPL <./COPYING>`__. It comes void of warranties and if you break\nthings it's on you.\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/WithIO/luh3417", "keywords": "", "license": "WTFPL", "maintainer": "", "maintainer_email": "", "name": "luh3417", "package_url": "https://pypi.org/project/luh3417/", "platform": "", "project_url": "https://pypi.org/project/luh3417/", "project_urls": { "Homepage": "https://github.com/WithIO/luh3417" }, "release_url": "https://pypi.org/project/luh3417/0.1.2/", "requires_dist": null, "requires_python": "", "summary": "LUH3417, a WordPress backup/restore/workflow tool", "version": "0.1.2" }, "last_serial": 5247876, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "4c8de68f0d65f65e40facf64621cf42d", "sha256": "3fe352e0e747473bae98b4fce126d919b1bd37448ed9484ca8316e3e2f8895fb" }, "downloads": -1, "filename": "luh3417-0.1.0.tar.gz", "has_sig": false, "md5_digest": "4c8de68f0d65f65e40facf64621cf42d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 33019, "upload_time": "2019-04-01T20:33:13", "url": "https://files.pythonhosted.org/packages/22/51/cdd02692637de5c57bbe00a0b524595e59304898873393929b631ba744ff/luh3417-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "1f803968af6b311ab8ecb0d7fb94eefb", "sha256": "056ee08f19b347bc4dc2c1a563d3b66822b7e7454f752269f3cd4bf92dea3f5d" }, "downloads": -1, "filename": "luh3417-0.1.1.tar.gz", "has_sig": false, "md5_digest": "1f803968af6b311ab8ecb0d7fb94eefb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 33208, "upload_time": "2019-04-18T08:12:57", "url": "https://files.pythonhosted.org/packages/65/25/fd48f9f73214c9dea1933145bc147d72ec864c381ac4640c1d5713334fa8/luh3417-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "786869432c7af6c4f5f4e89f9b857e62", "sha256": "9a0559dee28272c438282ba19d386a6981602fe65755815b68e8ab448f8af014" }, "downloads": -1, "filename": "luh3417-0.1.2.tar.gz", "has_sig": false, "md5_digest": "786869432c7af6c4f5f4e89f9b857e62", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 33645, "upload_time": "2019-05-09T14:45:11", "url": "https://files.pythonhosted.org/packages/3f/c9/75ad4722b0d70c05831bf669c182645bc37bd5ba258e3774a713889efd18/luh3417-0.1.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "786869432c7af6c4f5f4e89f9b857e62", "sha256": "9a0559dee28272c438282ba19d386a6981602fe65755815b68e8ab448f8af014" }, "downloads": -1, "filename": "luh3417-0.1.2.tar.gz", "has_sig": false, "md5_digest": "786869432c7af6c4f5f4e89f9b857e62", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 33645, "upload_time": "2019-05-09T14:45:11", "url": "https://files.pythonhosted.org/packages/3f/c9/75ad4722b0d70c05831bf669c182645bc37bd5ba258e3774a713889efd18/luh3417-0.1.2.tar.gz" } ] }