From e594aeca783cc324a156b8f95640b79c8494282d Mon Sep 17 00:00:00 2001 From: David Horsman Date: Tue, 9 Mar 2021 16:31:23 +0000 Subject: [PATCH] feat(core): make cloudwatch agent install optional --- THIRD-PARTY | 619 +++++++++++++++++- .../python/package/config.py | 6 +- .../ts/bin/config.ts | 6 +- .../aws-rfdk/lib/core/lib/cloudwatch-agent.ts | 60 +- .../scripts/bash/configureCloudWatchAgent.sh | 88 ++- .../powershell/configureCloudWatchAgent.ps1 | 119 +++- .../aws-rfdk/lib/core/test/asset-constants.ts | 12 +- .../lib/core/test/cloudwatch-agent.test.ts | 72 +- .../lib/core/test/mongodb-instance.test.ts | 8 +- .../lib/core/test/script-assets.test.ts | 38 +- .../deadline/lib/spot-event-plugin-fleet.ts | 2 +- .../lib/deadline/lib/worker-configuration.ts | 30 +- .../aws-rfdk/lib/deadline/lib/worker-fleet.ts | 2 +- .../lib/deadline/test/asset-constants.ts | 513 ++++++++++++++- .../lib/deadline/test/repository.test.ts | 10 +- .../test/worker-configuration.test.ts | 54 +- .../lib/deadline/test/worker-fleet.test.ts | 4 +- 17 files changed, 1435 insertions(+), 208 deletions(-) diff --git a/THIRD-PARTY b/THIRD-PARTY index 38c4ddd41..858eec52d 100644 --- a/THIRD-PARTY +++ b/THIRD-PARTY @@ -1,6 +1,7 @@ ** aws-cdk -- https://github.com/aws/aws-cdk ** jsii -- https://github.com/aws/jsii -** MongoDB NodeJs Driver -- https://github.com/mongodb/node-mongodb-native +** MongoDB NodeJs Driver -- +https://github.com/mongodb/node-mongodb-native Apache License @@ -213,8 +214,622 @@ limitations under the License. ------ +** GnuPG; version 2.2.27 -- https://gnupg.org/ +Copyright (C) 1997-2019 Werner Koch +Copyright (C) 1994-2021 Free Software Foundation, Inc. +Copyright (C) 2003-2021 g10 Code GmbH +Copyright (C) 2002 Klarälvdalens Datakonsult AB +Copyright (C) 1995-1997, 2000-2007 Ulrich Drepper +Copyright (C) 1994 X Consortium +Copyright (C) 1998 by The Internet Society. +Copyright (C) 1998-2004 The OpenLDAP Foundation +Copyright (C) 1998-2004 Kurt D. Zeilenga. +Copyright (C) 1998-2004 Net Boolean Incorporated. +Copyright (C) 2001-2004 IBM Corporation. +Copyright (C) 1999-2003 Howard Y.H. Chu. +Copyright (C) 1999-2003 Symas Corporation. +Copyright (C) 1998-2003 Hallvard B. Furuseth. +Copyright (C) 1992-1996 Regents of the University of Michigan. +Copyright (C) 2000 Dimitrios Souflis +Copyright (C) 2008,2009,2010,2012-2016 William Ahern +Copyright (C) 2017 Bundesamt für Sicherheit in der Informationstechnik + + * Package GnuPG's source code may be found at: + https://amazon-source-code-downloads.s3.amazonaws.com/aws/thinkbox/gnupg/gnupg-2.2.27.tar.bz2 + +GNU GENERAL PUBLIC LICENSE +Version 3, 29 June 2007 + +Copyright © 2007 Free Software Foundation, Inc. + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + +Preamble +The GNU General Public License is a free, copyleft license for software and +other kinds of works. + +The licenses for most software and other practical works are designed to take +away your freedom to share and change the works. By contrast, the GNU General +Public License is intended to guarantee your freedom to share and change all +versions of a program--to make sure it remains free software for all its users. +We, the Free Software Foundation, use the GNU General Public License for most +of our software; it applies also to any other work released this way by its +authors. You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our +General Public Licenses are designed to make sure that you have the freedom to +distribute copies of free software (and charge for them if you wish), that you +receive source code or can get it if you want it, that you can change the +software or use pieces of it in new free programs, and that you know you can do +these things. + +To protect your rights, we need to prevent others from denying you these rights +or asking you to surrender the rights. Therefore, you have certain +responsibilities if you distribute copies of the software, or if you modify it: +responsibilities to respect the freedom of others. + +For example, if you distribute copies of such a program, whether gratis or for +a fee, you must pass on to the recipients the same freedoms that you received. +You must make sure that they, too, receive or can get the source code. And you +must show them these terms so they know their rights. + +Developers that use the GNU GPL protect your rights with two steps: (1) assert +copyright on the software, and (2) offer you this License giving you legal +permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains that +there is no warranty for this free software. For both users' and authors' sake, +the GPL requires that modified versions be marked as changed, so that their +problems will not be attributed erroneously to authors of previous versions. + +Some devices are designed to deny users access to install or run modified +versions of the software inside them, although the manufacturer can do so. This +is fundamentally incompatible with the aim of protecting users' freedom to +change the software. The systematic pattern of such abuse occurs in the area of +products for individuals to use, which is precisely where it is most +unacceptable. Therefore, we have designed this version of the GPL to prohibit +the practice for those products. If such problems arise substantially in other +domains, we stand ready to extend this provision to those domains in future +versions of the GPL, as needed to protect the freedom of users. + +Finally, every program is threatened constantly by software patents. States +should not allow patents to restrict development and use of software on +general-purpose computers, but in those that do, we wish to avoid the special +danger that patents applied to a free program could make it effectively +proprietary. To prevent this, the GPL assures that patents cannot be used to +render the program non-free. + +The precise terms and conditions for copying, distribution and modification +follow. + +TERMS AND CONDITIONS +0. Definitions. +“This License” refers to version 3 of the GNU General Public License. + +“Copyright” also means copyright-like laws that apply to other kinds of works, +such as semiconductor masks. + +“The Program” refers to any copyrightable work licensed under this License. +Each licensee is addressed as “you”. “Licensees” and “recipients” may be +individuals or organizations. + +To “modify” a work means to copy from or adapt all or part of the work in a +fashion requiring copyright permission, other than the making of an exact copy. +The resulting work is called a “modified version” of the earlier work or a work +“based on” the earlier work. + +A “covered work” means either the unmodified Program or a work based on the +Program. + +To “propagate” a work means to do anything with it that, without permission, +would make you directly or secondarily liable for infringement under applicable +copyright law, except executing it on a computer or modifying a private copy. +Propagation includes copying, distribution (with or without modification), +making available to the public, and in some countries other activities as well. + +To “convey” a work means any kind of propagation that enables other parties to +make or receive copies. Mere interaction with a user through a computer +network, with no transfer of a copy, is not conveying. + +An interactive user interface displays “Appropriate Legal Notices” to the +extent that it includes a convenient and prominently visible feature that (1) +displays an appropriate copyright notice, and (2) tells the user that there is +no warranty for the work (except to the extent that warranties are provided), +that licensees may convey the work under this License, and how to view a copy +of this License. If the interface presents a list of user commands or options, +such as a menu, a prominent item in the list meets this criterion. + +1. Source Code. +The “source code” for a work means the preferred form of the work for making +modifications to it. “Object code” means any non-source form of a work. + +A “Standard Interface” means an interface that either is an official standard +defined by a recognized standards body, or, in the case of interfaces specified +for a particular programming language, one that is widely used among developers +working in that language. + +The “System Libraries” of an executable work include anything, other than the +work as a whole, that (a) is included in the normal form of packaging a Major +Component, but which is not part of that Major Component, and (b) serves only +to enable use of the work with that Major Component, or to implement a Standard +Interface for which an implementation is available to the public in source code +form. A “Major Component”, in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system (if any) on +which the executable work runs, or a compiler used to produce the work, or an +object code interpreter used to run it. + +The “Corresponding Source” for a work in object code form means all the source +code needed to generate, install, and (for an executable work) run the object +code and to modify the work, including scripts to control those activities. +However, it does not include the work's System Libraries, or general-purpose +tools or generally available free programs which are used unmodified in +performing those activities but which are not part of the work. For example, +Corresponding Source includes interface definition files associated with source +files for the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, such as +by intimate data communication or control flow between those subprograms and +other parts of the work. + +The Corresponding Source need not include anything that users can regenerate +automatically from other parts of the Corresponding Source. + +The Corresponding Source for a work in source code form is that same work. + +2. Basic Permissions. +All rights granted under this License are granted for the term of copyright on +the Program, and are irrevocable provided the stated conditions are met. This +License explicitly affirms your unlimited permission to run the unmodified +Program. The output from running a covered work is covered by this License only +if the output, given its content, constitutes a covered work. This License +acknowledges your rights of fair use or other equivalent, as provided by +copyright law. + +You may make, run and propagate covered works that you do not convey, without +conditions so long as your license otherwise remains in force. You may convey +covered works to others for the sole purpose of having them make modifications +exclusively for you, or provide you with facilities for running those works, +provided that you comply with the terms of this License in conveying all +material for which you do not control copyright. Those thus making or running +the covered works for you must do so exclusively on your behalf, under your +direction and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the +conditions stated below. Sublicensing is not allowed; section 10 makes it +unnecessary. + +3. Protecting Users' Legal Rights From Anti-Circumvention Law. +No covered work shall be deemed part of an effective technological measure +under any applicable law fulfilling obligations under article 11 of the WIPO +copyright treaty adopted on 20 December 1996, or similar laws prohibiting or +restricting circumvention of such measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention is +effected by exercising rights under this License with respect to the covered +work, and you disclaim any intention to limit operation or modification of the +work as a means of enforcing, against the work's users, your or third parties' +legal rights to forbid circumvention of technological measures. + +4. Conveying Verbatim Copies. +You may convey verbatim copies of the Program's source code as you receive it, +in any medium, provided that you conspicuously and appropriately publish on +each copy an appropriate copyright notice; keep intact all notices stating that +this License and any non-permissive terms added in accord with section 7 apply +to the code; keep intact all notices of the absence of any warranty; and give +all recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, and you may +offer support or warranty protection for a fee. + +5. Conveying Modified Source Versions. +You may convey a work based on the Program, or the modifications to produce it +from the Program, in the form of source code under the terms of section 4, +provided that you also meet all of these conditions: + +a) The work must carry prominent notices stating that you modified it, and +giving a relevant date. +b) The work must carry prominent notices stating that it is released under this +License and any conditions added under section 7. This requirement modifies the +requirement in section 4 to “keep intact all notices”. +c) You must license the entire work, as a whole, under this License to anyone +who comes into possession of a copy. This License will therefore apply, along +with any applicable section 7 additional terms, to the whole of the work, and +all its parts, regardless of how they are packaged. This License gives no +permission to license the work in any other way, but it does not invalidate +such permission if you have separately received it. +d) If the work has interactive user interfaces, each must display Appropriate +Legal Notices; however, if the Program has interactive interfaces that do not +display Appropriate Legal Notices, your work need not make them do so. +A compilation of a covered work with other separate and independent works, +which are not by their nature extensions of the covered work, and which are not +combined with it such as to form a larger program, in or on a volume of a +storage or distribution medium, is called an “aggregate” if the compilation and +its resulting copyright are not used to limit the access or legal rights of the +compilation's users beyond what the individual works permit. Inclusion of a +covered work in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +6. Conveying Non-Source Forms. +You may convey a covered work in object code form under the terms of sections 4 +and 5, provided that you also convey the machine-readable Corresponding Source +under the terms of this License, in one of these ways: + +a) Convey the object code in, or embodied in, a physical product (including a +physical distribution medium), accompanied by the Corresponding Source fixed on +a durable physical medium customarily used for software interchange. +b) Convey the object code in, or embodied in, a physical product (including a +physical distribution medium), accompanied by a written offer, valid for at +least three years and valid for as long as you offer spare parts or customer +support for that product model, to give anyone who possesses the object code +either (1) a copy of the Corresponding Source for all the software in the +product that is covered by this License, on a durable physical medium +customarily used for software interchange, for a price no more than your +reasonable cost of physically performing this conveying of source, or (2) +access to copy the Corresponding Source from a network server at no charge. +c) Convey individual copies of the object code with a copy of the written offer +to provide the Corresponding Source. This alternative is allowed only +occasionally and noncommercially, and only if you received the object code with +such an offer, in accord with subsection 6b. +d) Convey the object code by offering access from a designated place (gratis or +for a charge), and offer equivalent access to the Corresponding Source in the +same way through the same place at no further charge. You need not require +recipients to copy the Corresponding Source along with the object code. If the +place to copy the object code is a network server, the Corresponding Source may +be on a different server (operated by you or a third party) that supports +equivalent copying facilities, provided you maintain clear directions next to +the object code saying where to find the Corresponding Source. Regardless of +what server hosts the Corresponding Source, you remain obligated to ensure that +it is available for as long as needed to satisfy these requirements. +e) Convey the object code using peer-to-peer transmission, provided you inform +other peers where the object code and Corresponding Source of the work are +being offered to the general public at no charge under subsection 6d. +A separable portion of the object code, whose source code is excluded from the +Corresponding Source as a System Library, need not be included in conveying the +object code work. + +A “User Product” is either (1) a “consumer product”, which means any tangible +personal property which is normally used for personal, family, or household +purposes, or (2) anything designed or sold for incorporation into a dwelling. +In determining whether a product is a consumer product, doubtful cases shall be +resolved in favor of coverage. For a particular product received by a +particular user, “normally used” refers to a typical or common use of that +class of product, regardless of the status of the particular user or of the way +in which the particular user actually uses, or expects or is expected to use, +the product. A product is a consumer product regardless of whether the product +has substantial commercial, industrial or non-consumer uses, unless such uses +represent the only significant mode of use of the product. + +“Installation Information” for a User Product means any methods, procedures, +authorization keys, or other information required to install and execute +modified versions of a covered work in that User Product from a modified +version of its Corresponding Source. The information must suffice to ensure +that the continued functioning of the modified object code is in no case +prevented or interfered with solely because modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as part of a +transaction in which the right of possession and use of the User Product is +transferred to the recipient in perpetuity or for a fixed term (regardless of +how the transaction is characterized), the Corresponding Source conveyed under +this section must be accompanied by the Installation Information. But this +requirement does not apply if neither you nor any third party retains the +ability to install modified object code on the User Product (for example, the +work has been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates for a +work that has been modified or installed by the recipient, or for the User +Product in which it has been modified or installed. Access to a network may be +denied when the modification itself materially and adversely affects the +operation of the network or violates the rules and protocols for communication +across the network. + +Corresponding Source conveyed, and Installation Information provided, in accord +with this section must be in a format that is publicly documented (and with an +implementation available to the public in source code form), and must require +no special password or key for unpacking, reading or copying. + +7. Additional Terms. +“Additional permissions” are terms that supplement the terms of this License by +making exceptions from one or more of its conditions. Additional permissions +that are applicable to the entire Program shall be treated as though they were +included in this License, to the extent that they are valid under applicable +law. If additional permissions apply only to part of the Program, that part may +be used separately under those permissions, but the entire Program remains +governed by this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option remove any +additional permissions from that copy, or from any part of it. (Additional +permissions may be written to require their own removal in certain cases when +you modify the work.) You may place additional permissions on material, added +by you to a covered work, for which you have or can give appropriate copyright +permission. + +Notwithstanding any other provision of this License, for material you add to a +covered work, you may (if authorized by the copyright holders of that material) +supplement the terms of this License with terms: + +a) Disclaiming warranty or limiting liability differently from the terms of +sections 15 and 16 of this License; or +b) Requiring preservation of specified reasonable legal notices or author +attributions in that material or in the Appropriate Legal Notices displayed by +works containing it; or +c) Prohibiting misrepresentation of the origin of that material, or requiring +that modified versions of such material be marked in reasonable ways as +different from the original version; or +d) Limiting the use for publicity purposes of names of licensors or authors of +the material; or +e) Declining to grant rights under trademark law for use of some trade names, +trademarks, or service marks; or +f) Requiring indemnification of licensors and authors of that material by +anyone who conveys the material (or modified versions of it) with contractual +assumptions of liability to the recipient, for any liability that these +contractual assumptions directly impose on those licensors and authors. +All other non-permissive additional terms are considered “further restrictions” +within the meaning of section 10. If the Program as you received it, or any +part of it, contains a notice stating that it is governed by this License along +with a term that is a further restriction, you may remove that term. If a +license document contains a further restriction but permits relicensing or +conveying under this License, you may add to a covered work material governed +by the terms of that license document, provided that the further restriction +does not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you must place, +in the relevant source files, a statement of the additional terms that apply to +those files, or a notice indicating where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the form of a +separately written license, or stated as exceptions; the above requirements +apply either way. + +8. Termination. +You may not propagate or modify a covered work except as expressly provided +under this License. Any attempt otherwise to propagate or modify it is void, +and will automatically terminate your rights under this License (including any +patent licenses granted under the third paragraph of section 11). + +However, if you cease all violation of this License, then your license from a +particular copyright holder is reinstated (a) provisionally, unless and until +the copyright holder explicitly and finally terminates your license, and (b) +permanently, if the copyright holder fails to notify you of the violation by +some reasonable means prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is reinstated +permanently if the copyright holder notifies you of the violation by some +reasonable means, this is the first time you have received notice of violation +of this License (for any work) from that copyright holder, and you cure the +violation prior to 30 days after your receipt of the notice. + +Termination of your rights under this section does not terminate the licenses +of parties who have received copies or rights from you under this License. If +your rights have been terminated and not permanently reinstated, you do not +qualify to receive new licenses for the same material under section 10. + +9. Acceptance Not Required for Having Copies. +You are not required to accept this License in order to receive or run a copy +of the Program. Ancillary propagation of a covered work occurring solely as a +consequence of using peer-to-peer transmission to receive a copy likewise does +not require acceptance. However, nothing other than this License grants you +permission to propagate or modify any covered work. These actions infringe +copyright if you do not accept this License. Therefore, by modifying or +propagating a covered work, you indicate your acceptance of this License to do +so. + +10. Automatic Licensing of Downstream Recipients. +Each time you convey a covered work, the recipient automatically receives a +license from the original licensors, to run, modify and propagate that work, +subject to this License. You are not responsible for enforcing compliance by +third parties with this License. + +An “entity transaction” is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered work +results from an entity transaction, each party to that transaction who receives +a copy of the work also receives whatever licenses to the work the party's +predecessor in interest had or could give under the previous paragraph, plus a +right to possession of the Corresponding Source of the work from the +predecessor in interest, if the predecessor has it or can get it with +reasonable efforts. + +You may not impose any further restrictions on the exercise of the rights +granted or affirmed under this License. For example, you may not impose a +license fee, royalty, or other charge for exercise of rights granted under this +License, and you may not initiate litigation (including a cross-claim or +counterclaim in a lawsuit) alleging that any patent claim is infringed by +making, using, selling, offering for sale, or importing the Program or any +portion of it. + +11. Patents. +A “contributor” is a copyright holder who authorizes use under this License of +the Program or a work on which the Program is based. The work thus licensed is +called the contributor's “contributor version”. + +A contributor's “essential patent claims” are all patent claims owned or +controlled by the contributor, whether already acquired or hereafter acquired, +that would be infringed by some manner, permitted by this License, of making, +using, or selling its contributor version, but do not include claims that would +be infringed only as a consequence of further modification of the contributor +version. For purposes of this definition, “control” includes the right to grant +patent sublicenses in a manner consistent with the requirements of this +License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free patent +license under the contributor's essential patent claims, to make, use, sell, +offer for sale, import and otherwise run, modify and propagate the contents of +its contributor version. + +In the following three paragraphs, a “patent license” is any express agreement +or commitment, however denominated, not to enforce a patent (such as an express +permission to practice a patent or covenant not to sue for patent +infringement). To “grant” such a patent license to a party means to make such +an agreement or commitment not to enforce a patent against the party. + +If you convey a covered work, knowingly relying on a patent license, and the +Corresponding Source of the work is not available for anyone to copy, free of +charge and under the terms of this License, through a publicly available +network server or other readily accessible means, then you must either (1) +cause the Corresponding Source to be so available, or (2) arrange to deprive +yourself of the benefit of the patent license for this particular work, or (3) +arrange, in a manner consistent with the requirements of this License, to +extend the patent license to downstream recipients. “Knowingly relying” means +you have actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work in a +country, would infringe one or more identifiable patents in that country that +you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or arrangement, you +convey, or propagate by procuring conveyance of, a covered work, and grant a +patent license to some of the parties receiving the covered work authorizing +them to use, propagate, modify or convey a specific copy of the covered work, +then the patent license you grant is automatically extended to all recipients +of the covered work and works based on it. + +A patent license is “discriminatory” if it does not include within the scope of +its coverage, prohibits the exercise of, or is conditioned on the non-exercise +of one or more of the rights that are specifically granted under this License. +You may not convey a covered work if you are a party to an arrangement with a +third party that is in the business of distributing software, under which you +make payment to the third party based on the extent of your activity of +conveying the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory patent +license (a) in connection with copies of the covered work conveyed by you (or +copies made from those copies), or (b) primarily for and in connection with +specific products or compilations that contain the covered work, unless you +entered into that arrangement, or that patent license was granted, prior to 28 +March 2007. + +Nothing in this License shall be construed as excluding or limiting any implied +license or other defenses to infringement that may otherwise be available to +you under applicable patent law. + +12. No Surrender of Others' Freedom. +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not excuse +you from the conditions of this License. If you cannot convey a covered work so +as to satisfy simultaneously your obligations under this License and any other +pertinent obligations, then as a consequence you may not convey it at all. For +example, if you agree to terms that obligate you to collect a royalty for +further conveying from those to whom you convey the Program, the only way you +could satisfy both those terms and this License would be to refrain entirely +from conveying the Program. + +13. Use with the GNU Affero General Public License. +Notwithstanding any other provision of this License, you have permission to +link or combine any covered work with a work licensed under version 3 of the +GNU Affero General Public License into a single combined work, and to convey +the resulting work. The terms of this License will continue to apply to the +part which is the covered work, but the special requirements of the GNU Affero +General Public License, section 13, concerning interaction through a network +will apply to the combination as such. + +14. Revised Versions of this License. +The Free Software Foundation may publish revised and/or new versions of the GNU +General Public License from time to time. Such new versions will be similar in +spirit to the present version, but may differ in detail to address new problems +or concerns. + +Each version is given a distinguishing version number. If the Program specifies +that a certain numbered version of the GNU General Public License “or any later +version” applies to it, you have the option of following the terms and +conditions either of that numbered version or of any later version published by +the Free Software Foundation. If the Program does not specify a version number +of the GNU General Public License, you may choose any version ever published by +the Free Software Foundation. + +If the Program specifies that a proxy can decide which future versions of the +GNU General Public License can be used, that proxy's public statement of +acceptance of a version permanently authorizes you to choose that version for +the Program. + +Later license versions may give you additional or different permissions. +However, no additional obligations are imposed on any author or copyright +holder as a result of your choosing to follow a later version. + +15. Disclaimer of Warranty. +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE +LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER +PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER +EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE +QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + +16. Limitation of Liability. +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY +COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS +PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, +INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE +THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED +INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE +PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY +HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +17. Interpretation of Sections 15 and 16. +If the disclaimer of warranty and limitation of liability provided above cannot +be given local legal effect according to their terms, reviewing courts shall +apply local law that most closely approximates an absolute waiver of all civil +liability in connection with the Program, unless a warranty or assumption of +liability accompanies a copy of the Program in return for a fee. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs +If you develop a new program, and you want it to be of the greatest possible +use to the public, the best way to achieve this is to make it free software +which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach +them to the start of each source file to most effectively state the exclusion +of warranty; and each file should have at least the “copyright” line and a +pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +Also add information on how to contact you by electronic and paper mail. + +If the program does terminal interaction, make it output a short notice like +this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands might +be different; for a GUI interface, you would use an “about box”. + +You should also get your employer (if you work as a programmer) or school, if +any, to sign a “copyright disclaimer” for the program, if necessary. For more +information on this, and how to apply and follow the GNU GPL, see +. + +The GNU General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may consider +it more useful to permit linking proprietary applications with the library. If +this is what you want to do, use the GNU Lesser General Public License instead +of this License. But first, please read +. + +------ + ** openssl -- https://www.openssl.org/ -Copyright (c) 1998-2021 The OpenSSL Project +Copyright (c) 1998-2020 The OpenSSL Project Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson All rights reserved. diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/config.py b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/config.py index 808a3387c..a80f42d8a 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/config.py +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/python/package/config.py @@ -32,10 +32,10 @@ def __init__(self): # to pin to. Some examples of pinned version values are "10", "10.1", or "10.1.12" self.deadline_version: Optional[str] = None - # A map of regions to Deadline Client Linux AMIs. As an example, the Linux Deadline 10.1.12.1 AMI ID + # A map of regions to Deadline Client Linux AMIs. As an example, the Linux Deadline 10.1.13.2 AMI ID # from us-west-2 is filled in. It can be used as-is, added to, or replaced. Ideally the version here - # should match the one used for staging the render queue and usage based licensing recipes. - self.deadline_client_linux_ami_map: Mapping[str, str] = {'us-west-2': 'ami-039f0c1faba28b015'} + # should match the one used for fetching the render queue and usage based licensing images. + self.deadline_client_linux_ami_map: Mapping[str, str] = {'us-west-2': 'ami-0237f13ce87af168e'} # A secret (in binary form) in SecretsManager that stores the UBL certificates in a .zip file. self.ubl_certificate_secret_arn: str =\ diff --git a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/bin/config.ts b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/bin/config.ts index 167753128..105eca7ce 100644 --- a/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/bin/config.ts +++ b/examples/deadline/All-In-AWS-Infrastructure-Basic/ts/bin/config.ts @@ -31,11 +31,11 @@ class AppConfig { public readonly deadlineVersion?: string; /** - * A map of regions to Deadline Client Linux AMIs. As an example, the Linux Deadline 10.1.12.1 AMI ID from us-west-2 + * A map of regions to Deadline Client Linux AMIs. As an example, the Linux Deadline 10.1.13.2 AMI ID from us-west-2 * is filled in. It can be used as-is, added to, or replaced. Ideally the version here should match the one in - * package.json used for staging the render queue and usage based licensing recipes. + * package.json used for fetching the render queue and usage based licensing images. */ - public readonly deadlineClientLinuxAmiMap: Record = {['us-west-2']: 'ami-039f0c1faba28b015'}; + public readonly deadlineClientLinuxAmiMap: Record = {['us-west-2']: 'ami-0237f13ce87af168e'}; /** * (Optional) A secret (in binary form) in SecretsManager that stores the UBL certificates in a .zip file. diff --git a/packages/aws-rfdk/lib/core/lib/cloudwatch-agent.ts b/packages/aws-rfdk/lib/core/lib/cloudwatch-agent.ts index bc40d500e..aa7c69ef9 100644 --- a/packages/aws-rfdk/lib/core/lib/cloudwatch-agent.ts +++ b/packages/aws-rfdk/lib/core/lib/cloudwatch-agent.ts @@ -5,11 +5,12 @@ import * as path from 'path'; -import {IGrantable} from '@aws-cdk/aws-iam'; -import {Bucket} from '@aws-cdk/aws-s3'; -import {StringParameter} from '@aws-cdk/aws-ssm'; -import {Construct} from '@aws-cdk/core'; -import {IScriptHost, ScriptAsset} from './script-assets'; +import { IGrantable } from '@aws-cdk/aws-iam'; +import { Bucket } from '@aws-cdk/aws-s3'; +import { StringParameter } from '@aws-cdk/aws-ssm'; +import { Construct, Stack } from '@aws-cdk/core'; + +import { IScriptHost, ScriptAsset } from './script-assets'; /** * Properties for creating the resources needed for CloudWatch Agent configuration. @@ -26,6 +27,13 @@ export interface CloudWatchAgentProps { * The host instance/ASG/fleet with a CloudWatch Agent to be configured. */ readonly host: IScriptHost; + + /** + * Whether or not we should attempt to install the CloudWatch agent + * + * @default true + */ + readonly shouldInstallAgent?: boolean; } /** @@ -70,6 +78,11 @@ export class CloudWatchAgent extends Construct { */ private static readonly SKIP_CWAGENT_VALIDATION_FLAG = '-s'; + /** + * The flag for configureCloudWatchAgent script to skip CloudWatch agent installer validation. + */ + private static readonly INSTALL_CWAGENT_FLAG = '-i'; + /** * An S3 script asset that configures the CloudWatch agent. */ @@ -83,6 +96,8 @@ export class CloudWatchAgent extends Construct { constructor(scope: Construct, id: string, props: CloudWatchAgentProps) { super(scope, id); + const shouldInstallAgent = props.shouldInstallAgent ?? true; + // Create the asset for the configuration script this.configurationScript = ScriptAsset.fromPathConvention(scope, 'CloudWatchConfigurationScriptAsset', { osType: props.host.osType, @@ -97,7 +112,11 @@ export class CloudWatchAgent extends Construct { }); this.grantRead(props.host); - this.configure(props.host, this.node.tryGetContext(CloudWatchAgent.SKIP_CWAGENT_VALIDATION_CTX_VAR) === 'TRUE'); + this.configure( + props.host, + shouldInstallAgent, + this.node.tryGetContext(CloudWatchAgent.SKIP_CWAGENT_VALIDATION_CTX_VAR) === 'TRUE', + ); } /** @@ -114,18 +133,37 @@ export class CloudWatchAgent extends Construct { * This is done by adding UserData commands to the target host. * * @param host The host to configure the CloudWatch agent on + * @param shouldInstallAgent Attempts to install the CloudWatch agent on the instance if set to true. * @param skipValidation Skips the validation of the CloudWatch agent installer if set to true. */ - private configure(host: IScriptHost, skipValidation: boolean) { - // Grant access to the required CloudWatch Agent installer files - const cloudWatchAgentBucket = Bucket.fromBucketArn(this, 'CloudWatchAgentBucket', 'arn:aws:s3:::amazoncloudwatch-agent'); - cloudWatchAgentBucket.grantRead(host); + private configure( + host: IScriptHost, + shouldInstallAgent: boolean, + skipValidation: boolean, + ) { + const region = Stack.of(this).region; + if (shouldInstallAgent) { + // Grant access to the required CloudWatch Agent and GPG installer files. + const cloudWatchAgentBucket = Bucket.fromBucketArn(this, 'CloudWatchAgentBucket', `arn:aws:s3:::amazoncloudwatch-agent-${region}`); + cloudWatchAgentBucket.grantRead(host); + const gpgBucket = Bucket.fromBucketArn(this, 'GpgBucket', `arn:aws:s3:::rfdk-external-dependencies-${region}`); + gpgBucket.grantRead(host); + } const scriptArgs = []; + + // Flags must be set before positional arguments for some scripts + if (shouldInstallAgent) { + scriptArgs.push(CloudWatchAgent.INSTALL_CWAGENT_FLAG); + } if (skipValidation) { - // Flags must be set before positional arguments for some scripts scriptArgs.push(CloudWatchAgent.SKIP_CWAGENT_VALIDATION_FLAG); } + + // This assumes that the CloudWatch agent construct is always put in the same region as the instance or ASG + // using it, which should always hold true. + scriptArgs.push(region); + scriptArgs.push(this.ssmParameterForConfig.parameterName); this.configurationScript.executeOn({ diff --git a/packages/aws-rfdk/lib/core/scripts/bash/configureCloudWatchAgent.sh b/packages/aws-rfdk/lib/core/scripts/bash/configureCloudWatchAgent.sh index 771c14980..d9ef82c4d 100644 --- a/packages/aws-rfdk/lib/core/scripts/bash/configureCloudWatchAgent.sh +++ b/packages/aws-rfdk/lib/core/scripts/bash/configureCloudWatchAgent.sh @@ -6,49 +6,37 @@ # This script downloads, installs and configures the cloudwatch agent. Must be run as sudo capable user. usage() { - echo "This script downloads, installs and configures the cloudwatch agent. Must be run as sudo capable user. + echo "This script downloads, installs and configures the CloudWatch agent. Must be run as sudo capable user. Arguments: - -s: [Flag] Skips the verification of the cloudwatch agent installer - \$1: SSM parameter name - + -i: [Flag] Attempts to install the CloudWatch agent. If this isn't set we skip right to configuring it. + -s: [Flag] Skips the verification of the CloudWatch agent installer. Only relevent if we are trying to install the agent. + \$1: region + \$2: SSM parameter name + Note: Flags must appear before positional parameters" exit 1 } -# exit when any command fails -set -xeuo pipefail - -# Parse options -SKIP_VERIFICATION=false -OPTIND=1 # Reset index for getopts in case of previous invocations -while getopts "s" opt; do - case $opt in - s) SKIP_VERIFICATION=true ;; - \?) echo "ERROR: Unknown option specified"; usage ;; - esac -done -shift $((OPTIND - 1)) +# Don't exit if commands fail +set -x -# Parse positional arguments -if (($# != 1)) -then - echo "ERROR: Invalid arguments" - usage -fi -SSM_PARAMETER_NAME="$1" +function install_agent { + region="$1" + # Check if amazon-cloudwatch-agent is already installed + if rpm -qa | grep amazon-cloudwatch-agent + then + return + fi -# Check if amazon-cloudwatch-agent is already installed -if ! rpm -qa | grep amazon-cloudwatch-agent -then TMPDIR=$(mktemp -d) pushd $TMPDIR 2>&1 > /dev/null # Download CloudWatch agent installer - aws s3api get-object --bucket amazoncloudwatch-agent --key amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm amazon-cloudwatch-agent.rpm + aws s3api get-object --region $region --bucket amazoncloudwatch-agent-$region --key amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm amazon-cloudwatch-agent.rpm if [ "$SKIP_VERIFICATION" = false ] then - aws s3api get-object --bucket amazoncloudwatch-agent --key assets/amazon-cloudwatch-agent.gpg amazon-cloudwatch-agent.gpg + aws s3api get-object --region $region --bucket amazoncloudwatch-agent-$region --key assets/amazon-cloudwatch-agent.gpg amazon-cloudwatch-agent.gpg GPG_IMPORT_OUT=$(gpg --no-default-keyring --keyring ./keyring.gpg --import amazon-cloudwatch-agent.gpg 2>&1) GPG_KEY=$(echo "${GPG_IMPORT_OUT}" | grep -Eow 'key [0-9A-F]+' | awk '{print $2}') GPG_FINGERPRINT_OUT=$(gpg --no-default-keyring --keyring ./keyring.gpg --fingerprint ${GPG_KEY} 2>&1) @@ -57,15 +45,19 @@ then then # Key failed to verify. Alert AWS!! echo "ERROR: Key failed to verify." - exit 1 + popd + rm -rf ${TMPDIR} + return fi - aws s3api get-object --bucket amazoncloudwatch-agent --key amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm.sig amazon-cloudwatch-agent.rpm.sig + aws s3api get-object --region $region --bucket amazoncloudwatch-agent-$region --key amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm.sig amazon-cloudwatch-agent.rpm.sig if ! gpg --no-default-keyring --keyring ./keyring.gpg --verify amazon-cloudwatch-agent.rpm.sig amazon-cloudwatch-agent.rpm 2>&1 then # CloudWatch agent installer failed to verify. Alert AWS!! echo "ERROR: Agent installer failed to verify" - exit 1 + popd + rm -rf ${TMPDIR} + return fi fi @@ -74,9 +66,39 @@ then popd rm -rf ${TMPDIR} -fi +} +echo "Starting CloudWatch installation and configuration script." +# Parse options +SKIP_VERIFICATION=false +INSTALL_AGENT=false +OPTIND=1 # Reset index for getopts in case of previous invocations +while getopts "is" opt; do + case $opt in + i) INSTALL_AGENT=true ;; + s) SKIP_VERIFICATION=true ;; + \?) echo "ERROR: Unknown option specified"; usage ;; + esac +done +shift $((OPTIND - 1)) + +# Parse positional arguments +if (($# != 2)) +then + echo "ERROR: Invalid arguments" + usage +fi +REGION="$1" +SSM_PARAMETER_NAME="$2" + +# Check if we want to attempt to install the agent +if $INSTALL_AGENT +then + install_agent $REGION +else + echo "Skipped installation of CloudWatch agent" +fi # starts the agent /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a append-config -m ec2 -c ssm:$SSM_PARAMETER_NAME -s diff --git a/packages/aws-rfdk/lib/core/scripts/powershell/configureCloudWatchAgent.ps1 b/packages/aws-rfdk/lib/core/scripts/powershell/configureCloudWatchAgent.ps1 index fdff6a0fb..5d5dd4196 100644 --- a/packages/aws-rfdk/lib/core/scripts/powershell/configureCloudWatchAgent.ps1 +++ b/packages/aws-rfdk/lib/core/scripts/powershell/configureCloudWatchAgent.ps1 @@ -3,46 +3,47 @@ # This script downloads, installs and configures the cloudwatch agent. Must be run as sudo capable user. # Arguments: -# $1: SSM parameter name -# [Switch] s: Skips the verification of the cloudwatch agent installer +# $1: The region this script is running in +# $2: SSM parameter name +# [Switch] s: Skips the verification of the CloudWatch agent installer +# [Switch] i: Attempts to install the CloudWatch agent param ( - [Parameter(Mandatory=$True)] $ssmParameterName, + [Parameter(Mandatory=$True)] $region, + [Parameter(Mandatory=$True)] $ssmParameterName, - # This parameter name intentionally does not follow the standard PascalCase style used in Powershell - # so that in our Typescript code, we can pass the same flag regardless of the script being called - [switch] $s = $False + # These parameter names intentionally do not follow the standard PascalCase style used in Powershell + # so that in our Typescript code, we can pass the same flag regardless of the script being called + [switch] $i = $False, + [switch] $s = $False ) -$ErrorActionPreference = "Stop" -Write-Output "Starting CloudWatch installation and configuration script." - -$is_cloudwatch_installed = $False -try { - # If this command doesn't throw an error, we have the CloudWatch agent installed already - $status = & $Env:ProgramFiles\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1 -m ec2 -a status - $is_cloudwatch_installed = $True - Write-Output "Found CloudWatch agent already installed, skipping installation." -} catch { - Write-Output "CloudWatch agent is not already installed, proceeding with installation." -} +function Install-CloudWatchAgent($region) { + try { + # If this command doesn't throw an error, we have the CloudWatch agent installed already + $status = & $Env:ProgramFiles\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1 -m ec2 -a status + Write-Output "Found CloudWatch agent already installed, skipping installation." + return + } catch { + Write-Output "CloudWatch agent is not already installed, proceeding with installation." + } -if (-Not $is_cloudwatch_installed) { $cwa_installer = "$env:temp\amazon-cloudwatch-agent.msi" try { - Read-S3Object -BucketName amazoncloudwatch-agent -Key windows/amd64/latest/amazon-cloudwatch-agent.msi -File $cwa_installer -Region us-east-1 + Read-S3Object -BucketName amazoncloudwatch-agent-$region -Key windows/amd64/latest/amazon-cloudwatch-agent.msi -File $cwa_installer -Region $region } catch { Write-Output "Failed to download CloudWatch agent installer." - Exit 1 + return } $cwa_installer_sig = "$env:temp\amazon-cloudwatch-agent.msi.sig" try { - Read-S3Object -BucketName amazoncloudwatch-agent -Key windows/amd64/latest/amazon-cloudwatch-agent.msi.sig -File $cwa_installer_sig -Region us-east-1 + Read-S3Object -BucketName amazoncloudwatch-agent-$region -Key windows/amd64/latest/amazon-cloudwatch-agent.msi.sig -File $cwa_installer_sig -Region $region } catch { Write-Output "Failed to download CloudWatch agent installer signature file." - Exit 1 + Remove-Item -Path $cwa_installer -Force + return } if (-Not $s) { @@ -50,21 +51,35 @@ if (-Not $is_cloudwatch_installed) { # Download GPG $gpg_installer = "$env:temp\gnupg-w32-2.2.27_20210111.exe" - wget https://gnupg.org/ftp/gcrypt/binary/gnupg-w32-2.2.27_20210111.exe -OutFile $gpg_installer + try { + Read-S3Object -BucketName rfdk-external-dependencies-$region -Key gnupg-w32-2.2.27_20210111.exe -File $gpg_installer -Region $region + } catch { + Write-Output "Failed downloading GPG to verify CloudWatch agent." + Remove-Item -Path $cwa_installer -Force + Remove-Item -Path $cwa_installer_sig -Force + return + } # Verify GPG $gpg_sig = Get-AuthenticodeSignature $gpg_installer $status = $gpg_sig | Select-Object -ExpandProperty 'Status' if ( $status -ne 'Valid' ) { Write-Output "GPG installer does not have a valid signature." - Exit 1 + Remove-Item -Path $cwa_installer -Force + Remove-Item -Path $cwa_installer_sig -Force + Remove-Item -Path $gpg_installer -Force + return } + $sha256_expected = '5D89E239790822711EAE2899467A764879D21440AB68E9413452FA96CEDEBA50' $sha256 = Get-FileHash $gpg_installer -Algorithm SHA256 if ( $sha256 -inotmatch $sha256_expected) { Write-Output "GPG failed checksum verification. Expected sha256 to equal $sha256_expected but got:" Write-Output $sha256 - Exit 1 + Remove-Item -Path $cwa_installer -Force + Remove-Item -Path $cwa_installer_sig -Force + Remove-Item -Path $gpg_installer -Force + return } # Install GPG @@ -75,7 +90,17 @@ if (-Not $is_cloudwatch_installed) { # Download Amazon's public key and import it to GPG's keyring $cloudwatch_pub_key = "$env:temp\amazon-cloudwatch-agent.gpg" - Read-S3Object -BucketName amazoncloudwatch-agent -Key assets/amazon-cloudwatch-agent.gpg -File $cloudwatch_pub_key -Region us-east-1 + + try { + Read-S3Object -BucketName amazoncloudwatch-agent-$region -Key assets/amazon-cloudwatch-agent.gpg -File $cloudwatch_pub_key -Region $region + } catch { + Write-Output "Failed to download CloudWatch's GPG key." + Remove-Item -Path $cwa_installer -Force + Remove-Item -Path $cwa_installer_sig -Force + Remove-Item -Path $gpg_installer -Force + return + } + gpg --no-default-keyring --keyring $gpg_keyring --import $cloudwatch_pub_key # Verify that the imported key has the correct fingerprint @@ -86,7 +111,12 @@ if (-Not $is_cloudwatch_installed) { if ($keys -inotlike "*$fingerprint*") { Write-Output "Expected CloudWatch agent's public key to equal $fingerprint but got:" Get-Content $keys - Exit 1 + Remove-Item -Path $cwa_installer -Force + Remove-Item -Path $cwa_installer_sig -Force + Remove-Item -Path $gpg_installer -Force + Remove-Item -Path $cloudwatch_pub_key -Force + Remove-Item -Path $gpg_keyring -Force + return } # Now that we have the public key on the keyring, we can use gpg to perform the verification of the installer with the signature file. @@ -99,22 +129,43 @@ if (-Not $is_cloudwatch_installed) { if (-Not $verification) { Write-Output "Could not verify CloudWatch agent's signature file with GPG." Get-Content $gpg_output - Exit 1 + Remove-Item -Path $cwa_installer -Force + Remove-Item -Path $cwa_installer_sig -Force + Remove-Item -Path $gpg_installer -Force + Remove-Item -Path $cloudwatch_pub_key -Force + Remove-Item -Path $gpg_keyring -Force + Remove-Item -Path $gpg_output -Force + return } + + return } # Install the agent Start-Process "msiexec.exe" -ArgumentList "/i $cwa_installer /qn /norestart" -Wait -Passthru -NoNewWindow - Remove-Item -Path $cloudwatch_pub_key -Force Remove-Item -Path $cwa_installer -Force Remove-Item -Path $cwa_installer_sig -Force Remove-Item -Path $gpg_installer -Force - Remove-Item -Path $gpg_output -Force + Remove-Item -Path $cloudwatch_pub_key -Force Remove-Item -Path $gpg_keyring -Force + Remove-Item -Path $gpg_output -Force +} + + +Write-Output "Starting CloudWatch installation and configuration script." + +if ($i) { + Install-CloudWatchAgent $region +} else { + Write-Output "Skipped installation of CloudWatch agent" } -# Configure the agent from an ssm parameter-store parameter. -& 'C:/Program Files/Amazon/AmazonCloudWatchAgent/amazon-cloudwatch-agent-ctl.ps1' -a append-config -m ec2 -c ssm:$ssmParameterName -s +try { + # Configure the agent from an ssm parameter-store parameter. + & 'C:/Program Files/Amazon/AmazonCloudWatchAgent/amazon-cloudwatch-agent-ctl.ps1' -a append-config -m ec2 -c ssm:$ssmParameterName -s +} catch { + Write-Output "Failed attempt to configure the CloudWatch agent" +} -Write-Output "CloudWatch agent has been successfully installed and configured" +Write-Output "CloudWatch agent script has completed successfully" diff --git a/packages/aws-rfdk/lib/core/test/asset-constants.ts b/packages/aws-rfdk/lib/core/test/asset-constants.ts index 22495dfe9..d633a2400 100644 --- a/packages/aws-rfdk/lib/core/test/asset-constants.ts +++ b/packages/aws-rfdk/lib/core/test/asset-constants.ts @@ -7,14 +7,14 @@ import { stringLike } from '@aws-cdk/assert'; // ConfigureCloudWatchAgent.sh export const CWA_ASSET_LINUX = { - Bucket: 'AssetParameters3793207e75b2a1b5dd4ebe458ab7a5cc20154224e846267d2c22da1d0631f94fS3Bucket352E624B', - Key: 'AssetParameters3793207e75b2a1b5dd4ebe458ab7a5cc20154224e846267d2c22da1d0631f94fS3VersionKeyAE2B9691', + Bucket: 'AssetParametersf3261b0f6923b012a8fce5cd6984211bc48b9977844b3fa44229234dc6f21d43S3BucketCC60E56A', + Key: 'AssetParametersf3261b0f6923b012a8fce5cd6984211bc48b9977844b3fa44229234dc6f21d43S3VersionKey027288B6', }; // ConfigureCloudWatchAgent.ps1 export const CWA_ASSET_WINDOWS = { - Bucket: 'AssetParameters07782992a7a530f8752341d912c95ba2fe3f0a212d413b5d097959c51ea8e2ecS3Bucket95C4512E', - Key: 'AssetParameters07782992a7a530f8752341d912c95ba2fe3f0a212d413b5d097959c51ea8e2ecS3VersionKey3DB883AC', + Bucket: 'AssetParametersb3a03a74afa8a045b35e08f11a719544622172869cc031787f580407d665ee36S3BucketE3A6D532', + Key: 'AssetParametersb3a03a74afa8a045b35e08f11a719544622172869cc031787f580407d665ee36S3VersionKey0A26AF8C', }; // mountEbsBlockVolume.sh + metadataUtilities.sh + ec2-certificates.crt @@ -25,7 +25,3 @@ export const MOUNT_EBS_SCRIPT_LINUX = { export const INSTALL_MONGODB_3_6_SCRIPT_LINUX = { Bucket: stringLike('AssetParameters*S3BucketAF54A815'), }; - -export const MONGODB_INSTANCE_3_6_SCRIPT = { - Bucket: stringLike('AssetParameters*S3Bucket352E624B'), -}; diff --git a/packages/aws-rfdk/lib/core/test/cloudwatch-agent.test.ts b/packages/aws-rfdk/lib/core/test/cloudwatch-agent.test.ts index 1dec9446a..19aeca3db 100644 --- a/packages/aws-rfdk/lib/core/test/cloudwatch-agent.test.ts +++ b/packages/aws-rfdk/lib/core/test/cloudwatch-agent.test.ts @@ -173,8 +173,54 @@ describe('CloudWatchAgent', () => { ], Effect: 'Allow', Resource: [ - 'arn:aws:s3:::amazoncloudwatch-agent', - 'arn:aws:s3:::amazoncloudwatch-agent/*', + { + 'Fn::Join': [ + '', + [ + 'arn:aws:s3:::amazoncloudwatch-agent-', + { Ref: 'AWS::Region' }, + ], + ], + }, + { + 'Fn::Join': [ + '', + [ + 'arn:aws:s3:::amazoncloudwatch-agent-', + { Ref: 'AWS::Region' }, + '/*', + ], + ], + }, + ], + }, + { + Action: [ + 's3:GetObject*', + 's3:GetBucket*', + 's3:List*', + ], + Effect: 'Allow', + Resource: [ + { + 'Fn::Join': [ + '', + [ + 'arn:aws:s3:::rfdk-external-dependencies-', + { Ref: 'AWS::Region' }, + ], + ], + }, + { + 'Fn::Join': [ + '', + [ + 'arn:aws:s3:::rfdk-external-dependencies-', + { Ref: 'AWS::Region' }, + '/*', + ], + ], + }, ], }, ], @@ -185,7 +231,11 @@ describe('CloudWatchAgent', () => { })); }); - test('adds user data commands to fetch and execute the script (linux)', () => { + test.each([ + ["' -i ", undefined], + ["' -i ", true], + ["' ", false], + ])('adds user data commands to fetch and execute the script (linux). installFlag: %s shouldInstallAgent: %p', (installFlag: string, shouldInstallAgent?: boolean) => { // GIVEN const host = new Instance(stack, 'Instance', { instanceType: InstanceType.of(InstanceClass.T2, InstanceSize.LARGE), @@ -199,6 +249,7 @@ describe('CloudWatchAgent', () => { new CloudWatchAgent(stack, 'testResource', { cloudWatchConfig, host, + shouldInstallAgent, }); // THEN @@ -324,14 +375,20 @@ describe('CloudWatchAgent', () => { }, ], }, - "' ", + installFlag, + { Ref: 'AWS::Region' }, + ' ', { Ref: 'StringParameter472EED0E' }, ], ], }); }); - test('adds user data commands to fetch and execute the script (windows)', () => { + test.each([ + ["' -i ", undefined], + ["' -i ", true], + ["' ", false], + ])('adds user data commands to fetch and execute the script (windows). installFlag: %s shouldInstallAgent: %p', (installFlag: string, shouldInstallAgent?: boolean) => { // GIVEN const host = new Instance(stack, 'Instance', { instanceType: InstanceType.of(InstanceClass.T2, InstanceSize.LARGE), @@ -343,6 +400,7 @@ describe('CloudWatchAgent', () => { new CloudWatchAgent(stack, 'testResource', { cloudWatchConfig, host, + shouldInstallAgent, }); // THEN @@ -445,7 +503,9 @@ describe('CloudWatchAgent', () => { }, ], }, - "' ", + installFlag, + { Ref: 'AWS::Region' }, + ' ', { Ref: 'StringParameter472EED0E' }, "\nif (!$?) { Write-Error 'Failed to execute the file \"C:/temp/", { diff --git a/packages/aws-rfdk/lib/core/test/mongodb-instance.test.ts b/packages/aws-rfdk/lib/core/test/mongodb-instance.test.ts index 9912f299b..eb7642378 100644 --- a/packages/aws-rfdk/lib/core/test/mongodb-instance.test.ts +++ b/packages/aws-rfdk/lib/core/test/mongodb-instance.test.ts @@ -48,7 +48,7 @@ import { } from '../lib'; import { - MONGODB_INSTANCE_3_6_SCRIPT, + CWA_ASSET_LINUX, } from './asset-constants'; import { testConstructTags, @@ -199,7 +199,7 @@ describe('Test MongoDbInstance', () => { }, ':s3:::', { - Ref: MONGODB_INSTANCE_3_6_SCRIPT.Bucket, + Ref: CWA_ASSET_LINUX.Bucket, }, ], ], @@ -214,7 +214,7 @@ describe('Test MongoDbInstance', () => { }, ':s3:::', { - Ref: MONGODB_INSTANCE_3_6_SCRIPT.Bucket, + Ref: CWA_ASSET_LINUX.Bucket, }, '/*', ], @@ -334,7 +334,7 @@ describe('Test MongoDbInstance', () => { // CloudWatch Agent const setE = 'set -e\n'; const setChmod = 'chmod \\+x \'/tmp/' + token + token + '\'\n'; - const execute = '\'/tmp/' + token + token + '\' ' + token + '\n'; + const execute = '\'/tmp/' + token + token + '\' -i ${Token[AWS.Region.\\d+]} ' + token + '\n'; expect(userData).toMatch(new RegExp(escapeTokenRegex(createTempDir + s3Copy + setE + setChmod + execute))); // Make sure we mount EBS volume diff --git a/packages/aws-rfdk/lib/core/test/script-assets.test.ts b/packages/aws-rfdk/lib/core/test/script-assets.test.ts index a4883857b..b82797f8d 100644 --- a/packages/aws-rfdk/lib/core/test/script-assets.test.ts +++ b/packages/aws-rfdk/lib/core/test/script-assets.test.ts @@ -20,7 +20,7 @@ import { Stack } from '@aws-cdk/core'; import { ScriptAsset } from '../lib/script-assets'; -import { CWA_ASSET_LINUX } from './asset-constants'; +import { CWA_ASSET_LINUX, CWA_ASSET_WINDOWS } from './asset-constants'; const instanceType = InstanceType.of(InstanceClass.T3, InstanceSize.MICRO); const linuxImage = new AmazonLinuxImage(); @@ -37,9 +37,9 @@ describe('executeScriptAsset', () => { }); it.each([ - [linuxImage], - [windowsImage], - ])('grants read permissions', (machineImage: AmazonLinuxImage | WindowsImage) => { + [linuxImage, '../scripts/bash/configureCloudWatchAgent.sh', CWA_ASSET_LINUX.Bucket], + [windowsImage, '../scripts/powershell/configureCloudWatchAgent.ps1', CWA_ASSET_WINDOWS.Bucket], + ])('grants read permissions', (machineImage: AmazonLinuxImage | WindowsImage, scriptLocation: string, bucketKey: string) => { // GIVEN const instance = new Instance(stack, 'inst', { vpc, @@ -47,7 +47,7 @@ describe('executeScriptAsset', () => { machineImage, }); const asset = new ScriptAsset(stack, 'asset', { - path: path.join(__dirname, '../scripts/bash/configureCloudWatchAgent.sh'), + path: path.join(__dirname, scriptLocation), }); // WHEN @@ -72,7 +72,7 @@ describe('executeScriptAsset', () => { 'arn:', { Ref: 'AWS::Partition' }, ':s3:::', - { Ref: CWA_ASSET_LINUX.Bucket }, + { Ref: bucketKey }, ], ], }, @@ -83,7 +83,7 @@ describe('executeScriptAsset', () => { 'arn:', { Ref: 'AWS::Partition' }, ':s3:::', - { Ref: CWA_ASSET_LINUX.Bucket }, + { Ref: bucketKey }, '/*', ], ], @@ -255,7 +255,7 @@ describe('executeScriptAsset', () => { machineImage: windowsImage, }); const asset = new ScriptAsset(stack, 'asset', { - path: path.join(__dirname, '../scripts/bash/configureCloudWatchAgent.sh'), + path: path.join(__dirname, '../scripts/powershell/configureCloudWatchAgent.ps1'), }); // WHEN @@ -278,7 +278,7 @@ describe('executeScriptAsset', () => { { 'Fn::Split': [ '||', - { Ref: CWA_ASSET_LINUX.Key }, + { Ref: CWA_ASSET_WINDOWS.Key }, ], }, ], @@ -289,13 +289,13 @@ describe('executeScriptAsset', () => { { 'Fn::Split': [ '||', - { Ref: CWA_ASSET_LINUX.Key }, + { Ref: CWA_ASSET_WINDOWS.Key }, ], }, ], }, "' ) -ea 0\nRead-S3Object -BucketName '", - { Ref: CWA_ASSET_LINUX.Bucket }, + { Ref: CWA_ASSET_WINDOWS.Bucket }, "' -key '", { 'Fn::Select': [ @@ -303,7 +303,7 @@ describe('executeScriptAsset', () => { { 'Fn::Split': [ '||', - { Ref: CWA_ASSET_LINUX.Key }, + { Ref: CWA_ASSET_WINDOWS.Key }, ], }, ], @@ -314,7 +314,7 @@ describe('executeScriptAsset', () => { { 'Fn::Split': [ '||', - { Ref: CWA_ASSET_LINUX.Key }, + { Ref: CWA_ASSET_WINDOWS.Key }, ], }, ], @@ -326,7 +326,7 @@ describe('executeScriptAsset', () => { { 'Fn::Split': [ '||', - { Ref: CWA_ASSET_LINUX.Key }, + { Ref: CWA_ASSET_WINDOWS.Key }, ], }, ], @@ -337,7 +337,7 @@ describe('executeScriptAsset', () => { { 'Fn::Split': [ '||', - { Ref: CWA_ASSET_LINUX.Key }, + { Ref: CWA_ASSET_WINDOWS.Key }, ], }, ], @@ -349,7 +349,7 @@ describe('executeScriptAsset', () => { { 'Fn::Split': [ '||', - { Ref: CWA_ASSET_LINUX.Key }, + { Ref: CWA_ASSET_WINDOWS.Key }, ], }, ], @@ -360,7 +360,7 @@ describe('executeScriptAsset', () => { { 'Fn::Split': [ '||', - { Ref: CWA_ASSET_LINUX.Key }, + { Ref: CWA_ASSET_WINDOWS.Key }, ], }, ], @@ -372,7 +372,7 @@ describe('executeScriptAsset', () => { { 'Fn::Split': [ '||', - { Ref: CWA_ASSET_LINUX.Key }, + { Ref: CWA_ASSET_WINDOWS.Key }, ], }, ], @@ -383,7 +383,7 @@ describe('executeScriptAsset', () => { { 'Fn::Split': [ '||', - { Ref: CWA_ASSET_LINUX.Key }, + { Ref: CWA_ASSET_WINDOWS.Key }, ], }, ], diff --git a/packages/aws-rfdk/lib/deadline/lib/spot-event-plugin-fleet.ts b/packages/aws-rfdk/lib/deadline/lib/spot-event-plugin-fleet.ts index f8eea75d6..c8b89ccf1 100644 --- a/packages/aws-rfdk/lib/deadline/lib/spot-event-plugin-fleet.ts +++ b/packages/aws-rfdk/lib/deadline/lib/spot-event-plugin-fleet.ts @@ -456,7 +456,7 @@ export class SpotEventPluginFleet extends Construct implements ISpotEventPluginF const workerConfig = new WorkerInstanceConfiguration(this, id, { worker: this, - cloudwatchLogSettings: { + cloudWatchLogSettings: { logGroupPrefix: SpotEventPluginFleet.DEFAULT_LOG_GROUP_PREFIX, ...props.logGroupProps, }, diff --git a/packages/aws-rfdk/lib/deadline/lib/worker-configuration.ts b/packages/aws-rfdk/lib/deadline/lib/worker-configuration.ts index 0c82a0a46..9c17f53ff 100644 --- a/packages/aws-rfdk/lib/deadline/lib/worker-configuration.ts +++ b/packages/aws-rfdk/lib/deadline/lib/worker-configuration.ts @@ -150,7 +150,17 @@ export interface WorkerInstanceConfigurationProps { * * @default The Worker logs will not be streamed to CloudWatch. */ - readonly cloudwatchLogSettings?: LogGroupFactoryProps; + readonly cloudWatchLogSettings?: LogGroupFactoryProps; + + /** + * Whether or not the CloudWatch agent should be automatically installed onto all worker instances. + * This installation will be a best effort, but will not fail the deployment if it isn't completed + * successfully. Ideally the CloudWatch agent should be installed on the AMI to avoid issues. If + * the installation fails, logs will not be streamed off of the workers into CloudWatch. + * + * @default true + */ + readonly shouldInstallCloudWatchAgent?: boolean; /** * The settings to apply to the Deadline Worker. @@ -202,8 +212,13 @@ export class WorkerInstanceConfiguration extends Construct { constructor(scope: Construct, id: string, props: WorkerInstanceConfigurationProps) { super(scope, id); props.userDataProvider?.preCloudWatchAgent(props.worker); - if (props.cloudwatchLogSettings) { - this.configureCloudWatchLogStream(props.worker, id, props.cloudwatchLogSettings); + if (props.cloudWatchLogSettings) { + this.configureCloudWatchLogStream( + props.worker, + id, + props.cloudWatchLogSettings, + props.shouldInstallCloudWatchAgent, + ); } props.userDataProvider?.preRenderQueueConfiguration(props.worker); props.renderQueue?.configureClientInstance({ host: props.worker }); @@ -225,9 +240,15 @@ export class WorkerInstanceConfiguration extends Construct { * * @param worker The worker to configure. This can be an instance, auto scaling group, launch template, etc. * @param id Identifier to disambiguate the resources that are created. + * @param shouldInstallAgent Boolean for if the worker's User Data should attempt to install the CloudWatch agent * @param logGroupProps Configuration for the log group in CloudWatch. */ - protected configureCloudWatchLogStream(worker: IHost, id: string, logGroupProps?: LogGroupFactoryProps): void { + protected configureCloudWatchLogStream( + worker: IHost, + id: string, + logGroupProps: LogGroupFactoryProps, + shouldInstallAgent?: boolean, + ): void { const logGroup = LogGroupFactory.createOrFetch(this, `${id}LogGroupWrapper`, id, logGroupProps); logGroup.grantWrite(worker); @@ -259,6 +280,7 @@ export class WorkerInstanceConfiguration extends Construct { new CloudWatchAgent(this, `${id}LogsConfig`, { cloudWatchConfig: cloudWatchConfigurationBuilder.generateCloudWatchConfiguration(), host: worker, + shouldInstallAgent, }); } diff --git a/packages/aws-rfdk/lib/deadline/lib/worker-fleet.ts b/packages/aws-rfdk/lib/deadline/lib/worker-fleet.ts index 310aef644..a39b2aea9 100644 --- a/packages/aws-rfdk/lib/deadline/lib/worker-fleet.ts +++ b/packages/aws-rfdk/lib/deadline/lib/worker-fleet.ts @@ -499,7 +499,7 @@ export class WorkerInstanceFleet extends WorkerInstanceFleetBase { const workerConfig = new WorkerInstanceConfiguration(this, id, { worker: this.fleet, - cloudwatchLogSettings: { + cloudWatchLogSettings: { logGroupPrefix: WorkerInstanceFleet.DEFAULT_LOG_GROUP_PREFIX, ...props.logGroupProps, }, diff --git a/packages/aws-rfdk/lib/deadline/test/asset-constants.ts b/packages/aws-rfdk/lib/deadline/test/asset-constants.ts index ba32637aa..be8ccd004 100644 --- a/packages/aws-rfdk/lib/deadline/test/asset-constants.ts +++ b/packages/aws-rfdk/lib/deadline/test/asset-constants.ts @@ -55,8 +55,135 @@ export const RQ_CONNECTION_ASSET = { Key: 'AssetParameters74fd6cba5cebe5a13738b535ab6b010a0fe1154689bad4df3ef49ed7bddc1075S3VersionKey144181B5', }; -export function linuxConfigureWorkerScriptBoilerplate(scriptParams: string) { +export function linuxCloudWatchScriptBoilerplate(scriptParams: string) { return [ + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_LINUX.Key }, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_LINUX.Key }, + ], + }, + ], + }, + "')\naws s3 cp 's3://", + { + Ref: CWA_ASSET_LINUX.Bucket, + }, + '/', + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_LINUX.Key }, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_LINUX.Key }, + ], + }, + ], + }, + "' '/tmp/", + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_LINUX.Key }, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_LINUX.Key }, + ], + }, + ], + }, + "'\nset -e\nchmod +x '/tmp/", + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_LINUX.Key }, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_LINUX.Key }, + ], + }, + ], + }, + "'\n'/tmp/", + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_LINUX.Key }, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_LINUX.Key }, + ], + }, + ], + }, + "' -i ", + { + Ref: 'AWS::Region', + }, + ' ', + { + Ref: 'ConfigStringParameterC2BE550F', + }, + "\nmkdir -p $(dirname '/tmp/", { 'Fn::Select': [ 0, @@ -227,7 +354,6 @@ export function linuxConfigureWorkerScriptBoilerplate(scriptParams: string) { { 'Fn::Select': [ 0, - { 'Fn::Split': [ '||', @@ -273,7 +399,7 @@ export function linuxConfigureWorkerScriptBoilerplate(scriptParams: string) { ]; } -export function linuxCloudWatchScriptBoilerplate() { +export function linuxConfigureWorkerScriptBoilerplate(scriptParams: string) { return [ { 'Fn::Select': [ @@ -281,7 +407,7 @@ export function linuxCloudWatchScriptBoilerplate() { { 'Fn::Split': [ '||', - {Ref: CWA_ASSET_LINUX.Key}, + {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, ], }, ], @@ -292,13 +418,84 @@ export function linuxCloudWatchScriptBoilerplate() { { 'Fn::Split': [ '||', - {Ref: CWA_ASSET_LINUX.Key}, + {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, + ], + }, + ], + }, + "')\naws s3 cp 's3://", + {Ref: CONFIG_WORKER_ASSET_WINDOWS.Bucket}, + '/', + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, + ], + }, + ], + }, + "' '/tmp/", + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, + ], + }, + ], + }, + "'\nmkdir -p $(dirname '/tmp/", + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, ], }, ], }, '\')\naws s3 cp \'s3://', - {Ref: CWA_ASSET_LINUX.Bucket}, + {Ref: CONFIG_WORKER_ASSET_LINUX.Bucket}, '/', { 'Fn::Select': [ @@ -306,7 +503,7 @@ export function linuxCloudWatchScriptBoilerplate() { { 'Fn::Split': [ '||', - {Ref: CWA_ASSET_LINUX.Key}, + {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, ], }, ], @@ -317,7 +514,7 @@ export function linuxCloudWatchScriptBoilerplate() { { 'Fn::Split': [ '||', - {Ref: CWA_ASSET_LINUX.Key}, + {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, ], }, ], @@ -329,7 +526,7 @@ export function linuxCloudWatchScriptBoilerplate() { { 'Fn::Split': [ '||', - {Ref: CWA_ASSET_LINUX.Key}, + {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, ], }, ], @@ -340,7 +537,7 @@ export function linuxCloudWatchScriptBoilerplate() { { 'Fn::Split': [ '||', - {Ref: CWA_ASSET_LINUX.Key}, + {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, ], }, ], @@ -354,7 +551,7 @@ export function linuxCloudWatchScriptBoilerplate() { { 'Fn::Split': [ '||', - {Ref: CWA_ASSET_LINUX.Key}, + {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, ], }, ], @@ -365,7 +562,7 @@ export function linuxCloudWatchScriptBoilerplate() { { 'Fn::Split': [ '||', - {Ref: CWA_ASSET_LINUX.Key}, + {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, ], }, ], @@ -374,11 +571,33 @@ export function linuxCloudWatchScriptBoilerplate() { { 'Fn::Select': [ 0, - { 'Fn::Split': [ '||', - {Ref: CWA_ASSET_LINUX.Key}, + {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + {Ref: CONFIG_WORKER_ASSET_LINUX.Key}, + ], + }, + ], + }, + scriptParams, + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, ], }, ], @@ -389,7 +608,7 @@ export function linuxCloudWatchScriptBoilerplate() { { 'Fn::Split': [ '||', - {Ref: CWA_ASSET_LINUX.Key}, + {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, ], }, ], @@ -397,8 +616,129 @@ export function linuxCloudWatchScriptBoilerplate() { ]; } -export function windowsConfigureWorkerScriptBoilerplate(scriptParams: string) { +export function windowsCloudWatchScriptBoilerplate(scriptParams: string) { return [ + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_WINDOWS.Key }, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_WINDOWS.Key }, + ], + }, + ], + }, + "' ) -ea 0\nRead-S3Object -BucketName '", + { Ref: CWA_ASSET_WINDOWS.Bucket }, + "' -key '", + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_WINDOWS.Key }, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_WINDOWS.Key }, + ], + }, + ], + }, + "' -file 'C:/temp/", + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_WINDOWS.Key }, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_WINDOWS.Key }, + ], + }, + ], + }, + "' -ErrorAction Stop\n&'C:/temp/", + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_WINDOWS.Key }, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_WINDOWS.Key }, + ], + }, + ], + }, + "' -i ", + { Ref: 'AWS::Region' }, + ' ', + { Ref: 'ConfigStringParameterC2BE550F' }, + "\nif (!$?) { Write-Error 'Failed to execute the file \"C:/temp/", + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_WINDOWS.Key }, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + { Ref: CWA_ASSET_WINDOWS.Key }, + ], + }, + ], + }, + "\"' -ErrorAction Stop }\nmkdir (Split-Path -Path 'C:/temp/", { 'Fn::Select': [ 0, @@ -616,7 +956,7 @@ export function windowsConfigureWorkerScriptBoilerplate(scriptParams: string) { ]; } -export function windowsCloudWatchScriptBoilerplate() { +export function windowsConfigureWorkerScriptBoilerplate(scriptParams: string) { return [ { 'Fn::Select': [ @@ -624,7 +964,7 @@ export function windowsCloudWatchScriptBoilerplate() { { 'Fn::Split': [ '||', - {Ref: CWA_ASSET_WINDOWS.Key}, + {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, ], }, ], @@ -635,13 +975,13 @@ export function windowsCloudWatchScriptBoilerplate() { { 'Fn::Split': [ '||', - {Ref: CWA_ASSET_WINDOWS.Key}, + {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, ], }, ], }, '\' ) -ea 0\nRead-S3Object -BucketName \'', - {Ref: CWA_ASSET_WINDOWS.Bucket}, + {Ref: CONFIG_WORKER_ASSET_WINDOWS.Bucket}, '\' -key \'', { 'Fn::Select': [ @@ -649,7 +989,7 @@ export function windowsCloudWatchScriptBoilerplate() { { 'Fn::Split': [ '||', - {Ref: CWA_ASSET_WINDOWS.Key}, + {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, ], }, ], @@ -660,7 +1000,7 @@ export function windowsCloudWatchScriptBoilerplate() { { 'Fn::Split': [ '||', - {Ref: CWA_ASSET_WINDOWS.Key}, + {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, ], }, ], @@ -672,7 +1012,30 @@ export function windowsCloudWatchScriptBoilerplate() { { 'Fn::Split': [ '||', - {Ref: CWA_ASSET_WINDOWS.Key}, + {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + {Ref: CONFIG_WORKER_ASSET_WINDOWS.Key}, + ], + }, + ], + }, + "' -ErrorAction Stop\nmkdir (Split-Path -Path 'C:/temp/", + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, ], }, ], @@ -683,7 +1046,55 @@ export function windowsCloudWatchScriptBoilerplate() { { 'Fn::Split': [ '||', - {Ref: CWA_ASSET_WINDOWS.Key}, + {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, + ], + }, + ], + }, + "' ) -ea 0\nRead-S3Object -BucketName '", + {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Bucket}, + "' -key '", + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, + ], + }, + ], + }, + "' -file 'C:/temp/", + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, ], }, ], @@ -695,7 +1106,57 @@ export function windowsCloudWatchScriptBoilerplate() { { 'Fn::Split': [ '||', - {Ref: CWA_ASSET_WINDOWS.Key}, + {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, + ], + }, + ], + }, + scriptParams, + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + { + Ref: CONFIG_WORKER_ASSET_WINDOWS.Key, + }, + ], + }, + ], + }, + { + 'Fn::Select': [ + 1, + { + 'Fn::Split': [ + '||', + { + Ref: CONFIG_WORKER_ASSET_WINDOWS.Key, + }, + ], + }, + ], + }, + '\nif (!$?) { Write-Error \'Failed to execute the file \"C:/temp/', + { + 'Fn::Select': [ + 0, + { + 'Fn::Split': [ + '||', + {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, ], }, ], @@ -706,7 +1167,7 @@ export function windowsCloudWatchScriptBoilerplate() { { 'Fn::Split': [ '||', - {Ref: CWA_ASSET_WINDOWS.Key}, + {Ref: CONFIG_WORKER_PORT_ASSET_WINDOWS.Key}, ], }, ], diff --git a/packages/aws-rfdk/lib/deadline/test/repository.test.ts b/packages/aws-rfdk/lib/deadline/test/repository.test.ts index cd0192bae..6c3cb0515 100644 --- a/packages/aws-rfdk/lib/deadline/test/repository.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/repository.test.ts @@ -10,7 +10,6 @@ import { haveResource, haveResourceLike, ResourcePart, - stringLike, SynthUtils, } from '@aws-cdk/assert'; import {AutoScalingGroup} from '@aws-cdk/aws-autoscaling'; @@ -48,6 +47,9 @@ import { import { testConstructTags, } from '../../core/test/tag-helpers'; +import { + CWA_ASSET_LINUX, +} from '../../deadline/test/asset-constants'; import { DatabaseConnection, IVersion, @@ -259,6 +261,7 @@ IAM Policy document tests. The policy for the installer instance is: {}, // cloudwatch agent install script {}, // cloudwatch agent string parameters {}, // cloudwatch agent get installer permissions + {}, // gpg get installer permissions {}, // DocDB secret get {}, // filesystem mount script get {}, // installer get @@ -294,6 +297,7 @@ test('repository installer iam permissions: db secret access', () => { {}, {}, {}, + {}, { Action: [ 'secretsmanager:GetSecretValue', @@ -343,7 +347,7 @@ test('repository installer iam permissions: installer get', () => { }, ':s3:::', { - Ref: stringLike('AssetParameters*S3Bucket352E624B'), + Ref: CWA_ASSET_LINUX.Bucket, }, ], ], @@ -358,7 +362,7 @@ test('repository installer iam permissions: installer get', () => { }, ':s3:::', { - Ref: stringLike('AssetParameters*S3Bucket352E624B'), + Ref: CWA_ASSET_LINUX.Bucket, }, '/*', ], diff --git a/packages/aws-rfdk/lib/deadline/test/worker-configuration.test.ts b/packages/aws-rfdk/lib/deadline/test/worker-configuration.test.ts index 6cd972d65..c6b0d8cae 100644 --- a/packages/aws-rfdk/lib/deadline/test/worker-configuration.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/worker-configuration.test.ts @@ -26,9 +26,6 @@ import { import { ILogGroup, } from '@aws-cdk/aws-logs'; -import { - StringParameter, -} from '@aws-cdk/aws-ssm'; import { Stack, } from '@aws-cdk/core'; @@ -43,11 +40,10 @@ import { WorkerInstanceConfiguration, } from '../lib'; import { - CWA_ASSET_WINDOWS, - linuxCloudWatchScriptBoilerplate, linuxConfigureWorkerScriptBoilerplate, - windowsCloudWatchScriptBoilerplate, + linuxCloudWatchScriptBoilerplate, windowsConfigureWorkerScriptBoilerplate, + windowsCloudWatchScriptBoilerplate, } from './asset-constants'; describe('Test WorkerInstanceConfiguration for Linux', () => { @@ -143,11 +139,9 @@ describe('Test WorkerInstanceConfiguration for Linux', () => { // WHEN const config = new WorkerInstanceConfiguration(stack, 'Config', { worker: instance, - cloudwatchLogSettings: logGroupProps, + cloudWatchLogSettings: logGroupProps, }); - const ssmParam = config.node.findChild('StringParameter'); const logGroup = config.node.findChild('ConfigLogGroupWrapper'); - const ssmParamName = stack.resolve((ssmParam as StringParameter).parameterName); const logGroupName = stack.resolve((logGroup as ILogGroup).logGroupName); const userData = stack.resolve(instance.userData.render()); @@ -157,11 +151,7 @@ describe('Test WorkerInstanceConfiguration for Linux', () => { '', [ '#!/bin/bash\nmkdir -p $(dirname \'/tmp/', - ...linuxCloudWatchScriptBoilerplate(), - '\' ', - ssmParamName, - '\nmkdir -p $(dirname \'/tmp/', - ...linuxConfigureWorkerScriptBoilerplate( + ...linuxCloudWatchScriptBoilerplate( `\' \'\' \'\' \'\' \'${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}\' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} /tmp/`), ], ], @@ -282,11 +272,9 @@ describe('Test WorkerInstanceConfiguration for Windows', () => { // WHEN const config = new WorkerInstanceConfiguration(stack, 'Config', { worker: instance, - cloudwatchLogSettings: logGroupProps, + cloudWatchLogSettings: logGroupProps, }); - const ssmParam = config.node.findChild('StringParameter'); const logGroup = config.node.findChild('ConfigLogGroupWrapper'); - const ssmParamName = stack.resolve((ssmParam as StringParameter).parameterName); const logGroupName = stack.resolve((logGroup as ILogGroup).logGroupName); const userData = stack.resolve(instance.userData.render()); @@ -296,37 +284,7 @@ describe('Test WorkerInstanceConfiguration for Windows', () => { '', [ 'mkdir (Split-Path -Path \'C:/temp/', - ...windowsCloudWatchScriptBoilerplate(), - '\' ', - ssmParamName, - '\nif (!$?) { Write-Error \'Failed to execute the file \"C:/temp/', - { - 'Fn::Select': [ - 0, - { - 'Fn::Split': [ - '||', - { - Ref: CWA_ASSET_WINDOWS.Key, - }, - ], - }, - ], - }, - { - 'Fn::Select': [ - 1, - { - 'Fn::Split': [ - '||', - {Ref: CWA_ASSET_WINDOWS.Key}, - ], - }, - ], - }, - '\"\' -ErrorAction Stop }' + - '\nmkdir (Split-Path -Path \'C:/temp/', - ...windowsConfigureWorkerScriptBoilerplate( + ...windowsCloudWatchScriptBoilerplate( `\' \'\' \'\' \'\' \'${Version.MINIMUM_SUPPORTED_DEADLINE_VERSION.toString()}\' ${WorkerInstanceConfiguration['DEFAULT_LISTENER_PORT']} C:/temp/`), '\"\' -ErrorAction Stop }', ], diff --git a/packages/aws-rfdk/lib/deadline/test/worker-fleet.test.ts b/packages/aws-rfdk/lib/deadline/test/worker-fleet.test.ts index c583091c9..9e919ad3b 100644 --- a/packages/aws-rfdk/lib/deadline/test/worker-fleet.test.ts +++ b/packages/aws-rfdk/lib/deadline/test/worker-fleet.test.ts @@ -589,7 +589,7 @@ test('default worker fleet is created correctly custom subnet values', () => { }, ], }, - '\' ', + '\' -i us-east-1 ', {Ref: 'workerFleetStringParameterDB3717DA'}, '\nmkdir -p $(dirname \'/tmp/', { @@ -1082,7 +1082,7 @@ test('default worker fleet is created correctly with groups, pools and region', }, ], }, - "' ", + "' -i us-east-1 ", {Ref: 'workerFleetStringParameterDB3717DA'}, '\nmkdir -p $(dirname \'/tmp/', {