From bd1f382f2679a7e6889c1156a346fb3a1b9a8fa1 Mon Sep 17 00:00:00 2001 From: David Moreau Simard Date: Thu, 25 Feb 2021 15:20:16 -0500 Subject: [PATCH] opendev: Remove content and leave an URL to the GitHub repository Change-Id: Ib029323d2c040faec555202ad3e243a8408c360a --- .gitignore | 2 - LICENSE | 674 ------------------ README.md | 68 -- README.rst | 5 + doc/source/_static/ansible-role-ara-api.png | Bin 21679 -> 0 bytes doc/source/_static/ansible-role-ara-web.png | Bin 34924 -> 0 bytes doc/source/_static/ara-with-icon.png | Bin 20798 -> 0 bytes galaxy.yml | 13 - roles/ara_api/README.md | 90 --- roles/ara_api/defaults/main.yaml | 219 ------ roles/ara_api/files/ara-gunicorn.te | 15 - roles/ara_api/handlers/main.yaml | 26 - roles/ara_api/meta/main.yaml | 26 - roles/ara_api/tasks/config.yaml | 127 ---- ...server.db.backends.distributed_sqlite.yaml | 22 - .../django.db.backends.mysql.yaml | 55 -- .../django.db.backends.postgresql.yaml | 56 -- .../django.db.backends.sqlite3.yaml | 32 - roles/ara_api/tasks/install/distribution.yaml | 34 - roles/ara_api/tasks/install/pypi.yaml | 12 - roles/ara_api/tasks/install/source.yaml | 41 -- roles/ara_api/tasks/main.yaml | 44 -- roles/ara_api/tasks/pre-requirements.yaml | 84 --- roles/ara_api/tasks/wsgi_server/gunicorn.yaml | 74 -- roles/ara_api/templates/ara-api.service.j2 | 16 - roles/ara_api/vars/CentOS.yaml | 38 - roles/ara_api/vars/Debian.yaml | 1 - roles/ara_api/vars/Fedora.yaml | 39 - roles/ara_api/vars/RedHat.yaml | 1 - roles/ara_api/vars/Ubuntu.yaml | 38 - roles/ara_frontend_nginx/README.md | 44 -- roles/ara_frontend_nginx/handlers/main.yaml | 24 - roles/ara_frontend_nginx/meta/main.yaml | 26 - roles/ara_frontend_nginx/tasks/main.yaml | 80 --- .../templates/ara-api.conf.j2 | 39 - .../templates/ara-web.conf.j2 | 33 - roles/ara_frontend_nginx/vars/CentOS.yaml | 21 - roles/ara_frontend_nginx/vars/Debian.yaml | 1 - roles/ara_frontend_nginx/vars/Fedora.yaml | 21 - roles/ara_frontend_nginx/vars/RedHat.yaml | 1 - roles/ara_frontend_nginx/vars/Ubuntu.yaml | 21 - roles/ara_web/README.md | 80 --- roles/ara_web/defaults/main.yaml | 71 -- roles/ara_web/handlers/main.yaml | 31 - roles/ara_web/meta/main.yaml | 27 - roles/ara_web/tasks/install/source.yaml | 107 --- roles/ara_web/tasks/main.yaml | 28 - roles/ara_web/tasks/nodejs.yaml | 53 -- roles/ara_web/templates/ara-web.service.j2 | 16 - tests/test_tasks.yaml | 125 ---- tests/vars/distributed_sqlite_tests.yaml | 14 - tests/vars/mysql_tests.yaml | 18 - tests/vars/postgresql_tests.yaml | 18 - tests/with_distributed_sqlite.yaml | 55 -- tests/with_fedora_packages.yaml | 32 - tests/with_mysql.yaml | 82 --- tests/with_postgresql.yaml | 80 --- tests/zuul_metadata.yaml | 28 - tests/zuul_post_logs.yaml | 49 -- tests/zuul_post_with_mysql.yaml | 34 - tests/zuul_post_with_postgresql.yaml | 40 -- tests/zuul_pre_multinode_networking.yaml | 11 - 62 files changed, 5 insertions(+), 3157 deletions(-) delete mode 100644 .gitignore delete mode 100644 LICENSE delete mode 100644 README.md create mode 100644 README.rst delete mode 100644 doc/source/_static/ansible-role-ara-api.png delete mode 100644 doc/source/_static/ansible-role-ara-web.png delete mode 100755 doc/source/_static/ara-with-icon.png delete mode 100644 galaxy.yml delete mode 100644 roles/ara_api/README.md delete mode 100644 roles/ara_api/defaults/main.yaml delete mode 100644 roles/ara_api/files/ara-gunicorn.te delete mode 100644 roles/ara_api/handlers/main.yaml delete mode 100644 roles/ara_api/meta/main.yaml delete mode 100644 roles/ara_api/tasks/config.yaml delete mode 100644 roles/ara_api/tasks/database_engine/ara.server.db.backends.distributed_sqlite.yaml delete mode 100644 roles/ara_api/tasks/database_engine/django.db.backends.mysql.yaml delete mode 100644 roles/ara_api/tasks/database_engine/django.db.backends.postgresql.yaml delete mode 100644 roles/ara_api/tasks/database_engine/django.db.backends.sqlite3.yaml delete mode 100644 roles/ara_api/tasks/install/distribution.yaml delete mode 100644 roles/ara_api/tasks/install/pypi.yaml delete mode 100644 roles/ara_api/tasks/install/source.yaml delete mode 100644 roles/ara_api/tasks/main.yaml delete mode 100644 roles/ara_api/tasks/pre-requirements.yaml delete mode 100644 roles/ara_api/tasks/wsgi_server/gunicorn.yaml delete mode 100644 roles/ara_api/templates/ara-api.service.j2 delete mode 100644 roles/ara_api/vars/CentOS.yaml delete mode 120000 roles/ara_api/vars/Debian.yaml delete mode 100644 roles/ara_api/vars/Fedora.yaml delete mode 120000 roles/ara_api/vars/RedHat.yaml delete mode 100644 roles/ara_api/vars/Ubuntu.yaml delete mode 100644 roles/ara_frontend_nginx/README.md delete mode 100644 roles/ara_frontend_nginx/handlers/main.yaml delete mode 100644 roles/ara_frontend_nginx/meta/main.yaml delete mode 100644 roles/ara_frontend_nginx/tasks/main.yaml delete mode 100644 roles/ara_frontend_nginx/templates/ara-api.conf.j2 delete mode 100644 roles/ara_frontend_nginx/templates/ara-web.conf.j2 delete mode 100644 roles/ara_frontend_nginx/vars/CentOS.yaml delete mode 120000 roles/ara_frontend_nginx/vars/Debian.yaml delete mode 100644 roles/ara_frontend_nginx/vars/Fedora.yaml delete mode 120000 roles/ara_frontend_nginx/vars/RedHat.yaml delete mode 100644 roles/ara_frontend_nginx/vars/Ubuntu.yaml delete mode 100644 roles/ara_web/README.md delete mode 100644 roles/ara_web/defaults/main.yaml delete mode 100644 roles/ara_web/handlers/main.yaml delete mode 100644 roles/ara_web/meta/main.yaml delete mode 100644 roles/ara_web/tasks/install/source.yaml delete mode 100644 roles/ara_web/tasks/main.yaml delete mode 100644 roles/ara_web/tasks/nodejs.yaml delete mode 100644 roles/ara_web/templates/ara-web.service.j2 delete mode 100644 tests/test_tasks.yaml delete mode 100644 tests/vars/distributed_sqlite_tests.yaml delete mode 100644 tests/vars/mysql_tests.yaml delete mode 100644 tests/vars/postgresql_tests.yaml delete mode 100644 tests/with_distributed_sqlite.yaml delete mode 100644 tests/with_fedora_packages.yaml delete mode 100644 tests/with_mysql.yaml delete mode 100644 tests/with_postgresql.yaml delete mode 100644 tests/zuul_metadata.yaml delete mode 100644 tests/zuul_post_logs.yaml delete mode 100644 tests/zuul_post_with_mysql.yaml delete mode 100644 tests/zuul_post_with_postgresql.yaml delete mode 100644 tests/zuul_pre_multinode_networking.yaml diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 6f41c2a..0000000 --- a/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# ansible-galaxy collection build generates .tar.gz files -*.tar.gz diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 30ace6a..0000000 --- a/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - {one line to give the program's name and a brief idea of what it does.} - Copyright (C) {year} {name of author} - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - {project} Copyright (C) {year} {fullname} - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index cece44f..0000000 --- a/README.md +++ /dev/null @@ -1,68 +0,0 @@ -# ara-collection - -Opinionated collection of Ansible roles available on [Ansible Galaxy](https://galaxy.ansible.com/recordsansible/ara) -for deploying and configuring [ARA Records Ansible](https://github.com/ansible-community/ara). - -ARA Records Ansible and makes it easier to understand and troubleshoot. - -![ara](https://raw.githubusercontent.com/ansible-community/ara-collection/master/doc/source/_static/ara-with-icon.png) - -## ara_api - -![ara_api](https://raw.githubusercontent.com/ansible-community/ara-collection/master/doc/source/_static/ansible-role-ara-api.png) - -A role to install and run the ARA API server and built-in reporting interface -in various supported configurations. - -Documentation: [roles/ara_api/README.md](https://github.com/ansible-community/ara-collection/blob/master/roles/ara_api/README.md) - -## ara_web - -![ara_web](doc/source/_static/ansible-role-ara-web.png) - -Documentation: [roles/ara_web/README.md](https://github.com/ansible-community/ara-collection/blob/master/roles/ara_web/README.md) - -## ara_frontend_nginx - -A role that sets up a basic nginx reverse proxy for serving the API server as -well as ara-web. - -Documentation: [roles/ara_frontend_nginx/README.md](https://github.com/ansible-community/ara-collection/blob/master/roles/ara_frontend_nginx/README.md) - -# Community and getting help - -- Bugs, issues and enhancements: https://github.com/ansible-community/ara-collection/issues -- IRC: #ara on [Freenode](https://webchat.freenode.net/?channels=#ara) -- Slack: https://arecordsansible.slack.com ([invitation link](https://join.slack.com/t/arecordsansible/shared_invite/enQtMjMxNzI4ODAxMDQxLTU2NTU3YjMwYzRlYmRkZTVjZTFiOWIxNjE5NGRhMDQ3ZTgzZmQyZTY2NzY5YmZmNDA5ZWY4YTY1Y2Y1ODBmNzc)) - -- Website and blog: https://ara.recordsansible.org -- Twitter: https://twitter.com/recordsansible - -# Contributing - -Contributions to the project are welcome and appreciated ! - -Get started with the [contributor's documentation](https://ara.readthedocs.io/en/latest/contributing.html). - -# Authors - -Contributors to the project can be viewed on [GitHub](https://github.com/ansible-community/ara-collection/graphs/contributors). - -# Copyright - -``` -Copyright (c) 2020 The ARA Records Ansible authors - -ARA Records Ansible is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -ARA Records Ansible is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with ARA Records Ansible. If not, see . -``` diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..dc0935f --- /dev/null +++ b/README.rst @@ -0,0 +1,5 @@ +This project has been moved +--------------------------- + +This project's code and code review is now on GitHub: https://github.com/ansible-community/ara-collection + diff --git a/doc/source/_static/ansible-role-ara-api.png b/doc/source/_static/ansible-role-ara-api.png deleted file mode 100644 index 475115d9b332b9f899177eb7ecc472ed40a3f8e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21679 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 WdW%tR;vf=72?zHb-dnimMBM+E-4JO2 diff --git a/doc/source/_static/ansible-role-ara-web.png b/doc/source/_static/ansible-role-ara-web.png deleted file mode 100644 index 07a6bae98132b4f0becbf126f48733eae267360c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34924 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 Vw^{c!g9^W-B^6F3p16GPe*tQXyy^e| diff --git a/doc/source/_static/ara-with-icon.png b/doc/source/_static/ara-with-icon.png deleted file mode 100755 index 919811867a516bd5c1753dbb6bac806de94898a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20798 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 Y^+zh5tSS8}ftMpP&^6Vm(Q=IZALQc?+5i9m diff --git a/galaxy.yml b/galaxy.yml deleted file mode 100644 index be29f6d..0000000 --- a/galaxy.yml +++ /dev/null @@ -1,13 +0,0 @@ -namespace: recordsansible -name: ara -version: 0.0.4 -readme: README.md -authors: - - ARA Records Ansible (https://github.com/ansible-community/ara) -description: null -license_file: LICENSE -tags: null -repository: https://github.com/ansible-community/ara-collection -documentation: https://github.com/ansible-community/ara-collection -homepage: https://ara.recordsansible.org -issues: https://github.com/ansible-community/ara-collection/issues diff --git a/roles/ara_api/README.md b/roles/ara_api/README.md deleted file mode 100644 index aa728be..0000000 --- a/roles/ara_api/README.md +++ /dev/null @@ -1,90 +0,0 @@ -# Ansible role: ara_api - -![ara_api](https://raw.githubusercontent.com/ansible-community/ara-collection/master/doc/source/_static/ansible-role-ara-api.png) - -This Ansible role provides a framework for installing one or many instances of the -[ARA](https://github.com/ansible-community/ara) API Server in a variety of -opinionated deployment topologies. - -It is currently tested and supported against Ubuntu 18.04, Fedora 30 and CentOS 8. - -## Role Variables - -See [defaults/main.yaml](https://github.com/ansible-community/ara-collection/blob/master/roles/ara_api/defaults/main.yaml). - -## TL;DR - -Playbook that runs the role with defaults: - -```yaml -- name: Install ARA with default settings and no persistent API server - hosts: all - gather_facts: yes - roles: - - ara_api -``` - -What the role ends up doing by default: - -- Installs required packages (``git``, ``virtualenv``, etc.) if superuser privileges are available -- Stores everything in the home directory of the user in ``~/.ara`` -- Retrieves ARA from source -- Installs ARA in a virtualenv -- Generates a random secret key if none are already configured or provided -- Sets up API configuration in ``~/.ara/server/settings.yaml`` -- Runs the API SQL migrations (``ara-manage migrate``) - -## About deployment topologies - -This Ansible role is designed to support different opinionated topologies that -can be selected with role variables. - -For example, the following role variables are used to provide the topology from -the ``TL;DR`` above: - -- ``ara_api_install_method: source`` -- ``ara_api_wsgi_server: null`` -- ``ara_api_database_engine: django.db.backends.sqlite3`` -- ``ara_api_web_server: null`` - -The intent is that as the role gains support for other install methods, -wsgi servers, database engines or web servers, it will be possible to -mix and match according to preference or requirements. - -Perhaps ARA could be installed from pypi and run with gunicorn, nginx and mysql. -Or maybe it could be installed from distribution packages and set up to run -with apache, mod_wsgi and postgresql. -Or any combination of any of those. - -## Example playbooks - -Install ARA and set up the API to be served by a persistent gunicorn service: - -```yaml -- name: Install ARA and set up the API to be served by gunicorn - hosts: all - gather_facts: yes - vars: - ara_api_wsgi_server: gunicorn - roles: - - ara_api -``` - -Install ARA and set up the API to be served by nginx in front of gunicorn: - -```yaml -# Requires superuser privileges to set up nginx and the ara-api service -# The API will be reachable at http://api.ara.example.org -- name: Install ARA and set up the API to be served by nginx in front of gunicorn - hosts: all - gather_facts: yes - vars: - ara_api_frontend_server: nginx - ara_api_wsgi_server: gunicorn - ara_api_fqdn: api.ara.example.org - ara_api_allowed_hosts: - - api.ara.example.org - ara_api_frontend_vhost: custom_vhost.conf.j2 - roles: - - ara_api -``` diff --git a/roles/ara_api/defaults/main.yaml b/roles/ara_api/defaults/main.yaml deleted file mode 100644 index 65bc540..0000000 --- a/roles/ara_api/defaults/main.yaml +++ /dev/null @@ -1,219 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -# By default, tasks in this role that could result in configuration or -# credentials being printed by Ansible are set up to hide the output to prevent -# sensitive information from being exposed. -# Setting ara_api_secure_logging to false will make Ansible print the raw, -# unfiltered result of these tasks. -# Note that it does not have any impact on tasks that are recorded by ARA. -# It is only for the output when running this specific role. -ara_api_secure_logging: true - -# Root directory where every file for the ARA installation are located -ara_api_root_dir: "{{ ansible_user_dir }}/.ara" - -# Directory where logs are written to -ara_api_log_dir: "{{ ara_api_root_dir }}/logs" - -# Whether or not ara should be installed in a virtual environment. -# This defaults to true to prevent conflicting with system or distribution -# python packages. -ara_api_venv: true - -# When using a virtualenv, path to where it will be installed -ara_api_venv_path: "{{ ara_api_root_dir }}/virtualenv" - -# How ARA will be installed -# - source [default]: installs from a local or remote git repository -# - distribution: installs from distribution packages, if available -# - pypi [planned]: installs from pypi -ara_api_install_method: source - -# When installing from source, the URL or filesystem path where the git source -# repository can be cloned from. -ara_api_source: "https://opendev.org/recordsansible/ara" - -# When installing from source, location where the source repository will be checked out to. -ara_api_source_checkout: "{{ ara_api_root_dir }}/git/ara" - -# Version of ARA to install -# When installing from source, this can be a git ref (tag, branch, commit, etc) -# When installing from PyPi, it would be a version number that has been released. -# When using "latest" as the source version, HEAD will be used -# When using "latest" as the pypi version, the latest release will be used -ara_api_version: master - -# The frontend/web server for serving the ARA API -# It is recommended to specify a web server when deploying a production environment. -# - null [default]: No frontend server will be set up. -# - nginx: Nginx will be configured in front of the WSGI application server. -# - apache [planned] -ara_api_frontend_server: null - -# Path to a custom vhost configuration jinja template -# The vhost configuration templates provided by the role are simple by design -# and are not sufficient to cover every use cases. -# Use this variable if you need to have your own custom nginx or apache configuration. -ara_api_frontend_vhost: null - -# The WSGI server for running ARA's API server -# - null [default]: No persistent WSGI application server will be set up. Only the offline API client will work. -# - gunicorn: gunicorn will be installed and set up to run the API as a systemd service. -# - mod_wsgi [planned] -ara_api_wsgi_server: null - -# Address and port on which the wsgi server will bind -# Changing this value means you might need to adjust "ara_api_allowed_hosts" and -# "ara_api_cors_origin_whitelist". -ara_api_wsgi_bind: "127.0.0.1:8000" - -# Amount of worker processes for the wsgi server -# Recommended default formula by gunicorn: https://docs.gunicorn.org/en/stable/design.html#how-many-workers -ara_api_wsgi_workers: "{{ ansible_processor_count * ansible_processor_cores * ansible_processor_threads_per_core * 2 + 1 }}" - -# When using a frontend server, the domain or address it will be listening on -ara_api_fqdn: "{{ ansible_default_ipv4['address'] | default(ansible_default_ipv6['address']) }}" - -#################################### -# ara API configuration settings -# For more information, see documentation: https://ara.readthedocs.io -#################################### - -# ARA_BASE_DIR - Default directory for storing data and configuration -ara_api_base_dir: "{{ ara_api_root_dir }}/server" - -# ARA_SETTINGS - Path to an ARA API configuration file -ara_api_settings: "{{ ara_api_base_dir }}/settings.yaml" - -# ARA_ENV - Environment to load configuration for -ara_api_env: default - -# ARA_READ_LOGIN_REQUIRED - Whether authentication is required for reading data -ara_api_read_login_required: false - -# ARA_WRITE_LOGIN_REQUIRED - Whether authentication is required for writing data -ara_api_write_login_required: false - -# ARA_PAGE_SIZE - Amount of results returned per page by the API -ara_api_page_size: 100 - -# ARA_LOG_LEVEL - Log level of the different components -ara_api_log_level: INFO - -# ARA_LOGGING - Python logging configuration -ara_api_logging: - disable_existing_loggers: false - formatters: - normal: - format: '%(asctime)s %(levelname)s %(name)s: %(message)s' - handlers: - console: - class: logging.handlers.TimedRotatingFileHandler - formatter: normal - level: "{{ ara_api_log_level }}" - filename: "{{ ara_api_log_dir }}/server.log" - when: 'midnight' - interval: 1 - backupCount: 30 - loggers: - ara: - handlers: - - console - level: "{{ ara_api_log_level }}" - propagate: 0 - root: - handlers: - - console - level: "{{ ara_api_log_level }}" - version: 1 - -# ARA_CORS_ORIGIN_ALLOW_ALL - django-cors-headers’s CORS_ORIGIN_WHITELIST_ALLOW_ALL setting -ara_api_cors_origin_allow_all: false - -# ARA_CORS_ORIGIN_WHITELIST - django-cors-headers’s CORS_ORIGIN_WHITELIST setting -ara_api_cors_origin_whitelist: - - "http://127.0.0.1:8000" - - "http://localhost:3000" - -# ARA_CORS_ORIGIN_REGEX_WHITELIST - django-cors-headers’s CORS_ORIGIN_REGEX_WHITELIST setting -ara_api_cors_origin_regex_whitelist: [] - -# ARA_SERVER_ALLOWED_HOSTS - Django’s ALLOWED_HOSTS setting -ara_api_allowed_hosts: - - "127.0.0.1" - - "localhost" - - "::1" - - "{{ ara_api_fqdn }}" - -# ARA_DEBUG - Django's DEBUG setting -# It is not recommended to run with debug enabled in production. -ara_api_debug: false - -# ARA_SECRET_KEY - Django's SECRET_KEY setting -# Note: If no key is provided, a random one will be generated once and persisted -ara_api_secret_key: null - -# ARA_DISTRIBUTED_SQLITE - Whether to enable distributed sqlite backend -ara_api_distributed_sqlite: false - -# ARA_DISTRIBUTED_SQLITE_PREFIX - Prefix to delegate to the distributed sqlite backend -ara_api_distributed_sqlite_prefix: ara-report - -# ARA_DISTRIBUTED_SQLITE_ROOT - Root under which sqlite databases are expected -ara_api_distributed_sqlite_root: /var/www/logs - -# ARA_DATABASE_ENGINE - Django’s ENGINE database setting -ara_api_database_engine: "{{ ara_api_distributed_sqlite | ternary('ara.server.db.backends.distributed_sqlite', 'django.db.backends.sqlite3') }}" - -# ARA_DATABASE_NAME - Django’s NAME database setting -ara_api_database_name: "{{ ara_api_base_dir }}/ansible.sqlite" - -# ARA_DATABASE_USER - Django’s USER database setting -ara_api_database_user: null - -# ARA_DATABASE_PASSWORD - Django’s PASSWORD database setting -ara_api_database_password: null - -# ARA_DATABASE_HOST - Django’s HOST database setting -ara_api_database_host: null - -# ARA_DATABASE_PORT - Django’s PORT database setting -ara_api_database_port: null - -# ARA_DATABASE_CONN_MAX_AGE - Django's CONN_MAX_AGE database setting -ara_api_database_conn_max_age: 0 - -# ARA_TIME_ZONE - Time zone used when storing and returning results -# Note: the default provided by ARA is dynamic and is set to the local system -# timezone but Ansible doesn't provide, for example, an ansible_timezone fact -# that we could use here. With that in mind, UTC is the best default for now. -ara_api_time_zone: UTC - -# ARA cleanup settings -# The following settings configure daily maintenance cronjobs -ara_api_configure_cron: false - -# When configuring cronjobs, only provide the arguments for the ara CLI utility -ara_api_cleanup_crons: - - name: ara_api expire running playbooks - arguments: 'expire --server http://localhost:8000 --client http --confirm --hours 24' - special_time: 'daily' # you can also use other time arguments from the cron module - - name: ara_api prune old reports - arguments: 'playbook prune --server http://localhost:8000 --client http --confirm --days 30' - special_time: 'daily' diff --git a/roles/ara_api/files/ara-gunicorn.te b/roles/ara_api/files/ara-gunicorn.te deleted file mode 100644 index 57d006e..0000000 --- a/roles/ara_api/files/ara-gunicorn.te +++ /dev/null @@ -1,15 +0,0 @@ -module ara-gunicorn 1.0; - -require { - type init_t; - type user_home_t; - class file { create execute execute_no_trans ioctl lock map open read write }; - class lnk_file { getattr read }; -} - -#============= init_t ============== - -#!!!! This avc can be allowed using the boolean 'domain_can_mmap_files' -allow init_t user_home_t:file map; -allow init_t user_home_t:file { create execute execute_no_trans ioctl lock open read write }; -allow init_t user_home_t:lnk_file { getattr read }; diff --git a/roles/ara_api/handlers/main.yaml b/roles/ara_api/handlers/main.yaml deleted file mode 100644 index 7bfeae1..0000000 --- a/roles/ara_api/handlers/main.yaml +++ /dev/null @@ -1,26 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -- name: restart ara-api - become: yes - service: - name: ara-api - state: restarted - when: - - ara_api_wsgi_server is not none - - ara_api_service_enabled is not changed diff --git a/roles/ara_api/meta/main.yaml b/roles/ara_api/meta/main.yaml deleted file mode 100644 index 2a3c1b3..0000000 --- a/roles/ara_api/meta/main.yaml +++ /dev/null @@ -1,26 +0,0 @@ ---- -# Copyright (c) 2020 The ARA Records Ansible authors -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -galaxy_info: - author: The ARA Records Ansible authors - description: Installs an ARA API server and the built-in reporting interface - license: GPLv3 - min_ansible_version: 2.7 - platforms: - - name: EL - versions: - - 8 - - name: Fedora - versions: - - 31 - - 32 - - name: Ubuntu - versions: - - bionic - - focal - galaxy_tags: - - ansible - - ara - -dependencies: [] diff --git a/roles/ara_api/tasks/config.yaml b/roles/ara_api/tasks/config.yaml deleted file mode 100644 index 597a3b7..0000000 --- a/roles/ara_api/tasks/config.yaml +++ /dev/null @@ -1,127 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -- name: Verify if a configuration file exists - stat: - path: "{{ ara_api_settings }}" - register: settings_stat - -# If no secret key has been provided and this isn't the first time we are -# running, recover the secret key from the existing configuration file. -- when: - - ara_api_secret_key is none - - settings_stat.stat.exists - block: - - name: Read the existing configuration file - command: cat "{{ ara_api_settings }}" - changed_when: false - no_log: "{{ ara_api_secure_logging }}" - register: settings_contents - - - name: Recover existing secret key - vars: - config: "{{ settings_contents.stdout | from_yaml }}" - set_fact: - ara_api_secret_key: "{{ config[ara_api_env]['SECRET_KEY'] }}" - no_log: "{{ ara_api_secure_logging }}" - -# If no secret key has been provided and this is the first time we are -# running, generate a new random secret key that will be persisted in the -# configuration file. -- when: - - ara_api_secret_key is none - - not settings_stat.stat.exists - block: - - name: Generate a random secret key - environment: - PATH: "{{ path_with_virtualenv }}" - command: python3 -c "from django.utils.crypto import get_random_string; print(get_random_string(length=50))" - no_log: "{{ ara_api_secure_logging }}" - register: generated_key - - - name: Set ara_api_secret_key - set_fact: - ara_api_secret_key: "{{ generated_key.stdout }}" - no_log: "{{ ara_api_secure_logging }}" - -- name: Validate distributed sqlite configuration - assert: - that: - - "ara_api_database_engine == 'ara.server.db.backends.distributed_sqlite'" - msg: | - The database engine should be 'ara.server.db.backends.distributed_sqlite' - when 'ara_api_distributed_sqlite' is true. - when: ara_api_distributed_sqlite - -# Put configuration in a format we can write to a file -- name: Reconcile configuration - vars: - reconciled_configuration: - ALLOWED_HOSTS: "{{ ara_api_allowed_hosts }}" - BASE_DIR: "{{ ara_api_base_dir }}" - CORS_ORIGIN_ALLOW_ALL: "{{ ara_api_cors_origin_allow_all }}" - CORS_ORIGIN_WHITELIST: "{{ ara_api_cors_origin_whitelist }}" - CORS_ORIGIN_REGEX_WHITELIST: "{{ ara_api_cors_origin_regex_whitelist }}" - DATABASE_ENGINE: "{{ ara_api_database_engine }}" - DATABASE_NAME: "{{ ara_api_database_name }}" - DATABASE_USER: "{{ ara_api_database_user }}" - DATABASE_PASSWORD: "{{ ara_api_database_password }}" - DATABASE_HOST: "{{ ara_api_database_host }}" - DATABASE_PORT: "{{ ara_api_database_port }}" - DATABASE_CONN_MAX_AGE: "{{ ara_api_database_conn_max_age }}" - DEBUG: "{{ ara_api_debug }}" - DISTRIBUTED_SQLITE: "{{ ara_api_distributed_sqlite }}" - DISTRIBUTED_SQLITE_PREFIX: "{{ ara_api_distributed_sqlite_prefix }}" - DISTRIBUTED_SQLITE_ROOT: "{{ ara_api_distributed_sqlite_root }}" - LOGGING: "{{ ara_api_logging }}" - LOG_LEVEL: "{{ ara_api_log_level }}" - SECRET_KEY: "{{ ara_api_secret_key }}" - READ_LOGIN_REQUIRED: "{{ ara_api_read_login_required }}" - WRITE_LOGIN_REQUIRED: "{{ ara_api_write_login_required }}" - PAGE_SIZE: "{{ ara_api_page_size }}" - TIME_ZONE: "{{ ara_api_time_zone }}" - set_fact: - ara_api_configuration: "{'{{ ara_api_env }}': {{ reconciled_configuration }} }" - no_log: "{{ ara_api_secure_logging }}" - -- name: Set up the ARA API configuration file - copy: - content: | - --- - # Managed by the ara Ansible role - {{ ara_api_configuration | to_nice_yaml(indent=2) }} - dest: "{{ ara_api_settings }}" - mode: 0640 - notify: - - restart ara-api - no_log: "{{ ara_api_secure_logging }}" - -- name: Set up ARA API cronjobs - cron: - name: "{{ job['name'] }}" - special_time: "{{ job['special_time'] | default(omit) }}" - minute: "{{ job['minute'] | default(omit) }}" - hour: "{{ job['hour'] | default(omit) }}" - day: "{{ job['day'] | default(omit) }}" - weekday: "{{ job['weekday'] | default(omit) }}" - month: "{{ job['month'] | default(omit) }}" - job: "{{ ara_api_venv_path }}/bin/ara {{ job['arguments'] }} >/dev/null 2>&1" - loop: "{{ ara_api_cleanup_crons }}" - loop_control: - loop_var: 'job' - when: ara_api_configure_cron diff --git a/roles/ara_api/tasks/database_engine/ara.server.db.backends.distributed_sqlite.yaml b/roles/ara_api/tasks/database_engine/ara.server.db.backends.distributed_sqlite.yaml deleted file mode 100644 index 1394fee..0000000 --- a/roles/ara_api/tasks/database_engine/ara.server.db.backends.distributed_sqlite.yaml +++ /dev/null @@ -1,22 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -# This ensures the WSGI application servers are set up to use the right endpoint -- name: Set WSGI application to distributed_sqlite - set_fact: - _ara_api_wsgi_application: "ara.server.wsgi:distributed_sqlite" diff --git a/roles/ara_api/tasks/database_engine/django.db.backends.mysql.yaml b/roles/ara_api/tasks/database_engine/django.db.backends.mysql.yaml deleted file mode 100644 index 9400dd9..0000000 --- a/roles/ara_api/tasks/database_engine/django.db.backends.mysql.yaml +++ /dev/null @@ -1,55 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -- name: Retrieve list of missing required packages for mysql - set_fact: - _mysql_missing_packages: "{{ ara_api_mysql_packages | difference(ansible_facts.packages.keys()) }}" - -# Only attempt to elevate privileges if there are any missing packages -- when: _mysql_missing_packages | length > 0 - block: - - name: Install required packages - become: yes - package: - name: "{{ ara_api_mysql_packages }}" - state: present - rescue: - - name: Fail due to missing packages - fail: - msg: "Failed to elevate privileges and install missing required packages. Install the following packages before running this role again: {{ _mysql_missing_packages | join(' ') }}" - -# Django requires mysqclient when using mysql -# https://docs.djangoproject.com/en/2.2/ref/databases/#mysql-db-api-drivers -- name: Ensure mysqlclient is installed - pip: - name: mysqlclient - state: present - virtualenv: "{{ ara_api_venv | bool | ternary(ara_api_venv_path, omit) }}" - virtualenv_command: /usr/bin/python3 -m venv - -- name: Run SQL migrations - environment: - ARA_SETTINGS: "{{ ara_api_settings }}" - PATH: "{{ path_with_virtualenv }}" - command: ara-manage migrate - run_once: true - register: _ara_sql_migrations - retries: 3 - delay: 5 - until: _ara_sql_migrations is succeeded - changed_when: "'No migrations to apply' not in _ara_sql_migrations.stdout" diff --git a/roles/ara_api/tasks/database_engine/django.db.backends.postgresql.yaml b/roles/ara_api/tasks/database_engine/django.db.backends.postgresql.yaml deleted file mode 100644 index 7317249..0000000 --- a/roles/ara_api/tasks/database_engine/django.db.backends.postgresql.yaml +++ /dev/null @@ -1,56 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -- name: Retrieve list of missing required packages for postgresql - set_fact: - _postgresql_missing_packages: "{{ ara_api_postgresql_packages | difference(ansible_facts.packages.keys()) }}" - -# Only attempt to elevate privileges if there are any missing packages -- when: _postgresql_missing_packages | length > 0 - block: - - name: Install required packages - become: yes - package: - name: "{{ ara_api_postgresql_packages }}" - state: present - rescue: - - name: Fail due to missing packages - fail: - msg: "Failed to elevate privileges and install missing required packages. Install the following packages before running this role again: {{ _postgresql_missing_packages | join(' ') }}" - -# Django requires psycopg2 when using postgresql -# https://docs.djangoproject.com/en/2.2/ref/databases/#postgresql-notes -- name: Ensure psycopg2 is installed - pip: - name: psycopg2 - state: present - virtualenv: "{{ ara_api_venv | bool | ternary(ara_api_venv_path, omit) }}" - virtualenv_command: /usr/bin/python3 -m venv - -- name: Run SQL migrations - environment: - ARA_SETTINGS: "{{ ara_api_settings }}" - PATH: "{{ path_with_virtualenv }}" - command: ara-manage migrate - run_once: true - register: _ara_sql_migrations - retries: 3 - delay: 5 - until: _ara_sql_migrations is succeeded - register: _ara_sql_migrations - changed_when: "'No migrations to apply' not in _ara_sql_migrations.stdout" diff --git a/roles/ara_api/tasks/database_engine/django.db.backends.sqlite3.yaml b/roles/ara_api/tasks/database_engine/django.db.backends.sqlite3.yaml deleted file mode 100644 index 088c2ca..0000000 --- a/roles/ara_api/tasks/database_engine/django.db.backends.sqlite3.yaml +++ /dev/null @@ -1,32 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -- name: Ensure the database directory exists - become: "{{ (ansible_user_dir in ara_api_database_name) | ternary(false, true) }}" - file: - path: "{{ ara_api_database_name | dirname }}" - state: directory - -- name: Run SQL migrations - become: "{{ (ansible_user_dir in ara_api_database_name) | ternary(false, true) }}" - environment: - ARA_SETTINGS: "{{ ara_api_settings }}" - PATH: "{{ path_with_virtualenv }}" - command: ara-manage migrate - register: _ara_sql_migrations - changed_when: "'No migrations to apply' not in _ara_sql_migrations.stdout" diff --git a/roles/ara_api/tasks/install/distribution.yaml b/roles/ara_api/tasks/install/distribution.yaml deleted file mode 100644 index f360c92..0000000 --- a/roles/ara_api/tasks/install/distribution.yaml +++ /dev/null @@ -1,34 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -- name: Validate if the distribution is supported - fail: - msg: | - {{ ansible_distribution }} does not support installation from distribution packages yet. - when: ara_distribution_packages | length == 0 - -- name: Install ara from distribution packages - become: yes - package: - name: "{{ ara_distribution_packages }}" - state: present - -# This lets us use "path_with_virtualenv" without conditions everywhere -- name: Don't prefix the virtualenv bin directory to PATH - set_fact: - path_with_virtualenv: "{{ ansible_env.PATH }}" diff --git a/roles/ara_api/tasks/install/pypi.yaml b/roles/ara_api/tasks/install/pypi.yaml deleted file mode 100644 index 1969204..0000000 --- a/roles/ara_api/tasks/install/pypi.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -- name: Install required packages from Pypi - pip: - name: ara[server] - state: present - virtualenv: "{{ ara_api_venv | bool | ternary(ara_api_venv_path, omit) }}" - virtualenv_command: /usr/bin/python3 -m venv - -- name: Prefix the virtualenv bin directory to PATH - set_fact: - path_with_virtualenv: "{{ ara_api_venv_path }}/bin:{{ ansible_env.PATH }}" - when: ara_api_venv | bool diff --git a/roles/ara_api/tasks/install/source.yaml b/roles/ara_api/tasks/install/source.yaml deleted file mode 100644 index d73c1a5..0000000 --- a/roles/ara_api/tasks/install/source.yaml +++ /dev/null @@ -1,41 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -- name: Prepare git repository for ara - git: - repo: "{{ ara_api_source }}" - dest: "{{ ara_api_source_checkout }}" - version: "{{ (ara_api_version == 'latest') | ternary('HEAD', ara_api_version) }}" - -- name: Install ara - pip: - name: "{{ ara_api_source_checkout }}[server]" - state: present - virtualenv: "{{ ara_api_venv | bool | ternary(ara_api_venv_path, omit) }}" - virtualenv_command: /usr/bin/python3 -m venv - -- name: Prefix the virtualenv bin directory to PATH - set_fact: - path_with_virtualenv: "{{ ara_api_venv_path }}/bin:{{ ansible_env.PATH }}" - when: ara_api_venv | bool - -# This lets us use "path_with_virtualenv" without conditions everywhere -- name: Otherwise don't prefix the virtualenv bin directory to PATH - set_fact: - path_with_virtualenv: "{{ ansible_env.PATH }}" - when: not ara_api_venv | bool diff --git a/roles/ara_api/tasks/main.yaml b/roles/ara_api/tasks/main.yaml deleted file mode 100644 index 307dc9a..0000000 --- a/roles/ara_api/tasks/main.yaml +++ /dev/null @@ -1,44 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -- name: Include OS family/distribution specific variables - include_vars: "{{ item }}" - with_first_found: - - "{{ ansible_distribution }}.yaml" - - "{{ ansible_os_family }}.yaml" - -- name: Ensure pre-requirements for running are met - include_tasks: pre-requirements.yaml - -- name: Include installation of ARA - include_tasks: "install/{{ ara_api_install_method }}.yaml" - -- name: Include configuration of the ARA API - include_tasks: config.yaml - -- name: Include configuration of the database engine - include_tasks: "database_engine/{{ ara_api_database_engine }}.yaml" - -- name: Include installation of the WSGI backend server - include_tasks: "wsgi_server/{{ ara_api_wsgi_server }}.yaml" - when: ara_api_wsgi_server is not none - -- name: Include installation of the frontend server - include_role: - name: "ara_frontend_{{ ara_api_frontend_server }}" - when: ara_api_frontend_server is not none diff --git a/roles/ara_api/tasks/pre-requirements.yaml b/roles/ara_api/tasks/pre-requirements.yaml deleted file mode 100644 index 0ac0f3a..0000000 --- a/roles/ara_api/tasks/pre-requirements.yaml +++ /dev/null @@ -1,84 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -# EL8 doesn't install a python3 interpreter by default. -# System packages rely on /usr/libexec/platform-python and Ansible will use it -# but we want to use the non-system one. Install it if it's missing. -- name: Ensure python3 is installed for EL8 - package: - name: python3 - state: present - become: yes - when: - - ansible_distribution | lower in ["redhat", "centos"] - - ansible_distribution_major_version == "8" - -# The ansible_python_version fact might end up retrieving the version of -# python2 so we need to explicitely get the version of python 3 available. -- name: Validate availability of Python 3.5 - command: /usr/bin/python3 -c 'import sys; print(".".join(map(str, sys.version_info[:2])))' - changed_when: false - failed_when: false - register: python_version - -- name: Fail pre-emptively if running Python <3.5 - fail: - msg: "Python >=3.5 is required to run ARA" - when: python_version.stdout is version('3.5', '<') or python_version.rc != 0 - -- name: Get list of installed packages - package_facts: - manager: "auto" - no_log: "{{ ara_api_secure_logging }}" - -- name: Retrieve list of missing required packages - set_fact: - ara_api_missing_packages: "{{ ara_api_required_packages | difference(ansible_facts.packages.keys()) }}" - -# Only attempt to elevate privileges if there are any missing packages -- when: ara_api_missing_packages | length > 0 - block: - - name: Install required packages - become: yes - package: - name: "{{ ara_api_required_packages }}" - state: present - rescue: - - name: Fail due to missing packages - fail: - msg: "Failed to elevate privileges and install missing required packages. Install the following packages before running this role again: {{ ara_missing_packages | join(' ') }}" - -# The following tasks dynamically enable escalated privileges only when the -# directory to create is not located in the user's home directory. -- name: Ensure ara_api_root_dir exists - file: - path: "{{ ara_api_root_dir }}" - state: directory - mode: 0755 - -- name: Ensure ara_api_base_dir exists - file: - path: "{{ ara_api_base_dir }}" - state: directory - mode: 0750 - -- name: Ensure ara_api_log_dir exists - file: - path: "{{ ara_api_log_dir }}" - state: directory - mode: 0750 diff --git a/roles/ara_api/tasks/wsgi_server/gunicorn.yaml b/roles/ara_api/tasks/wsgi_server/gunicorn.yaml deleted file mode 100644 index 71f12cc..0000000 --- a/roles/ara_api/tasks/wsgi_server/gunicorn.yaml +++ /dev/null @@ -1,74 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -- name: Install gunicorn - pip: - name: gunicorn - state: present - virtualenv: "{{ ara_api_venv | bool | ternary(ara_api_venv_path, omit) }}" - virtualenv_command: /usr/bin/python3 -m venv - -- name: Get path to gunicorn - command: which gunicorn - changed_when: false - register: _gunicorn_cmd - environment: - PATH: "{{ path_with_virtualenv }}" - -- name: Set path to gunicorn - set_fact: - _gunicorn_path: "{{ _gunicorn_cmd.stdout }}" - -- when: ansible_os_family == "RedHat" - block: - - name: Transfer gunicorn selinux type enforcement file - copy: - src: ara-gunicorn.te - dest: "{{ ara_api_root_dir }}/ara-gunicorn.te" - - # TODO: Only compile a new module and policy package when necessary - - name: Compile ara-gunicorn selinux module - command: "checkmodule -M -m -o {{ ara_api_root_dir }}/ara-gunicorn.mod {{ ara_api_root_dir }}/ara-gunicorn.te" - - - name: Compile ara-gunicorn selinux policy package - command: "semodule_package -o {{ ara_api_root_dir }}/ara-gunicorn.pp -m {{ ara_api_root_dir }}/ara-gunicorn.mod" - -- become: yes - block: - # TODO: Only install the selinux module if it has changed - - name: Install selinux policy package - command: "semodule -i {{ ara_api_root_dir }}/ara-gunicorn.pp" - when: ansible_os_family == "RedHat" - - - name: Set up systemd unit file for gunicorn to run the ARA API - template: - src: ara-api.service.j2 - dest: /etc/systemd/system/ara-api.service - owner: root - group: root - mode: 0644 - notify: - - restart ara-api - - - name: Enable and start ara-api with gunicorn - service: - name: ara-api - state: started - enabled: yes - daemon_reload: yes - register: ara_api_service_enabled diff --git a/roles/ara_api/templates/ara-api.service.j2 b/roles/ara_api/templates/ara-api.service.j2 deleted file mode 100644 index aa2b079..0000000 --- a/roles/ara_api/templates/ara-api.service.j2 +++ /dev/null @@ -1,16 +0,0 @@ -[Unit] -Description=ARA Records Ansible API with gunicorn -After=network.target - -[Service] -User={{ ansible_user_id }} -RuntimeDirectory=ara-api -WorkingDirectory={{ ara_api_root_dir }} -Environment=ARA_SETTINGS={{ ara_api_settings }} -ExecStart={{ _gunicorn_path }} --workers={{ ara_api_wsgi_workers }} --bind {{ ara_api_wsgi_bind }} {{ _ara_api_wsgi_application | default('ara.server.wsgi') }} -ExecReload=/bin/kill -s HUP $MAINPID -ExecStop=/bin/kill -s TERM $MAINPID -PrivateTmp=true - -[Install] -WantedBy=multi-user.target diff --git a/roles/ara_api/vars/CentOS.yaml b/roles/ara_api/vars/CentOS.yaml deleted file mode 100644 index 066f134..0000000 --- a/roles/ara_api/vars/CentOS.yaml +++ /dev/null @@ -1,38 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -# ARA has not been packaged for CentOS or RHEL yet -ara_distribution_packages: [] - -ara_api_required_packages: - - git - - python3 - - policycoreutils-python-utils - -ara_api_postgresql_packages: - - postgresql - - postgresql-devel - - python3-devel - - gcc - -ara_api_mysql_packages: - - mariadb - - mariadb-connector-c-devel - - redhat-rpm-config - - python3-devel - - gcc diff --git a/roles/ara_api/vars/Debian.yaml b/roles/ara_api/vars/Debian.yaml deleted file mode 120000 index c81cefb..0000000 --- a/roles/ara_api/vars/Debian.yaml +++ /dev/null @@ -1 +0,0 @@ -Ubuntu.yaml \ No newline at end of file diff --git a/roles/ara_api/vars/Fedora.yaml b/roles/ara_api/vars/Fedora.yaml deleted file mode 100644 index f72e93f..0000000 --- a/roles/ara_api/vars/Fedora.yaml +++ /dev/null @@ -1,39 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -ara_distribution_packages: - - ara - - ara-server - -ara_api_required_packages: - - git - - python3-virtualenv - - python3-libselinux - - policycoreutils-python-utils - -ara_api_postgresql_packages: - - postgresql - - postgresql-devel - - gcc - -ara_api_mysql_packages: - - mariadb - - mariadb-connector-c-devel - - redhat-rpm-config - - python3-devel - - gcc diff --git a/roles/ara_api/vars/RedHat.yaml b/roles/ara_api/vars/RedHat.yaml deleted file mode 120000 index 87d36d4..0000000 --- a/roles/ara_api/vars/RedHat.yaml +++ /dev/null @@ -1 +0,0 @@ -CentOS.yaml \ No newline at end of file diff --git a/roles/ara_api/vars/Ubuntu.yaml b/roles/ara_api/vars/Ubuntu.yaml deleted file mode 100644 index 8eca4cb..0000000 --- a/roles/ara_api/vars/Ubuntu.yaml +++ /dev/null @@ -1,38 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -# ARA has not been packaged for Ubuntu yet -ara_distribution_packages: [] - -ara_api_required_packages: - - git - - python3-venv - - python3-setuptools - - python-pkg-resources - - python3-pkg-resources - -ara_api_postgresql_packages: - - postgresql - - postgresql-server-dev-10 - - gcc - -ara_api_mysql_packages: - - mariadb-client - - libmariadbclient-dev - - python3-dev - - gcc diff --git a/roles/ara_frontend_nginx/README.md b/roles/ara_frontend_nginx/README.md deleted file mode 100644 index d0067cb..0000000 --- a/roles/ara_frontend_nginx/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# Ansible role: ara_frontend_nginx - -A role for deploying a minimal installation of nginx for ara-api and ara-web. - -This role is not meant to be used on it's own, it should be included by the -``ara_api`` and ``ara_web`` roles in order to have the necessary variables -available. - -It is currently tested and supported against Ubuntu 18.04 and Fedora 29. - -## Role Variables - -- ``ara_api_frontend_vhost``: Path to a custom nginx vhost configuration file for ara-api. -- ``ara_web_frontend_vhost``: Path to a custom nginx vhost configuration file for ara-web. - -## Example playbooks - -Install ARA and set up the API to be served by nginx with a custom vhost configuration -in front of gunicorn: - -```yaml -# The API will be reachable at http://api.ara.example.org -# The web interface will be reachable at http://web.ara.example.org -# The web interface will be set up to query api.ara.example.org. -- name: Deploy ARA API server and web interface - hosts: all - gather_facts: yes - vars: - # ara_api - ara_api_frontend_server: nginx - ara_api_wsgi_server: gunicorn - ara_api_fqdn: api.ara.example.org - ara_api_allowed_hosts: - - api.ara.example.org - ara_api_frontend_vhost: custom_api_vhost.conf.j2 - # ara_web - ara_web_fqdn: web.ara.example.org - ara_web_api_endpoint: "http://api.ara.example.org" - ara_web_frontend_server: nginx - ara_web_frontend_vhost: custom_web_vhost.conf.j2 - roles: - - ara_api - - ara_web -``` diff --git a/roles/ara_frontend_nginx/handlers/main.yaml b/roles/ara_frontend_nginx/handlers/main.yaml deleted file mode 100644 index 08a43fc..0000000 --- a/roles/ara_frontend_nginx/handlers/main.yaml +++ /dev/null @@ -1,24 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -- name: restart nginx - become: yes - service: - name: nginx - state: restarted - when: ara_nginx_enabled is not changed diff --git a/roles/ara_frontend_nginx/meta/main.yaml b/roles/ara_frontend_nginx/meta/main.yaml deleted file mode 100644 index 14448af..0000000 --- a/roles/ara_frontend_nginx/meta/main.yaml +++ /dev/null @@ -1,26 +0,0 @@ ---- -# Copyright (c) 2020 The ARA Records Ansible authors -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -galaxy_info: - author: The ARA Records Ansible authors - description: Installs an nginx reverse proxy in front of ara-web or an ARA API server - license: GPLv3 - min_ansible_version: 2.7 - platforms: - - name: EL - versions: - - 8 - - name: Fedora - versions: - - 31 - - 32 - - name: Ubuntu - versions: - - bionic - - focal - galaxy_tags: - - ansible - - ara - -dependencies: [] diff --git a/roles/ara_frontend_nginx/tasks/main.yaml b/roles/ara_frontend_nginx/tasks/main.yaml deleted file mode 100644 index 8a197ac..0000000 --- a/roles/ara_frontend_nginx/tasks/main.yaml +++ /dev/null @@ -1,80 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -- name: Include OS family/distribution specific variables - include_vars: "{{ item }}" - with_first_found: - - "{{ ansible_distribution }}.yaml" - - "{{ ansible_os_family }}.yaml" - -- become: yes - block: - - name: Install nginx - package: - name: nginx - state: present - - - name: Set selinux boolean to allow nginx to reverse proxy - seboolean: - name: httpd_can_network_connect - state: yes - persistent: yes - when: ansible_os_family == "RedHat" - - - when: ara_api_fqdn is defined - block: - - name: Set up the ARA API nginx vhost - template: - src: "{{ ara_api_frontend_vhost | default('ara-api.conf.j2', True) }}" - dest: "{{ ara_nginx_config_path }}/ara-api.conf" - notify: - - restart nginx - - - name: Enable the API nginx configuration on Debian-like systems - file: - src: "{{ ara_nginx_config_path }}/ara-api.conf" - dest: /etc/nginx/sites-enabled/ara-api.conf - state: link - when: ansible_os_family == 'Debian' - notify: - - restart nginx - - - when: ara_web_fqdn is defined - block: - - name: Set up the ARA API nginx vhost - template: - src: "{{ ara_web_frontend_vhost | default('ara-web.conf.j2', True) }}" - dest: "{{ ara_nginx_config_path }}/ara-web.conf" - notify: - - restart nginx - - - name: Enable the web nginx configuration on Debian-like systems - file: - src: "{{ ara_nginx_config_path }}/ara-web.conf" - dest: /etc/nginx/sites-enabled/ara-web.conf - state: link - when: ansible_os_family == 'Debian' - notify: - - restart nginx - - - name: Enable and start nginx - service: - name: nginx - state: started - enabled: yes - register: ara_nginx_enabled diff --git a/roles/ara_frontend_nginx/templates/ara-api.conf.j2 b/roles/ara_frontend_nginx/templates/ara-api.conf.j2 deleted file mode 100644 index 7204eb3..0000000 --- a/roles/ara_frontend_nginx/templates/ara-api.conf.j2 +++ /dev/null @@ -1,39 +0,0 @@ -upstream ara_api { - # fail_timeout=0 means we always retry an upstream even if it failed - # to return a good HTTP response - server {{ ara_api_wsgi_bind }} fail_timeout=0; -} - -server { - listen 80; - keepalive_timeout 5; - server_name {{ ara_api_fqdn }}; - - access_log /var/log/nginx/{{ ara_api_fqdn }}_access.log; - error_log /var/log/nginx/{{ ara_api_fqdn }}_error.log; - - # There's nothing at /, redirect it to the actual API for convenience - location / { - return 301 http://{{ ara_api_fqdn }}/api/v1/; - } - - location /static { - expires 7d; - add_header Cache-Control "public"; - } - - # Everything, including static files, is served by the backend - location ~ { - # checks if the file exists, if not found proxy to app - try_files $uri @proxy_to_app; - } - - location @proxy_to_app { - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Host $http_host; - - proxy_redirect off; - proxy_pass http://ara_api; - } -} diff --git a/roles/ara_frontend_nginx/templates/ara-web.conf.j2 b/roles/ara_frontend_nginx/templates/ara-web.conf.j2 deleted file mode 100644 index 1fd01a6..0000000 --- a/roles/ara_frontend_nginx/templates/ara-web.conf.j2 +++ /dev/null @@ -1,33 +0,0 @@ -{% if ara_web_dev_server %} -upstream ara_web { - # fail_timeout=0 means we always retry an upstream even if it failed - # to return a good HTTP response - server {{ ara_web_dev_server_bind_address }}:{{ ara_web_dev_server_bind_port }} fail_timeout=0; -} -{% endif %} - -server { - listen 80; - keepalive_timeout 5; - server_name {{ ara_web_fqdn }}; - root {{ ara_web_static_dir }}; - - access_log /var/log/nginx/{{ ara_web_fqdn }}_access.log; - error_log /var/log/nginx/{{ ara_web_fqdn }}_error.log; - - {% if ara_web_dev_server %} - location / { - # checks if the file exists, if not found proxy to app - try_files $uri @proxy_to_app; - } - - location @proxy_to_app { - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Host $http_host; - - proxy_redirect off; - proxy_pass http://ara_web; - } - {% endif %} -} diff --git a/roles/ara_frontend_nginx/vars/CentOS.yaml b/roles/ara_frontend_nginx/vars/CentOS.yaml deleted file mode 100644 index 164743e..0000000 --- a/roles/ara_frontend_nginx/vars/CentOS.yaml +++ /dev/null @@ -1,21 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -ara_nginx_user: nginx -ara_nginx_group: nginx -ara_nginx_config_path: /etc/nginx/conf.d diff --git a/roles/ara_frontend_nginx/vars/Debian.yaml b/roles/ara_frontend_nginx/vars/Debian.yaml deleted file mode 120000 index c81cefb..0000000 --- a/roles/ara_frontend_nginx/vars/Debian.yaml +++ /dev/null @@ -1 +0,0 @@ -Ubuntu.yaml \ No newline at end of file diff --git a/roles/ara_frontend_nginx/vars/Fedora.yaml b/roles/ara_frontend_nginx/vars/Fedora.yaml deleted file mode 100644 index 164743e..0000000 --- a/roles/ara_frontend_nginx/vars/Fedora.yaml +++ /dev/null @@ -1,21 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -ara_nginx_user: nginx -ara_nginx_group: nginx -ara_nginx_config_path: /etc/nginx/conf.d diff --git a/roles/ara_frontend_nginx/vars/RedHat.yaml b/roles/ara_frontend_nginx/vars/RedHat.yaml deleted file mode 120000 index 87d36d4..0000000 --- a/roles/ara_frontend_nginx/vars/RedHat.yaml +++ /dev/null @@ -1 +0,0 @@ -CentOS.yaml \ No newline at end of file diff --git a/roles/ara_frontend_nginx/vars/Ubuntu.yaml b/roles/ara_frontend_nginx/vars/Ubuntu.yaml deleted file mode 100644 index 6f0120e..0000000 --- a/roles/ara_frontend_nginx/vars/Ubuntu.yaml +++ /dev/null @@ -1,21 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -ara_nginx_user: www-data -ara_nginx_group: www-data -ara_nginx_config_path: /etc/nginx/sites-available diff --git a/roles/ara_web/README.md b/roles/ara_web/README.md deleted file mode 100644 index df7e2dd..0000000 --- a/roles/ara_web/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# Ansible role: ara_web - -![ara_web](https://raw.githubusercontent.com/ansible-community/ara-collection/master/doc/source/_static/ansible-role-ara-web.png) - -This Ansible role provides a framework for installing one or many instances of -[ara-web](https://github.com/ansible-community/ara-web) in a variety of -opinionated deployment topologies. - -It is currently tested and supported against Ubuntu 18.04 and Fedora 29. - -## Role Variables - -See [defaults/main.yaml](https://github.com/ansible-community/ara-collection/blob/master/roles/ara_web/defaults/main.yaml). - -## TL;DR - -This is what the role does by default out of the box: - -- Retrieves ara-web from source -- Installs nodejs LTS (v10) -- Installs ara-web dependencies with npm -- Configures an ara-server API endpoint in ara-web's ``public/config.json`` file -- Sets up a systemd unit file for running ara-web with the embedded development server - -## About deployment topologies - -This Ansible role is designed to support different opinionated topologies that -can be selected with role variables. - -For example, the following role variables are defaults used to provide the -topology from the ``TL;DR`` above: - -- ``ara_web_install_method: source`` -- ``ara_web_dev_server: true`` -- ``ara_web_frontend_server: null`` - -The intent is that as the role gains support for other install methods or -frontend servers, it will be possible to mix and match according to preference -or requirements. - -## Example playbooks - -Deploy the ARA API and web client on the same machine with defaults: - -```yaml -- name: Deploy ARA API and web client - hosts: all - gather_facts: yes - vars: - # ara_api - ara_api_fqdn: api.ara.example.org - ara_api_wsgi_server: gunicorn - ara_api_allowed_hosts: - - api.ara.example.org - ara_api_cors_origin_whitelist: - - "http://web.ara.example.org" - # ara_web - ara_web_fqdn: web.ara.example.org - ara_web_frontend_server: nginx - ara_web_api_endpoint: "http://api.ara.example.org" - roles: - - ara_api - - ara_web -``` - -Deploy only ara-web behind nginx and point it to a remote API endpoint: - -```yaml -# Note: Don't forget to add the web fqdn in the remote cors_origin_whitelist. -# Otherwise, the web client might not be authorized to query the API. -- name: Deploy ara-web for remote API endpoint - hosts: all - gather_facts: yes - vars: - ara_web_fqdn: web.ara.example.org - ara_web_api_endpoint: "http://api.remoteara.example.org" - ara_web_frontend_server: nginx - ara_web_frontend_vhost: custom-web-vhost.conf.j2 - roles: - - ara_web diff --git a/roles/ara_web/defaults/main.yaml b/roles/ara_web/defaults/main.yaml deleted file mode 100644 index e91c3fe..0000000 --- a/roles/ara_web/defaults/main.yaml +++ /dev/null @@ -1,71 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -# Root of where files will be stored for ara-web -ara_web_root_dir: "{{ ansible_user_dir }}/.ara" - -# When using static builds without the dev server, path to ara-web static assets -ara_web_static_dir: "{{ ara_web_root_dir }}/www/ara-web" - -# How ara-web will be installed -# - source (default): installs from a local or remote git repository specified by ara_web_source -# - npm (planned): installs from npm -ara_web_install_method: source - -# When installing from source, the location of the remote or local git repository -ara_web_source: "https://opendev.org/recordsansible/ara-web" - -# Location where ara-web will be checked out -ara_web_source_checkout: "{{ ara_web_root_dir }}/git/ara-web" - -# Location where node_modules will be installed -ara_web_node_modules_dir: "{{ ara_web_source_checkout }}" - -# Version of ara-web to install -# This can be a git ref (tag, branch, commit) when installed from source -# When using "latest" as the source version, HEAD will be used -ara_web_version: latest - -# Whether to use the embedded react web server or not -# Setting this to false means ara-web will be statically built instead -ara_web_dev_server: true - -# When the development server is enabled, the address it will be listening on -ara_web_dev_server_bind_address: 127.0.0.1 - -# When the development server is enabled, the port it will be listening on -ara_web_dev_server_bind_port: 3000 - -# Version of nodesource nodejs repositories to install -ara_web_nodejs_version: 10 - -# ara-server API endpoint to use -ara_web_api_endpoint: "http://127.0.0.1:8000" - -# The frontend server for serving ara-web -# - null (default): none, users are expected to use the development server directly or deploy their own web server -# - nginx: when performance of the development server is an issue -# - apache (planned) -ara_web_frontend_server: null - -# When using a frontend server, you can override the default vhost configuration -# template by specifying the path to your own template file. -ara_web_frontend_vhost: null - -# When using a frontend server, the hostname to listen on -ara_web_fqdn: "{{ ansible_default_ipv4['address'] }}" diff --git a/roles/ara_web/handlers/main.yaml b/roles/ara_web/handlers/main.yaml deleted file mode 100644 index bb7feae..0000000 --- a/roles/ara_web/handlers/main.yaml +++ /dev/null @@ -1,31 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -# Is there a better way ? Static files are not created with the httpd context -- name: restore selinux context for static files - become: "{{ (ansible_user_dir in ara_web_static_dir) | ternary(false, true) }}" - command: "restorecon -Rv {{ ara_web_static_dir }}" - when: ansible_os_family == "RedHat" - -- name: restart ara-web - become: true - service: - name: ara-web - state: restarted - when: - - ara_web_service_enabled is not changed diff --git a/roles/ara_web/meta/main.yaml b/roles/ara_web/meta/main.yaml deleted file mode 100644 index 646b5bb..0000000 --- a/roles/ara_web/meta/main.yaml +++ /dev/null @@ -1,27 +0,0 @@ ---- -# Copyright (c) 2020 The ARA Records Ansible authors -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -galaxy_info: - author: The ARA Records Ansible authors - description: Installs an ara-web javascript interface - license: GPLv3 - min_ansible_version: 2.7 - platforms: - - name: EL - versions: - - 8 - - name: Fedora - versions: - - 31 - - 32 - - name: Ubuntu - versions: - - bionic - - focal - galaxy_tags: - - ansible - - ara - - ara-web - -dependencies: [] diff --git a/roles/ara_web/tasks/install/source.yaml b/roles/ara_web/tasks/install/source.yaml deleted file mode 100644 index 7dc0759..0000000 --- a/roles/ara_web/tasks/install/source.yaml +++ /dev/null @@ -1,107 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -- name: Ensure libselinux-python is installed for Red Hat derivatives - become: yes - package: - name: libselinux-python - state: present - when: ansible_os_family == "RedHat" - -- name: Ensure git is installed - become: yes - package: - name: git - state: present - -# TODO: node_modules and public/config.json are local to the git repository so this is not idempotent -- name: Prepare git repository for ara-web - git: - repo: "{{ ara_web_source }}" - dest: "{{ ara_web_source_checkout }}" - version: "{{ (ara_web_version == 'latest') | ternary('HEAD', ara_web_version) }}" - force: yes - -- name: Install ara-web npm dependencies - npm: - path: "{{ ara_web_source_checkout }}" - global: no - production: yes - state: present - notify: - - restart ara-web - -- name: Configure ara-server API endpoint for ara-web - vars: - web_config: - apiURL: "{{ ara_web_api_endpoint }}" - copy: - content: "{{ web_config | to_nice_json(indent=2) }}" - dest: "{{ ara_web_source_checkout }}/public/config.json" - mode: 0644 - notify: - - restart ara-web - -- when: ara_web_dev_server | bool - become: yes - block: - - name: Set up systemd unit file for ara-web - template: - src: ara-web.service.j2 - dest: /etc/systemd/system/ara-web.service - owner: root - group: root - mode: 0644 - notify: - - restart ara-web - - - name: Enable and start ara-web - service: - name: ara-web - state: started - enabled: yes - daemon_reload: yes - register: ara_web_service_enabled - -- when: not ara_web_dev_server | bool - block: - - name: Stop and disable ara-web - become: yes - service: - name: ara-web - state: stopped - enabled: no - - - name: Ensure systemd unit file is not configured - become: yes - file: - path: /etc/systemd/system/ara-web.service - state: absent - - - name: Run a production build of ara-web - command: npm run build - args: - chdir: "{{ ara_web_source_checkout }}" - creates: "{{ ara_web_source_checkout }}/build" - - - name: Synchronize build to web directory - become: "{{ (ansible_user_dir in ara_web_static_dir) | ternary(false, true) }}" - command: | - rsync -rlog --delete-delay {{ ara_web_source_checkout }}/build/ {{ ara_web_static_dir }} - notify: - - restore selinux context for static files diff --git a/roles/ara_web/tasks/main.yaml b/roles/ara_web/tasks/main.yaml deleted file mode 100644 index c358d4c..0000000 --- a/roles/ara_web/tasks/main.yaml +++ /dev/null @@ -1,28 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -- name: Install nodejs - include_tasks: nodejs.yaml - -- name: Include ara-web installation - include_tasks: install/{{ ara_web_install_method }}.yaml - -- name: Include frontend server installation - include_role: - name: "ara_frontend_{{ ara_web_frontend_server }}" - when: ara_web_frontend_server is not none diff --git a/roles/ara_web/tasks/nodejs.yaml b/roles/ara_web/tasks/nodejs.yaml deleted file mode 100644 index 1df9180..0000000 --- a/roles/ara_web/tasks/nodejs.yaml +++ /dev/null @@ -1,53 +0,0 @@ ---- -# Copyright (c) 2019 Red Hat, Inc. -# -# This file is part of ARA Records Ansible. -# -# ARA Records Ansible is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# ARA Records Ansible is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with ARA Records Ansible. If not, see . - -- when: ansible_os_family == "Debian" - become: yes - block: - - name: Install apt-transport-https - package: - name: apt-transport-https - state: present - - - name: Install nodesource repository key - apt_key: - url: "https://deb.nodesource.com/gpgkey/nodesource.gpg.key" - - - name: Install nodesource apt source repository - apt_repository: - repo: "deb-src https://deb.nodesource.com/node_{{ ara_web_nodejs_version }}.x {{ ansible_distribution_release }} main" - state: present - - - name: Install nodesource apt repository - apt_repository: - repo: "deb https://deb.nodesource.com/node_{{ ara_web_nodejs_version }}.x {{ ansible_distribution_release }} main" - state: present - update_cache: yes - -- name: Install Nodesource yum repository - become: yes - package: - name: "https://rpm.nodesource.com/pub_{{ ara_web_nodejs_version }}.x/fc/{{ ansible_distribution_major_version }}/{{ ansible_architecture }}/nodesource-release-fc{{ ansible_distribution_major_version }}-1.noarch.rpm" - state: present - when: ansible_os_family == "RedHat" - -- name: Install nodejs - become: yes - package: - name: nodejs - state: present diff --git a/roles/ara_web/templates/ara-web.service.j2 b/roles/ara_web/templates/ara-web.service.j2 deleted file mode 100644 index 95685e3..0000000 --- a/roles/ara_web/templates/ara-web.service.j2 +++ /dev/null @@ -1,16 +0,0 @@ -[Unit] -Description=ARA Records Ansible web client -After=network.target - -[Service] -PIDFile=/run/ara-web/pid -User={{ ansible_user_id }} -RuntimeDirectory=ara-web -WorkingDirectory={{ ara_web_source_checkout }} -ExecStart=/usr/bin/npm start --host {{ ara_web_dev_server_bind_address }} --port {{ ara_web_dev_server_bind_port }} -ExecReload=/bin/kill -s HUP $MAINPID -ExecStop=/bin/kill -s TERM $MAINPID -PrivateTmp=true - -[Install] -WantedBy=multi-user.target diff --git a/tests/test_tasks.yaml b/tests/test_tasks.yaml deleted file mode 100644 index b3f048e..0000000 --- a/tests/test_tasks.yaml +++ /dev/null @@ -1,125 +0,0 @@ ---- -# Copyright (c) 2020 The ARA Records Ansible authors -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# This is a list of tasks instead of a playbook. They are meant to be included -# as post_tasks inside the same play context as our roles so they have access -# to the play and role variables. - -- when: ara_api_install_method == "source" - block: - - name: Set defaults for Ansible package name and version - set_fact: - ara_tests_ansible_name: "{{ ara_tests_ansible_name | default('ansible') }}" - ara_tests_ansible_version: "{{ ara_tests_ansible_version | default('latest') }}" - - # If a version is not explicitly set we want to make sure to - # completely omit the version argument to pip, as it will be coming - # from the long-form integration_ansible_name variable. Additionally, if - # the version is the special value "latest", then we also want to omit - # any version number, but also set the package state to "latest". - - name: Set Ansible version for installation - set_fact: - _install_ansible_version: "{{ ara_tests_ansible_version }}" - when: ara_tests_ansible_version not in ("", "latest") - - - name: Set Ansible package state for installation - set_fact: - _install_ansible_state: latest - when: ara_tests_ansible_version == "latest" - - - name: Install Ansible alongside ARA - pip: - name: "{{ ara_tests_ansible_name }}" - version: "{{ _install_ansible_version | default(omit, True) }}" - state: "{{ _install_ansible_state | default(omit, True) }}" - virtualenv: "{{ ara_api_venv | bool | ternary(ara_api_venv_path, omit) }}" - virtualenv_command: /usr/bin/python3 -m venv - register: _ansible_pip_install - - rescue: - # Installation of Ansible's cryptography dependency can fail to install with older versions of pip - # with "No module named 'setuptools_rust': "https://github.com/pyca/cryptography/issues/5771 - - name: Update pip to workaround setuptools_rust issue - pip: - name: pip - state: latest - virtualenv: "{{ ara_api_venv | bool | ternary(ara_api_venv_path, omit) }}" - virtualenv_command: /usr/bin/python3 -m venv - register: _pip_update - when: "'setuptools_rust' in _ansible_pip_install.msg" - - - name: Retry installing Ansible with an up to date pip - pip: - name: "{{ ara_tests_ansible_name }}" - version: "{{ _install_ansible_version | default(omit, True) }}" - state: "{{ _install_ansible_state | default(omit, True) }}" - virtualenv: "{{ ara_api_venv | bool | ternary(ara_api_venv_path, omit) }}" - virtualenv_command: /usr/bin/python3 -m venv - when: _pip_update is changed - -- name: Install Ansible from distribution packages - become: yes - package: - name: ansible - state: present - when: ara_api_install_method == "distribution" - -- name: Get ARA plugins directory - environment: - PATH: "{{ path_with_virtualenv | default('/usr/bin:/usr/local/bin') }}" - command: python3 -m ara.setup.plugins - changed_when: false - register: ara_setup_plugins - -- name: Record Zuul metadata for ARA playbooks - include_tasks: zuul_metadata.yaml - when: zuul is defined - -# These aren't in the same task (i.e, with loop) so we can tell individual test -# runs apart easily rather than keeping all the output bundled in a single task. -- environment: - ANSIBLE_CALLBACK_PLUGINS: "{{ ara_setup_plugins.stdout }}/callback" - ANSIBLE_ACTION_PLUGINS: "{{ ara_setup_plugins.stdout }}/action" - ANSIBLE_LOOKUP_PLUGINS: "{{ ara_setup_plugins.stdout }}/lookup" - ARA_SETTINGS: "{{ ara_api_settings }}" - ARA_API_CLIENT: "{{ ara_api_client | default('offline') }}" - ARA_API_SERVER: "{{ ara_api_server | default('http://127.0.0.1:8000') }}" - ARA_DEFAULT_LABELS: "{{ _default_labels | join(', ') | default('default-label') }}" - PATH: "{{ path_with_virtualenv | default('/usr/bin:/usr/local/bin') }}" - vars: - _test_root: "{{ ara_api_source_checkout }}/tests/integration" - block: - # smoke.yaml tests setting ara_playbook_name in one of three plays - - name: Run smoke.yaml integration test - command: "ansible-playbook -vvv {{ _test_root }}/smoke.yaml" - - - name: Run lookups.yaml integration test - command: "ansible-playbook -vvv {{ _test_root }}/lookups.yaml" - - - name: Run hosts.yaml integration test - command: "ansible-playbook -vvv {{ _test_root }}/hosts.yaml" - - - name: Run import.yaml integration test - command: "ansible-playbook -vvv {{ _test_root }}/import.yaml" - - # Tests setting ara_playbook_name as an extra var - - name: Run failed.yaml integration test - command: > - ansible-playbook -vvv {{ _test_root }}/failed.yaml -e ara_playbook_name="Failed playbook" - ignore_errors: yes - - - name: Run incomplete.yaml integration test - shell: | - ansible-playbook -vvv {{ _test_root }}/incomplete.yaml & - sleep 5 - kill $! - args: - executable: /bin/bash - ignore_errors: yes - - - name: Generate static report - command: ara-manage generate {{ ara_api_root_dir }}/server/static - -- name: List static report files - command: ls -alR {{ ara_api_root_dir }}/server/static diff --git a/tests/vars/distributed_sqlite_tests.yaml b/tests/vars/distributed_sqlite_tests.yaml deleted file mode 100644 index cac3284..0000000 --- a/tests/vars/distributed_sqlite_tests.yaml +++ /dev/null @@ -1,14 +0,0 @@ -ara_tests_cleanup: true -ara_api_root_dir: "{{ ansible_user_dir }}/.ara-tests" -ara_api_distributed_sqlite_root: "{{ ansible_user_dir }}/.ara-tests" -ara_api_distributed_sqlite_prefix: ara-test-report -ara_api_wsgi_server: gunicorn -ara_api_secret_key: testing -ara_api_debug: true -ara_api_log_level: DEBUG -ara_api_server: "http://127.0.0.1:8000" -ara_api_client: http -_test_directories: - - "tests/some/path/ara-test-report" - - "tests/dev/ara-test-report" - - "tests/prod/ara-test-report" diff --git a/tests/vars/mysql_tests.yaml b/tests/vars/mysql_tests.yaml deleted file mode 100644 index 8e10196..0000000 --- a/tests/vars/mysql_tests.yaml +++ /dev/null @@ -1,18 +0,0 @@ -ara_tests_cleanup: true -ara_api_root_dir: "{{ ansible_user_dir }}/.ara-tests" -ara_api_secret_key: testing -ara_api_debug: true -ara_api_log_level: DEBUG -# Set to 0 because tests could be using the offline client -ara_api_database_conn_max_age: 0 -ara_api_database_engine: django.db.backends.mysql -ara_api_database_name: ara -ara_api_database_user: ara -ara_api_database_password: password -ara_api_database_port: 3306 -# Configure cleanup crons to exercise the code path during tests -ara_api_configure_cron: true -# The host is defined dynamically based on the address of the database server -# ara_api_database_host: 127.0.0.1 -_mysql_container_name: ara_tests_mariadb -_mysql_image_name: docker.io/mariadb:10 diff --git a/tests/vars/postgresql_tests.yaml b/tests/vars/postgresql_tests.yaml deleted file mode 100644 index fb74578..0000000 --- a/tests/vars/postgresql_tests.yaml +++ /dev/null @@ -1,18 +0,0 @@ -ara_tests_cleanup: true -ara_api_root_dir: "{{ ansible_user_dir }}/.ara-tests" -ara_api_secret_key: testing -ara_api_debug: true -ara_api_log_level: DEBUG -# Set to 0 because tests could be using the offline client -ara_api_database_conn_max_age: 0 -ara_api_database_engine: django.db.backends.postgresql -ara_api_database_name: ara -ara_api_database_user: ara -ara_api_database_password: password -ara_api_database_port: 5432 -# Configure cleanup crons to exercise the code path during tests -ara_api_configure_cron: true -# The host is defined dynamically based on the address of the database server -# ara_api_database_host: 127.0.0.1 -_postgresql_container_name: ara-postgresql-tests -_postgresql_image_name: docker.io/postgres:10 diff --git a/tests/with_distributed_sqlite.yaml b/tests/with_distributed_sqlite.yaml deleted file mode 100644 index 7e2b949..0000000 --- a/tests/with_distributed_sqlite.yaml +++ /dev/null @@ -1,55 +0,0 @@ ---- -# Copyright (c) 2020 The ARA Records Ansible authors -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: Test the ARA API with the distributed sqlite backend - hosts: all - gather_facts: yes - vars_files: - - vars/distributed_sqlite_tests.yaml - tasks: - # Generate ourselves a fresh database to run tests with - - name: Set up the API with the default sqlite backend - include_role: - name: ara_api - public: yes - - # These are tasks rather than a standalone playbook to give us an easy - # access to all the variables within the same play. - - include_tasks: test_tasks.yaml - - - name: Enable the distributed sqlite backend - vars: - ara_api_distributed_sqlite: true - include_role: - name: ara_api - public: yes - - - name: Ensure there are no pending handlers - meta: flush_handlers - - - name: Create test directories - file: - path: "{{ ara_api_distributed_sqlite_root }}/{{ item }}" - state: directory - recurse: yes - loop: "{{ _test_directories }}" - - - name: Copy the database to the test directories - copy: - src: "{{ ara_api_database_name }}" - dest: "{{ ara_api_distributed_sqlite_root }}/{{ item }}/ansible.sqlite" - remote_src: true - loop: "{{ _test_directories }}" - - - name: Test that the API works - uri: - url: "http://127.0.0.1:8000/{{ item }}/api/v1/" - return_content: yes - register: api_test - loop: "{{ _test_directories }}" - - - name: Print API responses for debug purposes - debug: - msg: "{{ item['json'] | to_nice_json }}" - loop: "{{ api_test.results }}" diff --git a/tests/with_fedora_packages.yaml b/tests/with_fedora_packages.yaml deleted file mode 100644 index 2fe6c5a..0000000 --- a/tests/with_fedora_packages.yaml +++ /dev/null @@ -1,32 +0,0 @@ ---- -# Copyright (c) 2020 The ARA Records Ansible authors -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: Test the ARA API with fedora packages - hosts: all - gather_facts: yes - vars: - ara_api_install_method: distribution - ara_api_version: latest - ara_api_root_dir: "{{ ansible_user_dir }}/.ara-tests" - ara_api_secret_key: testing - ara_api_debug: true - ara_api_log_level: DEBUG - tasks: - - block: - - name: Set up the API with the ara_api role - include_role: - name: ara_api - public: yes - - # Despite installing from packages, we need access to the source for - # running tests - - name: Prepare git repository for ara - git: - repo: "{{ ara_api_source }}" - dest: "{{ ara_api_source_checkout }}" - version: "{{ (ara_api_version == 'latest') | ternary('HEAD', ara_api_version) }}" - - # These are tasks rather than a standalone playbook to give us an easy - # access to all the variables within the same play. - - include_tasks: test_tasks.yaml diff --git a/tests/with_mysql.yaml b/tests/with_mysql.yaml deleted file mode 100644 index 45b98a2..0000000 --- a/tests/with_mysql.yaml +++ /dev/null @@ -1,82 +0,0 @@ ---- -# Copyright (c) 2020 The ARA Records Ansible authors -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: Start a mysql container - hosts: ara-database-server - gather_facts: yes - vars_files: - - vars/mysql_tests.yaml - tasks: - - name: Install podman - become: yes - package: - name: podman - state: present - - - name: Start a mysql container - command: | - podman run -d \ - --name {{ _mysql_container_name }} \ - -p {{ ara_api_database_port }}:{{ ara_api_database_port }} \ - -e MYSQL_RANDOM_ROOT_PASSWORD=yes \ - -e MYSQL_DATABASE={{ ara_api_database_name }} \ - -e MYSQL_USER={{ ara_api_database_user }} \ - -e MYSQL_PASSWORD={{ ara_api_database_password }} \ - {{ _mysql_image_name }} - register: db_container - retries: 3 - delay: 5 - until: db_container is succeeded - - # podman doesn't appear to be able to listen on ipv6 yet: https://github.com/containers/libpod/issues/3245 - # If we have a node on IPv6, redirect the traffic from v6 to v4 with socat - - when: ansible_host | ipv6 != false - become: yes - block: - - name: Install socat - package: - name: socat - state: present - - - name: Setup systemd service - copy: - dest: /etc/systemd/system/socat-mysql.service - owner: root - group: root - mode: 0644 - content: | - [Unit] - Description=socat mysql ipv6 to ipv4 - - [Service] - ExecStart=/usr/bin/socat TCP6-LISTEN:3306,fork,bind=[{{ ansible_host }}] TCP4:127.0.0.1:3306 - - [Install] - WantedBy=multi-user.target - - - name: Start socat network redirection for mysql over ipv6 - service: - name: socat-mysql - state: started - enabled: yes - daemon_reload: yes - -- name: Deploy and test ARA API with mysql - hosts: ara-api-server - gather_facts: yes - vars_files: - - vars/mysql_tests.yaml - tasks: - - name: Set database server host - set_fact: - ara_api_database_host: "{{ hostvars['database-server']['ansible_host'] }}" - - - name: Set up the API with the ara_api Ansible role - include_role: - name: ara_api - public: yes - - # These are tasks rather than a standalone playbook to give us an easy - # access to all the variables within the same play. - - include_tasks: test_tasks.yaml diff --git a/tests/with_postgresql.yaml b/tests/with_postgresql.yaml deleted file mode 100644 index 47463e0..0000000 --- a/tests/with_postgresql.yaml +++ /dev/null @@ -1,80 +0,0 @@ ---- -# Copyright (c) 2020 The ARA Records Ansible authors -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: Start a postgresql container - hosts: ara-database-server - gather_facts: yes - vars_files: - - vars/postgresql_tests.yaml - tasks: - - name: Install podman - become: yes - package: - name: podman - state: present - - - name: Start a postgresql container - command: | - podman run -d \ - --name {{ _postgresql_container_name }} \ - -p {{ ara_api_database_port }}:{{ ara_api_database_port }} \ - -e POSTGRES_DB={{ ara_api_database_name }} \ - -e POSTGRES_USER={{ ara_api_database_user }} \ - -e POSTGRES_PASSWORD={{ ara_api_database_password }} \ - {{ _postgresql_image_name }} - register: db_container - retries: 3 - delay: 5 - until: db_container is succeeded - - # podman doesn't appear to be able to listen on ipv6 yet: https://github.com/containers/libpod/issues/3245 - # If we have a node on IPv6, redirect the traffic from v6 to v4 with socat - - when: ansible_host | ipv6 != false - become: yes - block: - - name: Install socat - package: - name: socat - state: present - - - name: Setup systemd service - copy: - dest: /etc/systemd/system/socat-postgresql.service - owner: root - group: root - mode: 0644 - content: | - [Unit] - Description=socat postgresql ipv6 to ipv4 - [Service] - ExecStart=/usr/bin/socat TCP6-LISTEN:5432,fork,bind=[{{ ansible_host }}] TCP4:127.0.0.1:5432 - - [Install] - WantedBy=multi-user.target - - - name: Start socat network redirection for postgresql over ipv6 - service: - name: socat-postgresql - state: started - enabled: yes - daemon_reload: yes - -- name: Deploy and test ARA API with postgresql - hosts: ara-api-server - gather_facts: yes - vars_files: - - vars/postgresql_tests.yaml - tasks: - - name: Set database server host - set_fact: - ara_api_database_host: "{{ hostvars['database-server']['ansible_host'] }}" - - - name: Set up the API with the ara_api Ansible role - include_role: - name: ara_api - public: yes - - # These are tasks rather than a standalone playbook to give us an easy - # access to all the variables within the same play. - - include_tasks: test_tasks.yaml diff --git a/tests/zuul_metadata.yaml b/tests/zuul_metadata.yaml deleted file mode 100644 index 2c132dd..0000000 --- a/tests/zuul_metadata.yaml +++ /dev/null @@ -1,28 +0,0 @@ ---- -# Copyright (c) 2020 The ARA Records Ansible authors -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: Set default labels for check, gate and promote pipelines - set_fact: - _default_labels: - - "nodepool.provider:{{ nodepool.provider }}" - - "zuul.change:{{ zuul.change }}" - - "zuul.executor:{{ zuul.executor.hostname }}" - - "zuul.job:{{ zuul.job }}" - - "zuul.pipeline:{{ zuul.pipeline }}" - - "zuul.project:{{ zuul.project.canonical_name }}" - when: - - zuul.pipeline is defined - - zuul.pipeline in ["check", "gate", "promote"] - -- name: Set default labels for periodic and post pipelines - set_fact: - _default_labels: - - "nodepool.provider:{{ nodepool.provider }}" - - "zuul.executor:{{ zuul.executor.hostname }}" - - "zuul.job:{{ zuul.job }}" - - "zuul.pipeline:{{ zuul.pipeline }}" - - "zuul.project:{{ zuul.project.canonical_name }}" - when: - - zuul.pipeline is defined - - zuul.pipeline in ["periodic", "post"] diff --git a/tests/zuul_post_logs.yaml b/tests/zuul_post_logs.yaml deleted file mode 100644 index 312ee09..0000000 --- a/tests/zuul_post_logs.yaml +++ /dev/null @@ -1,49 +0,0 @@ ---- -# Copyright (c) 2020 The ARA Records Ansible authors -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: Recover API server data - hosts: ara-api-server - gather_facts: yes - vars: - ara_api_root_dir: "{{ ansible_user_dir }}/.ara-tests" - tasks: - # The zuul-output directory is retrieved by the fetch-output role - # https://opendev.org/zuul/zuul-jobs/src/branch/master/roles/fetch-output - - name: Create log directory - file: - path: "{{ ansible_user_dir }}/zuul-output/logs" - state: directory - recurse: yes - - - name: Recover integration test data - command: cp -rp {{ ara_api_root_dir }}/server {{ ansible_user_dir }}/zuul-output/logs/server - ignore_errors: yes - - - name: Link the static report to the Zuul build with multiple nodes - zuul_return: - data: - zuul: - artifacts: - - name: "Integration test static report for {{ inventory_hostname }}" - url: "{{ inventory_hostname }}/server/static/index.html" - when: groups['all'] | length > 1 - - - name: Link the static report to the Zuul build with a single node - zuul_return: - data: - zuul: - artifacts: - - name: Integration test static report - url: "server/static/index.html" - when: groups['all'] | length == 1 - -# Temporarily disable this to prevent "Executing local code is prohibited" -# https://review.opendev.org/#/c/742229/ -#- name: Generate Zuul ARA report -# hosts: localhost -# vars: -# ara_report_type: html -# ara_report_path: ara-report -# roles: -# - ara-report diff --git a/tests/zuul_post_with_mysql.yaml b/tests/zuul_post_with_mysql.yaml deleted file mode 100644 index 00b4035..0000000 --- a/tests/zuul_post_with_mysql.yaml +++ /dev/null @@ -1,34 +0,0 @@ ---- -# Copyright (c) 2020 The ARA Records Ansible authors -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: Recover mysql server data - hosts: ara-database-server - gather_facts: yes - vars_files: - - vars/mysql_tests.yaml - tasks: - - name: Ensure mysqldump is installed - become: yes - package: - name: mariadb - state: present - - # The zuul-output directory is retrieved by the fetch-output role - # https://opendev.org/zuul/zuul-jobs/src/branch/master/roles/fetch-output - - name: Create log directory - file: - path: "{{ ansible_user_dir }}/zuul-output/logs" - state: directory - recurse: yes - - # Dump is suffixed by .txt so we don't need magic mimetypes when - # viewing on the web. - - name: Dump database file - shell: | - mysqldump \ - --host=127.0.0.1 \ - --port={{ ara_api_database_port }} \ - --user={{ ara_api_database_user }} \ - --password={{ ara_api_database_password }} \ - {{ ara_api_database_name }} > {{ ansible_user_dir }}/zuul-output/logs/mysqldump.sql.txt diff --git a/tests/zuul_post_with_postgresql.yaml b/tests/zuul_post_with_postgresql.yaml deleted file mode 100644 index 83b8f14..0000000 --- a/tests/zuul_post_with_postgresql.yaml +++ /dev/null @@ -1,40 +0,0 @@ ---- -# Copyright (c) 2020 The ARA Records Ansible authors -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: Recover postgresql server data - hosts: ara-database-server - gather_facts: yes - vars_files: - - vars/postgresql_tests.yaml - tasks: - - name: Ensure pg_dump is installed - become: yes - package: - name: postgresql - state: present - - # The zuul-output directory is retrieved by the fetch-output role - # https://opendev.org/zuul/zuul-jobs/src/branch/master/roles/fetch-output - - name: Create log directory - file: - path: "{{ ansible_user_dir }}/zuul-output/logs" - state: directory - recurse: yes - - - name: Set up postgre password file for passwordless commands - lineinfile: - path: "{{ ansible_user_dir }}/.pgpass" - create: yes - line: "127.0.0.1:{{ ara_api_database_port }}:{{ ara_api_database_name }}:{{ ara_api_database_user }}:{{ ara_api_database_password }}" - mode: 0600 - - # Dump is suffixed by .txt so we don't need magic mimetypes when - # viewing on the web. - - name: Dump database file - command: | - pg_dump -w \ - --host=127.0.0.1 \ - --username={{ ara_api_database_user }} \ - --dbname={{ ara_api_database_name }} \ - --file={{ ansible_user_dir }}/zuul-output/logs/pg_dump.sql.txt diff --git a/tests/zuul_pre_multinode_networking.yaml b/tests/zuul_pre_multinode_networking.yaml deleted file mode 100644 index 8b87cf2..0000000 --- a/tests/zuul_pre_multinode_networking.yaml +++ /dev/null @@ -1,11 +0,0 @@ ---- -# Copyright (c) 2020 The ARA Records Ansible authors -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: Allow networking between multiple nodes - hosts: all - tasks: - # https://opendev.org/zuul/zuul-jobs/src/branch/master/roles/multi-node-firewall - - name: Set up multi-node firewall - include_role: - name: multi-node-firewall