# -*- coding: utf-8 -*-
from setuptools import setup

package_dir = \
{'': 'src'}

packages = \
['luh3417',
 'luh3417.replace',
 'luh3417.restore',
 'luh3417.snapshot',
 'luh3417.transfer']

package_data = \
{'': ['*']}

install_requires = \
['apache-libcloud>=2.0,<3.0', 'coloredlogs>=9.0']

entry_points = \
{'console_scripts': ['luh3417_replace = luh3417.replace.__main__:__main__',
                     'luh3417_restore = luh3417.restore.__main__:__main__',
                     'luh3417_snapshot = luh3417.snapshot.__main__:__main__',
                     'luh3417_transfer = luh3417.transfer.__main__:__main__']}

setup_kwargs = {
    'name': 'luh3417',
    'version': '0.1.5',
    'description': 'A WordPress backup/restore/workflow tool',
    'long_description': 'LUH3417\n=======\n\nThis is a tool to help you implement a WordPress development workflow. It has 3\nmain features:\n\n- **Snapshot** &mdash; Take snapshots of a running WordPress instance\n- **Restore** &mdash; Restore those snapshots in-place or to a different\n  location\n- **Transfer** &mdash; Transfer one instance over another using automated\n  backup, validation and configuration rules\n\nEverything can happen seamlessly in *local* or *through SSH*, allowing you to\nwork easily on remote servers from your local machine and to transfer instances\nfrom one server to another.\n\nThanks to this, putting your code to production is as simple as:\n\n```bash\npython -m luh3417.transfer -g my_project.py local production\n```\n\nWhile the `snapshot` and `restore` operations can be used individually, it is\nnot recommended to use them as the main tools. Indeed, `restore` can easily\noverride an instance without any previous backup. For this reason, it is better\nto use `transfer` whenever possible. It will ensure your safety within the\nworkflow that you defined.\n\n## Installation\n\n```\npip install luh3417\n```\n\n## Usage\n\nLUH3417 is made to use with Python\'s `-m` option. This way, if you want to\ninvoke 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 `bin`\ndirectory, namely `luh3417_snapshot`, `luh3417_restore` and `luh3417_transfer`.\n\nAll the locations can be in two formats:\n\n- `SSH` &mdash; `user@server:/location/on/server`\n- `Local` &mdash; `/location/on/current/machine`\n\nThis allows you to transfer data between remote servers and local machine quite\nseamlessly.\n\n> **NOTE** &mdash; You need to use an SSH agent in order for all the features\n> to work. No password prompt will show up. Usually it\'s as simple as to type\n> `ssh-add` in your terminal once during your session.\n\n### `snapshot`\n\nCreates a snapshot of a running WordPress instance. A snapshot is an archive\ncontaining:\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```\npython -m luh3417.snapshot [-h] [-n SNAPSHOT_BASE_NAME] [-t FILE_NAME_TEMPLATE] source backup_dir\n```\n\nExample:\n\n```\npython -m luh3417.snapshot root@prod-server.com:/var/www/html root@backup-server.com:/var/backups/wp\n```\n\nAdditional options:\n\n- `-n`/`--snapshot-base-name` &mdash; Base name for your snapshot file. See\n  the `--file-name-template` option to see how this name is used. The default\n  name is the database\'s name.\n- `-t`/`--file-name-template` &mdash; This template will be used to generate\n  the snapshot file name. By default it is `{base}_{time}.tar.gz` but you can\n  put whatever you want. `{base}` and `{time}` will be replaced respectively\n  by the base name (see `--snapshot-base-name`) and the ISO 8601 UTC date.\n  Independently of the name, the file will be placed in the `backup_dir`.\n\n### `restore`\n\nRestores a snapshot either in-place to its original location using the embedded\nmeta-data or to another location using a patch on the meta-data.\n\nIn addition to just restoring the files and database, the patch can trigger\nchanges in `wp-settings.php`, replace values in the database and much more.\n\n**`restore` will essentially override an instance with the content of a\nbackup, so make sure to use it wisely in order not to loose data. Also, see\n`transfer`**.\n\nUsage:\n\n```\npython -m luh3417.restore [-p PATCH] [-a ALLOW_IN_PLACE] snapshot\n```\n\nOptions:\n\n- `-p`/`--patch` &mdash; Location to the patch file (see below)\n- `-a`/`--allow-in-place` &mdash; Allows restoring the backup onto its original\n  location. This flag is required because otherwise it would be way too easy\n  to override\n\n#### Restore in-place\n\nIf you want to restore a backup to its original location, you just need to\nknow the file\'s location and pass the `-a` flag.\n\n```\npython -m luh3417.restore -a root@backup-server.com:/path/to/snapshot.tar.gz\n```\n\n> **NOTE** &mdash; If the snapshot was made locally, it will always be restored\n> locally because there is no way for LUH3417 to know the originating server so\n> it assumes that the snapshot file was not transferred to another machine.\n\n#### Restore to another location\n\nIn order to restore to another location, you need to use a patch file\n\n```\npython -m luh3417.restore -p patch.json root@backup-server.com:/path/to/snapshot.tar.gz\n```\n\nHere is an example of patch file:\n\n```json\n{\n    "args": {\n        "source": "root@new-server.com:/var/www/html"\n    },\n    "owner": "www-data:"\n}\n```\n\nSee below for detailed documentation of patch content\n\n##### `args.source`\n\nSet this one to define where to restore the archive.\n\n```json\n{\n    "args": {\n        "source": "root@new-server.com:/var/www/html"\n    }\n}\n```\n\n##### `wp_config`\n\nDatabase configuration from the WordPress\n\n```json\n{\n    "wp_config": {\n        "db_host": "localhost",\n        "db_name": "xxx",\n        "db_user": "xxx",\n        "db_password": "xxx"\n    }\n}\n```\n\n> **NOTE** &mdash; You need to make sure you match those values in `php_define`\n> unless you\'re using `transfer` which sets them automatically\n\n##### `owner`\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```json\n{\n    "owner": "www-data:"\n}\n```\n\n##### `git`\n\nReplaces some directories with a Git repository at a given version\n\n```json\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\n> **NOTE** &mdash; `.git` directories are excluded from snapshots, so unless\n> you specify this option there will be no git-enabled directories in the\n> restored files. On the other hand, git repositories will be created at\n> specified version, so it might not make sense to specify this option when\n> restoring a backup in-place.\n\n##### `setup_queries`\n\nA list of SQL queries to be run after the DB was restored\n\n```json\n{\n    "setup_queries": [\n        "delete from wp_options where option_name = \'gtm4wp-options\';"\n    ]\n}\n```\n\n##### `php_define`\n\nValues to be changed or added in `wp-config.php`. Any JSON-serializable value\ncan be used.\n\n```json\n{\n    "php_define": {\n        "WP_CACHE": false,\n        "WP_SENTRY_ENV": "new-env"\n    }\n}\n```\n\n##### `replace_in_dump`\n\nA list of strings with their replacement to be changed in the dump before\nrestoring it. This is mainly used to change the domain name of the instance.\nAs WordPress serializes its settings, a simple replace is not possible. This\nwill use a holistic heuristic which will try to keep PHP-serialized values\ncorrect even if quoted in a MySQL string.\n\n> **NOTE** &mdash; PHP-serialized values are prefixed by their length, this is\n> why a simple replace cannot be effective: if the length changes then the\n> whole value gets corrupted.\n\n```json\n{\n    "replace_in_dump": [\n        {\n            "search": "https://old-domain.com",\n            "replace": "https://new-domain.com"\n        }\n    ]\n}\n```\n\n##### `mysql_root`\n\nIn order to create the database and set the user password, the script needs\na root access to MySQL. Today, the only supported method is `socket`, because\nit is password-less. However it only works when the server is local and\nproperly configured (it\'s the default behavior in Debian-based distros).\n\n```json\n{\n    "mysql_root": {\n        "method": "socket",\n        "options": {\n            "sudo_user": "root",\n            "mysql_user": "root"\n        }\n    }\n}\n```\n\nAbout the options:\n\n- `sudo_user` &mdash; don\'t set it if you don\'t need to sudo to use the socket,\n  set it to `root` or whichever user is right otherwise.\n- `mysql_user` &mdash; name of the MySQL user to use\n\n##### `outer_files`\n\nCreates files on the server\'s file system. If the file name is relative then\nthe file is created relatively to the WordPress\'s root, otherwise it is created\nat the specified absolute location.\n\n```json\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": "<VirtualHost> ..."\n        }\n    ]\n}\n```\n\n> **NOTE** &mdash; There is not (yet) any form of privilege escalation to\n> create those files, so the local/remote user must have the rights to create\n> those files.\n\n##### `post_install`\n\nThose are shell scripts which run on the host server after the install is\ncomplete. Typically, you can enable your virtual host and reload Apache.\n\n```json\n{\n    "post_install": [\n        "a2ensite my-website.com",\n        "systemctl reload apache2"\n    ]\n}\n```\n\n##### `dns`\n\nYou might want to use your DNS provider\'s API in order to configure the domain\nthat is going to target your website. LUH3417 integrates with\n[libcloud](https://libcloud.readthedocs.io/en/latest/index.html) in order to\nprovide an abstraction over the most popular cloud providers.\n\nHere is an example entry:\n\n```json\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```\n\nLet\'s break this down\n\n###### `providers`\n\nThat\'s a list of the providers, associated to a domain name. The different keys\nare used like this:\n\n- `domain` &mdash; root domain name managed by this provider\n- `provider` &mdash; domain name provider (you can get the list\n  [here](https://github.com/apache/libcloud/blob/trunk/libcloud/dns/types.py#L32),\n  use the lower-case string value)\n- `credentials` &mdash; kwargs to be passed to the constructor of the provider\n\n###### `entries`\n\nEntries are either a single CNAME either a set of A/AAAA records for a same\ndomain name. LUH3417 will make sure that all records for this (sub-)domain\nmatch your specification and **will delete other records for 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` will be\n  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```json\n{\n    "type": "alias",\n    "params": {\n        "domain": "my-wp.my-corp.net",\n        "target": "load-balancer.my-corp.net"\n    }\n}\n```\n\nThe two params are:\n\n- `domain` &mdash; target (sub-)domain\n- `target` &mdash; 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, preferably\nv6 but legacy systems like v4 are still supported.\n\n```json\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- `domain` &mdash; is the target (sub-)domain\n- `ips` &mdash; is a list of IP address that will be set to AAAA and A records\n\n### `transfer`\n\nThe main goal of this package is to allow the setup of a custom workflow that\nallows easy copy of WordPress instances from an environment from the 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 the\n  settings and patches appropriate for this transfer.\n\nIt\'s **your responsibility** to write an settings generator, however there is\nan a documented example attached in this repository.\n\nUsage:\n\n```\npython -m luh3417.transfer [-h] -g SETTINGS_GENERATOR origin target\n```\n\nExample:\n\n```\npython -m luh3417.transfer -g example/generator.py develop local\n```\n\nTo see the content of the generator file, please refer to the\n[example/generator.py](example/generator.py) file and especially the\n`allow_transfer()` method\'s documentation which will explain the spirit of\nthe file.\n\n### `replace`\n\nSeeks and replaces serialized values. Values could be in quoted MySQL literals\nor serialized PHP values, they will be replaced and the containing string will\nbe re-serialized.\n\nThat\'s a complicated problem due to PHP serialized format which prefixes the\nstring\'s length to the string. If you want to replace a value you need to\nreplace its length.\n\nBy example:\n\n```php\necho serialize("foo");\n// s:3:"foo";\n\necho serialize("long foo");\n// s:8:"long foo";\n//   ^-- see here how the prefix changed from 3 to 8\n```\n\nThis command will do the replacing in a file and output to another file. Be\ncareful, it will not warn you of overwrites.\n\nUsage:\n\n```\npython -m luh3417.replace [-h] -i INPUT -o OUTPUT [-b BEFORE [BEFORE ...]] [-a AFTER [AFTER ...]] [-c CHARSET]\n```\n\nExample:\n\n```\npython -m luh3417.replace \\\n    -i dump.sql \\\n    -o dump_replaced.sql \\\n    -b old_domain.com \\\n    -a new_domain.com\n```\n\n## FAQ\n\n> Why the name `LUH3417`?\n\nIt\'s a character from THX1138. The author is not particularly fan of this\nmovie, however it expresses quite well the feeling of working with WordPress\nand 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 task\nthan 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\n[Dive Into Python](https://www.diveinto.org/python3/).\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 workflow\nonto all users. If such a workflow is suitable for your needs, example code\nand tutorial are provided so just have to adapt the code for yourself.\n\n## License\n\nThis project is distributed under the terms of the [WTFPL](./COPYING). It comes\nvoid of warranties and if you break things it\'s on you.\n',
    'author': 'Rémy Sanchez',
    'author_email': 'remy.sanchez@hyperthese.net',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/WithIO/luh3417',
    'package_dir': package_dir,
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'entry_points': entry_points,
    'python_requires': '>=3.6,<4.0',
}


setup(**setup_kwargs)
