diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-14 20:03:01 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-14 20:03:01 +0000 |
commit | a453ac31f3428614cceb99027f8efbdb9258a40b (patch) | |
tree | f61f87408f32a8511cbd91799f9cececb53e0374 /collections-debian-merged/ansible_collections/community/rabbitmq | |
parent | Initial commit. (diff) | |
download | ansible-a453ac31f3428614cceb99027f8efbdb9258a40b.tar.xz ansible-a453ac31f3428614cceb99027f8efbdb9258a40b.zip |
Adding upstream version 2.10.7+merged+base+2.10.8+dfsg.upstream/2.10.7+merged+base+2.10.8+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'collections-debian-merged/ansible_collections/community/rabbitmq')
98 files changed, 7955 insertions, 0 deletions
diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/.gitignore b/collections-debian-merged/ansible_collections/community/rabbitmq/.gitignore new file mode 100644 index 00000000..77a08355 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/.gitignore @@ -0,0 +1,5 @@ +# ansible-test stuff +/tests/output/ + +# antsibull-changelog stuff +/changelogs/.plugin-cache.yaml diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/CHANGELOG.rst b/collections-debian-merged/ansible_collections/community/rabbitmq/CHANGELOG.rst new file mode 100644 index 00000000..26da003c --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/CHANGELOG.rst @@ -0,0 +1,21 @@ +================================ +Community.Rabbitmq Release Notes +================================ + +.. contents:: Topics + + +v1.0.0 +====== + +Minor Changes +------------- + +- rabbitmq_publish - Support for connecting with SSL certificates. + +Bugfixes +-------- + +- Refactor RabbitMQ user module to first check the version of the daemon and then, when possible add flags to `rabbitmqctl` so that a machine readable output is returned. Also, depending on the version, parse the output in correctly. Expands tests accordingly. (https://github.com/ansible/ansible/issues/48890) +- rabbitmq lookup plugin - Fix for rabbitmq lookups failing when using pika v1.0.0 and newer. +- rabbitmq_publish - Fix to ensure the module works correctly for pika v1.0.0 and later. (https://github.com/ansible/ansible/pull/61960) diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/COPYING b/collections-debian-merged/ansible_collections/community/rabbitmq/COPYING new file mode 100644 index 00000000..f288702d --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> + 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 <https://www.gnu.org/licenses/>. + +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: + + <program> Copyright (C) <year> <name of author> + 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 +<https://www.gnu.org/licenses/>. + + 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 +<https://www.gnu.org/licenses/why-not-lgpl.html>. diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/FILES.json b/collections-debian-merged/ansible_collections/community/rabbitmq/FILES.json new file mode 100644 index 00000000..1b1ef2e9 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/FILES.json @@ -0,0 +1,1041 @@ +{ + "files": [ + { + "name": ".", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "meta/runtime.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "df18179bb2f5447a56ac92261a911649b96821c0b2c08eea62d5cc6b0195203f", + "format": 1 + }, + { + "name": "plugins", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/doc_fragments", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/doc_fragments/__init__.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "plugins/doc_fragments/rabbitmq.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "822d0d3404f7e110538441d3b6ad9b8146a5d0c508873fcb5273805513a1de88", + "format": 1 + }, + { + "name": "plugins/module_utils", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/module_utils/rabbitmq.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "56a7f82009b47c1934f7ac28e712613e479e0e7a0163f12c2d7d7e522468530a", + "format": 1 + }, + { + "name": "plugins/lookup", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/lookup/rabbitmq.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "42069fcbc731da36a64fa2c9210db6a0c874a929ba9a841b03a8ddc015da6706", + "format": 1 + }, + { + "name": "plugins/modules", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/modules/rabbitmq_plugin.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0b5e9d4dd24d4f9fc726593744193bc31463dac953880e5cc03c9f620a81473f", + "format": 1 + }, + { + "name": "plugins/modules/rabbitmq_queue.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "47149033893f6b9702004d4368761ae915b808d41464a9e611c4736fc7034b67", + "format": 1 + }, + { + "name": "plugins/modules/rabbitmq_global_parameter.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "57fadacb5703c08c0eb26a3a86c86750de43506f99cfbf6a34c4bda67db1bdf2", + "format": 1 + }, + { + "name": "plugins/modules/rabbitmq_publish.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6c5d342f20fa6a6c96f66913b8bd7a54f07dfd97ba8ee129648c8c7009512f5b", + "format": 1 + }, + { + "name": "plugins/modules/rabbitmq_exchange.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c985ac85e141edf4374f2c8d50a9306e6548fb627d477429b3c879b2aeebfb2f", + "format": 1 + }, + { + "name": "plugins/modules/rabbitmq_binding.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5b7e6fae9d34a096e7f35e230c4fad0ef83c77d1937ed19b59fdb69c2022516e", + "format": 1 + }, + { + "name": "plugins/modules/rabbitmq_user.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a525f8d3b97f910d19d698f3a4699dd11d23967cca042df78e925c4f3d974aa9", + "format": 1 + }, + { + "name": "plugins/modules/rabbitmq_vhost_limits.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5929611184413f575178cd69c2bb847a4bafa040b9aca0b7ac1a6db3799e9d51", + "format": 1 + }, + { + "name": "plugins/modules/rabbitmq_parameter.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ebc7fc1cf45081c6c6f6fae1376891722f4eb9dd41d3c383b3276884d50f17b6", + "format": 1 + }, + { + "name": "plugins/modules/rabbitmq_policy.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "7082bbb27a33a40708a170829fb9bfd4422ef531adb012833575b88b38d8a47f", + "format": 1 + }, + { + "name": "plugins/modules/rabbitmq_vhost.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "aeae60f80f5e316ddb9971e21635d309cb07699293217eb484f682c11c32f243", + "format": 1 + }, + { + "name": "README.md", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3a7b3f9d36cd1c42a0f527cbea428beee9ea40890fdcf0450a70a9bad76957fb", + "format": 1 + }, + { + "name": "CHANGELOG.rst", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "fddcb8f11bc37aaf53692c293545d389839d6159e52a8213186d8ad437868faa", + "format": 1 + }, + { + "name": "tests", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/sanity", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/sanity/ignore.txt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "972fd0ab0535c66cb4d8382134f0343caebde99b89675e6337bd93c67407afb5", + "format": 1 + }, + { + "name": "tests/sanity/ignore-2.10.txt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "972fd0ab0535c66cb4d8382134f0343caebde99b89675e6337bd93c67407afb5", + "format": 1 + }, + { + "name": "tests/sanity/ignore-2.11.txt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "972fd0ab0535c66cb4d8382134f0343caebde99b89675e6337bd93c67407afb5", + "format": 1 + }, + { + "name": "tests/unit", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/unit/compat", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/unit/compat/unittest.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5401a046e5ce71fa19b6d905abd0f9bdf816c0c635f7bdda6730b3ef06e67096", + "format": 1 + }, + { + "name": "tests/unit/compat/__init__.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "tests/unit/compat/builtins.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0ca4cac919e166b25e601e11acb01f6957dddd574ff0a62569cb994a5ecb63e1", + "format": 1 + }, + { + "name": "tests/unit/compat/mock.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0af958450cf6de3fbafe94b1111eae8ba5a8dbe1d785ffbb9df81f26e4946d99", + "format": 1 + }, + { + "name": "tests/unit/mock", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/unit/mock/loader.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c45064a0beb765cd0b6cfbb74ca0cd491ceed2f4c2d22808f60a57071d9712cc", + "format": 1 + }, + { + "name": "tests/unit/mock/__init__.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "tests/unit/mock/vault_helper.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4535613601c419f7d20f0c21e638dabccf69b4a7fac99d5f6f9b81d1519dafd6", + "format": 1 + }, + { + "name": "tests/unit/mock/path.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3ab46a5b17bf8fd082ea5bce19af80497a3f306893acb77cb97b022abfe175a3", + "format": 1 + }, + { + "name": "tests/unit/mock/yaml_helper.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "fada9f3506c951e21c60c2a0e68d3cdf3cadd71c8858b2d14a55c4b778f10983", + "format": 1 + }, + { + "name": "tests/unit/mock/procenv.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "abce72c74680f152cea9fc38f2ea0b24676eeeb446d64907a5a8336345013e33", + "format": 1 + }, + { + "name": "tests/unit/modules", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/unit/modules/messaging", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/unit/modules/messaging/rabbitmq", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/unit/modules/messaging/rabbitmq/__init__.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "tests/unit/modules/messaging/rabbitmq/test_rabbitmq_user.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9b681fb3e1d172ff599efc59db672db09649d574deed41026abfbe74a5608d9d", + "format": 1 + }, + { + "name": "tests/unit/modules/messaging/rabbitmq/rabbitmq_user_fixtures.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0293b05d8c9f9be64e8ef404ff42687741e152b1deedad5ffedd617d376e54b2", + "format": 1 + }, + { + "name": "tests/unit/modules/utils.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a1dc0fb8eb3acde716643491e2913972b86bc1c944690331af7eaac99e93b48c", + "format": 1 + }, + { + "name": "tests/integration", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_user", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_user/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_user/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6b11845fec8855951fdbf1ad471fa8174a6ba299ea4ee3d62a47a1605eaea95e", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_user/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4aae3a6bb79d44474ef4771afbd51d52222428d5cde402c6156d85e7f7c9f067", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_user/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_user/tasks/tests.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "65a13cee0383d287e48edab84cf6319baf490dff2e3b64d5b5f9048e28a8d6f6", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_user/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "27b82af4f4e91ff9565ee5a834d7b93b0322b25dec30ab06a23d07b178f515c9", + "format": 1 + }, + { + "name": "tests/integration/targets/setup_rabbitmq", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/setup_rabbitmq/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/setup_rabbitmq/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "018110439f4fa79f060ac894fe54567fd9c3eb410aedbdf0b4aaeee1ad5fd705", + "format": 1 + }, + { + "name": "tests/integration/targets/setup_rabbitmq/files", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/setup_rabbitmq/files/rabbitmq.conf", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "dea359f9769442f0fc490223a01fc949659b24e4675dc244182c6a32e7535662", + "format": 1 + }, + { + "name": "tests/integration/targets/setup_rabbitmq/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/setup_rabbitmq/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6d69d37ac47dfebba798b23319101e68e661a31571785e859adb551801e3cb04", + "format": 1 + }, + { + "name": "tests/integration/targets/setup_rabbitmq/tasks/ubuntu.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "446e7771b5c132226079c7797401d32c13920476bacf6141ffbd3da9e7034d8c", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_binding", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_binding/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_binding/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6b11845fec8855951fdbf1ad471fa8174a6ba299ea4ee3d62a47a1605eaea95e", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_binding/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4aae3a6bb79d44474ef4771afbd51d52222428d5cde402c6156d85e7f7c9f067", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_binding/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_binding/tasks/tests.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4ecbfe68f4cd668cbf7c05ff3c3e4075d62c279b9842518fefbd912a8e821193", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_binding/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c7c75c47bbd83a71d800e78edfd01d5e8d00dd71dc3490178e679e1e2f9226ff", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_plugin", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_plugin/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_plugin/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6b11845fec8855951fdbf1ad471fa8174a6ba299ea4ee3d62a47a1605eaea95e", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_plugin/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4aae3a6bb79d44474ef4771afbd51d52222428d5cde402c6156d85e7f7c9f067", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_plugin/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_plugin/tasks/tests.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "875aa7430bc2f242ede00e56ef4aad6c1e424d5e8dcc71f8b4c9a6c290ef6ee3", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_plugin/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "989a41fcbcfa0ebf3d94089cedabdae0a78272436964bfa3d5408db7b13b4104", + "format": 1 + }, + { + "name": "tests/integration/targets/setup_tls", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/setup_tls/files", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/setup_tls/files/client_certificate.pem", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1c88ee01e59fe19f497b74f0fb15a6d705bbac6df554d16f2f80fc25d2723bad", + "format": 1 + }, + { + "name": "tests/integration/targets/setup_tls/files/ca_key.pem", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0157029faae2207eaec99b67360db8ca46fe6964eb98165a0ca4ac56cbed7ebb", + "format": 1 + }, + { + "name": "tests/integration/targets/setup_tls/files/server_certificate.pem", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a93a860161059bf8b6d065d2b01a5218a7beefdb075fa704e0139d4f96bdb61c", + "format": 1 + }, + { + "name": "tests/integration/targets/setup_tls/files/ca_certificate.pem", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "47ddc514d030d2dd28b98eb257b690b8aa94abc7b657b43caf6e32e2e5a6bf9d", + "format": 1 + }, + { + "name": "tests/integration/targets/setup_tls/files/client_key.pem", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1ffc8420355a69fecd60242feb89bfef5517292aa9129ea79e99bb36ffd80dc6", + "format": 1 + }, + { + "name": "tests/integration/targets/setup_tls/files/server_key.pem", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0bb0b33983d37d5b6404c0feb969e80d0787331f774d2b8024570133d65851f6", + "format": 1 + }, + { + "name": "tests/integration/targets/setup_tls/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/setup_tls/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "093e768c82c92883583078a39f31a82ae4ad264242d1f9f61bf66abbc0a27db3", + "format": 1 + }, + { + "name": "tests/integration/targets/lookup_rabbitmq", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/lookup_rabbitmq/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/lookup_rabbitmq/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6b11845fec8855951fdbf1ad471fa8174a6ba299ea4ee3d62a47a1605eaea95e", + "format": 1 + }, + { + "name": "tests/integration/targets/lookup_rabbitmq/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6d2d1b24a167fc8fa4bcc147c7a73b991761c18232c99fd21208a32e1ee26f1d", + "format": 1 + }, + { + "name": "tests/integration/targets/lookup_rabbitmq/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/lookup_rabbitmq/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4191eddb2b4316a026b0b6073752948393447541f7cd615799e765ab6bca6fb0", + "format": 1 + }, + { + "name": "tests/integration/targets/lookup_rabbitmq/tasks/ubuntu.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "48630d10dccb3f01a142b78c9cbd559c7508dbadd18824b6a058ed6b4571a617", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_vhost_limits", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_vhost_limits/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_vhost_limits/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6b11845fec8855951fdbf1ad471fa8174a6ba299ea4ee3d62a47a1605eaea95e", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_vhost_limits/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4aae3a6bb79d44474ef4771afbd51d52222428d5cde402c6156d85e7f7c9f067", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_vhost_limits/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_vhost_limits/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4191eddb2b4316a026b0b6073752948393447541f7cd615799e765ab6bca6fb0", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_vhost_limits/tasks/ubuntu.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "99954f1917f3d6122c326ad3aa641f23a9961e60f537375b7beeefb501b393d0", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_vhost", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_vhost/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_vhost/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6b11845fec8855951fdbf1ad471fa8174a6ba299ea4ee3d62a47a1605eaea95e", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_vhost/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4aae3a6bb79d44474ef4771afbd51d52222428d5cde402c6156d85e7f7c9f067", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_vhost/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_vhost/tasks/tests.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6cee71b73c0e8b53de9ed8efb744d83ac99016294e3c5c569ba9024be3476da2", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_vhost/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "989a41fcbcfa0ebf3d94089cedabdae0a78272436964bfa3d5408db7b13b4104", + "format": 1 + }, + { + "name": "tests/integration/targets/setup_remote_tmp_dir", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/setup_remote_tmp_dir/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/setup_remote_tmp_dir/tasks/default.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2441ac1753320d2cd3bea299c160540e6ae31739ed235923ca478284d1fcfe09", + "format": 1 + }, + { + "name": "tests/integration/targets/setup_remote_tmp_dir/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "766ab141899717320ba54e2bb1a6ba8cbc3cc7642d0023670154b49981ed1a91", + "format": 1 + }, + { + "name": "tests/integration/targets/setup_remote_tmp_dir/tasks/default-cleanup.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e273324ab90d72180a971d99b9ab69f08689c8be2e6adb991154fc294cf1056e", + "format": 1 + }, + { + "name": "tests/integration/targets/setup_remote_tmp_dir/handlers", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/setup_remote_tmp_dir/handlers/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "050157a29c48915cf220b3cdcf5a032e53e359bdc4a210cd457c4836e8e32a4d", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_publish", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_publish/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_publish/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5175b4209935100fc9ff5cc8370cab247318cd974df9bed2653198844b5d918d", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_publish/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4aae3a6bb79d44474ef4771afbd51d52222428d5cde402c6156d85e7f7c9f067", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_publish/files", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_publish/files/image.gif", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d1132eda6d50ba2a89d60279ef2f891eca341bfbbca8df136c2c56d5e73c8a4c", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_publish/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_publish/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4191eddb2b4316a026b0b6073752948393447541f7cd615799e765ab6bca6fb0", + "format": 1 + }, + { + "name": "tests/integration/targets/rabbitmq_publish/tasks/ubuntu.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e98051f18c9aabf066c468a713bf648b1f32fab20e621103e7d4d6ae60dc50c8", + "format": 1 + }, + { + "name": "tests/utils", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/utils/shippable", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/utils/shippable/remote.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2a140a1cea2fbf3b291009694bcfcf0f2877e92ec01c7e929e787f5b4cdd6d92", + "format": 1 + }, + { + "name": "tests/utils/shippable/shippable.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c3daaf8cca5a89105adb9a5372140760cccf9c7cb0504412d3fbb69f79e2ed58", + "format": 1 + }, + { + "name": "tests/utils/shippable/osx.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2a140a1cea2fbf3b291009694bcfcf0f2877e92ec01c7e929e787f5b4cdd6d92", + "format": 1 + }, + { + "name": "tests/utils/shippable/timing.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ebb7d3553349747ad41d80899ed353e13cf32fcbecbb6566cf36e9d2bc33703e", + "format": 1 + }, + { + "name": "tests/utils/shippable/linux.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "07aa5e07a0b732a671bf9fdadfe073dd310b81857b897328ce2fa829e2c76315", + "format": 1 + }, + { + "name": "tests/utils/shippable/check_matrix.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "aa877ec932e06e496daf6dd15e9a952c75165f2c3963e5aff605b25e4ed47497", + "format": 1 + }, + { + "name": "tests/utils/shippable/timing.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f3f3cc03a997cdba719b0542fe668fc612451841cbe840ab36865f30aa54a1bd", + "format": 1 + }, + { + "name": "tests/utils/shippable/cloud.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "dd953f7e779b9962e76492c389142e03174e84a8115f53e56628e2af9e66b818", + "format": 1 + }, + { + "name": "tests/utils/shippable/units.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9741924310f7fbbde5eac792b8a34ee33f2ff42aa30ee4d3593410bbb2961bc3", + "format": 1 + }, + { + "name": "tests/utils/shippable/freebsd.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2a140a1cea2fbf3b291009694bcfcf0f2877e92ec01c7e929e787f5b4cdd6d92", + "format": 1 + }, + { + "name": "tests/utils/shippable/sanity.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1cd365c5bad1facb7e98cad97a20e34231f49fca169653ccd7d34bd955bd88f6", + "format": 1 + }, + { + "name": "tests/utils/shippable/rhel.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2a140a1cea2fbf3b291009694bcfcf0f2877e92ec01c7e929e787f5b4cdd6d92", + "format": 1 + }, + { + "name": "changelogs", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "changelogs/changelog.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c2d7fef356edafee40f0e9291094e3b0ef54ce86168d1b5d0c5f7df9e0701239", + "format": 1 + }, + { + "name": "changelogs/config.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1c6e8ebc7f2f2664502fc5df6d12761510a0ec8194e1127ca5dc088397aabc80", + "format": 1 + }, + { + "name": "COPYING", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3972dc9744f6499f0f9b2dbf76696f2ae7ad8af9b23dde66d6af86c9dfb36986", + "format": 1 + }, + { + "name": "shippable.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "76dfd368b6cdf7275d4f532abe1aa23a2d83dcd7383af139eed1405e3f958226", + "format": 1 + }, + { + "name": ".gitignore", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e2a78d88f86332d4e84527f98a0ccbf19c34e40b8378b89bc58d03f8b879922d", + "format": 1 + } + ], + "format": 1 +}
\ No newline at end of file diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/MANIFEST.json b/collections-debian-merged/ansible_collections/community/rabbitmq/MANIFEST.json new file mode 100644 index 00000000..03fac305 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/MANIFEST.json @@ -0,0 +1,31 @@ +{ + "collection_info": { + "namespace": "community", + "name": "rabbitmq", + "version": "1.0.1", + "authors": [ + "Ansible (https://github.com/ansible)", + "community.rabbitmq (https://github.com/ansible-collections/rabbitmq/graphs/contributors)" + ], + "readme": "README.md", + "tags": [ + "messaging" + ], + "description": null, + "license": [], + "license_file": "COPYING", + "dependencies": {}, + "repository": "https://github.com/ansible-collections/community.rabbitmq", + "documentation": "https://github.com/ansible-collections/community.rabbitmq/README.md", + "homepage": "https://github.com/ansible-collections/community.rabbitmq", + "issues": "https://github.com/ansible-collections/community.rabbitmq/issues" + }, + "file_manifest_file": { + "name": "FILES.json", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "bfcffba4d80eb6737b60e56ba84e031cdb5a21f368df865046722213ba43754a", + "format": 1 + }, + "format": 1 +}
\ No newline at end of file diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/README.md b/collections-debian-merged/ansible_collections/community/rabbitmq/README.md new file mode 100644 index 00000000..e7ffb2db --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/README.md @@ -0,0 +1,112 @@ +# community.rabbitmq Collection +<!-- Add CI and code coverage badges here. --> +<!-- Describe the collection and why a user would want to use it. What does the collection do? --> + +This repo hosts the `community.rabbitmq` Ansible Collection. + +The collection includes the rabbitmq modules and plugins supported by Ansible +rabbitmq community to help the management of rabbitmq infrastructure. + +## Tested with Ansible +<!-- List the versions of Ansible the collection has been tested with. Must match what is in galaxy.yml. --> +TBD + +## External requirements +<!-- List any external resources the collection depends on, for example minimum versions of an OS, libraries, or utilities. Do not list other Ansible collections here. --> +TBD + +### Supported connections +<!-- Optional. If your collection supports only specific connection types (such as HTTPAPI, netconf, or others), list them here. --> +TBD + +## Included content +<!-- Galaxy will eventually list the module docs within the UI, but until that is ready, you may need to either describe your plugins etc here, or point to an external docsite to cover that information. --> +TBD + +## Using this collection +<!--Include some quick examples that cover the most common use cases for your collection content. --> + +Before using the rabbitmq community collection, you need to install the +collection with the `ansible-galaxy` CLI: + +```bash +ansible-galaxy collection install community.rabbitmq +``` + +Alternatively, you can also include it in a `requirements.yml` file and +install it via `ansible-galaxy collection install -r requirements.yml` using +the format: + +```yaml +collections: +- name: community.rabbitmq +``` + +For more information regarding using collections with Ansible, see the Ansible +[user guide][3]. + +[3]: https://docs.ansible.com/ansible/latest/user_guide/collections_using.html + +## Contributing to this collection +<!--Describe how the community can contribute to your collection. At a minimum, include how and where users can create issues to report problems or request features for this collection. List contribution requirements, including preferred workflows and necessary testing, so you can benefit from community PRs. --> + +While this community is still developing its guidelines, the aspiration is to +follow the following general guidelines: + +- Changes should include tests and documentation where appropriate. +- Changes will be lint tested using standard python lint tests. +- No changes which do not pass CI testing will be approved/merged. +- The collection plugins must provide the same coverage of python support as + the versions of Ansible supported. +- The versions of Ansible supported by the collection must be the same as + those in developed, or those maintained, as shown in the Ansible [Release + and Maintenance][4] documentation. + +[4]: https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html + +As a fallback, the [Ansible Community Guide][5] remains our community +reference set of guidelines. + +[5]: https://docs.ansible.com/ansible/latest/community/index.html + +### Local Testing + +If you want to develop new content for this collection or improve what is +already here, the easiest way to work on the collection is to clone it into +one of the configured [COLLECTIONS_PATHS][2] and work on it there. + +[2]: https://docs.ansible.com/ansible/latest/reference_appendices/config.html#collections-paths + +### Testing with `ansible-test` + +TBD + +### Publishing New Version + +TBD + +## More Information +<!-- List out where the user can find additional information, such as working group meeting times, slack/IRC channels, or documentation for the product this collection automates. --> + +### Communication + +This is a small collection with a small number of contributors. As such, there +is no formal Ansible Working Group. To communicate with the maintainers, please +make contact via one of the following methods: + +- IRC on Freenode in #ansible-community +- [Issues](https://github.com/ansible-collections/rabbitmq/issues) on Github + +### Reference + +- [Ansible Collection overview](https://github.com/ansible-collections/overview) +- [Ansible User guide](https://docs.ansible.com/ansible/latest/user_guide/index.html) +- [Ansible Developer guide](https://docs.ansible.com/ansible/latest/dev_guide/index.html) +- [Ansible Community code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html) + +## License +<!-- Include the appropriate license information here and a pointer to the full licensing details. If the collection contains modules migrated from the ansible/ansible repo, you must use the same license that existed in the ansible/ansible repo. See the GNU license example below. --> + +GNU General Public License v3.0 or later. + +See [LICENCE](https://www.gnu.org/licenses/gpl-3.0.txt) to see the full text. diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/changelogs/changelog.yaml b/collections-debian-merged/ansible_collections/community/rabbitmq/changelogs/changelog.yaml new file mode 100644 index 00000000..04776650 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/changelogs/changelog.yaml @@ -0,0 +1,21 @@ +ancestor: null +releases: + 1.0.0: + changes: + bugfixes: + - Refactor RabbitMQ user module to first check the version of the daemon and + then, when possible add flags to `rabbitmqctl` so that a machine readable output + is returned. Also, depending on the version, parse the output in correctly. + Expands tests accordingly. (https://github.com/ansible/ansible/issues/48890) + - rabbitmq lookup plugin - Fix for rabbitmq lookups failing when using pika + v1.0.0 and newer. + - rabbitmq_publish - Fix to ensure the module works correctly for pika v1.0.0 + and later. (https://github.com/ansible/ansible/pull/61960) + minor_changes: + - rabbitmq_publish - Support for connecting with SSL certificates. + fragments: + - 55919-rabbitmq_publish-fix-for-recent-pika-versions.yml + - 66876-parse_post_rabbitmq_3.7_output_as_json.yaml + - lookup_rabbitmq-is_closing-bug.yml + - rabbitmq_publish-certificate-checks.yml + release_date: '2020-08-18' diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/changelogs/config.yaml b/collections-debian-merged/ansible_collections/community/rabbitmq/changelogs/config.yaml new file mode 100644 index 00000000..e47ffd37 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/changelogs/config.yaml @@ -0,0 +1,31 @@ +changelog_filename_template: ../CHANGELOG.rst +changelog_filename_version_depth: 0 +changes_file: changelog.yaml +changes_format: combined +ignore_other_fragment_extensions: true +keep_fragments: false +mention_ancestor: true +new_plugins_after_name: removed_features +notesdir: fragments +prelude_section_name: release_summary +prelude_section_title: Release Summary +sections: +- - major_changes + - Major Changes +- - minor_changes + - Minor Changes +- - breaking_changes + - Breaking Changes / Porting Guide +- - deprecated_features + - Deprecated Features +- - removed_features + - Removed Features (previously deprecated) +- - security_fixes + - Security Fixes +- - bugfixes + - Bugfixes +- - known_issues + - Known Issues +title: Community.Rabbitmq +trivial_section_name: trivial +use_fqcn: true diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/meta/runtime.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/meta/runtime.yml new file mode 100644 index 00000000..2ee3c9fa --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/meta/runtime.yml @@ -0,0 +1,2 @@ +--- +requires_ansible: '>=2.9.10' diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/doc_fragments/__init__.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/doc_fragments/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/doc_fragments/__init__.py diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/doc_fragments/rabbitmq.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/doc_fragments/rabbitmq.py new file mode 100644 index 00000000..acae82e8 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/doc_fragments/rabbitmq.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- + +# Copyright: (c) 2016, Jorge Rodriguez <jorge.rodriguez@tiriel.eu> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + + +class ModuleDocFragment(object): + # Parameters for RabbitMQ modules + DOCUMENTATION = r''' +options: + login_user: + description: + - RabbitMQ user for connection. + type: str + default: guest + login_password: + description: + - RabbitMQ password for connection. + type: str + default: guest + login_host: + description: + - RabbitMQ host for connection. + type: str + default: localhost + login_port: + description: + - RabbitMQ management API port. + type: str + default: '15672' + login_protocol: + description: + - RabbitMQ management API protocol. + type: str + choices: [ http , https ] + default: http + ca_cert: + description: + - CA certificate to verify SSL connection to management API. + type: path + aliases: [ cacert ] + client_cert: + description: + - Client certificate to send on SSL connections to management API. + type: path + aliases: [ cert ] + client_key: + description: + - Private key matching the client certificate. + type: path + aliases: [ key ] + vhost: + description: + - RabbitMQ virtual host. + type: str + default: "/" +''' diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/lookup/rabbitmq.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/lookup/rabbitmq.py new file mode 100644 index 00000000..406936de --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/lookup/rabbitmq.py @@ -0,0 +1,189 @@ +# (c) 2018, John Imison <john+github@imison.net> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +DOCUMENTATION = ''' + lookup: rabbitmq + author: John Imison <@Im0> + short_description: Retrieve messages from an AMQP/AMQPS RabbitMQ queue. + description: + - This lookup uses a basic get to retrieve all, or a limited number C(count), messages from a RabbitMQ queue. + options: + url: + description: + - An URI connection string to connect to the AMQP/AMQPS RabbitMQ server. + - For more information refer to the URI spec U(https://www.rabbitmq.com/uri-spec.html). + required: True + queue: + description: + - The queue to get messages from. + required: True + count: + description: + - How many messages to collect from the queue. + - If not set, defaults to retrieving all the messages from the queue. + requirements: + - The python pika package U(https://pypi.org/project/pika/). + notes: + - This lookup implements BlockingChannel.basic_get to get messages from a RabbitMQ server. + - After retrieving a message from the server, receipt of the message is acknowledged and the message on the server is deleted. + - Pika is a pure-Python implementation of the AMQP 0-9-1 protocol that tries to stay fairly independent of the underlying network support library. + - More information about pika can be found at U(https://pika.readthedocs.io/en/stable/). + - This plugin is tested against RabbitMQ. Other AMQP 0.9.1 protocol based servers may work but not tested/guaranteed. + - Assigning the return messages to a variable under C(vars) may result in unexpected results as the lookup is evaluated every time the + variable is referenced. + - Currently this plugin only handles text based messages from a queue. Unexpected results may occur when retrieving binary data. +''' + + +EXAMPLES = """ +- name: Get all messages off a queue + debug: + msg: "{{ lookup('community.rabbitmq.rabbitmq', url='amqp://guest:guest@192.168.0.10:5672/%2F', queue='hello') }}" + + +# If you are intending on using the returned messages as a variable in more than +# one task (eg. debug, template), it is recommended to set_fact. + +- name: Get 2 messages off a queue and set a fact for re-use + set_fact: + messages: "{{ lookup('community.rabbitmq.rabbiotmq', url='amqp://guest:guest@192.168.0.10:5672/%2F', queue='hello', count=2) }}" + +- name: Dump out contents of the messages + debug: + var: messages + +""" + +RETURN = """ + _list: + description: + - A list of dictionaries with keys and value from the queue. + type: list + contains: + content_type: + description: The content_type on the message in the queue. + type: str + delivery_mode: + description: The delivery_mode on the message in the queue. + type: str + delivery_tag: + description: The delivery_tag on the message in the queue. + type: str + exchange: + description: The exchange the message came from. + type: str + message_count: + description: The message_count for the message on the queue. + type: str + msg: + description: The content of the message. + type: str + redelivered: + description: The redelivered flag. True if the message has been delivered before. + type: bool + routing_key: + description: The routing_key on the message in the queue. + type: str + headers: + description: The headers for the message returned from the queue. + type: dict + json: + description: If application/json is specified in content_type, json will be loaded into variables. + type: dict + +""" + +import json + +from ansible.errors import AnsibleError, AnsibleParserError +from ansible.plugins.lookup import LookupBase +from ansible.module_utils._text import to_native, to_text +from ansible.utils.display import Display + +try: + import pika + from pika import spec + HAS_PIKA = True +except ImportError: + HAS_PIKA = False + +display = Display() + + +class LookupModule(LookupBase): + + def run(self, terms, variables=None, url=None, queue=None, count=None): + if not HAS_PIKA: + raise AnsibleError('pika python package is required for rabbitmq lookup.') + if not url: + raise AnsibleError('URL is required for rabbitmq lookup.') + if not queue: + raise AnsibleError('Queue is required for rabbitmq lookup.') + + display.vvv(u"terms:%s : variables:%s url:%s queue:%s count:%s" % (terms, variables, url, queue, count)) + + try: + parameters = pika.URLParameters(url) + except Exception as e: + raise AnsibleError("URL malformed: %s" % to_native(e)) + + try: + connection = pika.BlockingConnection(parameters) + except Exception as e: + raise AnsibleError("Connection issue: %s" % to_native(e)) + + try: + conn_channel = connection.channel() + except pika.exceptions.AMQPChannelError as e: + try: + connection.close() + except pika.exceptions.AMQPConnectionError as ie: + raise AnsibleError("Channel and connection closing issues: %s / %s" % to_native(e), to_native(ie)) + raise AnsibleError("Channel issue: %s" % to_native(e)) + + ret = [] + idx = 0 + + while True: + method_frame, properties, body = conn_channel.basic_get(queue=queue) + if method_frame: + display.vvv(u"%s, %s, %s " % (method_frame, properties, to_text(body))) + + # TODO: In the future consider checking content_type and handle text/binary data differently. + msg_details = dict({ + 'msg': to_text(body), + 'message_count': method_frame.message_count, + 'routing_key': method_frame.routing_key, + 'delivery_tag': method_frame.delivery_tag, + 'redelivered': method_frame.redelivered, + 'exchange': method_frame.exchange, + 'delivery_mode': properties.delivery_mode, + 'content_type': properties.content_type, + 'headers': properties.headers + }) + if properties.content_type == 'application/json': + try: + msg_details['json'] = json.loads(msg_details['msg']) + except ValueError as e: + raise AnsibleError("Unable to decode JSON for message %s: %s" % (method_frame.delivery_tag, to_native(e))) + + ret.append(msg_details) + conn_channel.basic_ack(method_frame.delivery_tag) + idx += 1 + if method_frame.message_count == 0 or idx == count: + break + # If we didn't get a method_frame, exit. + else: + break + + if connection.is_closed: + return [ret] + else: + try: + connection.close() + except pika.exceptions.AMQPConnectionError: + pass + return [ret] diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/module_utils/rabbitmq.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/module_utils/rabbitmq.py new file mode 100644 index 00000000..cf764006 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/module_utils/rabbitmq.py @@ -0,0 +1,220 @@ +# -*- coding: utf-8 -*- +# +# Copyright: (c) 2016, Jorge Rodriguez <jorge.rodriguez@tiriel.eu> +# Copyright: (c) 2018, John Imison <john+github@imison.net> +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +from ansible.module_utils._text import to_native +from ansible.module_utils.basic import missing_required_lib +from ansible.module_utils.six.moves.urllib import parse as urllib_parse +from mimetypes import MimeTypes + +import os +import json +import traceback + +PIKA_IMP_ERR = None +try: + import pika + import pika.exceptions + from pika import spec + HAS_PIKA = True +except ImportError: + PIKA_IMP_ERR = traceback.format_exc() + HAS_PIKA = False + + +def rabbitmq_argument_spec(): + return dict( + login_user=dict(type='str', default='guest'), + login_password=dict(type='str', default='guest', no_log=True), + login_host=dict(type='str', default='localhost'), + login_port=dict(type='str', default='15672'), + login_protocol=dict(type='str', default='http', choices=['http', 'https']), + ca_cert=dict(type='path', aliases=['cacert']), + client_cert=dict(type='path', aliases=['cert']), + client_key=dict(type='path', aliases=['key']), + vhost=dict(type='str', default='/'), + ) + + +# notification/rabbitmq_basic_publish.py +class RabbitClient(): + def __init__(self, module): + self.module = module + self.params = module.params + self.check_required_library() + self.check_host_params() + self.url = self.params['url'] + self.proto = self.params['proto'] + self.username = self.params['username'] + self.password = self.params['password'] + self.host = self.params['host'] + self.port = self.params['port'] + self.vhost = self.params['vhost'] + self.queue = self.params['queue'] + self.headers = self.params['headers'] + self.cafile = self.params['cafile'] + self.certfile = self.params['certfile'] + self.keyfile = self.params['keyfile'] + + if self.host is not None: + self.build_url() + + if self.cafile is not None: + self.append_ssl_certs() + + self.connect_to_rabbitmq() + + def check_required_library(self): + if not HAS_PIKA: + self.module.fail_json(msg=missing_required_lib("pika"), exception=PIKA_IMP_ERR) + + def check_host_params(self): + # Fail if url is specified and other conflicting parameters have been specified + if self.params['url'] is not None and any(self.params[k] is not None for k in ['proto', 'host', 'port', 'password', 'username', 'vhost']): + self.module.fail_json(msg="url and proto, host, port, vhost, username or password cannot be specified at the same time.") + + # Fail if url not specified and there is a missing parameter to build the url + if self.params['url'] is None and any(self.params[k] is None for k in ['proto', 'host', 'port', 'password', 'username', 'vhost']): + self.module.fail_json(msg="Connection parameters must be passed via url, or, proto, host, port, vhost, username or password.") + + def append_ssl_certs(self): + ssl_options = {} + if self.cafile: + ssl_options['cafile'] = self.cafile + if self.certfile: + ssl_options['certfile'] = self.certfile + if self.keyfile: + ssl_options['keyfile'] = self.keyfile + + self.url = self.url + '?ssl_options=' + urllib_parse.quote(json.dumps(ssl_options)) + + @staticmethod + def rabbitmq_argument_spec(): + return dict( + url=dict(type='str'), + proto=dict(type='str', choices=['amqp', 'amqps']), + host=dict(type='str'), + port=dict(type='int'), + username=dict(type='str'), + password=dict(type='str', no_log=True), + vhost=dict(type='str'), + queue=dict(type='str') + ) + + ''' Consider some file size limits here ''' + def _read_file(self, path): + try: + with open(path, "rb") as file_handle: + return file_handle.read() + except IOError as e: + self.module.fail_json(msg="Unable to open file %s: %s" % (path, to_native(e))) + + @staticmethod + def _check_file_mime_type(path): + mime = MimeTypes() + return mime.guess_type(path) + + def build_url(self): + self.url = '{0}://{1}:{2}@{3}:{4}/{5}'.format(self.proto, + self.username, + self.password, + self.host, + self.port, + self.vhost) + + def connect_to_rabbitmq(self): + """ + Function to connect to rabbitmq using username and password + """ + try: + parameters = pika.URLParameters(self.url) + except Exception as e: + self.module.fail_json(msg="URL malformed: %s" % to_native(e)) + + try: + self.connection = pika.BlockingConnection(parameters) + except Exception as e: + self.module.fail_json(msg="Connection issue: %s" % to_native(e)) + + try: + self.conn_channel = self.connection.channel() + except pika.exceptions.AMQPChannelError as e: + self.close_connection() + self.module.fail_json(msg="Channel issue: %s" % to_native(e)) + + def close_connection(self): + try: + self.connection.close() + except pika.exceptions.AMQPConnectionError: + pass + + def basic_publish(self): + self.content_type = self.params.get("content_type") + + if self.params.get("body") is not None: + args = dict( + body=self.params.get("body"), + exchange=self.params.get("exchange"), + routing_key=self.params.get("routing_key"), + properties=pika.BasicProperties(content_type=self.content_type, delivery_mode=1, headers=self.headers)) + + # If src (file) is defined and content_type is left as default, do a mime lookup on the file + if self.params.get("src") is not None and self.content_type == 'text/plain': + self.content_type = RabbitClient._check_file_mime_type(self.params.get("src"))[0] + self.headers.update( + filename=os.path.basename(self.params.get("src")) + ) + + args = dict( + body=self._read_file(self.params.get("src")), + exchange=self.params.get("exchange"), + routing_key=self.params.get("routing_key"), + properties=pika.BasicProperties(content_type=self.content_type, + delivery_mode=1, + headers=self.headers + )) + elif self.params.get("src") is not None: + args = dict( + body=self._read_file(self.params.get("src")), + exchange=self.params.get("exchange"), + routing_key=self.params.get("routing_key"), + properties=pika.BasicProperties(content_type=self.content_type, + delivery_mode=1, + headers=self.headers + )) + + try: + # If queue is not defined, RabbitMQ will return the queue name of the automatically generated queue. + if self.queue is None: + result = self.conn_channel.queue_declare(durable=self.params.get("durable"), + exclusive=self.params.get("exclusive"), + auto_delete=self.params.get("auto_delete")) + self.conn_channel.confirm_delivery() + self.queue = result.method.queue + else: + self.conn_channel.queue_declare(queue=self.queue, + durable=self.params.get("durable"), + exclusive=self.params.get("exclusive"), + auto_delete=self.params.get("auto_delete")) + self.conn_channel.confirm_delivery() + except Exception as e: + self.module.fail_json(msg="Queue declare issue: %s" % to_native(e)) + + # https://github.com/ansible/ansible/blob/devel/lib/ansible/module_utils/cloudstack.py#L150 + if args['routing_key'] is None: + args['routing_key'] = self.queue + + if args['exchange'] is None: + args['exchange'] = '' + + try: + self.conn_channel.basic_publish(**args) + return True + except pika.exceptions.UnroutableError: + return False diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_binding.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_binding.py new file mode 100644 index 00000000..80194e20 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_binding.py @@ -0,0 +1,298 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2015, Manuel Sousa <manuel.sousa@gmail.com> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: rabbitmq_binding +author: Manuel Sousa (@manuel-sousa) + +short_description: Manage rabbitMQ bindings +description: + - This module uses rabbitMQ REST APIs to create / delete bindings. +requirements: [ "requests >= 1.0.0" ] +options: + state: + description: + - Whether the bindings should be present or absent. + type: str + choices: [ "present", "absent" ] + default: present + name: + description: + - source exchange to create binding on. + type: str + required: true + aliases: [ "src", "source" ] + destination: + description: + - destination exchange or queue for the binding. + type: str + required: true + aliases: [ "dst", "dest" ] + destination_type: + description: + - Either queue or exchange. + type: str + required: true + choices: [ "queue", "exchange" ] + aliases: [ "type", "dest_type" ] + routing_key: + description: + - routing key for the binding. + type: str + default: "#" + arguments: + description: + - extra arguments for exchange. If defined this argument is a key/value dictionary + type: dict + required: false + default: {} +extends_documentation_fragment: + - community.rabbitmq.rabbitmq + +''' + +EXAMPLES = ''' +# Bind myQueue to directExchange with routing key info +- community.rabbitmq.rabbitmq_binding: + name: directExchange + destination: myQueue + type: queue + routing_key: info + +# Bind directExchange to topicExchange with routing key *.info +- community.rabbitmq.rabbitmq_binding: + name: topicExchange + destination: topicExchange + type: exchange + routing_key: '*.info' +''' + +import json +import traceback + +REQUESTS_IMP_ERR = None +try: + import requests + HAS_REQUESTS = True +except ImportError: + REQUESTS_IMP_ERR = traceback.format_exc() + HAS_REQUESTS = False + +from ansible.module_utils.six.moves.urllib import parse as urllib_parse +from ansible.module_utils.basic import AnsibleModule, missing_required_lib +from ansible_collections.community.rabbitmq.plugins.module_utils.rabbitmq import rabbitmq_argument_spec + + +class RabbitMqBinding(object): + def __init__(self, module): + """ + :param module: + """ + self.module = module + self.name = self.module.params['name'] + self.login_user = self.module.params['login_user'] + self.login_password = self.module.params['login_password'] + self.login_host = self.module.params['login_host'] + self.login_port = self.module.params['login_port'] + self.login_protocol = self.module.params['login_protocol'] + self.vhost = self.module.params['vhost'] + self.destination = self.module.params['destination'] + self.destination_type = 'q' if self.module.params['destination_type'] == 'queue' else 'e' + self.routing_key = self.module.params['routing_key'] + self.arguments = self.module.params['arguments'] + self.verify = self.module.params['ca_cert'] + self.cert = self.module.params['client_cert'] + self.key = self.module.params['client_key'] + self.props = urllib_parse.quote(self.routing_key) if self.routing_key != '' else '~' + self.base_url = '{0}://{1}:{2}/api/bindings'.format(self.login_protocol, + self.login_host, + self.login_port) + self.url = '{0}/{1}/e/{2}/{3}/{4}/{5}'.format(self.base_url, + urllib_parse.quote(self.vhost, safe=''), + urllib_parse.quote(self.name, safe=''), + self.destination_type, + urllib_parse.quote(self.destination, safe=''), + self.props) + self.result = { + 'changed': False, + 'name': self.module.params['name'], + } + self.authentication = ( + self.login_user, + self.login_password + ) + self.request = requests + self.http_check_states = { + 200: True, + 404: False, + } + self.http_actionable_states = { + 201: True, + 204: True, + } + self.api_result = self.request.get(self.url, auth=self.authentication, verify=self.verify, cert=(self.cert, self.key)) + + def run(self): + """ + :return: + """ + self.check_presence() + self.check_mode() + self.action_mode() + + def check_presence(self): + """ + :return: + """ + if self.check_should_throw_fail(): + self.fail() + + def change_required(self): + """ + :return: + """ + if self.module.params['state'] == 'present': + if not self.is_present(): + return True + elif self.module.params['state'] == 'absent': + if self.is_present(): + return True + return False + + def is_present(self): + """ + :return: + """ + return self.http_check_states.get(self.api_result.status_code, False) + + def check_mode(self): + """ + :return: + """ + if self.module.check_mode: + result = self.result + result['changed'] = self.change_required() + result['details'] = self.api_result.json() if self.is_present() else self.api_result.text + result['arguments'] = self.module.params['arguments'] + self.module.exit_json(**result) + + def check_reply_is_correct(self): + """ + :return: + """ + if self.api_result.status_code in self.http_check_states: + return True + return False + + def check_should_throw_fail(self): + """ + :return: + """ + if not self.is_present(): + if not self.check_reply_is_correct(): + return True + return False + + def action_mode(self): + """ + :return: + """ + result = self.result + if self.change_required(): + if self.module.params['state'] == 'present': + self.create() + if self.module.params['state'] == 'absent': + self.remove() + if self.action_should_throw_fail(): + self.fail() + result['changed'] = True + result['destination'] = self.module.params['destination'] + self.module.exit_json(**result) + else: + result['changed'] = False + self.module.exit_json(**result) + + def action_reply_is_correct(self): + """ + :return: + """ + if self.api_result.status_code in self.http_actionable_states: + return True + return False + + def action_should_throw_fail(self): + """ + :return: + """ + if not self.action_reply_is_correct(): + return True + return False + + def create(self): + """ + :return: + """ + self.url = '{0}/{1}/e/{2}/{3}/{4}'.format(self.base_url, + urllib_parse.quote(self.vhost, safe=''), + urllib_parse.quote(self.name, safe=''), + self.destination_type, + urllib_parse.quote(self.destination, safe='')) + self.api_result = self.request.post(self.url, + auth=self.authentication, + verify=self.verify, + cert=(self.cert, self.key), + headers={"content-type": "application/json"}, + data=json.dumps({ + 'routing_key': self.routing_key, + 'arguments': self.arguments + })) + + def remove(self): + """ + :return: + """ + self.api_result = self.request.delete(self.url, auth=self.authentication, verify=self.verify, cert=(self.cert, self.key)) + + def fail(self): + """ + :return: + """ + self.module.fail_json( + msg="Unexpected reply from API", + status=self.api_result.status_code, + details=self.api_result.text + ) + + +def main(): + + argument_spec = rabbitmq_argument_spec() + argument_spec.update( + dict( + state=dict(default='present', choices=['present', 'absent'], type='str'), + name=dict(required=True, aliases=["src", "source"], type='str'), + destination=dict(required=True, aliases=["dst", "dest"], type='str'), + destination_type=dict(required=True, aliases=["type", "dest_type"], choices=["queue", "exchange"], + type='str'), + routing_key=dict(default='#', type='str'), + arguments=dict(default=dict(), type='dict') + ) + ) + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) + + if not HAS_REQUESTS: + module.fail_json(msg=missing_required_lib("requests"), exception=REQUESTS_IMP_ERR) + + RabbitMqBinding(module).run() + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_exchange.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_exchange.py new file mode 100644 index 00000000..0feb07ed --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_exchange.py @@ -0,0 +1,209 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2015, Manuel Sousa <manuel.sousa@gmail.com> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: rabbitmq_exchange +author: Manuel Sousa (@manuel-sousa) + +short_description: Manage rabbitMQ exchanges +description: + - This module uses rabbitMQ Rest API to create/delete exchanges +requirements: [ "requests >= 1.0.0" ] +options: + name: + description: + - Name of the exchange to create + type: str + required: true + state: + description: + - Whether the exchange should be present or absent + type: str + choices: [ "present", "absent" ] + required: false + default: present + durable: + description: + - whether exchange is durable or not + type: bool + required: false + default: yes + exchange_type: + description: + - type for the exchange + type: str + required: false + choices: [ "fanout", "direct", "headers", "topic" ] + aliases: [ "type" ] + default: direct + auto_delete: + description: + - if the exchange should delete itself after all queues/exchanges unbound from it + type: bool + required: false + default: no + internal: + description: + - exchange is available only for other exchanges + type: bool + required: false + default: no + arguments: + description: + - extra arguments for exchange. If defined this argument is a key/value dictionary + type: dict + required: false + default: {} +extends_documentation_fragment: + - community.rabbitmq.rabbitmq + +''' + +EXAMPLES = ''' +# Create direct exchange +- community.rabbitmq.rabbitmq_exchange: + name: directExchange + +# Create topic exchange on vhost +- community.rabbitmq.rabbitmq_exchange: + name: topicExchange + type: topic + vhost: myVhost +''' + +import json +import traceback + +REQUESTS_IMP_ERR = None +try: + import requests + HAS_REQUESTS = True +except ImportError: + REQUESTS_IMP_ERR = traceback.format_exc() + HAS_REQUESTS = False + +from ansible.module_utils.basic import AnsibleModule, missing_required_lib +from ansible.module_utils.six.moves.urllib import parse as urllib_parse +from ansible_collections.community.rabbitmq.plugins.module_utils.rabbitmq import rabbitmq_argument_spec + + +def main(): + + argument_spec = rabbitmq_argument_spec() + argument_spec.update( + dict( + state=dict(default='present', choices=['present', 'absent'], type='str'), + name=dict(required=True, type='str'), + durable=dict(default=True, type='bool'), + auto_delete=dict(default=False, type='bool'), + internal=dict(default=False, type='bool'), + exchange_type=dict(default='direct', aliases=['type'], + choices=['fanout', 'direct', 'headers', 'topic'], + type='str'), + arguments=dict(default=dict(), type='dict') + ) + ) + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) + + url = "%s://%s:%s/api/exchanges/%s/%s" % ( + module.params['login_protocol'], + module.params['login_host'], + module.params['login_port'], + urllib_parse.quote(module.params['vhost'], ''), + urllib_parse.quote(module.params['name'], '') + ) + + if not HAS_REQUESTS: + module.fail_json(msg=missing_required_lib("requests"), exception=REQUESTS_IMP_ERR) + + result = dict(changed=False, name=module.params['name']) + + # Check if exchange already exists + r = requests.get(url, auth=(module.params['login_user'], module.params['login_password']), + verify=module.params['ca_cert'], cert=(module.params['client_cert'], module.params['client_key'])) + + if r.status_code == 200: + exchange_exists = True + response = r.json() + elif r.status_code == 404: + exchange_exists = False + response = r.text + else: + module.fail_json( + msg="Invalid response from RESTAPI when trying to check if exchange exists", + details=r.text + ) + + if module.params['state'] == 'present': + change_required = not exchange_exists + else: + change_required = exchange_exists + + # Check if attributes change on existing exchange + if not change_required and r.status_code == 200 and module.params['state'] == 'present': + if not ( + response['durable'] == module.params['durable'] and + response['auto_delete'] == module.params['auto_delete'] and + response['internal'] == module.params['internal'] and + response['type'] == module.params['exchange_type'] + ): + module.fail_json( + msg="RabbitMQ RESTAPI doesn't support attribute changes for existing exchanges" + ) + + # Exit if check_mode + if module.check_mode: + result['changed'] = change_required + result['details'] = response + result['arguments'] = module.params['arguments'] + module.exit_json(**result) + + # Do changes + if change_required: + if module.params['state'] == 'present': + r = requests.put( + url, + auth=(module.params['login_user'], module.params['login_password']), + headers={"content-type": "application/json"}, + data=json.dumps({ + "durable": module.params['durable'], + "auto_delete": module.params['auto_delete'], + "internal": module.params['internal'], + "type": module.params['exchange_type'], + "arguments": module.params['arguments'] + }), + verify=module.params['ca_cert'], + cert=(module.params['client_cert'], module.params['client_key']) + ) + elif module.params['state'] == 'absent': + r = requests.delete(url, auth=(module.params['login_user'], module.params['login_password']), + verify=module.params['ca_cert'], cert=(module.params['client_cert'], module.params['client_key'])) + + # RabbitMQ 3.6.7 changed this response code from 204 to 201 + if r.status_code == 204 or r.status_code == 201: + result['changed'] = True + module.exit_json(**result) + else: + module.fail_json( + msg="Error creating exchange", + status=r.status_code, + details=r.text + ) + + else: + module.exit_json( + changed=False, + name=module.params['name'] + ) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_global_parameter.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_global_parameter.py new file mode 100644 index 00000000..97fc90cb --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_global_parameter.py @@ -0,0 +1,155 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2013, Chatham Financial <oss@chathamfinancial.com> +# Copyright: (c) 2017, Juergen Kirschbaum <jk@jk-itc.de> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: rabbitmq_global_parameter +short_description: Manage RabbitMQ global parameters +description: + - Manage dynamic, cluster-wide global parameters for RabbitMQ +author: "Juergen Kirschbaum (@jgkirschbaum)" +options: + name: + description: + - Name of the global parameter being set + type: str + required: true + default: null + value: + description: + - Value of the global parameter, as a JSON term + type: str + required: false + default: null + node: + description: + - erlang node name of the rabbit we wish to configure + type: str + required: false + default: rabbit + state: + description: + - Specify if user is to be added or removed + type: str + required: false + default: present + choices: [ 'present', 'absent'] +''' + +EXAMPLES = ''' +# Set the global parameter 'cluster_name' to a value of 'mq-cluster' (in quotes) +- community.rabbitmq.rabbitmq_global_parameter: + name: cluster_name + value: "{{ 'mq-cluster' | to_json }}" + state: present +''' + +RETURN = ''' +name: + description: name of the global parameter being set + returned: success + type: str + sample: "cluster_name" +value: + description: value of the global parameter, as a JSON term + returned: changed + type: str + sample: "the-cluster-name" +''' + +import json +from ansible.module_utils.basic import AnsibleModule + + +class RabbitMqGlobalParameter(object): + def __init__(self, module, name, value, node): + self.module = module + self.name = name + self.value = value + self.node = node + + self._value = None + + self._rabbitmqctl = module.get_bin_path('rabbitmqctl', True) + + def _exec(self, args, run_in_check_mode=False): + if not self.module.check_mode or (self.module.check_mode and run_in_check_mode): + cmd = [self._rabbitmqctl, '-q', '-n', self.node] + rc, out, err = self.module.run_command(cmd + args, check_rc=True) + return out.splitlines() + return list() + + def get(self): + global_parameters = self._exec(['list_global_parameters'], True) + + for param_item in global_parameters: + name, value = param_item.split('\t') + + if name == self.name: + self._value = json.loads(value) + return True + return False + + def set(self): + self._exec(['set_global_parameter', + self.name, + json.dumps(self.value)]) + + def delete(self): + self._exec(['clear_global_parameter', self.name]) + + def has_modifications(self): + return self.value != self._value + + +def main(): + arg_spec = dict( + name=dict(type='str', required=True), + value=dict(type='str', default=None), + state=dict(default='present', choices=['present', 'absent']), + node=dict(type='str', default='rabbit') + ) + module = AnsibleModule( + argument_spec=arg_spec, + supports_check_mode=True + ) + + name = module.params['name'] + value = module.params['value'] + if isinstance(value, str): + value = json.loads(value) + state = module.params['state'] + node = module.params['node'] + + result = dict(changed=False) + rabbitmq_global_parameter = RabbitMqGlobalParameter(module, name, value, node) + + if rabbitmq_global_parameter.get(): + if state == 'absent': + rabbitmq_global_parameter.delete() + result['changed'] = True + else: + if rabbitmq_global_parameter.has_modifications(): + rabbitmq_global_parameter.set() + result['changed'] = True + elif state == 'present': + rabbitmq_global_parameter.set() + result['changed'] = True + + result['name'] = name + result['value'] = value + result['state'] = state + + module.exit_json(**result) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_parameter.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_parameter.py new file mode 100644 index 00000000..d88bdcd6 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_parameter.py @@ -0,0 +1,155 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2013, Chatham Financial <oss@chathamfinancial.com> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: rabbitmq_parameter +short_description: Manage RabbitMQ parameters +description: + - Manage dynamic, cluster-wide parameters for RabbitMQ +author: Chris Hoffman (@chrishoffman) +options: + component: + description: + - Name of the component of which the parameter is being set + type: str + required: true + name: + description: + - Name of the parameter being set + type: str + required: true + value: + description: + - Value of the parameter, as a JSON term + type: str + vhost: + description: + - vhost to apply access privileges. + type: str + default: / + node: + description: + - erlang node name of the rabbit we wish to configure + type: str + default: rabbit + state: + description: + - Specify if user is to be added or removed + type: str + default: present + choices: [ 'present', 'absent'] +''' + +EXAMPLES = """ +# Set the federation parameter 'local_username' to a value of 'guest' (in quotes) +- community.rabbitmq.rabbitmq_parameter: + component: federation + name: local-username + value: '"guest"' + state: present +""" +import json +from ansible.module_utils.basic import AnsibleModule + + +class RabbitMqParameter(object): + def __init__(self, module, component, name, value, vhost, node): + self.module = module + self.component = component + self.name = name + self.value = value + self.vhost = vhost + self.node = node + + self._value = None + + self._rabbitmqctl = module.get_bin_path('rabbitmqctl', True) + + def _exec(self, args, run_in_check_mode=False): + if not self.module.check_mode or (self.module.check_mode and run_in_check_mode): + cmd = [self._rabbitmqctl, '-q', '-n', self.node] + rc, out, err = self.module.run_command(cmd + args, check_rc=True) + return out.strip().splitlines() + return list() + + def get(self): + parameters = [param for param in self._exec(['list_parameters', '-p', self.vhost], True) if param.strip()] + + for param_item in parameters: + component, name, value = param_item.split('\t') + + if component == self.component and name == self.name: + self._value = json.loads(value) + return True + return False + + def set(self): + self._exec(['set_parameter', + '-p', + self.vhost, + self.component, + self.name, + json.dumps(self.value)]) + + def delete(self): + self._exec(['clear_parameter', '-p', self.vhost, self.component, self.name]) + + def has_modifications(self): + return self.value != self._value + + +def main(): + arg_spec = dict( + component=dict(required=True), + name=dict(required=True), + value=dict(default=None), + vhost=dict(default='/'), + state=dict(default='present', choices=['present', 'absent']), + node=dict(default='rabbit') + ) + module = AnsibleModule( + argument_spec=arg_spec, + supports_check_mode=True + ) + + component = module.params['component'] + name = module.params['name'] + value = module.params['value'] + if isinstance(value, str): + value = json.loads(value) + vhost = module.params['vhost'] + state = module.params['state'] + node = module.params['node'] + + result = dict(changed=False) + rabbitmq_parameter = RabbitMqParameter(module, component, name, value, vhost, node) + + if rabbitmq_parameter.get(): + if state == 'absent': + rabbitmq_parameter.delete() + result['changed'] = True + else: + if rabbitmq_parameter.has_modifications(): + rabbitmq_parameter.set() + result['changed'] = True + elif state == 'present': + rabbitmq_parameter.set() + result['changed'] = True + + result['component'] = component + result['name'] = name + result['vhost'] = vhost + result['state'] = state + module.exit_json(**result) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_plugin.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_plugin.py new file mode 100644 index 00000000..87a08b9f --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_plugin.py @@ -0,0 +1,187 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2013, Chatham Financial <oss@chathamfinancial.com> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: rabbitmq_plugin +short_description: Manage RabbitMQ plugins +description: + - This module can be used to enable or disable RabbitMQ plugins. +author: + - Chris Hoffman (@chrishoffman) +options: + names: + description: + - Comma-separated list of plugin names. Also, accepts plugin name. + type: str + required: true + aliases: [name] + new_only: + description: + - Only enable missing plugins. + - Does not disable plugins that are not in the names list. + type: bool + default: "no" + state: + description: + - Specify if plugins are to be enabled or disabled. + type: str + default: enabled + choices: [enabled, disabled] + broker_state: + description: + - Specify whether the broker should be online or offline for the plugin change. + type: str + default: online + choices: [online, offline] + prefix: + description: + - Specify a custom install prefix to a Rabbit. + type: str +''' + +EXAMPLES = ''' +- name: Enables the rabbitmq_management plugin + community.rabbitmq.rabbitmq_plugin: + names: rabbitmq_management + state: enabled + +- name: Enable multiple rabbitmq plugins + community.rabbitmq.rabbitmq_plugin: + names: rabbitmq_management,rabbitmq_management_visualiser + state: enabled + +- name: Disable plugin + community.rabbitmq.rabbitmq_plugin: + names: rabbitmq_management + state: disabled + +- name: Enable every plugin in list with existing plugins + community.rabbitmq.rabbitmq_plugin: + names: rabbitmq_management,rabbitmq_management_visualiser,rabbitmq_shovel,rabbitmq_shovel_management + state: enabled + new_only: 'yes' + +- name: Enables the rabbitmq_peer_discovery_aws plugin without requiring a broker connection. + community.rabbitmq.rabbitmq_plugin: + names: rabbitmq_peer_discovery_aws_plugin + state: enabled + broker_state: offline +''' + +RETURN = ''' +enabled: + description: list of plugins enabled during task run + returned: always + type: list + sample: ["rabbitmq_management"] +disabled: + description: list of plugins disabled during task run + returned: always + type: list + sample: ["rabbitmq_management"] +''' + +import os +from ansible.module_utils.basic import AnsibleModule + + +class RabbitMqPlugins(object): + + def __init__(self, module): + self.module = module + bin_path = '' + if module.params['prefix']: + if os.path.isdir(os.path.join(module.params['prefix'], 'bin')): + bin_path = os.path.join(module.params['prefix'], 'bin') + elif os.path.isdir(os.path.join(module.params['prefix'], 'sbin')): + bin_path = os.path.join(module.params['prefix'], 'sbin') + else: + # No such path exists. + module.fail_json(msg="No binary folder in prefix %s" % module.params['prefix']) + + self._rabbitmq_plugins = os.path.join(bin_path, "rabbitmq-plugins") + else: + self._rabbitmq_plugins = module.get_bin_path('rabbitmq-plugins', True) + + def _exec(self, args, run_in_check_mode=False): + if not self.module.check_mode or (self.module.check_mode and run_in_check_mode): + cmd = [self._rabbitmq_plugins] + rc, out, err = self.module.run_command(cmd + args, check_rc=True) + return out.splitlines() + return list() + + def get_all(self): + list_output = self._exec(['list', '-E', '-m'], True) + plugins = [] + for plugin in list_output: + if not plugin: + break + plugins.append(plugin) + + return plugins + + def enable(self, name): + self._exec(['enable', "--%s" % self.module.params['broker_state'], name]) + + def disable(self, name): + self._exec(['disable', "--%s" % self.module.params['broker_state'], name]) + + +def main(): + arg_spec = dict( + names=dict(required=True, aliases=['name']), + new_only=dict(default='no', type='bool'), + state=dict(default='enabled', choices=['enabled', 'disabled']), + broker_state=dict(default='online', choices=['online', 'offline']), + prefix=dict(required=False, default=None) + ) + module = AnsibleModule( + argument_spec=arg_spec, + supports_check_mode=True + ) + + result = dict() + names = module.params['names'].split(',') + new_only = module.params['new_only'] + state = module.params['state'] + + rabbitmq_plugins = RabbitMqPlugins(module) + enabled_plugins = rabbitmq_plugins.get_all() + + enabled = [] + disabled = [] + if state == 'enabled': + if not new_only: + for plugin in enabled_plugins: + if " " in plugin: + continue + if plugin not in names: + rabbitmq_plugins.disable(plugin) + disabled.append(plugin) + + for name in names: + if name not in enabled_plugins: + rabbitmq_plugins.enable(name) + enabled.append(name) + else: + for plugin in enabled_plugins: + if plugin in names: + rabbitmq_plugins.disable(plugin) + disabled.append(plugin) + + result['changed'] = len(enabled) > 0 or len(disabled) > 0 + result['enabled'] = enabled + result['disabled'] = disabled + module.exit_json(**result) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_policy.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_policy.py new file mode 100644 index 00000000..41faebaa --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_policy.py @@ -0,0 +1,248 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2013, John Dewey <john@dewey.ws> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: rabbitmq_policy +short_description: Manage the state of policies in RabbitMQ +description: + - Manage the state of a policy in RabbitMQ. +author: John Dewey (@retr0h) +options: + name: + description: + - The name of the policy to manage. + type: str + required: true + vhost: + description: + - The name of the vhost to apply to. + type: str + default: / + apply_to: + description: + - What the policy applies to. Requires RabbitMQ 3.2.0 or later. + type: str + default: all + choices: [all, exchanges, queues] + pattern: + description: + - A regex of queues to apply the policy to. Required when + C(state=present). This option is no longer required as of Ansible 2.9. + type: str + required: false + default: null + tags: + description: + - A dict or string describing the policy. Required when + C(state=present). This option is no longer required as of Ansible 2.9. + type: dict + required: false + default: null + priority: + description: + - The priority of the policy. + type: str + default: '0' + node: + description: + - Erlang node name of the rabbit we wish to configure. + type: str + default: rabbit + state: + description: + - The state of the policy. + type: str + default: present + choices: [present, absent] +''' + +EXAMPLES = ''' +- name: ensure the default vhost contains the HA policy via a dict + community.rabbitmq.rabbitmq_policy: + name: HA + pattern: .* + args: + tags: + ha-mode: all + +- name: ensure the default vhost contains the HA policy + community.rabbitmq.rabbitmq_policy: + name: HA + pattern: .* + tags: + ha-mode: all +''' + +import json +import re +from distutils.version import LooseVersion as Version + +from ansible.module_utils.basic import AnsibleModule + + +class RabbitMqPolicy(object): + + def __init__(self, module, name): + self._module = module + self._name = name + self._vhost = module.params['vhost'] + self._pattern = module.params['pattern'] + self._apply_to = module.params['apply_to'] + self._tags = module.params['tags'] + self._priority = module.params['priority'] + self._node = module.params['node'] + self._rabbitmqctl = module.get_bin_path('rabbitmqctl', True) + + self._version = self._rabbit_version() + + def _exec(self, + args, + run_in_check_mode=False, + split_lines=True, + add_vhost=True): + if (not self._module.check_mode + or (self._module.check_mode and run_in_check_mode)): + cmd = [self._rabbitmqctl, '-q', '-n', self._node] + + if add_vhost: + args.insert(1, '-p') + args.insert(2, self._vhost) + + rc, out, err = self._module.run_command(cmd + args, check_rc=True) + if split_lines: + return out.splitlines() + + return out + return list() + + def _rabbit_version(self): + status = self._exec(['status'], True, False, False) + + # 3.7.x erlang style output + version_match = re.search('{rabbit,".*","(?P<version>.*)"}', status) + if version_match: + return Version(version_match.group('version')) + + # 3.8.x style ouput + version_match = re.search('RabbitMQ version: (?P<version>.*)', status) + if version_match: + return Version(version_match.group('version')) + + return None + + def _list_policies(self): + if self._version and self._version >= Version('3.7.9'): + # Remove first header line from policies list for version > 3.7.9 + return self._exec(['list_policies'], True)[1:] + + return self._exec(['list_policies'], True) + + def has_modifications(self): + if self._pattern is None or self._tags is None: + self._module.fail_json( + msg=('pattern and tags are required for ' + 'state=present')) + + if self._version and self._version >= Version('3.7.0'): + # Change fields order in rabbitmqctl output in version 3.7 + return not any( + self._policy_check(policy, apply_to_fno=3, pattern_fno=2) + for policy in self._list_policies()) + else: + return not any( + self._policy_check(policy) for policy in self._list_policies()) + + def should_be_deleted(self): + return any( + self._policy_check_by_name(policy) + for policy in self._list_policies()) + + def set(self): + args = ['set_policy'] + args.append(self._name) + args.append(self._pattern) + args.append(json.dumps(self._tags)) + args.append('--priority') + args.append(self._priority) + if self._apply_to != 'all': + args.append('--apply-to') + args.append(self._apply_to) + return self._exec(args) + + def clear(self): + return self._exec(['clear_policy', self._name]) + + def _policy_check(self, + policy, + name_fno=1, + apply_to_fno=2, + pattern_fno=3, + tags_fno=4, + priority_fno=5): + if not policy: + return False + + policy_data = policy.split('\t') + + policy_name = policy_data[name_fno] + apply_to = policy_data[apply_to_fno] + pattern = policy_data[pattern_fno].replace('\\\\', '\\') + tags = json.loads(policy_data[tags_fno]) + priority = policy_data[priority_fno] + + return (policy_name == self._name and apply_to == self._apply_to + and tags == self._tags and priority == self._priority + and pattern == self._pattern) + + def _policy_check_by_name(self, policy): + if not policy: + return False + + policy_name = policy.split('\t')[1] + + return policy_name == self._name + + +def main(): + arg_spec = dict( + name=dict(required=True), + vhost=dict(default='/'), + pattern=dict(required=False, default=None), + apply_to=dict(default='all', choices=['all', 'exchanges', 'queues']), + tags=dict(type='dict', required=False, default=None), + priority=dict(default='0'), + node=dict(default='rabbit'), + state=dict(default='present', choices=['present', 'absent']), + ) + + module = AnsibleModule( + argument_spec=arg_spec, + supports_check_mode=True + ) + + name = module.params['name'] + state = module.params['state'] + rabbitmq_policy = RabbitMqPolicy(module, name) + + result = dict(changed=False, name=name, state=state) + + if state == 'present' and rabbitmq_policy.has_modifications(): + rabbitmq_policy.set() + result['changed'] = True + elif state == 'absent' and rabbitmq_policy.should_be_deleted(): + rabbitmq_policy.clear() + result['changed'] = True + + module.exit_json(**result) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_publish.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_publish.py new file mode 100644 index 00000000..12f7af31 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_publish.py @@ -0,0 +1,220 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# (c) 2018, John Imison <john+github@imison.net> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: rabbitmq_publish +short_description: Publish a message to a RabbitMQ queue. +description: + - Publish a message on a RabbitMQ queue using a blocking connection. +options: + url: + description: + - An URL connection string to connect to the RabbitMQ server. + - I(url) and I(host)/I(port)/I(user)/I(pass)/I(vhost) are mutually exclusive, use either or but not both. + type: str + proto: + description: + - The protocol to use. + type: str + choices: [amqps, amqp] + host: + description: + - The RabbitMQ server hostname or IP. + type: str + port: + description: + - The RabbitMQ server port. + type: int + username: + description: + - The RabbitMQ username. + type: str + password: + description: + - The RabbitMQ password. + type: str + vhost: + description: + - The virtual host to target. + - If default vhost is required, use C('%2F'). + type: str + queue: + description: + - The queue to publish a message to. If no queue is specified, RabbitMQ will return a random queue name. + type: str + exchange: + description: + - The exchange to publish a message to. + type: str + routing_key: + description: + - The routing key. + type: str + body: + description: + - The body of the message. + - A C(body) cannot be provided if a C(src) is specified. + type: str + src: + description: + - A file to upload to the queue. Automatic mime type detection is attempted if content_type is not defined (left as default). + - A C(src) cannot be provided if a C(body) is specified. + - The filename is added to the headers of the posted message to RabbitMQ. Key being the C(filename), value is the filename. + type: path + aliases: ['file'] + content_type: + description: + - The content type of the body. + type: str + default: text/plain + durable: + description: + - Set the queue to be durable. + type: bool + default: False + exclusive: + description: + - Set the queue to be exclusive. + type: bool + default: False + auto_delete: + description: + - Set the queue to auto delete. + type: bool + default: False + headers: + description: + - A dictionary of headers to post with the message. + type: dict + default: {} + cafile: + description: + - CA file used during connection to the RabbitMQ server over SSL. + - If this option is specified, also I(certfile) and I(keyfile) must be specified. + type: str + certfile: + description: + - Client certificate to establish SSL connection. + - If this option is specified, also I(cafile) and I(keyfile) must be specified. + type: str + keyfile: + description: + - Client key to establish SSL connection. + - If this option is specified, also I(cafile) and I(certfile) must be specified. + type: str + + + +requirements: [ pika ] +notes: + - This module requires the pika python library U(https://pika.readthedocs.io/). + - Pika is a pure-Python implementation of the AMQP 0-9-1 protocol that tries to stay fairly independent of the underlying network support library. + - This module is tested against RabbitMQ. Other AMQP 0.9.1 protocol based servers may work but not tested/guaranteed. + - The certificate authentication was tested with certificates created + via U(https://www.rabbitmq.com/ssl.html#automated-certificate-generation) and RabbitMQ + configuration variables C(ssl_options.verify = verify_peer) & C(ssl_options.fail_if_no_peer_cert = true). +author: "John Imison (@Im0)" +''' + +EXAMPLES = ''' +- name: Publish a message to a queue with headers + community.rabbitmq.rabbitmq_publish: + url: "amqp://guest:guest@192.168.0.32:5672/%2F" + queue: 'test' + body: "Hello world from ansible module rabbitmq_publish" + content_type: "text/plain" + headers: + myHeader: myHeaderValue + + +- name: Publish a file to a queue + community.rabbitmq.rabbitmq_publish: + url: "amqp://guest:guest@192.168.0.32:5672/%2F" + queue: 'images' + file: 'path/to/logo.gif' + +- name: RabbitMQ auto generated queue + community.rabbitmq.rabbitmq_publish: + url: "amqp://guest:guest@192.168.0.32:5672/%2F" + body: "Hello world random queue from ansible module rabbitmq_publish" + content_type: "text/plain" + +- name: Publish with certs + community.rabbitmq.rabbitmq_publish: + url: "amqps://guest:guest@192.168.0.32:5671/%2F" + body: "Hello test queue from ansible module rabbitmq_publish via SSL certs" + queue: 'test' + content_type: "text/plain" + cafile: 'ca_certificate.pem' + certfile: 'client_certificate.pem' + keyfile: 'client_key.pem' + +''' + +RETURN = ''' +result: + description: + - Contains the status I(msg), content type I(content_type) and the queue name I(queue). + returned: success + type: dict + sample: | + 'result': { 'content_type': 'text/plain', 'msg': 'Successfully published to queue test', 'queue': 'test' } +''' + +try: + import pika + HAS_PIKA = True +except ImportError: + HAS_PIKA = False + + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils._text import to_native, to_text +from ansible_collections.community.rabbitmq.plugins.module_utils.rabbitmq import RabbitClient + + +def main(): + argument_spec = RabbitClient.rabbitmq_argument_spec() + argument_spec.update( + exchange=dict(type='str', default=''), + routing_key=dict(type='str', required=False), + body=dict(type='str', required=False), + src=dict(aliases=['file'], type='path', required=False), + content_type=dict(default="text/plain", type='str'), + durable=dict(default=False, type='bool'), + exclusive=dict(default=False, type='bool'), + auto_delete=dict(default=False, type='bool'), + headers=dict(default={}, type='dict'), + cafile=dict(type='str', required=False), + certfile=dict(type='str', required=False), + keyfile=dict(type='str', required=False), + ) + module = AnsibleModule( + argument_spec=argument_spec, + mutually_exclusive=[['body', 'src']], + required_together=[['cafile', 'certfile', 'keyfile']], + supports_check_mode=False + ) + + rabbitmq = RabbitClient(module) + + if rabbitmq.basic_publish(): + rabbitmq.close_connection() + module.exit_json(changed=True, result={"msg": "Successfully published to queue %s" % rabbitmq.queue, + "queue": rabbitmq.queue, + "content_type": rabbitmq.content_type}) + else: + rabbitmq.close_connection() + module.fail_json(changed=False, msg="Unsuccessful publishing to queue %s" % rabbitmq.queue) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_queue.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_queue.py new file mode 100644 index 00000000..85878773 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_queue.py @@ -0,0 +1,257 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2015, Manuel Sousa <manuel.sousa@gmail.com> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: rabbitmq_queue +author: Manuel Sousa (@manuel-sousa) + +short_description: Manage rabbitMQ queues +description: + - This module uses rabbitMQ Rest API to create/delete queues +requirements: [ "requests >= 1.0.0" ] +options: + name: + description: + - Name of the queue + type: str + required: true + state: + description: + - Whether the queue should be present or absent + type: str + choices: [ "present", "absent" ] + default: present + durable: + description: + - whether queue is durable or not + type: bool + default: 'yes' + auto_delete: + description: + - if the queue should delete itself after all queues/queues unbound from it + type: bool + default: 'no' + message_ttl: + description: + - How long a message can live in queue before it is discarded (milliseconds) + type: int + auto_expires: + description: + - How long a queue can be unused before it is automatically deleted (milliseconds) + type: int + max_length: + description: + - How many messages can the queue contain before it starts rejecting + type: int + dead_letter_exchange: + description: + - Optional name of an exchange to which messages will be republished if they + - are rejected or expire + type: str + dead_letter_routing_key: + description: + - Optional replacement routing key to use when a message is dead-lettered. + - Original routing key will be used if unset + type: str + max_priority: + description: + - Maximum number of priority levels for the queue to support. + - If not set, the queue will not support message priorities. + - Larger numbers indicate higher priority. + type: int + arguments: + description: + - extra arguments for queue. If defined this argument is a key/value dictionary + type: dict + default: {} +extends_documentation_fragment: +- community.rabbitmq.rabbitmq + +''' + +EXAMPLES = ''' +# Create a queue +- community.rabbitmq.rabbitmq_queue: + name: myQueue + +# Create a queue on remote host +- community.rabbitmq.rabbitmq_queue: + name: myRemoteQueue + login_user: user + login_password: secret + login_host: remote.example.org +''' + +import json +import traceback + +REQUESTS_IMP_ERR = None +try: + import requests + HAS_REQUESTS = True +except ImportError: + REQUESTS_IMP_ERR = traceback.format_exc() + HAS_REQUESTS = False + +from ansible.module_utils.basic import AnsibleModule, missing_required_lib +from ansible.module_utils.six.moves.urllib import parse as urllib_parse +from ansible_collections.community.rabbitmq.plugins.module_utils.rabbitmq import rabbitmq_argument_spec + + +def main(): + + argument_spec = rabbitmq_argument_spec() + argument_spec.update( + dict( + state=dict(default='present', choices=['present', 'absent'], type='str'), + name=dict(required=True, type='str'), + durable=dict(default=True, type='bool'), + auto_delete=dict(default=False, type='bool'), + message_ttl=dict(default=None, type='int'), + auto_expires=dict(default=None, type='int'), + max_length=dict(default=None, type='int'), + dead_letter_exchange=dict(default=None, type='str'), + dead_letter_routing_key=dict(default=None, type='str'), + arguments=dict(default=dict(), type='dict'), + max_priority=dict(default=None, type='int') + ) + ) + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) + + url = "%s://%s:%s/api/queues/%s/%s" % ( + module.params['login_protocol'], + module.params['login_host'], + module.params['login_port'], + urllib_parse.quote(module.params['vhost'], ''), + module.params['name'] + ) + + if not HAS_REQUESTS: + module.fail_json(msg=missing_required_lib("requests"), exception=REQUESTS_IMP_ERR) + + result = dict(changed=False, name=module.params['name']) + + # Check if queue already exists + r = requests.get(url, auth=(module.params['login_user'], module.params['login_password']), + verify=module.params['ca_cert'], cert=(module.params['client_cert'], module.params['client_key'])) + + if r.status_code == 200: + queue_exists = True + response = r.json() + elif r.status_code == 404: + queue_exists = False + response = r.text + else: + module.fail_json( + msg="Invalid response from RESTAPI when trying to check if queue exists", + details=r.text + ) + + if module.params['state'] == 'present': + change_required = not queue_exists + else: + change_required = queue_exists + + # Check if attributes change on existing queue + if not change_required and r.status_code == 200 and module.params['state'] == 'present': + if not ( + response['durable'] == module.params['durable'] and + response['auto_delete'] == module.params['auto_delete'] and + ( + ('x-message-ttl' in response['arguments'] and response['arguments']['x-message-ttl'] == module.params['message_ttl']) or + ('x-message-ttl' not in response['arguments'] and module.params['message_ttl'] is None) + ) and + ( + ('x-expires' in response['arguments'] and response['arguments']['x-expires'] == module.params['auto_expires']) or + ('x-expires' not in response['arguments'] and module.params['auto_expires'] is None) + ) and + ( + ('x-max-length' in response['arguments'] and response['arguments']['x-max-length'] == module.params['max_length']) or + ('x-max-length' not in response['arguments'] and module.params['max_length'] is None) + ) and + ( + ('x-dead-letter-exchange' in response['arguments'] and + response['arguments']['x-dead-letter-exchange'] == module.params['dead_letter_exchange']) or + ('x-dead-letter-exchange' not in response['arguments'] and module.params['dead_letter_exchange'] is None) + ) and + ( + ('x-dead-letter-routing-key' in response['arguments'] and + response['arguments']['x-dead-letter-routing-key'] == module.params['dead_letter_routing_key']) or + ('x-dead-letter-routing-key' not in response['arguments'] and module.params['dead_letter_routing_key'] is None) + ) and + ( + ('x-max-priority' in response['arguments'] and + response['arguments']['x-max-priority'] == module.params['max_priority']) or + ('x-max-priority' not in response['arguments'] and module.params['max_priority'] is None) + ) + ): + module.fail_json( + msg="RabbitMQ RESTAPI doesn't support attribute changes for existing queues", + ) + + # Copy parameters to arguments as used by RabbitMQ + for k, v in { + 'message_ttl': 'x-message-ttl', + 'auto_expires': 'x-expires', + 'max_length': 'x-max-length', + 'dead_letter_exchange': 'x-dead-letter-exchange', + 'dead_letter_routing_key': 'x-dead-letter-routing-key', + 'max_priority': 'x-max-priority' + }.items(): + if module.params[k] is not None: + module.params['arguments'][v] = module.params[k] + + # Exit if check_mode + if module.check_mode: + result['changed'] = change_required + result['details'] = response + result['arguments'] = module.params['arguments'] + module.exit_json(**result) + + # Do changes + if change_required: + if module.params['state'] == 'present': + r = requests.put( + url, + auth=(module.params['login_user'], module.params['login_password']), + headers={"content-type": "application/json"}, + data=json.dumps({ + "durable": module.params['durable'], + "auto_delete": module.params['auto_delete'], + "arguments": module.params['arguments'] + }), + verify=module.params['ca_cert'], + cert=(module.params['client_cert'], module.params['client_key']) + ) + elif module.params['state'] == 'absent': + r = requests.delete(url, auth=(module.params['login_user'], module.params['login_password']), + verify=module.params['ca_cert'], cert=(module.params['client_cert'], module.params['client_key'])) + + # RabbitMQ 3.6.7 changed this response code from 204 to 201 + if r.status_code == 204 or r.status_code == 201: + result['changed'] = True + module.exit_json(**result) + else: + module.fail_json( + msg="Error creating queue", + status=r.status_code, + details=r.text + ) + + else: + module.exit_json( + changed=False, + name=module.params['name'] + ) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_user.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_user.py new file mode 100644 index 00000000..1902e88c --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_user.py @@ -0,0 +1,463 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2013, Chatham Financial <oss@chathamfinancial.com> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: rabbitmq_user +short_description: Manage RabbitMQ users +description: + - Add or remove users to RabbitMQ and assign permissions +author: Chris Hoffman (@chrishoffman) +options: + user: + description: + - Name of user to add + type: str + required: true + aliases: [username, name] + password: + description: + - Password of user to add. + - To change the password of an existing user, you must also specify + C(update_password=always). + type: str + tags: + description: + - User tags specified as comma delimited + type: str + permissions: + description: + - a list of dicts, each dict contains vhost, configure_priv, write_priv, and read_priv, + and represents a permission rule for that vhost. + - This option should be preferable when you care about all permissions of the user. + - You should use vhost, configure_priv, write_priv, and read_priv options instead + if you care about permissions for just some vhosts. + type: list + elements: dict + default: [] + vhost: + description: + - vhost to apply access privileges. + - This option will be ignored when permissions option is used. + type: str + default: / + node: + description: + - erlang node name of the rabbit we wish to configure + type: str + default: rabbit + configure_priv: + description: + - Regular expression to restrict configure actions on a resource + for the specified vhost. + - By default all actions are restricted. + - This option will be ignored when permissions option is used. + type: str + default: '^$' + write_priv: + description: + - Regular expression to restrict configure actions on a resource + for the specified vhost. + - By default all actions are restricted. + - This option will be ignored when permissions option is used. + type: str + default: '^$' + read_priv: + description: + - Regular expression to restrict configure actions on a resource + for the specified vhost. + - By default all actions are restricted. + - This option will be ignored when permissions option is used. + type: str + default: '^$' + force: + description: + - Deletes and recreates the user. + type: bool + default: 'no' + state: + description: + - Specify if user is to be added or removed + type: str + default: present + choices: ['present', 'absent'] + update_password: + description: + - C(on_create) will only set the password for newly created users. C(always) will update passwords if they differ. + type: str + required: false + default: on_create + choices: ['on_create', 'always'] +''' + +EXAMPLES = ''' +# Add user to server and assign full access control on / vhost. +# The user might have permission rules for other vhost but you don't care. +- community.rabbitmq.rabbitmq_user: + user: joe + password: changeme + vhost: / + configure_priv: .* + read_priv: .* + write_priv: .* + state: present + +# Add user to server and assign full access control on / vhost. +# The user doesn't have permission rules for other vhosts +- community.rabbitmq.rabbitmq_user: + user: joe + password: changeme + permissions: + - vhost: / + configure_priv: .* + read_priv: .* + write_priv: .* + state: present +''' + +import distutils.version +import json +import re + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.common.collections import count + + +def normalized_permissions(vhost_permission_list): + """Older versions of RabbitMQ output permissions with slightly different names. + + In older versions of RabbitMQ, the names of the permissions had the `_priv` suffix, which was removed in versions + >= 3.7.6. For simplicity we only check the `configure` permission. If it's in the old format then all the other + ones will be wrong too. + """ + for vhost_permission in vhost_permission_list: + if 'configure_priv' in vhost_permission: + yield { + 'configure': vhost_permission['configure_priv'], + 'read': vhost_permission['read_priv'], + 'write': vhost_permission['write_priv'], + 'vhost': vhost_permission['vhost'] + } + else: + yield vhost_permission + + +def as_permission_dict(vhost_permission_list): + return dict([(vhost_permission['vhost'], vhost_permission) for vhost_permission + in normalized_permissions(vhost_permission_list)]) + + +def only(vhost, vhost_permissions): + return {vhost: vhost_permissions.get(vhost, {})} + + +def first(iterable): + return next(iter(iterable)) + + +class RabbitMqUser(object): + def __init__(self, module, username, password, tags, permissions, + node, bulk_permissions=False): + self.module = module + self.username = username + self.password = password or '' + self.node = node + self.tags = list() if not tags else tags.replace(' ', '').split(',') + self.permissions = as_permission_dict(permissions) + self.bulk_permissions = bulk_permissions + + self.existing_tags = None + self.existing_permissions = dict() + self._rabbitmqctl = module.get_bin_path('rabbitmqctl', True) + self._version = self._check_version() + + def _check_version(self): + """Get the version of the RabbitMQ server.""" + version = self._rabbitmq_version_post_3_7(fail_on_error=False) + if not version: + version = self._rabbitmq_version_pre_3_7(fail_on_error=False) + if not version: + self.module.fail_json(msg="Could not determine the version of the RabbitMQ server.") + return version + + def _fail(self, msg, stop_execution=False): + if stop_execution: + self.module.fail_json(msg=msg) + # This is a dummy return to prevent linters from throwing errors. + return None + + def _rabbitmq_version_post_3_7(self, fail_on_error=False): + """Use the JSON formatter to get a machine readable output of the version. + + At this point we do not know which RabbitMQ server version we are dealing with and which + version of `rabbitmqctl` we are using, so we will try to use the JSON formatter and see + what happens. In some versions of + """ + def int_list_to_str(ints): + return ''.join([chr(i) for i in ints]) + + rc, output, err = self._exec(['status', '--formatter', 'json'], check_rc=False) + if rc != 0: + return self._fail(msg="Could not parse the version of the RabbitMQ server, " + "because `rabbitmqctl status` returned no output.", + stop_execution=fail_on_error) + try: + status_json = json.loads(output) + if 'rabbitmq_version' in status_json: + return distutils.version.StrictVersion(status_json['rabbitmq_version']) + for application in status_json.get('running_applications', list()): + if application[0] == 'rabbit': + if isinstance(application[1][0], int): + return distutils.version.StrictVersion(int_list_to_str(application[2])) + else: + return distutils.version.StrictVersion(application[1]) + return self._fail(msg="Could not find RabbitMQ version of `rabbitmqctl status` command.", + stop_execution=fail_on_error) + except ValueError as e: + return self._fail(msg="Could not parse output of `rabbitmqctl status` as JSON: {exc}.".format(exc=repr(e)), + stop_execution=fail_on_error) + + def _rabbitmq_version_pre_3_7(self, fail_on_error=False): + """Get the version of the RabbitMQ Server. + + Before version 3.7.6 the `rabbitmqctl` utility did not support the + `--formatter` flag, so the output has to be parsed using regular expressions. + """ + version_reg_ex = r"{rabbit,\"RabbitMQ\",\"([0-9]+\.[0-9]+\.[0-9]+)\"}" + rc, output, err = self._exec(['status'], check_rc=False) + if rc != 0: + if fail_on_error: + self.module.fail_json(msg="Could not parse the version of the RabbitMQ server, because" + " `rabbitmqctl status` returned no output.") + else: + return None + reg_ex_res = re.search(version_reg_ex, output, re.IGNORECASE) + if not reg_ex_res: + return self._fail(msg="Could not parse the version of the RabbitMQ server from the output of " + "`rabbitmqctl status` command: {output}.".format(output=output), + stop_execution=fail_on_error) + try: + return distutils.version.StrictVersion(reg_ex_res.group(1)) + except ValueError as e: + return self._fail(msg="Could not parse the version of the RabbitMQ server: {exc}.".format(exc=repr(e)), + stop_execution=fail_on_error) + + def _exec(self, args, check_rc=True): + """Execute a command using the `rabbitmqctl` utility. + + By default the _exec call will cause the module to fail, if the error code is non-zero. If the `check_rc` + flag is set to False, then the exit_code, stdout and stderr will be returned to the calling function to + perform whatever error handling it needs. + + :param args: the arguments to pass to the `rabbitmqctl` utility + :param check_rc: when set to True, fail if the utility's exit code is non-zero + :return: the output of the command or all the outputs plus the error code in case of error + """ + cmd = [self._rabbitmqctl, '-q'] + if self.node: + cmd.extend(['-n', self.node]) + rc, out, err = self.module.run_command(cmd + args) + if check_rc and rc != 0: + # check_rc is not passed to the `run_command` method directly to allow for more fine grained checking of + # error messages returned by `rabbitmqctl`. + user_error_msg_regex = r"(Only root or .* .* run rabbitmqctl)" + user_error_msg = re.search(user_error_msg_regex, out) + if user_error_msg: + self.module.fail_json(msg="Wrong user used to run the `rabbitmqctl` utility: {err}" + .format(err=user_error_msg.group(1))) + else: + self.module.fail_json(msg="rabbitmqctl exited with non-zero code: {err}".format(err=err), + rc=rc, stdout=out) + return out if check_rc else (rc, out, err) + + def get(self): + """Retrieves the list of registered users from the node. + + If the user is already present, the node will also be queried for the user's permissions. + If the version of the node is >= 3.7.6 the JSON formatter will be used, otherwise the plaintext will be + parsed. + """ + if self._version >= distutils.version.StrictVersion('3.7.6'): + users = dict([(user_entry['user'], user_entry['tags']) + for user_entry in json.loads(self._exec(['list_users', '--formatter', 'json']))]) + else: + users = self._exec(['list_users']) + + def process_tags(tags): + if not tags: + return list() + return tags.replace('[', '').replace(']', '').replace(' ', '').strip('\t').split(',') + + users_and_tags = [user_entry.split('\t') for user_entry in users.strip().split('\n')] + users = dict([(user, process_tags(tags)) for user, tags in users_and_tags]) + + self.existing_tags = users.get(self.username, list()) + self.existing_permissions = self._get_permissions() if self.username in users else dict() + return self.username in users + + def _get_permissions(self): + """Get permissions of the user from RabbitMQ.""" + if self._version >= distutils.version.StrictVersion('3.7.6'): + permissions = json.loads(self._exec(['list_user_permissions', self.username, '--formatter', 'json'])) + else: + output = self._exec(['list_user_permissions', self.username]).strip().split('\n') + perms_out = [perm.split('\t') for perm in output if perm.strip()] + # Filter out headers from the output of the command in case they are still present + perms_out = [perm for perm in perms_out if perm != ["vhost", "configure", "write", "read"]] + + permissions = list() + for vhost, configure, write, read in perms_out: + permissions.append(dict(vhost=vhost, configure=configure, write=write, read=read)) + + if self.bulk_permissions: + return as_permission_dict(permissions) + else: + return only(first(self.permissions.keys()), as_permission_dict(permissions)) + + def check_password(self): + """Return `True` if the user can authenticate successfully.""" + rc, out, err = self._exec(['authenticate_user', self.username, self.password], check_rc=False) + return rc == 0 + + def add(self): + self._exec(['add_user', self.username, self.password or '']) + if not self.password: + self._exec(['clear_password', self.username]) + + def delete(self): + self._exec(['delete_user', self.username]) + + def change_password(self): + if self.password: + self._exec(['change_password', self.username, self.password]) + else: + self._exec(['clear_password', self.username]) + + def set_tags(self): + self._exec(['set_user_tags', self.username] + self.tags) + + def set_permissions(self): + permissions_to_add = list() + for vhost, permission_dict in self.permissions.items(): + if permission_dict != self.existing_permissions.get(vhost, {}): + permissions_to_add.append(permission_dict) + + permissions_to_clear = list() + for vhost in self.existing_permissions.keys(): + if vhost not in self.permissions: + permissions_to_clear.append(vhost) + + for vhost in permissions_to_clear: + cmd = 'clear_permissions -p {vhost} {username}'.format(username=self.username, vhost=vhost) + self._exec(cmd.split(' ')) + for permissions in permissions_to_add: + cmd = ('set_permissions -p {vhost} {username} {configure} {write} {read}' + .format(username=self.username, **permissions)) + self._exec(cmd.split(' ')) + self.existing_permissions = self._get_permissions() + + def has_tags_modifications(self): + return set(self.tags) != set(self.existing_tags) + + def has_permissions_modifications(self): + return self.existing_permissions != self.permissions + + +def main(): + arg_spec = dict( + user=dict(required=True, aliases=['username', 'name']), + password=dict(default=None, no_log=True), + tags=dict(default=None), + permissions=dict(default=list(), type='list', elements='dict'), + vhost=dict(default='/'), + configure_priv=dict(default='^$'), + write_priv=dict(default='^$'), + read_priv=dict(default='^$'), + force=dict(default='no', type='bool'), + state=dict(default='present', choices=['present', 'absent']), + node=dict(default='rabbit'), + update_password=dict(default='on_create', choices=['on_create', 'always'], no_log=False) + ) + module = AnsibleModule( + argument_spec=arg_spec, + supports_check_mode=True + ) + + username = module.params['user'] + password = module.params['password'] + tags = module.params['tags'] + permissions = module.params['permissions'] + vhost = module.params['vhost'] + configure_priv = module.params['configure_priv'] + write_priv = module.params['write_priv'] + read_priv = module.params['read_priv'] + force = module.params['force'] + state = module.params['state'] + node = module.params['node'] + update_password = module.params['update_password'] + + if permissions: + vhosts = [permission.get('vhost', '/') for permission in permissions] + if any([vhost_count > 1 for vhost_count in count(vhosts).values()]): + module.fail_json(msg="Error parsing vhost permissions: You can't " + "have two permission dicts for the same vhost") + bulk_permissions = True + else: + perm = { + 'vhost': vhost, + 'configure_priv': configure_priv, + 'write_priv': write_priv, + 'read_priv': read_priv + } + permissions.append(perm) + bulk_permissions = False + + for permission in permissions: + if not permission['vhost']: + module.fail_json(msg="Error parsing vhost permissions: You can't" + "have an empty vhost when setting permissions") + + rabbitmq_user = RabbitMqUser(module, username, password, tags, permissions, + node, bulk_permissions=bulk_permissions) + + result = dict(changed=False, user=username, state=state) + if rabbitmq_user.get(): + if state == 'absent': + rabbitmq_user.delete() + result['changed'] = True + else: + if force: + rabbitmq_user.delete() + rabbitmq_user.add() + rabbitmq_user.get() + result['changed'] = True + elif update_password == 'always': + if not rabbitmq_user.check_password(): + rabbitmq_user.change_password() + result['changed'] = True + + if rabbitmq_user.has_tags_modifications(): + rabbitmq_user.set_tags() + result['changed'] = True + + if rabbitmq_user.has_permissions_modifications(): + rabbitmq_user.set_permissions() + result['changed'] = True + elif state == 'present': + rabbitmq_user.add() + rabbitmq_user.set_tags() + rabbitmq_user.set_permissions() + result['changed'] = True + + module.exit_json(**result) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_vhost.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_vhost.py new file mode 100644 index 00000000..3c1eee52 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_vhost.py @@ -0,0 +1,142 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2013, Chatham Financial <oss@chathamfinancial.com> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: rabbitmq_vhost +short_description: Manage the state of a virtual host in RabbitMQ +description: + - Manage the state of a virtual host in RabbitMQ +author: Chris Hoffman (@chrishoffman) +options: + name: + description: + - The name of the vhost to manage + type: str + required: true + aliases: [vhost] + node: + description: + - erlang node name of the rabbit we wish to configure + type: str + default: rabbit + tracing: + description: + - Enable/disable tracing for a vhost + type: bool + default: 'no' + aliases: [trace] + state: + description: + - The state of vhost + type: str + default: present + choices: [present, absent] +''' + +EXAMPLES = ''' +# Ensure that the vhost /test exists. +- community.rabbitmq.rabbitmq_vhost: + name: /test + state: present +''' + +from ansible.module_utils.basic import AnsibleModule + + +class RabbitMqVhost(object): + def __init__(self, module, name, tracing, node): + self.module = module + self.name = name + self.tracing = tracing + self.node = node + + self._tracing = False + self._rabbitmqctl = module.get_bin_path('rabbitmqctl', True) + + def _exec(self, args, run_in_check_mode=False): + if not self.module.check_mode or (self.module.check_mode and run_in_check_mode): + cmd = [self._rabbitmqctl, '-q', '-n', self.node] + rc, out, err = self.module.run_command(cmd + args, check_rc=True) + return out.splitlines() + return list() + + def get(self): + vhosts = self._exec(['list_vhosts', 'name', 'tracing'], True) + + for vhost in vhosts: + if '\t' not in vhost: + continue + + name, tracing = vhost.split('\t') + if name == self.name: + self._tracing = self.module.boolean(tracing) + return True + return False + + def add(self): + return self._exec(['add_vhost', self.name]) + + def delete(self): + return self._exec(['delete_vhost', self.name]) + + def set_tracing(self): + if self.tracing != self._tracing: + if self.tracing: + self._enable_tracing() + else: + self._disable_tracing() + return True + return False + + def _enable_tracing(self): + return self._exec(['trace_on', '-p', self.name]) + + def _disable_tracing(self): + return self._exec(['trace_off', '-p', self.name]) + + +def main(): + arg_spec = dict( + name=dict(required=True, aliases=['vhost']), + tracing=dict(default='off', aliases=['trace'], type='bool'), + state=dict(default='present', choices=['present', 'absent']), + node=dict(default='rabbit'), + ) + + module = AnsibleModule( + argument_spec=arg_spec, + supports_check_mode=True + ) + + name = module.params['name'] + tracing = module.params['tracing'] + state = module.params['state'] + node = module.params['node'] + result = dict(changed=False, name=name, state=state) + rabbitmq_vhost = RabbitMqVhost(module, name, tracing, node) + + if rabbitmq_vhost.get(): + if state == 'absent': + rabbitmq_vhost.delete() + result['changed'] = True + else: + if rabbitmq_vhost.set_tracing(): + result['changed'] = True + elif state == 'present': + rabbitmq_vhost.add() + rabbitmq_vhost.set_tracing() + result['changed'] = True + + module.exit_json(**result) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_vhost_limits.py b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_vhost_limits.py new file mode 100644 index 00000000..4d54df10 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/plugins/modules/rabbitmq_vhost_limits.py @@ -0,0 +1,173 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2018, Hiroyuki Matsuo <h.matsuo.engineer@gmail.com> +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: rabbitmq_vhost_limits +author: Hiroyuki Matsuo (@h-matsuo) + +short_description: Manage the state of virtual host limits in RabbitMQ +description: + - This module sets/clears certain limits on a virtual host. + - The configurable limits are I(max_connections) and I(max-queues). + +options: + max_connections: + description: + - Max number of concurrent client connections. + - Negative value means "no limit". + - Ignored when the I(state) is C(absent). + type: int + default: -1 + max_queues: + description: + - Max number of queues. + - Negative value means "no limit". + - Ignored when the I(state) is C(absent). + type: int + default: -1 + node: + description: + - Name of the RabbitMQ Erlang node to manage. + type: str + state: + description: + - Specify whether the limits are to be set or cleared. + - If set to C(absent), the limits of both I(max_connections) and I(max-queues) will be cleared. + type: str + default: present + choices: [present, absent] + vhost: + description: + - Name of the virtual host to manage. + type: str + default: / +''' + +EXAMPLES = ''' +# Limit both of the max number of connections and queues on the vhost '/'. +- community.rabbitmq.rabbitmq_vhost_limits: + vhost: / + max_connections: 64 + max_queues: 256 + state: present + +# Limit the max number of connections on the vhost '/'. +# This task implicitly clears the max number of queues limit using default value: -1. +- community.rabbitmq.rabbitmq_vhost_limits: + vhost: / + max_connections: 64 + state: present + +# Clear the limits on the vhost '/'. +- community.rabbitmq.rabbitmq_vhost_limits: + vhost: / + state: absent +''' + +RETURN = ''' # ''' + + +import json +from ansible.module_utils.basic import AnsibleModule + + +class RabbitMqVhostLimits(object): + def __init__(self, module): + self._module = module + self._max_connections = module.params['max_connections'] + self._max_queues = module.params['max_queues'] + self._node = module.params['node'] + self._state = module.params['state'] + self._vhost = module.params['vhost'] + self._rabbitmqctl = module.get_bin_path('rabbitmqctl', True) + + def _exec(self, args): + cmd = [self._rabbitmqctl, '-q', '-p', self._vhost] + if self._node is not None: + cmd.extend(['-n', self._node]) + rc, out, err = self._module.run_command(cmd + args, check_rc=True) + return dict(rc=rc, out=out.splitlines(), err=err.splitlines()) + + def list(self): + exec_result = self._exec(['list_vhost_limits']) + vhost_limits = exec_result['out'][0] + max_connections = None + max_queues = None + if vhost_limits: + vhost_limits = json.loads(vhost_limits) + if 'max-connections' in vhost_limits: + max_connections = vhost_limits['max-connections'] + if 'max-queues' in vhost_limits: + max_queues = vhost_limits['max-queues'] + return dict( + max_connections=max_connections, + max_queues=max_queues + ) + + def set(self): + if self._module.check_mode: + return + json_str = '{{"max-connections": {0}, "max-queues": {1}}}'.format(self._max_connections, self._max_queues) + self._exec(['set_vhost_limits', json_str]) + + def clear(self): + if self._module.check_mode: + return + self._exec(['clear_vhost_limits']) + + +def main(): + arg_spec = dict( + max_connections=dict(default=-1, type='int'), + max_queues=dict(default=-1, type='int'), + node=dict(default=None, type='str'), + state=dict(default='present', choices=['present', 'absent'], type='str'), + vhost=dict(default='/', type='str') + ) + + module = AnsibleModule( + argument_spec=arg_spec, + supports_check_mode=True + ) + + max_connections = module.params['max_connections'] + max_queues = module.params['max_queues'] + node = module.params['node'] + state = module.params['state'] + vhost = module.params['vhost'] + + module_result = dict(changed=False) + rabbitmq_vhost_limits = RabbitMqVhostLimits(module) + current_status = rabbitmq_vhost_limits.list() + + if state == 'present': + wanted_status = dict( + max_connections=max_connections, + max_queues=max_queues + ) + else: # state == 'absent' + wanted_status = dict( + max_connections=None, + max_queues=None + ) + + if current_status != wanted_status: + module_result['changed'] = True + if state == 'present': + rabbitmq_vhost_limits.set() + else: # state == 'absent' + rabbitmq_vhost_limits.clear() + + module.exit_json(**module_result) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/shippable.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/shippable.yml new file mode 100644 index 00000000..c0b5154b --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/shippable.yml @@ -0,0 +1,58 @@ +language: python + +env: + matrix: + - T=none + +matrix: + exclude: + - env: T=none + include: + - env: T=sanity/1 + - env: T=sanity/2 + - env: T=sanity/3 + - env: T=sanity/4 + - env: T=sanity/5 + + - env: T=units/2.6/1 + - env: T=units/2.7/1 + - env: T=units/3.5/1 + - env: T=units/3.6/1 + - env: T=units/3.7/1 + - env: T=units/3.8/1 + - env: T=units/3.9/1 + +# - env: T=aix/7.2/1 +# - env: T=osx/10.11/1 + - env: T=rhel/7.8/1 + - env: T=rhel/8.2/1 + - env: T=freebsd/11.1/1 + - env: T=freebsd/12.1/1 + - env: T=linux/centos6/1 + - env: T=linux/centos7/1 + - env: T=linux/centos8/1 + - env: T=linux/fedora31/1 + - env: T=linux/fedora32/1 + - env: T=linux/opensuse15py2/1 + - env: T=linux/opensuse15/1 + - env: T=linux/ubuntu1604/1 + - env: T=linux/ubuntu1804/1 + + +branches: + except: + - "*-patch-*" + - "revert-*-*" + +build: + ci: + - tests/utils/shippable/timing.sh tests/utils/shippable/shippable.sh $T + +integrations: + notifications: + - integrationName: email + type: email + on_success: never + on_failure: never + on_start: never + on_pull_request: never diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/lookup_rabbitmq/aliases b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/lookup_rabbitmq/aliases new file mode 100644 index 00000000..ea7b5233 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/lookup_rabbitmq/aliases @@ -0,0 +1,7 @@ +destructive +shippable/posix/group1 +skip/aix +skip/osx +skip/freebsd +skip/rhel +skip/python2.6 # lookups are controller only, and we no longer support Python 2.6 on the controller diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/lookup_rabbitmq/meta/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/lookup_rabbitmq/meta/main.yml new file mode 100644 index 00000000..05ab5900 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/lookup_rabbitmq/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - setup_rabbitmq diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/lookup_rabbitmq/tasks/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/lookup_rabbitmq/tasks/main.yml new file mode 100644 index 00000000..740f8998 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/lookup_rabbitmq/tasks/main.yml @@ -0,0 +1,5 @@ +# Rabbitmq lookup +- include: ubuntu.yml + when: + - ansible_distribution == 'Ubuntu' + - ansible_distribution_release != 'trusty' diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/lookup_rabbitmq/tasks/ubuntu.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/lookup_rabbitmq/tasks/ubuntu.yml new file mode 100644 index 00000000..d653b493 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/lookup_rabbitmq/tasks/ubuntu.yml @@ -0,0 +1,138 @@ +- name: Test failure without pika installed + set_fact: + rabbit_missing_pika: "{{ lookup('community.rabbitmq.rabbitmq', url='amqp://guest:guest@192.168.250.1:5672/%2F', queue='hello', count=3) }}" + ignore_errors: yes + register: rabbitmq_missing_pika_error + +- assert: + that: + - "'pika python package is required' in rabbitmq_missing_pika_error.msg" + +- name: Install pika and requests + pip: + name: pika<1.0.0,requests + state: latest + +- name: Test that giving an incorrect amqp protocol in URL will error + set_fact: + rabbitmq_test_protocol: "{{ lookup('community.rabbitmq.rabbitmq', url='zzzamqp://guest:guest@192.168.250.1:5672/%2F', queue='hello', count=3) }}" + ignore_errors: yes + register: rabbitmq_protocol_error + +- assert: + that: + - "rabbitmq_protocol_error is failed" + - "'URL malformed' in rabbitmq_protocol_error.msg" + +- name: Test that giving an incorrect IP address in URL will error + set_fact: + rabbitmq_test_protocol: "{{ lookup('community.rabbitmq.rabbitmq', url='amqp://guest:guest@xxxxx192.112312368.250.1:5672/%2F', queue='hello', count=3) }}" + ignore_errors: yes + register: rabbitmq_ip_error + +- assert: + that: + - "rabbitmq_ip_error is failed" + - "'Connection issue' in rabbitmq_ip_error.msg" + +- name: Test missing parameters will error + set_fact: + rabbitmq_test_protocol: "{{ lookup('community.rabbitmq.rabbitmq') }}" + ignore_errors: yes + register: rabbitmq_params_error + +- assert: + that: + - "rabbitmq_params_error is failed" + - "'URL is required for rabbitmq lookup.' in rabbitmq_params_error.msg" + +- name: Test missing queue will error + set_fact: + rabbitmq_queue_protocol: "{{ lookup('community.rabbitmq.rabbitmq', url='amqp://guest:guest@192.168.250.1:5672/%2F') }}" + ignore_errors: yes + register: rabbitmq_queue_error + +- assert: + that: + - "rabbitmq_queue_error is failed" + - "'Queue is required for rabbitmq lookup' in rabbitmq_queue_error.msg" + +- name: Enables the rabbitmq_management plugin + rabbitmq_plugin: + names: rabbitmq_management + state: enabled + +- name: Setup test queue + rabbitmq_queue: + name: hello + +- name: Post test message to the exchange (string) + uri: + url: http://localhost:15672/api/exchanges/%2f/amq.default/publish + method: POST + body: '{"properties":{},"routing_key":"hello","payload":"ansible-test","payload_encoding":"string"}' + user: guest + password: guest + force_basic_auth: yes + return_content: yes + headers: + Content-Type: "application/json" + register: post_data + + +- name: Post test message to the exchange (json) + uri: + url: http://localhost:15672/api/exchanges/%2f/amq.default/publish + method: POST + body: '{"properties":{"content_type": "application/json"},"routing_key":"hello","payload":"{\"key\": \"value\" }","payload_encoding":"string"}' + user: guest + password: guest + force_basic_auth: yes + return_content: yes + headers: + Content-Type: "application/json" + register: post_data_json + +- name: Test retrieve messages + set_fact: + rabbitmq_msg: "{{ lookup('community.rabbitmq.rabbitmq', url='amqp://guest:guest@localhost:5672/%2f/hello', queue='hello') }}" + ignore_errors: yes + register: rabbitmq_msg_error + +- name: Ensure two messages received + assert: + that: + - "rabbitmq_msg_error is not failed" + - rabbitmq_msg | length == 2 + +- name: Ensure first message is a string + assert: + that: + - rabbitmq_msg[0].msg == "ansible-test" + +- name: Ensure second message is json + assert: + that: + - rabbitmq_msg[1].json.key == "value" + +- name: Test missing vhost + set_fact: + rabbitmq_msg: "{{ lookup('community.rabbitmq.rabbitmq', url='amqp://guest:guest@localhost:5672/missing/', queue='hello') }}" + ignore_errors: yes + register: rabbitmq_vhost_error + +- assert: + that: + - "rabbitmq_vhost_error is failed" + - "'NOT_ALLOWED' in rabbitmq_vhost_error.msg" + +# Tidy up +- name: Uninstall pika and requests + pip: + name: pika,requests + state: absent + +- name: Disable the rabbitmq_management plugin + rabbitmq_plugin: + names: rabbitmq_management + state: disabled diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_binding/aliases b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_binding/aliases new file mode 100644 index 00000000..f37e6c6f --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_binding/aliases @@ -0,0 +1,6 @@ +destructive +shippable/posix/group1 +skip/aix +skip/osx +skip/freebsd +skip/rhel diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_binding/meta/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_binding/meta/main.yml new file mode 100644 index 00000000..05ab5900 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_binding/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - setup_rabbitmq diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_binding/tasks/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_binding/tasks/main.yml new file mode 100644 index 00000000..4d3414ea --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_binding/tasks/main.yml @@ -0,0 +1,3 @@ +--- +- import_tasks: tests.yml + when: ansible_distribution == 'Ubuntu' diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_binding/tasks/tests.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_binding/tasks/tests.yml new file mode 100644 index 00000000..5021ed22 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_binding/tasks/tests.yml @@ -0,0 +1,132 @@ +--- +- name: Add test requisites + block: + - name: Add exchange + rabbitmq_exchange: + name: "{{ item }}" + type: direct + with_items: + - exchange-foo + - exchange-bar + + - name: Add queue + rabbitmq_queue: + name: queue-foo + +- name: Test add binding in check mode + block: + - name: Add binding + rabbitmq_binding: + source: exchange-foo + destination: queue-foo + type: queue + check_mode: true + register: add_binding + + - name: Check that binding succeeds with a change + assert: + that: + - add_binding.changed == true + +- name: Test add binding + block: + - name: Add binding + rabbitmq_binding: + source: exchange-foo + destination: queue-foo + type: queue + register: add_binding + + - name: Check that binding succeeds with a change + assert: + that: + - add_binding.changed == true + +- name: Test add binding idempotence + block: + - name: Add binding + rabbitmq_binding: + source: exchange-foo + destination: queue-foo + type: queue + register: add_binding + + - name: Check that binding succeeds without a change + assert: + that: + - add_binding.changed == false + +- name: Test remove binding in check mode + block: + - name: Remove binding + rabbitmq_binding: + source: exchange-foo + destination: queue-foo + type: queue + state: absent + check_mode: true + register: remove_binding + + - name: Check that binding succeeds with a change + assert: + that: + - remove_binding.changed == true + +- name: Test remove binding + block: + - name: Remove binding + rabbitmq_binding: + source: exchange-foo + destination: queue-foo + type: queue + state: absent + register: remove_binding + + - name: Check that binding succeeds with a change + assert: + that: + - remove_binding.changed == true + +- name: Test remove binding idempotence + block: + - name: Remove binding + rabbitmq_binding: + source: exchange-foo + destination: queue-foo + type: queue + state: absent + register: remove_binding + + - name: Check that binding succeeds with a change + assert: + that: + - remove_binding.changed == false + +- name: Test add exchange to exchange binding + block: + - name: Add binding + rabbitmq_binding: + source: exchange-foo + destination: exchange-bar + type: exchange + register: add_binding + + - name: Check that binding succeeds with a change + assert: + that: + - add_binding.changed == true + +- name: Test remove exchange to exchange binding + block: + - name: Remove binding + rabbitmq_binding: + source: exchange-foo + destination: exchange-bar + type: exchange + state: absent + register: remove_binding + + - name: Check that binding succeeds with a change + assert: + that: + - remove_binding.changed == true diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_plugin/aliases b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_plugin/aliases new file mode 100644 index 00000000..f37e6c6f --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_plugin/aliases @@ -0,0 +1,6 @@ +destructive +shippable/posix/group1 +skip/aix +skip/osx +skip/freebsd +skip/rhel diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_plugin/meta/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_plugin/meta/main.yml new file mode 100644 index 00000000..05ab5900 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_plugin/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - setup_rabbitmq diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_plugin/tasks/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_plugin/tasks/main.yml new file mode 100644 index 00000000..593906fb --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_plugin/tasks/main.yml @@ -0,0 +1,2 @@ +- import_tasks: tests.yml + when: ansible_distribution == 'Ubuntu' diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_plugin/tasks/tests.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_plugin/tasks/tests.yml new file mode 100644 index 00000000..148f1914 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_plugin/tasks/tests.yml @@ -0,0 +1,137 @@ +- block: + - set_fact: + plugin_name: rabbitmq_top + + - name: Enable plugin [online] + rabbitmq_plugin: + name: "{{ plugin_name }}" + state: enabled + new_only: True + register: result + + - name: Get rabbitmq-plugins output + shell: "rabbitmq-plugins list | grep {{ plugin_name }}" + register: cli_result + + - name: Check that the plugin is enabled + assert: + that: + - result is changed + - result is success + - '"{{ plugin_name }}" in result.enabled' + - result.disabled == [] + - '"[E" in cli_result.stdout' + + - name: Enable plugin [online] (idempotency) + rabbitmq_plugin: + name: "{{ plugin_name }}" + state: enabled + new_only: True + register: result + + - name: Check idempotency + assert: + that: + - result is not changed + + - name: Disable plugin [online] + rabbitmq_plugin: + name: "{{ plugin_name }}" + state: disabled + register: result + + - name: Get rabbitmq-plugins output + shell: "rabbitmq-plugins list | grep {{ plugin_name }}" + register: cli_result + + - name: Check that the plugin is disabled + assert: + that: + - result is changed + - result is success + - result.enabled == [] + - '"{{ plugin_name }}" in result.disabled' + - '"[E" not in cli_result.stdout' + + - name: Disable plugin [online] (idempotency) + rabbitmq_plugin: + name: "{{ plugin_name }}" + state: disabled + register: result + + - name: Check idempotency + assert: + that: + - result is not changed + + - name: Enable plugin [offline] + rabbitmq_plugin: + name: "{{ plugin_name }}" + state: enabled + broker_state: offline + new_only: True + register: result + + - name: Get rabbitmq-plugins output + shell: "rabbitmq-plugins list | grep {{ plugin_name }}" + register: cli_result + + - name: Check that the plugin is enabled + assert: + that: + - result is changed + - result is success + - '"{{ plugin_name }}" in result.enabled' + - result.disabled == [] + - '"[E" in cli_result.stdout' + + - name: Enable plugin [offline] (idempotency) + rabbitmq_plugin: + name: "{{ plugin_name }}" + state: enabled + broker_state: offline + new_only: True + register: result + + - name: Check idempotency + assert: + that: + - result is not changed + + - name: Disable plugin [offline] + rabbitmq_plugin: + name: "{{ plugin_name }}" + state: disabled + broker_state: offline + register: result + + - name: Get rabbitmq-plugins output + shell: "rabbitmq-plugins list | grep {{ plugin_name }}" + register: cli_result + + - name: Check that the plugin is disabled + assert: + that: + - result is changed + - result is success + - result.enabled == [] + - '"{{ plugin_name }}" in result.disabled' + - '"[E" not in cli_result.stdout' + + - name: Disable plugin [offline] (idempotency) + rabbitmq_plugin: + name: "{{ plugin_name }}" + state: disabled + broker_state: offline + register: result + + - name: Check idempotency + assert: + that: + - result is not changed + + always: + - name: Disable plugin + rabbitmq_plugin: + name: "{{ plugin_name }}" + state: disabled diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_publish/aliases b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_publish/aliases new file mode 100644 index 00000000..f37e6c6f --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_publish/aliases @@ -0,0 +1,6 @@ +destructive +shippable/posix/group1 +skip/aix +skip/osx +skip/freebsd +skip/rhel diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_publish/files/image.gif b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_publish/files/image.gif Binary files differnew file mode 100644 index 00000000..0589d208 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_publish/files/image.gif diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_publish/meta/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_publish/meta/main.yml new file mode 100644 index 00000000..f0eb571b --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_publish/meta/main.yml @@ -0,0 +1,3 @@ +dependencies: + - setup_rabbitmq + - setup_remote_tmp_dir diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_publish/tasks/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_publish/tasks/main.yml new file mode 100644 index 00000000..740f8998 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_publish/tasks/main.yml @@ -0,0 +1,5 @@ +# Rabbitmq lookup +- include: ubuntu.yml + when: + - ansible_distribution == 'Ubuntu' + - ansible_distribution_release != 'trusty' diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_publish/tasks/ubuntu.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_publish/tasks/ubuntu.yml new file mode 100644 index 00000000..698c72e2 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_publish/tasks/ubuntu.yml @@ -0,0 +1,171 @@ +- name: Install requests and pika + pip: + name: requests,pika<1.0.0 + state: present + +- name: RabbitMQ basic publish test + rabbitmq_publish: + url: "amqp://guest:guest@localhost:5672/%2F" + queue: 'publish_test' + body: "Hello world from ansible module rabbitmq_publish" + content_type: "text/plain" + register: rabbit_basic_output1 + +- assert: + that: + - "rabbit_basic_output1 is not failed" + - "'publish_test' in rabbit_basic_output1.result.msg" + - "'publish_test' in rabbit_basic_output1.result.queue" + - "'text/plain' in rabbit_basic_output1.result.content_type" + + +# Testing random queue +- name: Publish to random queue + rabbitmq_publish: + url: "amqp://guest:guest@localhost:5672/%2F" + body: "RANDOM QUEUE POST" + content_type: "text/plain" + register: rabbit_random_queue_output + +- assert: + that: + - "rabbit_random_queue_output is not failed" + - "'amq.gen' in rabbit_random_queue_output.result.msg" + - "'amq.gen' in rabbit_random_queue_output.result.queue" + - "'text/plain' in rabbit_random_queue_output.result.content_type" + +- name: Copy binary to remote + copy: + src: "{{ role_path }}/files/image.gif" + dest: "{{ remote_tmp_dir }}/image.gif" + +- name: Publish binary to a queue + rabbitmq_publish: + url: "amqp://guest:guest@localhost:5672/%2F" + queue: publish_test + src: "{{ remote_tmp_dir }}/image.gif" + register: rabbitmq_publish_file + +- assert: + that: + - "rabbitmq_publish_file is not failed" + - "'publish_test' in rabbitmq_publish_file.result.queue" + - "'image/gif' in rabbitmq_publish_file.result.content_type" + +- name: Raise error for src and body defined + rabbitmq_publish: + url: "amqp://guest:guest@localhost:5672/%2F" + queue: 'publish_test' + src: "{{ remote_tmp_dir }}/image.gif" + body: blah + register: rabbit_basic_fail_output1 + ignore_errors: yes + +- assert: + that: + - "rabbit_basic_fail_output1 is failed" + - "'parameters are mutually exclusive' in rabbit_basic_fail_output1.msg" + +- name: Publish a file that does not exist + rabbitmq_publish: + url: "amqp://guest:guest@localhost:5672/%2F" + queue: 'publish_test' + src: 'aaaaaaajax-loader.gif' + register: file_missing_fail + ignore_errors: yes + +- assert: + that: + - "file_missing_fail is failed" + - "'Unable to open file' in file_missing_fail.msg" + +- name: Publish with proto/host/port/user/pass + rabbitmq_publish: + proto: amqp + host: localhost + port: 5672 + username: guest + password: guest + vhost: '%2F' + queue: publish_test + body: Testing with proto/host/port/username/password/vhost + register: host_port_output + +- assert: + that: + - "host_port_output is not failed" + +- name: Publish with host/port/user but missing proto + rabbitmq_publish: + host: localhost + port: 5672 + username: guest + password: guest + vhost: '%2F' + queue: publish_test + body: Testing with proto/host/port/username/password/vhost + ignore_errors: yes + register: host_port_missing_proto_output + +- assert: + that: + - "host_port_missing_proto_output is failed" + - "'Connection parameters must be passed via' in host_port_missing_proto_output.msg" + +- name: Publish with proto/host/port/user and url + rabbitmq_publish: + url: "amqp://guest:guest@localhost:5672/%2F" + proto: amqp + host: localhost + port: 5672 + username: guest + password: guest + vhost: '%2F' + queue: publish_test + body: Testing with proto/host/port/username/password/vhost + ignore_errors: yes + register: host_and_url_output + +- assert: + that: + - "host_and_url_output is failed" + - "'cannot be specified at the same time' in host_and_url_output.msg" + +- name: Publish headers to queue + rabbitmq_publish: + url: "amqp://guest:guest@localhost:5672/%2F" + queue: 'publish_test' + body: blah + headers: + myHeader: Value1 + secondHeader: Value2 + register: test_headers1 + ignore_errors: yes + +- name: Publish headers with file + rabbitmq_publish: + url: "amqp://guest:guest@localhost:5672/%2F" + queue: 'publish_test' + src: "{{ remote_tmp_dir }}/image.gif" + headers: + myHeader: Value1 + secondHeader: Value2 + register: test_headers2 + ignore_errors: yes + +- name: Collect all messages off the publish queue + set_fact: + messages: "{{ lookup('community.rabbitmq.rabbitmq', url='amqp://guest:guest@localhost:5672/%2F', queue='publish_test') }}" + +- name: Check contents of published messages + assert: + that: + - messages|length == 5 + - "'Hello world from ansible module rabbitmq_publish' in messages[0]['msg']" + - "'text/plain' in messages[0]['content_type']" + - "'image/gif' in messages[1]['content_type']" + - "'image.gif' in messages[1]['headers']['filename']" + - "'Testing with proto/host/port/username/password/vhost' in messages[2]['msg']" +# - messages[3]['headers']['myHeader'] is defined +# - messages[4]['headers']['filename'] is defined +# - messages[4]['headers']['secondHeader'] is defined diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user/aliases b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user/aliases new file mode 100644 index 00000000..f37e6c6f --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user/aliases @@ -0,0 +1,6 @@ +destructive +shippable/posix/group1 +skip/aix +skip/osx +skip/freebsd +skip/rhel diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user/meta/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user/meta/main.yml new file mode 100644 index 00000000..05ab5900 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - setup_rabbitmq diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user/tasks/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user/tasks/main.yml new file mode 100644 index 00000000..e03d4c7a --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user/tasks/main.yml @@ -0,0 +1,10 @@ +--- + +- when: ansible_distribution == 'Ubuntu' + block: + + - import_tasks: tests.yml + + - import_tasks: tests.yml + environment: + RABBITMQ_NODENAME: test diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user/tasks/tests.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user/tasks/tests.yml new file mode 100644 index 00000000..62274374 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_user/tasks/tests.yml @@ -0,0 +1,89 @@ +--- + +- name: Test add user + block: + - name: Add user + rabbitmq_user: user=joe password=changeme + register: add_user + + - name: Check that user adding succeeds with a change + assert: + that: + - add_user.changed == true + +- name: Test add user idempotence + block: + - name: Add user + rabbitmq_user: user=joe password=changeme + register: add_user + + - name: Check that user adding succeeds without a change + assert: + that: + - add_user.changed == false + +- name: Test change user permissions + block: + - name: Add user with permissions + rabbitmq_user: user=joe password=changeme vhost=/ configure_priv=.* read_priv=.* write_priv=.* + register: add_user + + - name: Check that changing permissions succeeds with a change + assert: + that: + - add_user.changed == true + +- name: Test change user permissions idempotence + block: + - name: Add user with permissions + rabbitmq_user: user=joe password=changeme vhost=/ configure_priv=.* read_priv=.* write_priv=.* + register: add_user + + - name: Check that changing permissions succeeds without a change + assert: + that: + - add_user.changed == false + +- name: Test add user tags + block: + - name: Add user with tags + rabbitmq_user: user=joe password=changeme vhost=/ configure_priv=.* read_priv=.* write_priv=.* tags=management,administrator + register: add_user + + - name: Check that adding tags succeeds with a change + assert: + that: + - add_user.changed == true + +- name: Test add user tags idempotence + block: + - name: Add user with tags + rabbitmq_user: user=joe password=changeme vhost=/ configure_priv=.* read_priv=.* write_priv=.* tags=administrator,management + register: add_user + + - name: Check that adding tags succeeds without a change + assert: + that: + - add_user.changed == false + +- name: Test remove user + block: + - name: Remove user + rabbitmq_user: user=joe state=absent + register: remove_user + + - name: Check that user removing succeeds with a change + assert: + that: + - remove_user.changed == true + +- name: Test remove user idempotence + block: + - name: Remove user + rabbitmq_user: user=joe state=absent + register: remove_user + + - name: Check that user removing succeeds without a change + assert: + that: + - remove_user.changed == false diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost/aliases b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost/aliases new file mode 100644 index 00000000..f37e6c6f --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost/aliases @@ -0,0 +1,6 @@ +destructive +shippable/posix/group1 +skip/aix +skip/osx +skip/freebsd +skip/rhel diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost/meta/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost/meta/main.yml new file mode 100644 index 00000000..05ab5900 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - setup_rabbitmq diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost/tasks/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost/tasks/main.yml new file mode 100644 index 00000000..593906fb --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost/tasks/main.yml @@ -0,0 +1,2 @@ +- import_tasks: tests.yml + when: ansible_distribution == 'Ubuntu' diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost/tasks/tests.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost/tasks/tests.yml new file mode 100644 index 00000000..019c5ede --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost/tasks/tests.yml @@ -0,0 +1,121 @@ +- block: + - set_fact: + vhost_name: /test + + - name: Add host + rabbitmq_vhost: + name: "{{ vhost_name }}" + state: present + register: result + + - name: Check that the host was created successfuly + shell: "rabbitmqctl list_vhosts name tracing | grep {{ vhost_name }}" + register: ctl_result + + - name: Check that the host is added + assert: + that: + - result is changed + - result is success + - '"false" in ctl_result.stdout' # value for tracing, false is disabled + + - name: Add host (idempotency) + rabbitmq_vhost: + name: "{{ vhost_name }}" + state: present + register: result + + - name: Check idempotency + assert: + that: + - result is not changed + + - name: Enable tracing + rabbitmq_vhost: + name: "{{ vhost_name }}" + tracing: yes + register: result + + - name: Get rabbitmqctl output + shell: "rabbitmqctl list_vhosts name tracing | grep {{ vhost_name }}" + register: ctl_result + + - name: Check that tracing is enabled + assert: + that: + - result is changed + - result is success + - '"true" in ctl_result.stdout' # value for tracing, true is enabled + + - name: Enable tracing (idempotency) + rabbitmq_vhost: + name: "{{ vhost_name }}" + tracing: yes + register: result + + - name: Check idempotency + assert: + that: + - result is not changed + + - name: Disable tracing + rabbitmq_vhost: + name: "{{ vhost_name }}" + tracing: no + register: result + + - name: Get rabbitmqctl output + shell: "rabbitmqctl list_vhosts name tracing | grep {{ vhost_name }}" + register: ctl_result + + - name: Check that tracing is disabled + assert: + that: + - result is changed + - result is success + - '"false" in ctl_result.stdout' # value for tracing, false is disabled + + - name: Disable tracing (idempotency) + rabbitmq_vhost: + name: "{{ vhost_name }}" + tracing: no + register: result + + - name: Check idempotency + assert: + that: + - result is not changed + + - name: Remove host + rabbitmq_vhost: + name: "{{ vhost_name }}" + state: absent + register: result + + - name: Get rabbitmqctl output + shell: "rabbitmqctl list_vhosts name tracing | grep {{ vhost_name }}" + register: ctl_result + failed_when: ctl_result.rc == 0 + + - name: Check that the host is removed + assert: + that: + - result is changed + - result is success + + - name: Remove host (idempotency) + rabbitmq_vhost: + name: "{{ vhost_name }}" + state: absent + register: result + + - name: Check idempotency + assert: + that: + - result is not changed + + always: + - name: Remove host + rabbitmq_vhost: + name: "{{ vhost_name }}" + state: absent diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost_limits/aliases b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost_limits/aliases new file mode 100644 index 00000000..f37e6c6f --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost_limits/aliases @@ -0,0 +1,6 @@ +destructive +shippable/posix/group1 +skip/aix +skip/osx +skip/freebsd +skip/rhel diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost_limits/meta/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost_limits/meta/main.yml new file mode 100644 index 00000000..05ab5900 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost_limits/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - setup_rabbitmq diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost_limits/tasks/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost_limits/tasks/main.yml new file mode 100644 index 00000000..740f8998 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost_limits/tasks/main.yml @@ -0,0 +1,5 @@ +# Rabbitmq lookup +- include: ubuntu.yml + when: + - ansible_distribution == 'Ubuntu' + - ansible_distribution_release != 'trusty' diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost_limits/tasks/ubuntu.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost_limits/tasks/ubuntu.yml new file mode 100644 index 00000000..8d0a6480 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/rabbitmq_vhost_limits/tasks/ubuntu.yml @@ -0,0 +1,163 @@ +--- + +- name: Test setting virtual host limits in check mode + block: + - name: Set virtual host limits in check mode + rabbitmq_vhost_limits: + vhost: / + max_connections: 64 + max_queues: 256 + state: present + check_mode: true + register: module_result + + - name: Check that the module's result is correct + assert: + that: + - module_result is changed + - module_result is success + + - name: Get a list of configured virtual host limits + shell: "rabbitmqctl list_vhost_limits" + register: shell_result + + - name: Check that the check mode does not make any changes + assert: + that: + - shell_result is success + - "'\"max-connections\":64' not in shell_result.stdout" + - "'\"max-queues\":256' not in shell_result.stdout" + +- name: Test setting virtual host limits + block: + - name: Set virtual host limits + rabbitmq_vhost_limits: + vhost: / + max_connections: 64 + max_queues: 256 + state: present + register: module_result + + - name: Check that the module's result is correct + assert: + that: + - module_result is changed + - module_result is success + + - name: Get a list of configured virtual host limits + shell: "rabbitmqctl list_vhost_limits" + register: shell_result + + - name: Check that the virtual host limits are actually set + assert: + that: + - shell_result is success + - "'\"max-connections\":64' in shell_result.stdout" + - "'\"max-queues\":256' in shell_result.stdout" + +- name: Test setting virtual host limits (idempotence) + block: + - name: Set virtual host limits (idempotence) + rabbitmq_vhost_limits: + vhost: / + max_connections: 64 + max_queues: 256 + state: present + register: module_result + + - name: Check the idempotence + assert: + that: + - module_result is not changed + - module_result is success + +- name: Test changing virtual host limits + block: + - name: Change virtual host limits + rabbitmq_vhost_limits: + vhost: / + max_connections: 32 + state: present + register: module_result + + - name: Check that the module's result is correct + assert: + that: + - module_result is changed + - module_result is success + + - name: Get a list of configured virtual host limits + shell: "rabbitmqctl list_vhost_limits" + register: shell_result + + - name: Check that the virtual host limits are actually set + assert: + that: + - shell_result is success + - "'\"max-connections\":32' in shell_result.stdout" + - "'\"max-queues\":-1' in shell_result.stdout" + +- name: Test clearing virtual host limits in check mode + block: + - name: Clear virtual host limits in check mode + rabbitmq_vhost_limits: + vhost: / + state: absent + check_mode: true + register: module_result + + - name: Check that the module's result is correct + assert: + that: + - module_result is changed + - module_result is success + + - name: Get a list of configured virtual host limits + shell: "rabbitmqctl list_vhost_limits" + register: shell_result + + - name: Check that the check mode does not make any changes + assert: + that: + - shell_result is success + - "'\"max-connections\":32' in shell_result.stdout" + - "'\"max-queues\":-1' in shell_result.stdout" + +- name: Test clearing virtual host limits + block: + - name: Clear virtual host limits + rabbitmq_vhost_limits: + vhost: / + state: absent + register: module_result + + - name: Check that the module's result is correct + assert: + that: + - module_result is changed + - module_result is success + + - name: Get a list of configured virtual host limits + shell: "rabbitmqctl list_vhost_limits" + register: shell_result + + - name: Check that the virtual host limits are actually cleared + assert: + that: + - shell_result is success + - "'\"max-connections\":' not in shell_result.stdout" + - "'\"max-queues\":' not in shell_result.stdout" + +- name: Test clearing virtual host limits (idempotence) + block: + - name: Clear virtual host limits (idempotence) + rabbitmq_vhost_limits: + vhost: / + state: absent + register: module_result + + - name: Check the idempotence + assert: + that: + - module_result is not changed + - module_result is success diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_rabbitmq/files/rabbitmq.conf b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_rabbitmq/files/rabbitmq.conf new file mode 100644 index 00000000..1e602175 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_rabbitmq/files/rabbitmq.conf @@ -0,0 +1,8 @@ +listeners.ssl.default = 5671 + +ssl_options.cacertfile = /tls/ca_certificate.pem +ssl_options.certfile = /tls/server_certificate.pem +ssl_options.keyfile = /tls/server_key.pem +ssl_options.password = bunnies +ssl_options.verify = verify_peer +ssl_options.fail_if_no_peer_cert = false diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_rabbitmq/meta/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_rabbitmq/meta/main.yml new file mode 100644 index 00000000..af05db79 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_rabbitmq/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - setup_tls diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_rabbitmq/tasks/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_rabbitmq/tasks/main.yml new file mode 100644 index 00000000..4f35f16f --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_rabbitmq/tasks/main.yml @@ -0,0 +1,3 @@ +--- +- include: ubuntu.yml + when: ansible_distribution == 'Ubuntu' diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_rabbitmq/tasks/ubuntu.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_rabbitmq/tasks/ubuntu.yml new file mode 100644 index 00000000..6d7a3ef0 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_rabbitmq/tasks/ubuntu.yml @@ -0,0 +1,63 @@ +--- +# https://www.rabbitmq.com/install-debian.html#apt-pinning +- name: Pin erlang version that rabbitmq supports + copy: + dest: /etc/apt/preferences.d/erlang + content: | + Package: erlang* + Pin: version 1:20.3.8.18-1 + Pin-Priority: 1000 + + Package: esl-erlang + Pin: version 1:20.3.6 + Pin-Priority: 1000 + +- name: Install https transport for apt + apt: + name: apt-transport-https + state: latest + force: yes + +- name: Add RabbitMQ release signing key + apt_key: + url: https://ansible-ci-files.s3.amazonaws.com/test/integration/targets/setup_rabbitmq/rabbitmq-release-signing-key.asc + state: present + +- name: Add RabbitMQ Erlang repository + apt_repository: + repo: "deb https://dl.bintray.com/rabbitmq-erlang/debian {{ ansible_distribution_release }} erlang-20.x" + filename: 'rabbitmq-erlang' + state: present + update_cache: yes + +# Required by the rabbitmq modules that uses the management API +- name: Install requests + pip: + name: requests + +- name: Install RabbitMQ Server + apt: + deb: https://s3.amazonaws.com/ansible-ci-files/test/integration/targets/setup_rabbitmq/rabbitmq-server_3.7.14-1_all.deb + +- name: Install RabbitMQ TLS dependencies + apt: + name: "{{ item }}" + state: latest + loop: + - erlang-asn1 + - erlang-crypto + - erlang-public-key + - erlang-ssl + +- name: Ensure TLS config + copy: + src: rabbitmq.conf + dest: /etc/rabbitmq/rabbitmq.conf + +- name: Start RabbitMQ service + service: + name: rabbitmq-server + state: started + +- name: Enable management + command: rabbitmq-plugins enable --online rabbitmq_management diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_remote_tmp_dir/handlers/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_remote_tmp_dir/handlers/main.yml new file mode 100644 index 00000000..229037c8 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_remote_tmp_dir/handlers/main.yml @@ -0,0 +1,5 @@ +- name: delete temporary directory + include_tasks: default-cleanup.yml + +- name: delete temporary directory (windows) + include_tasks: windows-cleanup.yml diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_remote_tmp_dir/tasks/default-cleanup.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_remote_tmp_dir/tasks/default-cleanup.yml new file mode 100644 index 00000000..39872d74 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_remote_tmp_dir/tasks/default-cleanup.yml @@ -0,0 +1,5 @@ +- name: delete temporary directory + file: + path: "{{ remote_tmp_dir }}" + state: absent + no_log: yes diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_remote_tmp_dir/tasks/default.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_remote_tmp_dir/tasks/default.yml new file mode 100644 index 00000000..1e0f51b8 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_remote_tmp_dir/tasks/default.yml @@ -0,0 +1,11 @@ +- name: create temporary directory + tempfile: + state: directory + suffix: .test + register: remote_tmp_dir + notify: + - delete temporary directory + +- name: record temporary directory + set_fact: + remote_tmp_dir: "{{ remote_tmp_dir.path }}" diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_remote_tmp_dir/tasks/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_remote_tmp_dir/tasks/main.yml new file mode 100644 index 00000000..f8df391b --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_remote_tmp_dir/tasks/main.yml @@ -0,0 +1,10 @@ +- name: make sure we have the ansible_os_family and ansible_distribution_version facts + setup: + gather_subset: distribution + when: ansible_facts == {} + +- include_tasks: "{{ lookup('first_found', files)}}" + vars: + files: + - "{{ ansible_os_family | lower }}.yml" + - "default.yml" diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/ca_certificate.pem b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/ca_certificate.pem new file mode 100644 index 00000000..a438d926 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/ca_certificate.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDAjCCAeqgAwIBAgIJANguFROhaWocMA0GCSqGSIb3DQEBCwUAMDExIDAeBgNV +BAMMF1RMU0dlblNlbGZTaWduZWR0Um9vdENBMQ0wCwYDVQQHDAQkJCQkMB4XDTE5 +MDExMTA4MzMxNVoXDTI5MDEwODA4MzMxNVowMTEgMB4GA1UEAwwXVExTR2VuU2Vs +ZlNpZ25lZHRSb290Q0ExDTALBgNVBAcMBCQkJCQwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQDqVt84czSxWnWW4Ng6hmKE3NarbLsycwtjrYBokV7Kk7Mp +7PrBbYF05FOgSdJLvL6grlRSQK2VPsXdLfEv5uFXX6gyd2WQwKCiGGf4UY4ZIl4l +JVpSDsBV2orR4pOIf1s1+iSwvcRQkX46SVjoKWbDUc4VLo1uy8UvavQI+DMioYyy +0K2MbRs7oG2rdKks8zisfT0ymKnrFTdVeUjIrg0sStaMnf9VVkcEeYkfNY0vWqdn +CV5wPfDBlnnxGMgqGdLSpzfyJ7qafFET+q+gOvjsEqzn7DvlPkmk86hIIWXKi3aM +A9swknL3rnagJL6GioWRpYUwKdRKmZxdyr4I2JTTAgMBAAGjHTAbMAwGA1UdEwQF +MAMBAf8wCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBAQACTpPBf5WSwZ7r +hrbPUN3qVh70HI0ZNK2jlK6b5fpSdw3JI/GQl0Kw3eGICLzwTByWvhD62U7IigL5 +0UWxWuEod310Y/qo/7OxRVPp5PH/0oNGoKHhEzas2ii0heQYGsHQUKGzYNNyVfjy +nqBFz5AcKf067LcXivYqod6JDQHqFq/5/hWlIsHHrZIeijqqtthPq39GlGAYO+AB +U66nzlH7YQgmfYfy6l7O4LsjXf/bz9rWvueO3NqCsmXV+FacDkOkwWA5Kf6rcgNL +3G+2HAVTRIXDnO4ShnK6aYMW+UklpYRlVYBBUOdwoNIp5gI+BlSc1IuF6PdLVt3q +VdjN1MjY +-----END CERTIFICATE----- diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/ca_key.pem b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/ca_key.pem new file mode 100644 index 00000000..0a950eda --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/ca_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDqVt84czSxWnWW +4Ng6hmKE3NarbLsycwtjrYBokV7Kk7Mp7PrBbYF05FOgSdJLvL6grlRSQK2VPsXd +LfEv5uFXX6gyd2WQwKCiGGf4UY4ZIl4lJVpSDsBV2orR4pOIf1s1+iSwvcRQkX46 +SVjoKWbDUc4VLo1uy8UvavQI+DMioYyy0K2MbRs7oG2rdKks8zisfT0ymKnrFTdV +eUjIrg0sStaMnf9VVkcEeYkfNY0vWqdnCV5wPfDBlnnxGMgqGdLSpzfyJ7qafFET ++q+gOvjsEqzn7DvlPkmk86hIIWXKi3aMA9swknL3rnagJL6GioWRpYUwKdRKmZxd +yr4I2JTTAgMBAAECggEBALpg9ZDUMCiOpc+mbNO/ZkP90M7u38Q0M+7HY8XHOPkt +l+XUkWueSMRLhSeLDzMlnwf1HyN8RZLaJkzP6XAL1VXEwuXAiIskaZ4Cg07Arp/W +8cHhf4CcMuUVuCtOZcC+ajD4Do5zn9vkm9yH0ap0o0LdoWa/a8WfU+luy0EHBsSW +6qqI+nqNFmISluVbfWt7t3zp273+8sir6YeHQu9G91/jzggv8rHmu4EHhi3cnU0K +vY6OPCGBL7nrg9Rv1LSFpH95TvlIM6/Cm0AjgW7m6XwWUTaI9p+GvKzrYUSLd9L/ +QxlmAwiu/sBTXLrsWyr8XEtj+lVGxQ6eFbf6E+lUm8ECgYEA+8Wgmhf3VsC3gvJz +w2jApEoOioD5iGOWGClGVURkfaBhFELr4XCTVMdBuCtxT7LYTMHTAlBqIbdWDjB4 +m/E417hLGogSDy7j0R0Mx75OOGEitxYUhe0VGDNoytgCNd2UnTMt42lp+9vAHZag +INhVDOnxRNdtNTf1yYkWUMEbh1sCgYEA7kZNJXPVYJtR78+km/Gcv64Umci7KUV+ +hYc7chR5xv3cXvXg5eojKa4G7CyMQTX7VnRa6CiQKdN73AbIAhS4Oy5UlCOKtmb8 +xnBiOAYwSpOfIeZhjq0RvEeZX0t6u7XsErBZ03rEPKXF2nNDo1x8byrlKPtlUzwJ +gb5yjmK/mekCgYEA1TWQAs5m4+2Bun+tbv7nnHkmhT4hktGays0xRYYMf6Jwc6MU +dC5MZg/zZI5Nf8uZhq7hDWWh6vmCA7QifxSxKWVlHIu8l2UDAhRSvVg4j2Aa8Obe +7GdQZNUsWhLBFHKXpuQvaRTc7q8yqxvicM4igDQg4EZ6sgW4vDm+TxapRF8CgYAz +n6mhPqpxRtWGxo8cdkmGwfmWpAXg2DykQ3teqQ8FTQUM0erLBWJe6mR3kONGUaLF +xWnYuMkbNsW0EwgMY17S+6O5gMXR5RhJChpNlxGpZrhoiNiEJ/0atMyG9/x8ZNrj +5a9ggU248hWe0bBK2YPgNgP2UBlQ4kYRBSkerkhi2QKBgF+tlpyqcU+0iY82qRS2 +wMf7oI2pWR8nX9LPAY/nnvwWvqwcAFJPMlSMTu8Ext6h7l9yu+7JGL6JWwsO57Lb +Gm/RxbuZ/kG/13+lSNmZiyHrhj6hZhkAMeFM34fpT4+DBXqSxZuvdrmwBc5B2jYg +F9Bv8gcmZlGhqONL23evr9Gu +-----END PRIVATE KEY----- diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/client_certificate.pem b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/client_certificate.pem new file mode 100644 index 00000000..501d8389 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/client_certificate.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDRjCCAi6gAwIBAgIBAjANBgkqhkiG9w0BAQsFADAxMSAwHgYDVQQDDBdUTFNH +ZW5TZWxmU2lnbmVkdFJvb3RDQTENMAsGA1UEBwwEJCQkJDAeFw0xOTAxMTEwODMz +MThaFw0yOTAxMDgwODMzMThaMC0xGjAYBgNVBAMMEWFuc2libGUudGxzLnRlc3Rz +MQ8wDQYDVQQKDAZjbGllbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCoM+OQ3HCnCUAAz9KGGTwWB9hQbUfAZXm/stlb2/uOAp3rNwxAlCs/giymBHE6 +Iu6mrK006Vn+Z9ibqIrD2LuCOxcu25y8goqG62TgdP5sa9wR+597s0XssnwnaY8y +bJ3p2zWAJvMgqQ0iNW/ZynpWbO85K5SryUykF7FAeNU9ogGGlIwCPjHhPvnwjkqd +yDqaA1VaJKDUWIF9joI7sV4VLgGhQvzXRrHULsTeIF2m0+ebL0PTNEWHQ0dtgLYX +kW7YO4Y6+n3cjHNH4qTof8V30EK8pk8kTdJ/x6ubwf+klFCAyroOxNOaxUy299Oo +yD6qIPJPnGkPhrKtWnWIhNzJAgMBAAGjbTBrMAkGA1UdEwQCMAAwCwYDVR0PBAQD +AgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMCMDwGA1UdEQQ1MDOCEWFuc2libGUudGxz +LnRlc3RzghNNYWNCb29rLVByby00LmxvY2Fsgglsb2NhbGhvc3QwDQYJKoZIhvcN +AQELBQADggEBAK214+VVXnGnsUlvd9Q6A2Ea6UGrr6b7xkmlnIaNd+6xoUsDsHob +srHYm7UC0uLi1KwSunI7AU5ZELVEUfAmJzh3O4d6C5sQyqKYPqd5harWOQ3BOD0I +plHpp7qMtsPDuJBtmE/bmvF85eto0H7pPz+cTTXRlOaVVeiHjMggFcXdy1MzGo9C +X/4wLQmsFeypTfe+ZGqvDh99VV+ffNMIsMh+opWEloaKiHmDKB6S9aC/MsVVM4RR +nHm/UKTOukaGE9QIPkSSaygv3sBkVnQ2SHMvvtnjPHVHlizNoq6+YTnuOvKpo4o5 +V7Bij+W7rkBQLsEfwv2IC+gzmRz2yxr2tXk= +-----END CERTIFICATE----- diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/client_key.pem b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/client_key.pem new file mode 100644 index 00000000..850260a8 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/client_key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAqDPjkNxwpwlAAM/Shhk8FgfYUG1HwGV5v7LZW9v7jgKd6zcM +QJQrP4IspgRxOiLupqytNOlZ/mfYm6iKw9i7gjsXLtucvIKKhutk4HT+bGvcEfuf +e7NF7LJ8J2mPMmyd6ds1gCbzIKkNIjVv2cp6VmzvOSuUq8lMpBexQHjVPaIBhpSM +Aj4x4T758I5Kncg6mgNVWiSg1FiBfY6CO7FeFS4BoUL810ax1C7E3iBdptPnmy9D +0zRFh0NHbYC2F5Fu2DuGOvp93IxzR+Kk6H/Fd9BCvKZPJE3Sf8erm8H/pJRQgMq6 +DsTTmsVMtvfTqMg+qiDyT5xpD4ayrVp1iITcyQIDAQABAoIBAHPszzpXs4xr46Cr +mvyxB6hnX76OkpUXWwGz0fptcsI9K3mhRuB7PhNXNE53YVIgITreZ8G/0jZ0e+VM +E9dG2HS5JRE2ap/BmJfERJIuD+vJqrL6KMCondi0arz/E6I9GdjDK+xW69nmqRaa +nawM0KQgD//m+WAsLJYrfg5hORZwI2SHaahawnCp0QaMmz3bdDWKRacM3q0UFX46 +Ze6CaZkUn+e1rHsTMcZBvxQWIVzysFNXh150idIB/PxL5YfCQqTSAj1c/nxaxz6a +BvHFlpaYR3tvXXlexxfjglCwsGyckbvTyP1cBZqpv5oES+VKt2PrOve9Zyax+CYT +0uQf6cECgYEA09+46QHXLfWh6jiJYu9skC9UrLU5czfCNB6PrUtFcjPFMYjZDcw9 +inJmcuTPXmfplxc47YDfpwotU+szTJDF+R8kknnfw9zVr/sIwZ5wsFfUQl/56Svn +AIOVvHHvcvMX95XKGiuTsoCIJZNjJN3l3ztu/bRciuiVLyizglwIVrMCgYEAyzvK +PFlWilbp3GPJlnW7x1bUxe1ziLE/Um+ujZx96+fy34hJLFdNdNzpNUjoOf3IDTGq +6xl+vXcf12gimWMFcD3qNIGKHBDM9cIB2RDbb6YcqI8lOqopsmOyGmVLPkRpCoUK +72kacQwvw6M9xjmpiG3dN8lE881jDmZi+hyCnJMCgYEAoIQnQAhP8Jbeo2dP1q+T +bS0elnX532uH6xqYOW8EXwAPznZiEw0ANspzCWqGHHzXQMusKmtvhcq1CpXvWHt6 +MUHB4GMK/wVosxmZya5yq3bu7ZZu7JOBQCdwosMi6NB5AO7vnaIUFLFB9E3UWBLw +243YicdCMU8B7yeD0ChPfPcCgYA1dYHKBBn+g8Q6Y8lIGaoOUmnfsok8gJtOfPAm +ce6xmi7J29iboE9QmTeC+62Sa44u4ky6UNeE0QwAJnVLcb+hebfcneKNZWH0l1bT +GVsPcFuDfzvkxZP4R782sERtmaMj0EFDHpuE9xatWIhMVyigKX4SSZAorXML+6S3 +c75rnwKBgBR+WU934wS+DbwTLlUB2mJWqJMEbOH/CUwPC7+VN4h1h3/i455iAeiU +BizLS0SlD+MoSbC7URcZuquqGkmMlnJXoxF+NdxoWZK78tYNftryWoR87TloiVc/ +LhkxZxje4tgW/mTLqH3zKDoyyzDzG6Q6tAUN2ZTjJFEws7qF30Qe +-----END RSA PRIVATE KEY----- diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/server_certificate.pem b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/server_certificate.pem new file mode 100644 index 00000000..4a0ebc6e --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/server_certificate.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDRjCCAi6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAxMSAwHgYDVQQDDBdUTFNH +ZW5TZWxmU2lnbmVkdFJvb3RDQTENMAsGA1UEBwwEJCQkJDAeFw0xOTAxMTEwODMz +MTZaFw0yOTAxMDgwODMzMTZaMC0xGjAYBgNVBAMMEWFuc2libGUudGxzLnRlc3Rz +MQ8wDQYDVQQKDAZzZXJ2ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQDIwErHwAesRBfd9HiZkmB3VYh28c1QkE9I8nYyHJKX2ZBUhAzK+h80BkcTJJ94 +265qWyACH/wl54Xe/ofFUFrGa4vz0qz4UkL/KI0OGw28Y4qnKdorb9DumbiIPB+9 +I9TJT9vhtXTxBNlBTpv3ONHL8EzdV6ZmuvELU11H27oQ4xoUYhfXPXLMLK0sOnXZ +lt0BOMMd5fVpJVa8fvXiw3626a0aXCr4e/MWUsBFRnzrXfgoW+AjYoTjKKS2hLYo +8//MM05h7ROIXrNe990sf9C1G+fOThmOMszK9sjMhu2xHranRcz5aA0UTfyOjTs8 +9WexUYhC5VorYyRWtVZu2mDjAgMBAAGjbTBrMAkGA1UdEwQCMAAwCwYDVR0PBAQD +AgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMDwGA1UdEQQ1MDOCEWFuc2libGUudGxz +LnRlc3RzghNNYWNCb29rLVByby00LmxvY2Fsgglsb2NhbGhvc3QwDQYJKoZIhvcN +AQELBQADggEBAFoPBeB6tQhFS1198sia5NDHDDrghDOIlE0QbaoA+MSKzsaIy8Mu +mNcM2ewYpT600XXTBxcqF6/vuKL9OEbvivtRYQu1YfkifN1jzREoWTieUkR5ytzt +8ATfFkgTWJmiRiOIb/fNgewvhd+aKxep0OGwDiSKKl1ab6F17Cp4iK8sDBWmnUb6 +0Wf7pfver1Gl0Gp8vRXGUuc8a7udA9a8mV70HJlLkMdMvR9U8Bqih0+iRaqNWXRZ +7Lc6v5LbzrW/ntilmgU6F0lwxPydg49MY4UrSXcjYLZs9T4iYHwTfLxFjFMIgGwn +peYMKRj18akP9i2mjj5O2mRu4K+ecuUSOGI= +-----END CERTIFICATE----- diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/server_key.pem b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/server_key.pem new file mode 100644 index 00000000..c79ab648 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/files/server_key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAyMBKx8AHrEQX3fR4mZJgd1WIdvHNUJBPSPJ2MhySl9mQVIQM +yvofNAZHEySfeNuualsgAh/8JeeF3v6HxVBaxmuL89Ks+FJC/yiNDhsNvGOKpyna +K2/Q7pm4iDwfvSPUyU/b4bV08QTZQU6b9zjRy/BM3VemZrrxC1NdR9u6EOMaFGIX +1z1yzCytLDp12ZbdATjDHeX1aSVWvH714sN+tumtGlwq+HvzFlLARUZ86134KFvg +I2KE4yiktoS2KPP/zDNOYe0TiF6zXvfdLH/QtRvnzk4ZjjLMyvbIzIbtsR62p0XM ++WgNFE38jo07PPVnsVGIQuVaK2MkVrVWbtpg4wIDAQABAoIBAHw3wA3pnNXTLJGC +fD1KfbZZjp9K76gyI10X6lsHow2i6dPiAah3LGecms4VkzfNdxcIW7303Kj3obZh ++ND277RnR6oPakgdXqdUCDP6OX2gemMFWqIWBkodhDmIOntmeHw4le4LwdiBD42B +frBy0B5JCsbLPYPDmPNRGh8krvVS+Eir4hb4tK95TPMSL0vEjvHYFbCxv7//Ri1p +3CROGp2CGX0WZ+Zs0crRNoIhRRM6kLAhROcqejtnEy6o7l5CWpCAL2vxlE9y8/kL +iRawSZRFZnz/zGnqpx0vswgvijkuPfcNGMSzdwaiDgQz8D0GkJ7s9VgzZJazNy+1 +ET/4YIECgYEA612rwP9Ar9qdYbmmMPaJzITnaIrNGfO2JvaQqZt+DG8sVgdxL7V5 +D6emcw406drKRZvFAxnW6ZW2bVpmit02osl0re2A/nOTXLNuo338Qkap/hG8YZrF +bw7w75pFa/rwlDtedjBnGHO2KbRXeU5Hn5wLoKjYgJoF6Ht+PPdL0IsCgYEA2lnC +pQEhM51iRMDqNdmVJyvsTNU1ikoO8HaXHq+LwOQETaKMnDwp4Bn14E815CTulAc/ +tsDTKSDk6umZ+IufG1a2v7CqgKVwkB4HkgxKFQs2gQdTFfoMi5eeHR+njuNtklp1 +9fWfKHsP/ddrg+iTVTRZBLWexgKK89IMHYalpAkCgYEAy0Q3a9NF81mTJ+3kOE8C +zO1OyLtuzGXsvxOb9c6C+owctyNwPeq05a89EgqH6hr5K0qOx9HOCCcyyJgVDQJl +CAuByB/gkmAQOTQBbhMFA9vxPanljknTDsnRjKwoHkw2712ig+Hjd3ufK79C+FGB +i7eBVzva1p2uUowshsxv3mcCgYAOFiRciMofjlO8o8V4W+Undcn02vxtQ4HbOYte +S2z0sMEmUQpJOghpkMMwCWwsn8VUf3M40w/MY3bhQNjSFA/br6hyjW8yhXnRkl5i +qbBN0z9c66AMlukgSFPHBTfGHB4Bhxx9Fa+C6Q2LDs6839BBevMTPrRTie509GQb +s4gUIQKBgAvE8wLcmozno0GLDnBdKRZP/C7tmVnAINuraITPUBTASwI+Qo8ILigQ +LRLaDqF84BEpjb8vdzkYFQqRQSZ8BI8NydfuKEFSBfL27sBvSGMYQJVm6bryUmPq +T3ayaeZ4Wb3FFDijgtM9dRKyf7p4hQPOqM44QrntAtb43b2Q5L7M +-----END RSA PRIVATE KEY----- diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/tasks/main.yml b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/tasks/main.yml new file mode 100644 index 00000000..c5b7a23a --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/integration/targets/setup_tls/tasks/main.yml @@ -0,0 +1,21 @@ +--- +# Generated certificate with: https://github.com/michaelklishin/tls-gen +# ~/tls-gen/basic# make PASSWORD=bunnies CN=ansible.tls.tests +# verify with: make info + +- name: ensure target directory is present + file: + path: /tls + state: directory + +- name: ensure TLS files are present + copy: + src: "{{ item }}" + dest: "/tls/{{ item }}" + loop: + - ca_certificate.pem + - ca_key.pem + - client_certificate.pem + - client_key.pem + - server_certificate.pem + - server_key.pem diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/sanity/ignore-2.10.txt b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/sanity/ignore-2.10.txt new file mode 100644 index 00000000..3cf68c0d --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/sanity/ignore-2.10.txt @@ -0,0 +1 @@ +tests/utils/shippable/timing.py shebang diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/sanity/ignore-2.11.txt b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/sanity/ignore-2.11.txt new file mode 100644 index 00000000..3cf68c0d --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/sanity/ignore-2.11.txt @@ -0,0 +1 @@ +tests/utils/shippable/timing.py shebang diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/sanity/ignore.txt b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/sanity/ignore.txt new file mode 100644 index 00000000..3cf68c0d --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/sanity/ignore.txt @@ -0,0 +1 @@ +tests/utils/shippable/timing.py shebang diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/compat/__init__.py b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/compat/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/compat/__init__.py diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/compat/builtins.py b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/compat/builtins.py new file mode 100644 index 00000000..f60ee678 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/compat/builtins.py @@ -0,0 +1,33 @@ +# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com> +# +# This file is part of Ansible +# +# 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. +# +# 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 Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +# +# Compat for python2.7 +# + +# One unittest needs to import builtins via __import__() so we need to have +# the string that represents it +try: + import __builtin__ +except ImportError: + BUILTINS = 'builtins' +else: + BUILTINS = '__builtin__' diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/compat/mock.py b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/compat/mock.py new file mode 100644 index 00000000..0972cd2e --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/compat/mock.py @@ -0,0 +1,122 @@ +# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com> +# +# This file is part of Ansible +# +# 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. +# +# 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 Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +''' +Compat module for Python3.x's unittest.mock module +''' +import sys + +# Python 2.7 + +# Note: Could use the pypi mock library on python3.x as well as python2.x. It +# is the same as the python3 stdlib mock library + +try: + # Allow wildcard import because we really do want to import all of mock's + # symbols into this compat shim + # pylint: disable=wildcard-import,unused-wildcard-import + from unittest.mock import * +except ImportError: + # Python 2 + # pylint: disable=wildcard-import,unused-wildcard-import + try: + from mock import * + except ImportError: + print('You need the mock library installed on python2.x to run tests') + + +# Prior to 3.4.4, mock_open cannot handle binary read_data +if sys.version_info >= (3,) and sys.version_info < (3, 4, 4): + file_spec = None + + def _iterate_read_data(read_data): + # Helper for mock_open: + # Retrieve lines from read_data via a generator so that separate calls to + # readline, read, and readlines are properly interleaved + sep = b'\n' if isinstance(read_data, bytes) else '\n' + data_as_list = [l + sep for l in read_data.split(sep)] + + if data_as_list[-1] == sep: + # If the last line ended in a newline, the list comprehension will have an + # extra entry that's just a newline. Remove this. + data_as_list = data_as_list[:-1] + else: + # If there wasn't an extra newline by itself, then the file being + # emulated doesn't have a newline to end the last line remove the + # newline that our naive format() added + data_as_list[-1] = data_as_list[-1][:-1] + + for line in data_as_list: + yield line + + def mock_open(mock=None, read_data=''): + """ + A helper function to create a mock to replace the use of `open`. It works + for `open` called directly or used as a context manager. + + The `mock` argument is the mock object to configure. If `None` (the + default) then a `MagicMock` will be created for you, with the API limited + to methods or attributes available on standard file handles. + + `read_data` is a string for the `read` methoddline`, and `readlines` of the + file handle to return. This is an empty string by default. + """ + def _readlines_side_effect(*args, **kwargs): + if handle.readlines.return_value is not None: + return handle.readlines.return_value + return list(_data) + + def _read_side_effect(*args, **kwargs): + if handle.read.return_value is not None: + return handle.read.return_value + return type(read_data)().join(_data) + + def _readline_side_effect(): + if handle.readline.return_value is not None: + while True: + yield handle.readline.return_value + for line in _data: + yield line + + global file_spec + if file_spec is None: + import _io + file_spec = list(set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO)))) + + if mock is None: + mock = MagicMock(name='open', spec=open) + + handle = MagicMock(spec=file_spec) + handle.__enter__.return_value = handle + + _data = _iterate_read_data(read_data) + + handle.write.return_value = None + handle.read.return_value = None + handle.readline.return_value = None + handle.readlines.return_value = None + + handle.read.side_effect = _read_side_effect + handle.readline.side_effect = _readline_side_effect() + handle.readlines.side_effect = _readlines_side_effect + + mock.return_value = handle + return mock diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/compat/unittest.py b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/compat/unittest.py new file mode 100644 index 00000000..98f08ad6 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/compat/unittest.py @@ -0,0 +1,38 @@ +# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com> +# +# This file is part of Ansible +# +# 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. +# +# 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 Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +''' +Compat module for Python2.7's unittest module +''' + +import sys + +# Allow wildcard import because we really do want to import all of +# unittests's symbols into this compat shim +# pylint: disable=wildcard-import,unused-wildcard-import +if sys.version_info < (2, 7): + try: + # Need unittest2 on python2.6 + from unittest2 import * + except ImportError: + print('You need unittest2 installed on python2.6.x to run tests') +else: + from unittest import * diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/mock/__init__.py b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/mock/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/mock/__init__.py diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/mock/loader.py b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/mock/loader.py new file mode 100644 index 00000000..0ee47fbb --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/mock/loader.py @@ -0,0 +1,116 @@ +# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com> +# +# This file is part of Ansible +# +# 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. +# +# 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 Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os + +from ansible.errors import AnsibleParserError +from ansible.parsing.dataloader import DataLoader +from ansible.module_utils._text import to_bytes, to_text + + +class DictDataLoader(DataLoader): + + def __init__(self, file_mapping=None): + file_mapping = {} if file_mapping is None else file_mapping + assert type(file_mapping) == dict + + super(DictDataLoader, self).__init__() + + self._file_mapping = file_mapping + self._build_known_directories() + self._vault_secrets = None + + def load_from_file(self, path, cache=True, unsafe=False): + path = to_text(path) + if path in self._file_mapping: + return self.load(self._file_mapping[path], path) + return None + + # TODO: the real _get_file_contents returns a bytestring, so we actually convert the + # unicode/text it's created with to utf-8 + def _get_file_contents(self, path): + path = to_text(path) + if path in self._file_mapping: + return (to_bytes(self._file_mapping[path]), False) + else: + raise AnsibleParserError("file not found: %s" % path) + + def path_exists(self, path): + path = to_text(path) + return path in self._file_mapping or path in self._known_directories + + def is_file(self, path): + path = to_text(path) + return path in self._file_mapping + + def is_directory(self, path): + path = to_text(path) + return path in self._known_directories + + def list_directory(self, path): + ret = [] + path = to_text(path) + for x in (list(self._file_mapping.keys()) + self._known_directories): + if x.startswith(path): + if os.path.dirname(x) == path: + ret.append(os.path.basename(x)) + return ret + + def is_executable(self, path): + # FIXME: figure out a way to make paths return true for this + return False + + def _add_known_directory(self, directory): + if directory not in self._known_directories: + self._known_directories.append(directory) + + def _build_known_directories(self): + self._known_directories = [] + for path in self._file_mapping: + dirname = os.path.dirname(path) + while dirname not in ('/', ''): + self._add_known_directory(dirname) + dirname = os.path.dirname(dirname) + + def push(self, path, content): + rebuild_dirs = False + if path not in self._file_mapping: + rebuild_dirs = True + + self._file_mapping[path] = content + + if rebuild_dirs: + self._build_known_directories() + + def pop(self, path): + if path in self._file_mapping: + del self._file_mapping[path] + self._build_known_directories() + + def clear(self): + self._file_mapping = dict() + self._known_directories = [] + + def get_basedir(self): + return os.getcwd() + + def set_vault_secrets(self, vault_secrets): + self._vault_secrets = vault_secrets diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/mock/path.py b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/mock/path.py new file mode 100644 index 00000000..e988116b --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/mock/path.py @@ -0,0 +1,8 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from ansible_collections.ansible.rabbitmq.tests.unit.compat.mock import MagicMock +from ansible.utils.path import unfrackpath + + +mock_unfrackpath_noop = MagicMock(spec_set=unfrackpath, side_effect=lambda x, *args, **kwargs: x) diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/mock/procenv.py b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/mock/procenv.py new file mode 100644 index 00000000..56d44b01 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/mock/procenv.py @@ -0,0 +1,90 @@ +# (c) 2016, Matt Davis <mdavis@ansible.com> +# (c) 2016, Toshio Kuratomi <tkuratomi@ansible.com> +# +# This file is part of Ansible +# +# 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. +# +# 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 Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import sys +import json + +from contextlib import contextmanager +from io import BytesIO, StringIO +from ansible_collections.ansible.rabbitmq.tests.unit.compat import unittest +from ansible.module_utils.six import PY3 +from ansible.module_utils._text import to_bytes + + +@contextmanager +def swap_stdin_and_argv(stdin_data='', argv_data=tuple()): + """ + context manager that temporarily masks the test runner's values for stdin and argv + """ + real_stdin = sys.stdin + real_argv = sys.argv + + if PY3: + fake_stream = StringIO(stdin_data) + fake_stream.buffer = BytesIO(to_bytes(stdin_data)) + else: + fake_stream = BytesIO(to_bytes(stdin_data)) + + try: + sys.stdin = fake_stream + sys.argv = argv_data + + yield + finally: + sys.stdin = real_stdin + sys.argv = real_argv + + +@contextmanager +def swap_stdout(): + """ + context manager that temporarily replaces stdout for tests that need to verify output + """ + old_stdout = sys.stdout + + if PY3: + fake_stream = StringIO() + else: + fake_stream = BytesIO() + + try: + sys.stdout = fake_stream + + yield fake_stream + finally: + sys.stdout = old_stdout + + +class ModuleTestCase(unittest.TestCase): + def setUp(self, module_args=None): + if module_args is None: + module_args = {'_ansible_remote_tmp': '/tmp', '_ansible_keep_remote_files': False} + + args = json.dumps(dict(ANSIBLE_MODULE_ARGS=module_args)) + + # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually + self.stdin_swap = swap_stdin_and_argv(stdin_data=args) + self.stdin_swap.__enter__() + + def tearDown(self): + # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually + self.stdin_swap.__exit__(None, None, None) diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/mock/vault_helper.py b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/mock/vault_helper.py new file mode 100644 index 00000000..dcce9c78 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/mock/vault_helper.py @@ -0,0 +1,39 @@ +# 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. +# +# 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 Ansible. If not, see <http://www.gnu.org/licenses/>. + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from ansible.module_utils._text import to_bytes + +from ansible.parsing.vault import VaultSecret + + +class TextVaultSecret(VaultSecret): + '''A secret piece of text. ie, a password. Tracks text encoding. + + The text encoding of the text may not be the default text encoding so + we keep track of the encoding so we encode it to the same bytes.''' + + def __init__(self, text, encoding=None, errors=None, _bytes=None): + super(TextVaultSecret, self).__init__() + self.text = text + self.encoding = encoding or 'utf-8' + self._bytes = _bytes + self.errors = errors or 'strict' + + @property + def bytes(self): + '''The text encoded with encoding, unless we specifically set _bytes.''' + return self._bytes or to_bytes(self.text, encoding=self.encoding, errors=self.errors) diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/mock/yaml_helper.py b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/mock/yaml_helper.py new file mode 100644 index 00000000..1ef17215 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/mock/yaml_helper.py @@ -0,0 +1,124 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import io +import yaml + +from ansible.module_utils.six import PY3 +from ansible.parsing.yaml.loader import AnsibleLoader +from ansible.parsing.yaml.dumper import AnsibleDumper + + +class YamlTestUtils(object): + """Mixin class to combine with a unittest.TestCase subclass.""" + def _loader(self, stream): + """Vault related tests will want to override this. + + Vault cases should setup a AnsibleLoader that has the vault password.""" + return AnsibleLoader(stream) + + def _dump_stream(self, obj, stream, dumper=None): + """Dump to a py2-unicode or py3-string stream.""" + if PY3: + return yaml.dump(obj, stream, Dumper=dumper) + else: + return yaml.dump(obj, stream, Dumper=dumper, encoding=None) + + def _dump_string(self, obj, dumper=None): + """Dump to a py2-unicode or py3-string""" + if PY3: + return yaml.dump(obj, Dumper=dumper) + else: + return yaml.dump(obj, Dumper=dumper, encoding=None) + + def _dump_load_cycle(self, obj): + # Each pass though a dump or load revs the 'generation' + # obj to yaml string + string_from_object_dump = self._dump_string(obj, dumper=AnsibleDumper) + + # wrap a stream/file like StringIO around that yaml + stream_from_object_dump = io.StringIO(string_from_object_dump) + loader = self._loader(stream_from_object_dump) + # load the yaml stream to create a new instance of the object (gen 2) + obj_2 = loader.get_data() + + # dump the gen 2 objects directory to strings + string_from_object_dump_2 = self._dump_string(obj_2, + dumper=AnsibleDumper) + + # The gen 1 and gen 2 yaml strings + self.assertEqual(string_from_object_dump, string_from_object_dump_2) + # the gen 1 (orig) and gen 2 py object + self.assertEqual(obj, obj_2) + + # again! gen 3... load strings into py objects + stream_3 = io.StringIO(string_from_object_dump_2) + loader_3 = self._loader(stream_3) + obj_3 = loader_3.get_data() + + string_from_object_dump_3 = self._dump_string(obj_3, dumper=AnsibleDumper) + + self.assertEqual(obj, obj_3) + # should be transitive, but... + self.assertEqual(obj_2, obj_3) + self.assertEqual(string_from_object_dump, string_from_object_dump_3) + + def _old_dump_load_cycle(self, obj): + '''Dump the passed in object to yaml, load it back up, dump again, compare.''' + stream = io.StringIO() + + yaml_string = self._dump_string(obj, dumper=AnsibleDumper) + self._dump_stream(obj, stream, dumper=AnsibleDumper) + + yaml_string_from_stream = stream.getvalue() + + # reset stream + stream.seek(0) + + loader = self._loader(stream) + # loader = AnsibleLoader(stream, vault_password=self.vault_password) + obj_from_stream = loader.get_data() + + stream_from_string = io.StringIO(yaml_string) + loader2 = self._loader(stream_from_string) + # loader2 = AnsibleLoader(stream_from_string, vault_password=self.vault_password) + obj_from_string = loader2.get_data() + + stream_obj_from_stream = io.StringIO() + stream_obj_from_string = io.StringIO() + + if PY3: + yaml.dump(obj_from_stream, stream_obj_from_stream, Dumper=AnsibleDumper) + yaml.dump(obj_from_stream, stream_obj_from_string, Dumper=AnsibleDumper) + else: + yaml.dump(obj_from_stream, stream_obj_from_stream, Dumper=AnsibleDumper, encoding=None) + yaml.dump(obj_from_stream, stream_obj_from_string, Dumper=AnsibleDumper, encoding=None) + + yaml_string_stream_obj_from_stream = stream_obj_from_stream.getvalue() + yaml_string_stream_obj_from_string = stream_obj_from_string.getvalue() + + stream_obj_from_stream.seek(0) + stream_obj_from_string.seek(0) + + if PY3: + yaml_string_obj_from_stream = yaml.dump(obj_from_stream, Dumper=AnsibleDumper) + yaml_string_obj_from_string = yaml.dump(obj_from_string, Dumper=AnsibleDumper) + else: + yaml_string_obj_from_stream = yaml.dump(obj_from_stream, Dumper=AnsibleDumper, encoding=None) + yaml_string_obj_from_string = yaml.dump(obj_from_string, Dumper=AnsibleDumper, encoding=None) + + assert yaml_string == yaml_string_obj_from_stream + assert yaml_string == yaml_string_obj_from_stream == yaml_string_obj_from_string + assert (yaml_string == yaml_string_obj_from_stream == yaml_string_obj_from_string == yaml_string_stream_obj_from_stream == + yaml_string_stream_obj_from_string) + assert obj == obj_from_stream + assert obj == obj_from_string + assert obj == yaml_string_obj_from_stream + assert obj == yaml_string_obj_from_string + assert obj == obj_from_stream == obj_from_string == yaml_string_obj_from_stream == yaml_string_obj_from_string + return {'obj': obj, + 'yaml_string': yaml_string, + 'yaml_string_from_stream': yaml_string_from_stream, + 'obj_from_stream': obj_from_stream, + 'obj_from_string': obj_from_string, + 'yaml_string_obj_from_string': yaml_string_obj_from_string} diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/modules/messaging/rabbitmq/__init__.py b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/modules/messaging/rabbitmq/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/modules/messaging/rabbitmq/__init__.py diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/modules/messaging/rabbitmq/rabbitmq_user_fixtures.py b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/modules/messaging/rabbitmq/rabbitmq_user_fixtures.py new file mode 100644 index 00000000..c2b8925a --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/modules/messaging/rabbitmq/rabbitmq_user_fixtures.py @@ -0,0 +1,181 @@ +rabbitmq_3_6_status = ''' +Status of node rabbit@vagrant +[{pid,5519}, + {running_applications, + [{rabbit,"RabbitMQ","version_num"}, + {mnesia,"MNESIA CXC 138 12","4.15.3"}, + {ranch,"Socket acceptor pool for TCP protocols.","1.3.0"}, + {ssl,"Erlang/OTP SSL application","8.2.3"}, + {public_key,"Public key infrastructure","1.5.2"}, + {asn1,"The Erlang ASN1 compiler version 5.0.4","5.0.4"}, + {rabbit_common, + "Modules shared by rabbitmq-server and rabbitmq-erlang-client", + "3.6.10"}, + {xmerl,"XML parser","1.3.16"}, + {crypto,"CRYPTO","4.2"}, + {compiler,"ERTS CXC 138 10","7.1.4"}, + {os_mon,"CPO CXC 138 46","2.4.4"}, + {syntax_tools,"Syntax tools","2.1.4"}, + {sasl,"SASL CXC 138 11","3.1.1"}, + {stdlib,"ERTS CXC 138 10","3.4.3"}, + {kernel,"ERTS CXC 138 10","5.4.1"}]}, + {os,{unix,linux}}, + {erlang_version, + "Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:64] [kernel-poll:true]\n"}, + {memory, + [{total,49712064}, + {connection_readers,0}, + {connection_writers,0}, + {connection_channels,0}, + {connection_other,0}, + {queue_procs,2744}, + {queue_slave_procs,0}, + {plugins,0}, + {other_proc,17493000}, + {mnesia,65128}, + {metrics,184272}, + {mgmt_db,0}, + {msg_index,41832}, + {other_ets,1766176}, + {binary,43576}, + {code,21390833}, + {atom,891849}, + {other_system,8014118}]}, + {alarms,[]}, + {listeners,[{clustering,25672,"::"},{amqp,5672,"::"}]}, + {vm_memory_high_watermark,0.4}, + {vm_memory_limit,413340467}, + {disk_free_limit,50000000}, + {disk_free,61216505856}, + {file_descriptors, + [{total_limit,65436}, + {total_used,2}, + {sockets_limit,58890}, + {sockets_used,0}]}, + {processes,[{limit,1048576},{used,153}]}, + {run_queue,0}, + {uptime,1795}, + {kernel,{net_ticktime,60}}] +root@vagrant:/home/vagrant# rabbitmqctl -q status +[{pid,5519}, + {running_applications, + [{rabbit,"RabbitMQ","3.6.10"}, + {mnesia,"MNESIA CXC 138 12","4.15.3"}, + {ranch,"Socket acceptor pool for TCP protocols.","1.3.0"}, + {ssl,"Erlang/OTP SSL application","8.2.3"}, + {public_key,"Public key infrastructure","1.5.2"}, + {asn1,"The Erlang ASN1 compiler version 5.0.4","5.0.4"}, + {rabbit_common, + "Modules shared by rabbitmq-server and rabbitmq-erlang-client", + "3.6.10"}, + {xmerl,"XML parser","1.3.16"}, + {crypto,"CRYPTO","4.2"}, + {compiler,"ERTS CXC 138 10","7.1.4"}, + {os_mon,"CPO CXC 138 46","2.4.4"}, + {syntax_tools,"Syntax tools","2.1.4"}, + {sasl,"SASL CXC 138 11","3.1.1"}, + {stdlib,"ERTS CXC 138 10","3.4.3"}, + {kernel,"ERTS CXC 138 10","5.4.1"}]}, + {os,{unix,linux}}, + {erlang_version, + "Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:64] [kernel-poll:true]\n"}, + {memory, + [{total,49770912}, + {connection_readers,0}, + {connection_writers,0}, + {connection_channels,0}, + {connection_other,0}, + {queue_procs,2744}, + {queue_slave_procs,0}, + {plugins,0}, + {other_proc,17554528}, + {mnesia,65128}, + {metrics,184272}, + {mgmt_db,0}, + {msg_index,41832}, + {other_ets,1766176}, + {binary,42816}, + {code,21390833}, + {atom,891849}, + {other_system,8012198}]}, + {alarms,[]}, + {listeners,[{clustering,25672,"::"},{amqp,5672,"::"}]}, + {vm_memory_high_watermark,0.4}, + {vm_memory_limit,413340467}, + {disk_free_limit,50000000}, + {disk_free,61216497664}, + {file_descriptors, + [{total_limit,65436}, + {total_used,2}, + {sockets_limit,58890}, + {sockets_used,0}]}, + {processes,[{limit,1048576},{used,153}]}, + {run_queue,0}, + {uptime,17139}, + {kernel,{net_ticktime,60}}]''' + +rabbitmq_3_7_status = \ + '{"pid":31701,"running_applications":[' \ + '["rabbit",[82,97,98,98,105,116,77,81],version_num],' \ + '["rabbit_common",[77,111,100,117,108,101,115,32,115,104,97,114,101,100,32,98,121,32,114,97,98,98,105,116,109,' \ + '113,45,115,101,114,118,101,114,32,97,110,100,32,114,97,98,98,105,116,109,113,45,101,114,108,97,110,103,45,99,' \ + '108,105,101,110,116],[51,46,55,46,54]],' \ + '["ranch_proxy_protocol",[82,97,110,99,104,32,80,114,111,120,121,32,80,114,111,116,111,99,111,108,32,84,114,97,' \ + '110,115,112,111,114,116],[49,46,53,46,48]],' \ + '["ranch",[83,111,99,107,101,116,32,97,99,99,101,112,116,111,114,32,112,111,111,108,32,102,111,114,32,84,67,80,' \ + '32,112,114,111,116,111,99,111,108,115,46],[49,46,53,46,48]],["ssl",[69,114,108,97,110,103,47,79,84,80,32,83,83,' \ + '76,32,97,112,112,108,105,99,97,116,105,111,110],[56,46,50,46,51]],' \ + '["public_key",[80,117,98,108,105,99,32,107,101,121,32,105,110,102,114,97,115,116,114,117,99,116,117,114,101],' \ + '[49,46,53,46,50]],' \ + '["asn1",[84,104,101,32,69,114,108,97,110,103,32,65,83,78,49,32,99,111,109,112,105,108,101,114,32,118,101,114,' \ + '115,105,111,110,32,53,46,48,46,52],[53,46,48,46,52]],' \ + '["crypto",[67,82,89,80,84,79],[52,46,50]],["xmerl",[88,77,76,32,112,97,114,115,101,114],[49,46,51,46,49,54]],' \ + '["recon",[68,105,97,103,110,111,115,116,105,99,32,116,111,111,108,115,32,102,111,114,32,112,114,111,100,117,99,' \ + '116,105,111,110,32,117,115,101],[50,46,51,46,50]],' \ + '["inets",[73,78,69,84,83,32,32,67,88,67,32,49,51,56,32,52,57],[54,46,52,46,53]],' \ + '["jsx",[97,32,115,116,114,101,97,109,105,110,103,44,32,101,118,101,110,116,101,100,32,106,115,111,110,32,112,97,' \ + '114,115,105,110,103,32,116,111,111,108,107,105,116],[50,46,56,46,50]],["os_mon",[67,80,79,32,32,67,88,67,32,49,' \ + '51,56,32,52,54],[50,46,52,46,52]],' \ + '["mnesia",[77,78,69,83,73,65,32,32,67,88,67,32,49,51,56,32,49,50],[52,46,49,53,46,51]],' \ + '["lager",[69,114,108,97,110,103,32,108,111,103,103,105,110,103,32,102,114,97,109,101,119,111,114,107],' \ + '[51,46,53,46,49]],' \ + '["goldrush",[69,114,108,97,110,103,32,101,118,101,110,116,32,115,116,114,101,97,109,32,112,114,111,99,101,115,' \ + '115,111,114],[48,46,49,46,57]],["compiler",[69,82,84,83,32,32,67,88,67,32,49,51,56,32,49,48],[55,46,49,46,52]],' \ + '["syntax_tools",[83,121,110,116,97,120,32,116,111,111,108,115],[50,46,49,46,52]],' \ + '["syslog",[65,110,32,82,70,67,32,51,49,54,52,32,97,110,100,32,82,70,67,32,53,52,50,52,32,99,111,109,112,108,' \ + '105,97,110,116,32,108,111,103,103,105,110,103,32,102,114,97,109,101,119,111,114,107,46],[51,46,52,46,50]],' \ + '["sasl",[83,65,83,76,32,32,67,88,67,32,49,51,56,32,49,49],[51,46,49,46,49]],' \ + '["stdlib",[69,82,84,83,32,32,67,88,67,32,49,51,56,32,49,48],[51,46,52,46,51]],' \ + '["kernel",[69,82,84,83,32,32,67,88,67,32,49,51,56,32,49,48],[53,46,52,46,49]]],' \ + '"os":["unix","linux"],"erlang_version":[69,114,108,97,110,103,47,79,84,80,32,50,48,32,91,101,114,116,115,45,57,' \ + '46,50,93,32,91,115,111,117,114,99,101,93,32,91,54,52,45,98,105,116,93,32,91,115,109,112,58,49,58,49,93,32,91,' \ + '100,115,58,49,58,49,58,49,48,93,32,91,97,115,121,110,99,45,116,104,114,101,97,100,115,58,54,52,93,32,91,107,' \ + '101,114,110,101,108,45,112,111,108,108,58,116,114,117,101,93,10],' \ + '"memory":{"connection_readers":0,"connection_writers":0,"connection_channels":0,' \ + '"connection_other":0,"queue_procs":0,"queue_slave_procs":0,"plugins":5736,"other_proc":23159832,' \ + '"metrics":184608,"mgmt_db":0,"mnesia":76896,"other_ets":1882856,"binary":64120,"msg_index":57184,' \ + '"code":24981937,"atom":1041593,"other_system":8993494,"allocated_unused":13066752,"reserved_unallocated":0,' \ + '"strategy":"rss","total":{"erlang":60448256,"rss":72720384,"allocated":73515008}},"alarms":[],' \ + '"listeners":[["clustering",25672,[58,58]],["amqp",5672,[58,58]]],"vm_memory_calculation_strategy":"rss",' \ + '"vm_memory_high_watermark":0.4,"vm_memory_limit":413340467,"disk_free_limit":50000000,"disk_free":61108576256,' \ + '"file_descriptors":{"total_limit":924,"total_used":4,"sockets_limit":829,"sockets_used":0},' \ + '"processes":{"limit":1048576,"used":214},"run_queue":0,"uptime":173,"kernel":["net_ticktime",60]}' + +rabbitmq_3_8_status = \ + '{"active_plugins":[],"alarms":[],"config_files":[],"data_directory":"/var/lib/rabbitmq/mnesia/rabbit@vagrant",' \ + '"disk_free":60898615296,"disk_free_limit":50000000,"enabled_plugin_file":"/etc/rabbitmq/enabled_plugins",' \ + '"erlang_version":"Erlang/OTP 21 [erts-10.3.5.8] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:64]",' \ + '"file_descriptors":{"sockets_limit":29399,"sockets_used":0,"total_limit":32668,"total_used":4},' \ + '"listeners":[{"interface":"[::]","node":"rabbit@vagrant","port":25672,"protocol":"clustering",' \ + '"purpose":"inter-node and CLI tool communication"},{"interface":"[::]","node":"rabbit@vagrant",' \ + '"port":5672,"protocol":"amqp","purpose":"AMQP 0-9-1 and AMQP 1.0"}],' \ + '"log_files":["/var/log/rabbitmq/rabbit@vagrant.log","/var/log/rabbitmq/rabbit@vagrant_upgrade.log"],' \ + '"memory":{"allocated_unused":14962432,"atom":1180881,"binary":82304,"code":26631176,"connection_channels":0,' \ + '"connection_other":0,"connection_readers":0,"connection_writers":0,"metrics":195308,"mgmt_db":0,"mnesia":76896,' \ + '"msg_index":57088,"other_ets":2666736,"other_proc":25333896,"other_system":10068879,"plugins":11732,' \ + '"queue_procs":0,"queue_slave_procs":0,"quorum_ets":42368,"quorum_queue_procs":0,"reserved_unallocated":0,' \ + '"strategy":"rss","total":{"erlang":66347264,"rss":80506880,"allocated":81309696}},"net_ticktime":60,' \ + '"os":"Linux","pid":9829,"processes":{"limit":1048576,"used":259},"rabbitmq_version":"version_num","run_queue":1,' \ + '"totals":{"virtual_host_count":2,"connection_count":0,"queue_count":0},"uptime":66,' \ + '"vm_memory_calculation_strategy":"rss","vm_memory_high_watermark_limit":413340467,' \ + '"vm_memory_high_watermark_setting":{"relative":0.4}}' diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/modules/messaging/rabbitmq/test_rabbitmq_user.py b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/modules/messaging/rabbitmq/test_rabbitmq_user.py new file mode 100644 index 00000000..8cc529ed --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/modules/messaging/rabbitmq/test_rabbitmq_user.py @@ -0,0 +1,357 @@ +# -*- coding: utf-8 -*- + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import distutils.version + +from ansible_collections.community.rabbitmq.plugins.modules import rabbitmq_user +from ansible.module_utils import six +from itertools import chain + +if six.PY3: + from itertools import zip_longest +else: + from itertools import izip_longest as zip_longest + +from ansible_collections.community.rabbitmq.tests.unit.compat.mock import patch +from ansible_collections.community.rabbitmq.tests.unit.modules.utils import AnsibleExitJson, AnsibleFailJson, ModuleTestCase, set_module_args + +from ansible_collections.community.rabbitmq.tests.unit.modules.messaging.rabbitmq.rabbitmq_user_fixtures import ( + rabbitmq_3_6_status, + rabbitmq_3_7_status, + rabbitmq_3_8_status) + + +def flatten(args): + return list(chain(*args)) + + +def lists_equal(l1, l2): + return all(map(lambda t: t[0] == t[1], zip_longest(l1, l2))) + + +class TestRabbitMQUserModule(ModuleTestCase): + def setUp(self): + super(TestRabbitMQUserModule, self).setUp() + self.module = rabbitmq_user + + def tearDown(self): + super(TestRabbitMQUserModule, self).tearDown() + + def _assert(self, exc, attribute, expected_value, msg=''): + value = exc.message[attribute] if hasattr(exc, attribute) else exc.args[0][attribute] + assert value == expected_value, msg + + def test_without_required_parameters(self): + """Failure must occur when all parameters are missing.""" + with self.assertRaises(AnsibleFailJson): + set_module_args({}) + self.module.main() + + @patch('ansible.module_utils.basic.AnsibleModule.get_bin_path') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser._check_version') + def test_permissions_with_same_vhost(self, _check_version, get_bin_path): + set_module_args({ + 'user': 'someuser', + 'password': 'somepassword', + 'state': 'present', + 'permissions': [{'vhost': '/'}, {'vhost': '/'}], + }) + _check_version.return_value = distutils.version.StrictVersion('3.6.10') + get_bin_path.return_value = '/rabbitmqctl' + try: + self.module.main() + except AnsibleFailJson as e: + self._assert(e, 'failed', True) + self._assert(e, 'msg', "Error parsing vhost " + "permissions: You can't have two permission dicts for the same vhost") + + @patch('ansible.module_utils.basic.AnsibleModule.get_bin_path') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser.get') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser._check_version') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser.check_password') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser.has_tags_modifications') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser.has_permissions_modifications') + def test_password_changes_only_when_needed(self, + has_permissions_modifications, + has_tags_modifications, + check_password, + _check_version, + get, + get_bin_path): + set_module_args({ + 'user': 'someuser', + 'password': 'somepassword', + 'state': 'present', + 'update_password': 'always', + }) + get.return_value = True + _check_version.return_value = distutils.version.StrictVersion('3.6.10') + get_bin_path.return_value = '/rabbitmqctl' + check_password.return_value = True + has_tags_modifications.return_value = False + has_permissions_modifications.return_value = False + try: + self.module.main() + except AnsibleExitJson as e: + self._assert(e, 'changed', False) + self._assert(e, 'state', 'present') + + @patch('ansible.module_utils.basic.AnsibleModule.get_bin_path') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser._exec') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser._check_version') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser._get_permissions') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser.has_tags_modifications') + def test_same_permissions_not_changing(self, + has_tags_modifications, + _get_permissions, + _check_version, + _exec, + get_bin_path): + set_module_args({ + 'user': 'someuser', + 'password': 'somepassword', + 'state': 'present', + 'permissions': [{'vhost': '/', 'configure_priv': '.*', 'write_priv': '.*', 'read_priv': '.*'}], + }) + _get_permissions.return_value = {'/': {'read': '.*', 'write': '.*', 'configure': '.*', 'vhost': '/'}} + _exec.return_value = 'someuser\t[]' + _check_version.return_value = distutils.version.StrictVersion('3.6.10') + get_bin_path.return_value = '/rabbitmqctl' + has_tags_modifications.return_value = False + try: + self.module.main() + except AnsibleExitJson as e: + self._assert(e, 'changed', False) + self._assert(e, 'state', 'present') + + @patch('ansible.module_utils.basic.AnsibleModule') + def test_status_can_be_parsed(self, module): + """Test correct parsing of the output of the status command.""" + module.get_bin_path.return_value = '/rabbitmqctl' + module.check_mode = False + + versions = ['3.6.10', '3.6.16'] + for version_num in versions: + def side_effect(args): + assert '-q' in args + if '--formatter' in args: + return 64, '', '' + return 0, rabbitmq_3_6_status.replace('version_num', version_num), '' + + module.run_command.side_effect = side_effect + user_controller = rabbitmq_user.RabbitMqUser(module, 'someuser', 'somepassword', list(), list(), 'rabbit') + self.assertEqual(len(module.run_command.call_args_list), 2) + last_call_args = flatten(module.run_command.call_args_list[-1][0]) + self.assertTrue('-q' in last_call_args) + self.assertTrue('--formatter' not in last_call_args) + self.assertEqual(user_controller._version, distutils.version.StrictVersion(version_num)) + module.run_command.reset_mock() + + versions = ['3.7.6', '3.7.7', '3.7.8', '3.7.9', '3.7.10', '3.7.11', '3.7.12', '3.7.13', '3.7.14', '3.7.15', + '3.7.16', '3.7.17', '3.7.18', '3.7.19', '3.7.20', '3.7.21', '3.7.22', '3.7.23'] + for version_num in versions: + def side_effect(args): + self.assertTrue('-q' in args) + self.assertTrue('--formatter' in args) + self.assertTrue('json' in args) + return 0, rabbitmq_3_7_status.replace('version_num', str([ord(c) for c in version_num])), '' + + module.run_command.side_effect = side_effect + user_controller = rabbitmq_user.RabbitMqUser(module, 'someuser', 'somepassword', list(), list(), 'rabbit') + self.assertEqual(1, module.run_command.call_count) + self.assertEqual(user_controller._version, distutils.version.StrictVersion(version_num)) + module.run_command.reset_mock() + + versions = ['3.8.0', '3.8.1', '3.8.2'] + for version_num in versions: + def side_effect(args): + self.assertTrue('-q' in args) + self.assertTrue('--formatter' in args) + self.assertTrue('json' in args) + return 0, rabbitmq_3_8_status.replace('version_num', version_num), '' + + module.run_command.side_effect = side_effect + user_controller = rabbitmq_user.RabbitMqUser(module, 'someuser', 'somepassword', list(), list(), 'rabbit') + self.assertEqual(1, module.run_command.call_count) + self.assertEqual(user_controller._version, distutils.version.StrictVersion(version_num)) + module.run_command.reset_mock() + + @patch('ansible.module_utils.basic.AnsibleModule.get_bin_path') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser._exec') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser._check_version') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser._get_permissions') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser.has_tags_modifications') + def test_permissions_are_fixed(self, + has_tags_modifications, + _get_permissions, + _check_version, + _exec, + get_bin_path): + """Test changes in permissions are fixed. + + Ensure that permissions that do not need to be changed are not, permissions with differences are + fixed and permissions are cleared when needed, with the minimum number of operations. The + permissions are fed into the module using the pre-3.7 version format. + """ + set_module_args({ + 'user': 'someuser', + 'password': 'somepassword', + 'state': 'present', + 'permissions': [ + {'vhost': '/', 'configure_priv': '.*', 'write_priv': '.*', 'read_priv': '.*'}, + {'vhost': '/ok', 'configure': '^$', 'write': '^$', 'read': '^$'} + ], + }) + get_bin_path.return_value = '/rabbitmqctl' + has_tags_modifications.return_value = False + _check_version.return_value = distutils.version.StrictVersion('3.6.10') + _get_permissions.return_value = { + '/wrong_vhost': {'vhost': '/wrong_vhost', 'configure': '', 'write': '', 'read': ''}, + '/ok': {'vhost': '/ok', 'configure': '^$', 'write': '^$', 'read': '^$'} + } + + def side_effect(args): + if 'list_users' in args: + self.assertTrue('--formatter' not in args) + self.assertTrue('json' not in args) + return 'someuser\t[administrator, management]' + if 'clear_permissions' in args: + self.assertTrue('someuser' in args) + self.assertTrue('/wrong_vhost' in args) + return '' + if 'set_permissions' in args: + self.assertTrue('someuser' in args) + self.assertTrue('/' in args) + self.assertTrue(['.*', '.*', '.*'] == args[-3:]) + return '' + _exec.side_effect = side_effect + + try: + self.module.main() + except AnsibleExitJson as e: + self._assert(e, 'changed', True) + self._assert(e, 'state', 'present') + self.assertEqual(_exec.call_count, 3) + self.assertTrue(['clear_permissions', '-p', '/wrong_vhost', 'someuser'] == + flatten(_exec.call_args_list[-2][0])) + self.assertTrue(['set_permissions', '-p', '/', 'someuser', '.*', '.*', '.*'] == + flatten(_exec.call_args_list[-1][0])) + + @patch('ansible.module_utils.basic.AnsibleModule.get_bin_path') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser._exec') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser._check_version') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser._get_permissions') + def test_tags_are_fixed(self, _get_permissions, _check_version, _exec, get_bin_path): + """Test user tags are fixed.""" + set_module_args({ + 'user': 'someuser', + 'password': 'somepassword', + 'state': 'present', + 'tags': 'tag1,tags2', + }) + get_bin_path.return_value = '/rabbitmqctl' + _check_version.return_value = distutils.version.StrictVersion('3.6.10') + _get_permissions.return_value = {'/': {'vhost': '/', 'configure': '^$', 'write': '^$', 'read': '^$'}} + + def side_effect(args): + if 'list_users' in args: + self.assertTrue('--formatter' not in args) + self.assertTrue('json' not in args) + return 'someuser\t[tag1, tag3]' + return '' + _exec.side_effect = side_effect + + try: + self.module.main() + except AnsibleExitJson as e: + self._assert(e, 'changed', True) + self._assert(e, 'state', 'present') + self.assertEqual(_exec.call_count, 2) + self.assertTrue(lists_equal(['set_user_tags', 'someuser', 'tag1', 'tags2'], + flatten(_exec.call_args_list[-1][0]))) + + @patch('ansible.module_utils.basic.AnsibleModule') + def test_user_json_data_can_be_parsed(self, module): + """Ensure that user json data can be parsed. + + From version 3.7 onwards `rabbitmqctl` can output the user data in proper json format. Check that parsing + works correctly. + """ + + def side_effect(args): + self.assertTrue('-q' in args) + self.assertTrue('--formatter' in args) + self.assertTrue('json' in args) + if 'status' in args: + return 0, rabbitmq_3_8_status.replace('version_num', '3.8.1'), '' + if 'list_users' in args: + return 0, '''[ +{"user":"someuser","tags":["administrator","management"]} +]''', '' + if 'list_user_permissions' in args: + return 0, '''[ +{"vhost":"/test","configure":"^$","write":"^$","read":"^$"} +,{"vhost":"/","configure":"^$","write":"^$","read":"^$"} +]''', '' + return 100, '', '' + + module.run_command.side_effect = side_effect + user_controller = rabbitmq_user.RabbitMqUser( + module, 'someuser', 'somepassword', list(), + [{'vhost': '/', 'configure': '^$', 'write': '^$', 'read': '^$'}], 'rabbit', + bulk_permissions=True) + self.assertTrue(user_controller.get()) + self.assertTrue(user_controller._version, distutils.version.StrictVersion('3.8.1')) + self.assertTrue(user_controller.existing_tags, ["administrator", "management"]) + self.assertTrue(user_controller.existing_permissions == { + '/test': {'vhost': '/test', 'configure': '^$', 'write': '^$', 'read': '^$'}, + '/': {'vhost': '/', 'configure': '^$', 'write': '^$', 'read': '^$'}}) + self.assertEqual(module.run_command.call_count, 3) + + @patch('ansible.module_utils.basic.AnsibleModule') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser._exec') + @patch('ansible_collections.community.rabbitmq.plugins.modules.rabbitmq_user.RabbitMqUser._check_version') + def test_non_bulk_permissions_are_parsed_and_set(self, _check_version, _exec, module): + """Test that non bulk permissions are parsed correctly. + + Non-bulk permissions mean that only the permissions of the VHost specified will be changed if needed. + If the same user has permissions in other VHosts, these will not be modified. + """ + module.get_bin_path.return_value = '/rabbitmqctl' + module.check_mode = False + _check_version.return_value = distutils.version.StrictVersion('3.8.0') + + def side_effect(args): + self.assertTrue('--formatter' in args, args) + self.assertTrue('json' in args, args) + if 'list_users' in args: + return '''[ +{"user":"someuser","tags":["administrator","management"]} +]''' + if 'list_user_permissions' in args: + self.assertTrue('someuser' in args, args) + return '''[ +{"vhost":"/test","configure":"^$","write":"^$","read":"^$"} +,{"vhost":"/","configure":"^$","write":"^$","read":"^$"} +]''' + raise Exception('wrong command: ' + str(args)) + + _exec.side_effect = side_effect + user_controller = rabbitmq_user.RabbitMqUser( + module, 'someuser', 'somepassword', list(), [{ + 'vhost': '/', + 'configure_priv': '.*', + 'write_priv': '.*', + 'read_priv': '.*' + }], 'rabbit' + ) + user_controller.get() + + self.assertEqual(_exec.call_count, 2) + self.assertListEqual(list(user_controller.existing_permissions.keys()), ['/']) + self.assertEqual(user_controller.existing_permissions['/']['write'], '^$') + self.assertEqual(user_controller.existing_permissions['/']['read'], '^$') + self.assertEqual(user_controller.existing_permissions['/']['configure'], '^$') + self.assertTrue(user_controller.has_permissions_modifications()) diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/modules/utils.py b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/modules/utils.py new file mode 100644 index 00000000..6261a177 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/unit/modules/utils.py @@ -0,0 +1,50 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import json + +from ansible_collections.community.rabbitmq.tests.unit.compat import unittest +from ansible_collections.community.rabbitmq.tests.unit.compat.mock import patch +from ansible.module_utils import basic +from ansible.module_utils._text import to_bytes + + +def set_module_args(args): + if '_ansible_remote_tmp' not in args: + args['_ansible_remote_tmp'] = '/tmp' + if '_ansible_keep_remote_files' not in args: + args['_ansible_keep_remote_files'] = False + + args = json.dumps({'ANSIBLE_MODULE_ARGS': args}) + basic._ANSIBLE_ARGS = to_bytes(args) + + +class AnsibleExitJson(Exception): + pass + + +class AnsibleFailJson(Exception): + pass + + +def exit_json(*args, **kwargs): + if 'changed' not in kwargs: + kwargs['changed'] = False + raise AnsibleExitJson(kwargs) + + +def fail_json(*args, **kwargs): + kwargs['failed'] = True + raise AnsibleFailJson(kwargs) + + +class ModuleTestCase(unittest.TestCase): + + def setUp(self): + self.mock_module = patch.multiple(basic.AnsibleModule, exit_json=exit_json, fail_json=fail_json) + self.mock_module.start() + self.mock_sleep = patch('time.sleep') + self.mock_sleep.start() + set_module_args({}) + self.addCleanup(self.mock_module.stop) + self.addCleanup(self.mock_sleep.stop) diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/check_matrix.py b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/check_matrix.py new file mode 100755 index 00000000..c9b0462f --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/check_matrix.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python +"""Verify the currently executing Shippable test matrix matches the one defined in the "shippable.yml" file.""" +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import datetime +import json +import os +import re +import sys +import time + +from ansible.module_utils.urls import open_url + +try: + from typing import NoReturn +except ImportError: + NoReturn = None + + +def main(): # type: () -> None + """Main entry point.""" + repo_full_name = os.environ['REPO_FULL_NAME'] + required_repo_full_name = 'ansible-collections/general' + + if repo_full_name != required_repo_full_name: + sys.stderr.write('Skipping matrix check on repo "%s" which is not "%s".\n' % (repo_full_name, required_repo_full_name)) + return + + with open('shippable.yml', 'rb') as yaml_file: + yaml = yaml_file.read().decode('utf-8').splitlines() + + defined_matrix = [match.group(1) for match in [re.search(r'^ *- env: T=(.*)$', line) for line in yaml] if match and match.group(1) != 'none'] + + if not defined_matrix: + fail('No matrix entries found in the "shippable.yml" file.', + 'Did you modify the "shippable.yml" file?') + + run_id = os.environ['SHIPPABLE_BUILD_ID'] + sleep = 1 + jobs = [] + + for attempts_remaining in range(4, -1, -1): + try: + jobs = json.loads(open_url('https://api.shippable.com/jobs?runIds=%s' % run_id).read()) + + if not isinstance(jobs, list): + raise Exception('Shippable run %s data is not a list.' % run_id) + + break + except Exception as ex: + if not attempts_remaining: + fail('Unable to retrieve Shippable run %s matrix.' % run_id, + str(ex)) + + sys.stderr.write('Unable to retrieve Shippable run %s matrix: %s\n' % (run_id, ex)) + sys.stderr.write('Trying again in %d seconds...\n' % sleep) + time.sleep(sleep) + sleep *= 2 + + if len(jobs) != len(defined_matrix): + if len(jobs) == 1: + hint = '\n\nMake sure you do not use the "Rebuild with SSH" option.' + else: + hint = '' + + fail('Shippable run %s has %d jobs instead of the expected %d jobs.' % (run_id, len(jobs), len(defined_matrix)), + 'Try re-running the entire matrix.%s' % hint) + + actual_matrix = dict((job.get('jobNumber'), dict(tuple(line.split('=', 1)) for line in job.get('env', [])).get('T', '')) for job in jobs) + errors = [(job_number, test, actual_matrix.get(job_number)) for job_number, test in enumerate(defined_matrix, 1) if actual_matrix.get(job_number) != test] + + if len(errors): + error_summary = '\n'.join('Job %s expected "%s" but found "%s" instead.' % (job_number, expected, actual) for job_number, expected, actual in errors) + + fail('Shippable run %s has a job matrix mismatch.' % run_id, + 'Try re-running the entire matrix.\n\n%s' % error_summary) + + +def fail(message, output): # type: (str, str) -> NoReturn + # Include a leading newline to improve readability on Shippable "Tests" tab. + # Without this, the first line becomes indented. + output = '\n' + output.strip() + + timestamp = datetime.datetime.utcnow().replace(microsecond=0).isoformat() + + # hack to avoid requiring junit-xml, which isn't pre-installed on Shippable outside our test containers + xml = ''' +<?xml version="1.0" encoding="utf-8"?> +<testsuites disabled="0" errors="1" failures="0" tests="1" time="0.0"> +\t<testsuite disabled="0" errors="1" failures="0" file="None" log="None" name="ansible-test" skipped="0" tests="1" time="0" timestamp="%s" url="None"> +\t\t<testcase classname="timeout" name="timeout"> +\t\t\t<error message="%s" type="error">%s</error> +\t\t</testcase> +\t</testsuite> +</testsuites> +''' % (timestamp, message, output) + + path = 'shippable/testresults/check-matrix.xml' + dir_path = os.path.dirname(path) + + if not os.path.exists(dir_path): + os.makedirs(dir_path) + + with open(path, 'w') as junit_fd: + junit_fd.write(xml.lstrip()) + + sys.stderr.write(message + '\n') + sys.stderr.write(output + '\n') + + sys.exit(1) + + +if __name__ == '__main__': + main() diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/cloud.sh b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/cloud.sh new file mode 100755 index 00000000..d76c3228 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/cloud.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set -o pipefail -eux + +declare -a args +IFS='/:' read -ra args <<< "$1" + +cloud="${args[0]}" +python="${args[1]}" +group="${args[2]}" + +target="shippable/${cloud}/group${group}/" + +stage="${S:-prod}" + +# shellcheck disable=SC2086 +ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \ + --remote-terminate always --remote-stage "${stage}" \ + --docker --python "${python}" diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/freebsd.sh b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/freebsd.sh new file mode 100755 index 00000000..cd3014cc --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/freebsd.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +set -o pipefail -eux + +declare -a args +IFS='/:' read -ra args <<< "$1" + +platform="${args[0]}" +version="${args[1]}" + +if [ "${#args[@]}" -gt 2 ]; then + target="shippable/posix/group${args[2]}/" +else + target="shippable/posix/" +fi + +stage="${S:-prod}" +provider="${P:-default}" + +# shellcheck disable=SC2086 +ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \ + --remote "${platform}/${version}" --remote-terminate always --remote-stage "${stage}" --remote-provider "${provider}" diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/linux.sh b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/linux.sh new file mode 100755 index 00000000..9cc2f966 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/linux.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +set -o pipefail -eux + +declare -a args +IFS='/:' read -ra args <<< "$1" + +image="${args[1]}" + +if [ "${#args[@]}" -gt 2 ]; then + target="shippable/posix/group${args[2]}/" +else + target="shippable/posix/" +fi + +# shellcheck disable=SC2086 +ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \ + --docker "${image}" diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/osx.sh b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/osx.sh new file mode 100755 index 00000000..cd3014cc --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/osx.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +set -o pipefail -eux + +declare -a args +IFS='/:' read -ra args <<< "$1" + +platform="${args[0]}" +version="${args[1]}" + +if [ "${#args[@]}" -gt 2 ]; then + target="shippable/posix/group${args[2]}/" +else + target="shippable/posix/" +fi + +stage="${S:-prod}" +provider="${P:-default}" + +# shellcheck disable=SC2086 +ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \ + --remote "${platform}/${version}" --remote-terminate always --remote-stage "${stage}" --remote-provider "${provider}" diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/remote.sh b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/remote.sh new file mode 100755 index 00000000..cd3014cc --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/remote.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +set -o pipefail -eux + +declare -a args +IFS='/:' read -ra args <<< "$1" + +platform="${args[0]}" +version="${args[1]}" + +if [ "${#args[@]}" -gt 2 ]; then + target="shippable/posix/group${args[2]}/" +else + target="shippable/posix/" +fi + +stage="${S:-prod}" +provider="${P:-default}" + +# shellcheck disable=SC2086 +ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \ + --remote "${platform}/${version}" --remote-terminate always --remote-stage "${stage}" --remote-provider "${provider}" diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/rhel.sh b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/rhel.sh new file mode 100755 index 00000000..cd3014cc --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/rhel.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +set -o pipefail -eux + +declare -a args +IFS='/:' read -ra args <<< "$1" + +platform="${args[0]}" +version="${args[1]}" + +if [ "${#args[@]}" -gt 2 ]; then + target="shippable/posix/group${args[2]}/" +else + target="shippable/posix/" +fi + +stage="${S:-prod}" +provider="${P:-default}" + +# shellcheck disable=SC2086 +ansible-test integration --color -v --retry-on-error "${target}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} ${UNSTABLE:+"$UNSTABLE"} \ + --remote "${platform}/${version}" --remote-terminate always --remote-stage "${stage}" --remote-provider "${provider}" diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/sanity.sh b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/sanity.sh new file mode 100755 index 00000000..0c54a42c --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/sanity.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -o pipefail -eux + +# shellcheck disable=SC2086 +ansible-test sanity --color -v --junit ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} \ + --docker \ diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/shippable.sh b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/shippable.sh new file mode 100755 index 00000000..3cc948d5 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/shippable.sh @@ -0,0 +1,133 @@ +#!/usr/bin/env bash + +### Environment variables + +ANSIBLE_VERSION="devel" +PYTHON_VERSION="3.7" + +### + +set -o pipefail -eux + +declare -a args +IFS='/:' read -ra args <<< "$1" + +script="${args[0]}" + +test="$1" + +docker images ansible/ansible +docker images quay.io/ansible/* +docker ps + +for container in $(docker ps --format '{{.Image}} {{.ID}}' | grep -v '^drydock/' | sed 's/^.* //'); do + docker rm -f "${container}" || true # ignore errors +done + +docker ps + +if [ -d /home/shippable/cache/ ]; then + ls -la /home/shippable/cache/ +fi + +command -v python +python -V + +command -v pip +pip --version +pip list --disable-pip-version-check + +export PATH="${PWD}/bin:${PATH}" +export PYTHONIOENCODING='utf-8' + +if [ "${JOB_TRIGGERED_BY_NAME:-}" == "nightly-trigger" ]; then + COVERAGE=yes + COMPLETE=yes +fi + +if [ -n "${COVERAGE:-}" ]; then + # on-demand coverage reporting triggered by setting the COVERAGE environment variable to a non-empty value + export COVERAGE="--coverage" +elif [[ "${COMMIT_MESSAGE}" =~ ci_coverage ]]; then + # on-demand coverage reporting triggered by having 'ci_coverage' in the latest commit message + export COVERAGE="--coverage" +else + # on-demand coverage reporting disabled (default behavior, always-on coverage reporting remains enabled) + export COVERAGE="--coverage-check" +fi + +if [ -n "${COMPLETE:-}" ]; then + # disable change detection triggered by setting the COMPLETE environment variable to a non-empty value + export CHANGED="" +elif [[ "${COMMIT_MESSAGE}" =~ ci_complete ]]; then + # disable change detection triggered by having 'ci_complete' in the latest commit message + export CHANGED="" +else + # enable change detection (default behavior) + export CHANGED="--changed" +fi + +if [ "${IS_PULL_REQUEST:-}" == "true" ]; then + # run unstable tests which are targeted by focused changes on PRs + export UNSTABLE="--allow-unstable-changed" +else + # do not run unstable tests outside PRs + export UNSTABLE="" +fi + +virtualenv --python /usr/bin/python${PYTHON_VERSION} ~/ansible-venv +set +ux +. ~/ansible-venv/bin/activate +set -ux + +# Install Ansible +pip install https://github.com/ansible/ansible/archive/${ANSIBLE_VERSION}.tar.gz --disable-pip-version-check + +COLLECTION_DIR="${HOME}/.ansible/ansible_collections/" +TEST_DIR="${COLLECTION_DIR}/community/rabbitmq" +mkdir -p "${TEST_DIR}" +cp -aT "${SHIPPABLE_BUILD_DIR}" "${TEST_DIR}" +cd "${TEST_DIR}" + +function cleanup +{ + if [ -d tests/output/coverage/ ]; then + if find tests/output/coverage/ -mindepth 1 -name '.*' -prune -o -print -quit | grep -q .; then + # for complete on-demand coverage generate a report for all files with no coverage on the "other" job so we only have one copy + if [ "${COVERAGE}" == "--coverage" ] && [ "${CHANGED}" == "" ] && [ "${test}" == "sanity/1" ]; then + stub="--stub" + else + stub="" + fi + + # shellcheck disable=SC2086 + ansible-test coverage xml --color -v --requirements --group-by command --group-by version ${stub:+"$stub"} + cp -a tests/output/reports/coverage=*.xml shippable/codecoverage/ + fi + fi + + if [ -d tests/output/junit/ ]; then + cp -aT tests/output/junit/ shippable/testresults/ + fi + + if [ -d tests/output/data/ ]; then + cp -a tests/output/data/ shippable/testresults/ + fi + + if [ -d tests/output/bot/ ]; then + cp -aT tests/output/bot/ shippable/testresults/ + fi +} + +trap cleanup EXIT + +if [[ "${COVERAGE:-}" == "--coverage" ]]; then + timeout=60 +else + timeout=45 +fi + +ansible-test env --dump --show --timeout "${timeout}" --color -v + +"tests/utils/shippable/check_matrix.py" +"tests/utils/shippable/${script}.sh" "${test}" diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/timing.py b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/timing.py new file mode 100755 index 00000000..fb538271 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/timing.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3.7 +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import sys +import time + +start = time.time() + +sys.stdin.reconfigure(errors='surrogateescape') +sys.stdout.reconfigure(errors='surrogateescape') + +for line in sys.stdin: + seconds = time.time() - start + sys.stdout.write('%02d:%02d %s' % (seconds // 60, seconds % 60, line)) + sys.stdout.flush() diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/timing.sh b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/timing.sh new file mode 100755 index 00000000..77e25783 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/timing.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -o pipefail -eu + +"$@" 2>&1 | "$(dirname "$0")/timing.py" diff --git a/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/units.sh b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/units.sh new file mode 100755 index 00000000..e2ff963f --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/rabbitmq/tests/utils/shippable/units.sh @@ -0,0 +1,110 @@ +#!/usr/bin/env bash + +set -o pipefail -eux + +declare -a args +IFS='/:' read -ra args <<< "$1" + +version="${args[1]}" +group="${args[2]}" + +if [[ "${COVERAGE:-}" == "--coverage" ]]; then + timeout=90 +else + timeout=30 +fi + +group1=() +group2=() +group3=() + +# create three groups by putting network tests into separate groups +# add or remove network platforms as needed to balance the groups + +networks2=( + aireos + apconos + aruba + asa + avi + check_point + cloudengine + cloudvision + cnos + cumulus + dellos10 + dellos6 + dellos9 + edgeos + edgeswitch + enos + eos + eric_eccli + exos + f5 + fortimanager + frr + ftd + icx + ingate + ios + iosxr + ironware + itential + junos + netact + netscaler + netvisor + nos + nso + nuage + nxos + onyx + opx + ovs + radware + routeros + slxos + voss + vyos +) + +networks3=( + fortios +) + +for network in "${networks2[@]}"; do + test_path="test/units/modules/network/${network}/" + + if [ -d "${test_path}" ]; then + group1+=(--exclude "${test_path}") + group2+=("${test_path}") + fi +done + +for network in "${networks3[@]}"; do + test_path="test/units/modules/network/${network}/" + + if [ -d "${test_path}" ]; then + group1+=(--exclude "${test_path}") + group3+=("${test_path}") + fi +done + +case "${group}" in + 1) options=("${group1[@]:+${group1[@]}}") ;; + 2) options=("${group2[@]:+${group2[@]}}") ;; + 3) options=("${group3[@]:+${group3[@]}}") ;; +esac + +if [ ${#options[@]} -eq 0 ] && [ "${group}" -gt 1 ]; then + # allow collection migration unit tests for groups other than 1 to "pass" without updating shippable.yml or this script during migration + echo "No unit tests found for group ${group}." + exit +fi + +ansible-test env --timeout "${timeout}" --color -v + +# shellcheck disable=SC2086 +ansible-test units --color -v --docker default --python "${version}" ${COVERAGE:+"$COVERAGE"} ${CHANGED:+"$CHANGED"} \ + "${options[@]:+${options[@]}}" \ |