diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4639f6ea85f0f2..6a84fcf6d37e1e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -18,6 +18,8 @@ /components/gitpod-messagebus @gitpod-io/engineering-webapp /components/gitpod-protocol @gitpod-io/engineering-webapp /components/gitpod-protocol/java @gitpod-io/engineering-ide +/components/iam @gitpod-io/engineering-webapp +/components/iam-api @gitpod-io/engineering-webapp /components/ide @gitpod-io/engineering-ide /components/ide-metrics @gitpod-io/engineering-ide /components/ide-metrics-api @gitpod-io/engineering-ide @@ -47,6 +49,7 @@ /install/installer/pkg/components/image-builder-mk3 @gitpod-io/engineering-workspace /install/installer/pkg/components/openvsx-proxy @gitpod-io/engineering-ide /install/installer/pkg/components/proxy @gitpod-io/engineering-webapp +/install/installer/pkg/components/refresh-credential @gitpod-io/engineering-workspace /install/installer/pkg/components/registry-facade @gitpod-io/engineering-workspace /install/installer/pkg/components/public-api-server @gitpod-io/engineering-webapp /install/installer/pkg/components/iam @gitpod-io/engineering-webapp @@ -73,9 +76,11 @@ # Any team can make changes to the experimental package /components/public-api/gitpod/experimental @gitpod-io/engineering-workspace @gitpod-io/engineering-webapp @gitpod-io/engineering-delivery-operations-experience @gitpod-io/engineering-ide /components/public-api-server @gitpod-io/engineering-webapp +/components/refresh-credential @gitpod-io/engineering-workspace /components/registry-facade-api @csweichel @aledbf /components/registry-facade @gitpod-io/engineering-workspace /components/server @gitpod-io/engineering-webapp +/components/server/src/ide-service.* @gitpod-io/engineering-ide /components/service-waiter @gitpod-io/engineering-webapp /components/supervisor-api/*.proto @csweichel @akosyakov /components/supervisor @gitpod-io/engineering-ide diff --git a/.werft/jobs/build/trigger-integration-tests.ts b/.werft/jobs/build/trigger-integration-tests.ts index 1981ddd0c7133d..9346891cde63f7 100644 --- a/.werft/jobs/build/trigger-integration-tests.ts +++ b/.werft/jobs/build/trigger-integration-tests.ts @@ -24,7 +24,7 @@ export async function runIntegrationTests(werft: Werft, config: JobConfig, usern try { exec( - `KUBECONFIG="${PREVIEW_K3S_KUBECONFIG_PATH}" GOOGLE_APPLICATION_CREDENTIALS=/home/gitpod/.config/gcloud/legacy_credentials/cd-gitpod-deployer@gitpod-core-dev.iam.gserviceaccount.com/adc.json /workspace/test/run.sh ${config.withIntegrationTests}`, + `KUBECONFIG="${PREVIEW_K3S_KUBECONFIG_PATH}" GOOGLE_APPLICATION_CREDENTIALS=/home/gitpod/.config/gcloud/legacy_credentials/cd-gitpod-deployer@gitpod-core-dev.iam.gserviceaccount.com/adc.json /workspace/test/run.sh -s ${config.withIntegrationTests}`, ); werft.done(phases.RUN_INTEGRATION_TESTS); } catch (err) { diff --git a/.werft/workspace-run-integration-tests.sh b/.werft/workspace-run-integration-tests.sh index 753e72ac7d1904..3dacdc21c07606 100755 --- a/.werft/workspace-run-integration-tests.sh +++ b/.werft/workspace-run-integration-tests.sh @@ -198,7 +198,7 @@ werft log slice "running integration test" export INTEGRATION_TEST_USERNAME="$USERNAME" export INTEGRATION_TEST_USER_TOKEN="$USER_TOKEN" set +e -KUBECONFIG=/home/gitpod/.kube/config GOOGLE_APPLICATION_CREDENTIALS=/home/gitpod/.config/gcloud/legacy_credentials/cd-gitpod-deployer@gitpod-core-dev.iam.gserviceaccount.com/adc.json ./run.sh workspace | tee test-result.log +KUBECONFIG=/home/gitpod/.kube/config GOOGLE_APPLICATION_CREDENTIALS=/home/gitpod/.config/gcloud/legacy_credentials/cd-gitpod-deployer@gitpod-core-dev.iam.gserviceaccount.com/adc.json ./run.sh -s workspace | tee test-result.log RC=${PIPESTATUS[0]} set -e RUN_COUNT=1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 3dcea4418288f5..8f566517eb9c3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Change Log ## December 2022 +- Update beta notice for the JetBrains integration ([#15371](https://github.com/gitpod-io/gitpod/pull/15371)) - [@gtsiolis](https://github.com/gtsiolis) +- Allow specifying CA certificate to configure SSL secured database connections ([#15320](https://github.com/gitpod-io/gitpod/pull/15320)) - [@geropl](https://github.com/geropl) +- Replace prebuild duration message emoji ([#15364](https://github.com/gitpod-io/gitpod/pull/15364)) - [@gtsiolis](https://github.com/gtsiolis) +- Replace prebuild message emoji ([#15367](https://github.com/gitpod-io/gitpod/pull/15367)) - [@gtsiolis](https://github.com/gtsiolis) +- Support AWS ECR container registry ([#15313](https://github.com/gitpod-io/gitpod/pull/15313)) - [@jenting](https://github.com/jenting), [@mrsimonemms](https://github.com/mrsimonemms) +- Show team usage tab only for team owners ([#15350](https://github.com/gitpod-io/gitpod/pull/15350)) - [@gtsiolis](https://github.com/gtsiolis) - Projects can now be deleted from the corresponding Settings page for that project. ([#15316](https://github.com/gitpod-io/gitpod/pull/15316)) - [@selfcontained](https://github.com/selfcontained) - [installer]: add required bucket name to mirror kots command ([#15296](https://github.com/gitpod-io/gitpod/pull/15296)) - [@mrsimonemms](https://github.com/mrsimonemms) - Allow setting workspace class for prebuilds ([#15288](https://github.com/gitpod-io/gitpod/pull/15288)) - [@svenefftinge](https://github.com/svenefftinge) diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000000000..0ad25db4bd1d86 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are 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. + + 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. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + 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 Affero 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. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + 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 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 work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero 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 Affero 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 Affero 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 Affero 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 Affero 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + 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 AGPL, see +. diff --git a/License.AGPL.txt b/License.AGPL.txt index 0ad25db4bd1d86..c55822befd78e9 100644 --- a/License.AGPL.txt +++ b/License.AGPL.txt @@ -1,661 +1 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are 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. - - 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. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - 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 Affero 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. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - 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 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 work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero 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 Affero 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 Affero 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 Affero 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 Affero 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - 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 AGPL, see -. +Find the license text in LICENSE.md diff --git a/License.MIT.txt b/License.MIT.txt deleted file mode 100644 index 38e6bfa1b1f557..00000000000000 --- a/License.MIT.txt +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 TypeFox - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/License.enterprise.txt b/License.enterprise.txt deleted file mode 100644 index 141f525a2da203..00000000000000 --- a/License.enterprise.txt +++ /dev/null @@ -1,118 +0,0 @@ - - -# Gitpod Self-Hosted Free License Terms and -# Gitpod Enterprise Source Code License - - -### 1 Preamble - -1.1 These Software Licensing Terms (“Terms”) provide the terms and conditions -that govern usage of the Software Gitpod Self-Hosted Free Edition in source and -binary form (“Software”). The Software is provided by Gitpod GmbH, Am -Germaniahafen 1, 24143 Kiel (“Gitpod”). By downloading or using to the -Software, you agree to be bound by the following Terms. - -### 2 Scope of Terms - -2.1 These Terms apply to the usage of the Software, which is designed to be used -for business purposes. - -2.2 These Terms apply to the binary code and to the source code of the Software, -unless the header of a source file explicitly refers to a different license. - -2.3 These Terms apply unless you have a separate agreement with Gitpod in -written form that explicitly supersedes these Terms. - -### 3 License Fees - -3.1 The use of the Software as described in Sec. 2 is free of charge. It is -however limited to the features that are accessible without a license key and -may only take place in accordance with these Terms. - -3.2 In case you want to use additional features or distribute the Software or -modifications to it without the restrictions of these Terms, please reach out -for a license key, which is subject to different legal and commercial terms. - -### 4 Granting of Rights - -4.1 Permission is hereby granted to obtain a copy of the Software and their -accompanying documentation to use, reproduce and execute the Software for -internal purposes in accordance with these Terms and to distribute the -unmodified software without charging a fee for it. - -4.2 Subject to the conditions of these Terms, you may modify the Software, -including patching it. You agree that Gitpod retains all right, title and -interest in and to all such modifications and patches (“Modifications”). You may -only use, reproduce and execute the Modifications for internal purposes in -accordance with these Terms. You may not distribute Modifications to any third -party. Nonetheless, you may make such modifications publicly available as fork -of the repository which hosts the original version of the Software, however only -under these Terms and only, if accompanied by the complete machine-readable -source code of the Modifications and of the Software. - -4.3 The copyright notices in the Software and this entire statement, including -the above license grant and these Terms must be included in all copies of the -Software (in whole or in part). Copyright notices, serial numbers and other -features aimed at product identification or control may not be removed, altered, -suppressed or otherwise bypassed under any circumstances. For the avoidance of -doubt, the software may neither in source nor in binary form be modified in -order to enable or activate any features of the software that would otherwise -require a valid license key. - -4.4 Any other usage of the Software, in particular modifying, combining it with -other software and providing it to third parties on a commercial basis, is -prohibited. This includes any sale, lease, indirect use of the Software to the -benefit of third parties and its provision as a commercial service, or offering -it as a part of a commercial service or platform. - -4.5 The Software remains the exclusive intellectual property of Gitpod at all -times. Mandatory rights resulting from applicable copyright law (e.g. related to -decompilation) remain unaffected. - -4.6 Gitpod provides the source code of the Software on a voluntary basis and is -not obligated to do so. Furthermore, Gitpod is not obligated to provide any -updates or upgrades it may develop. - -4.7 Please consider purchasing a license key (see above Sec. 3) for further -usage rights and additional features. - -### 5 Telemetry - -5.1 Gitpod intends to collect certain statistical data on the use of the -Software on an anonymized basis in the future with a future version of the -Software. The data will only be used to improve the Software and the data will -not be sold to third parties. Gitpod will inform about this with the future -release. - -### 6 Warranty and Liability - -6.1 THE SOFTWARE IS PROVIDED FREE OF CHARGE ON AN “AS IS” BASIS, WITHOUT -WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND -NON-INFRINGEMENT. - -6.2 IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE -BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF -OR OTHER DEALINGS IN THE SOFTWARE. - -6.3 THIS LIMITATION OF LIABILITY DOES NOT EXCLUDE MANDATORY LEGAL GROUNDS FOR -LIABILITY SUCH AS LIABILITY FOR PERSONAL INJURY, GROSS NEGLIGENCE, WILLFUL -INTENT OR LAWS ON PRODUCT LIABILITY. - -### 7 Third-party Components - -7.1 The Software contains third-party components including open source software -(“Third-Party Components“). Parts of such Third-Party Components are subject to -deviating license terms (“Third-Party License Terms“). A list of such -Third-Party Components and its respective Third-Party License Terms are -available via the files License.third-party.npm.txt and -License.third-party.go.txt. No stipulation in these Terms is intended to impose -further restrictions on your use of such Third-Party Components licensed under -Third-Party License Terms. - -7.2 Gitpod reserves the right to introduce deviating or additional Third-Party -License Terms in the course of modifications of the Software and in case of -updates for the Software to the extent necessary due to additional Third-Party -Components or due to changed Third-Party License Terms. - diff --git a/License.txt b/License.txt deleted file mode 100644 index 7763afdf503923..00000000000000 --- a/License.txt +++ /dev/null @@ -1,16 +0,0 @@ -To determine under which license you may use a file from the Gitpod source code, -please resort to the header of that file. - -If the file has no header, the following rules apply -1. install scripts are licensed under MIT, see License.MIT.txt -2. enterprise features are licensed under Gitpod Self-Hosted Free Licensing Terms, see License.enterprise.txt -3. source code that is neither (1) nor (2) is licensed under AGPL, see License.AGPL.txt - -On request, licenses under different terms are available. - -Install scripts can be found in the folders install/ and chart/ - -Source code of enterprise features are files that -* are in folders named "ee" or in subfolders of such folders. -* contain the strings "_ee" or "ee_" in its file name. -The files can be found by running the command `find . -iname ee -or -iname "*_ee*" -or -iname "*ee_*"` diff --git a/README.md b/README.md index 1b0f69afa6738b..cedb79194bb887 100644 --- a/README.md +++ b/README.md @@ -44,8 +44,6 @@ Tightly integrated with GitLab, GitHub, and Bitbucket, Gitpod automatically and [Learn more 👉](https://www.gitpod.io/) -Gitpod is provided as a [managed Saas version](https://gitpod.io) with a free subscription for open-source or a [free self-hosted version](https://www.gitpod.io/self-hosted). An enterprise license is available [here](https://www.gitpod.io/self-hosted). - ## Getting Started You can start using Gitpod in one or more of the following ways: @@ -61,7 +59,7 @@ You can start using Gitpod in one or more of the following ways: All documentation can be found on https://www.gitpod.io/docs. For example, see [Introduction](https://www.gitpod.io/docs) and [Getting Started](https://www.gitpod.io/docs/getting-started) sections. 📚 -Also check out [**awesome-gitpod**](https://github.com/shaal/awesome-gitpod) ✨ +Also check out [**awesome-gitpod**](https://github.com/Gitpod-Samples/awesome-gitpod) ✨ ## Questions diff --git a/WORKSPACE.yaml b/WORKSPACE.yaml index 94c3c320525b07..5e09e4fc4f3448 100644 --- a/WORKSPACE.yaml +++ b/WORKSPACE.yaml @@ -7,8 +7,8 @@ defaultArgs: publishToNPM: true publishToJBMarketplace: true localAppVersion: unknown - codeCommit: 164ef2430ec1b55bc2831aa2ed3df5e67ded458f - codeVersion: 1.74.0 + codeCommit: f61505031707bcaea82167b6c9a4e7fc7d8a7668 + codeVersion: 1.74.1 codeQuality: stable noVerifyJBPlugin: false intellijDownloadUrl: "https://download.jetbrains.com/idea/ideaIU-2022.3.tar.gz" diff --git a/components/blobserve/README.md b/components/blobserve/README.md new file mode 100644 index 00000000000000..d07283600db41d --- /dev/null +++ b/components/blobserve/README.md @@ -0,0 +1,27 @@ +# Required Permssion + +If you want it to work in a particular public cloud, you may need to grant some permissions. +Below is a reference for this. + +## AWS IAM Policy + +If you would like to use ECR as a container registry, please add the following IAM policy below. +Also, if you want to use ECR as public, you should add `ecr-public` too. + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "VisualEditor0", + "Effect": "Allow", + "Action": [ + "ecr:GetDownloadUrlForLayer", + "ecr:BatchGetImage", + "ecr:GetAuthorizationToken" + ], + "Resource": "*" + } + ] +} +``` diff --git a/components/dashboard/src/components/ConfirmationModal.tsx b/components/dashboard/src/components/ConfirmationModal.tsx index cc31acf91cea6a..f57ea2786f1d1b 100644 --- a/components/dashboard/src/components/ConfirmationModal.tsx +++ b/components/dashboard/src/components/ConfirmationModal.tsx @@ -20,7 +20,7 @@ export default function ConfirmationModal(props: { onConfirm: () => void; }) { const children: React.ReactChild[] = [ -

+

{props.areYouSureText}

, ]; diff --git a/components/dashboard/src/components/UsageBasedBillingConfig.tsx b/components/dashboard/src/components/UsageBasedBillingConfig.tsx index 2bec4ed0cd3c69..f3f8fa0e4c0896 100644 --- a/components/dashboard/src/components/UsageBasedBillingConfig.tsx +++ b/components/dashboard/src/components/UsageBasedBillingConfig.tsx @@ -293,11 +293,8 @@ export default function UsageBasedBillingConfig({ attributionId }: Props) { {currency === "EUR" ? "€" : "$"}0.36 for 10 credits or 1 hour of Standard workspace usage, excluding VAT.{" "} - - Learn more about credits + + Estimate costs @@ -319,11 +316,8 @@ export default function UsageBasedBillingConfig({ attributionId }: Props) { {usageLimit} credits {usageLimit / 10} hours of Standard workspace usage.{" "} - - Learn more about credits + + Estimate costs diff --git a/components/dashboard/src/projects/ProjectListItem.tsx b/components/dashboard/src/projects/ProjectListItem.tsx new file mode 100644 index 00000000000000..672ebf322b2c4c --- /dev/null +++ b/components/dashboard/src/projects/ProjectListItem.tsx @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2022 Gitpod GmbH. All rights reserved. + * Licensed under the GNU Affero General Public License (AGPL). + * See License.AGPL.txt in the project root for license information. + */ + +import { FunctionComponent, useMemo, useState } from "react"; +import dayjs from "dayjs"; +import { PrebuildWithStatus, Project } from "@gitpod/gitpod-protocol"; +import { Link } from "react-router-dom"; +import ContextMenu from "../components/ContextMenu"; +import { useCurrentTeam } from "../teams/teams-context"; +import { RemoveProjectModal } from "./RemoveProjectModal"; +import { toRemoteURL } from "./render-utils"; +import { prebuildStatusIcon } from "./Prebuilds"; + +type ProjectListItemProps = { + project: Project; + prebuild?: PrebuildWithStatus; + onProjectRemoved: () => void; +}; + +export const ProjectListItem: FunctionComponent = ({ project, prebuild, onProjectRemoved }) => { + const team = useCurrentTeam(); + const [showRemoveModal, setShowRemoveModal] = useState(false); + + const teamOrUserSlug = useMemo(() => { + return !!team ? "t/" + team.slug : "projects"; + }, [team]); + + return ( +
+
+
+
+ + +
+ setShowRemoveModal(true), + }, + ]} + /> +
+
+ +

+ {toRemoteURL(project.cloneUrl)} +

+
+
+
+ + Branches + + · + + Prebuilds + +
+
+
+ {prebuild ? ( +
+ + {prebuildStatusIcon(prebuild)} +
+ {prebuild?.info?.branch} +
+ · +
+ {dayjs(prebuild?.info?.startedAt).fromNow()} +
+ + + View All → + +
+ ) : ( +
+

No recent prebuilds

+
+ )} +
+ {showRemoveModal && ( + setShowRemoveModal(false)} + onRemoved={onProjectRemoved} + /> + )} +
+ ); +}; + +type ProjectLinkProps = { + project: Project; + teamOrUserSlug: string; +}; +const ProjectLink: FunctionComponent = ({ project, teamOrUserSlug }) => { + let slug = ""; + const name = project.name; + + if (project.slug) { + slug = project.slug; + } else { + // For existing GitLab projects that don't have a slug yet + slug = name; + } + + return ( + + {name} + + ); +}; diff --git a/components/dashboard/src/projects/ProjectSettings.tsx b/components/dashboard/src/projects/ProjectSettings.tsx index 3b6ec792d91a3c..424567689d4e57 100644 --- a/components/dashboard/src/projects/ProjectSettings.tsx +++ b/components/dashboard/src/projects/ProjectSettings.tsx @@ -260,13 +260,14 @@ export default function () { )} -
-

Delete Project

+
+

Remove Project

- Removing the project from this team will also remove team members access to it. + This will delete the project and all project-level environment variables you've set for this + project.

{showRemoveModal && ( diff --git a/components/dashboard/src/projects/Projects.tsx b/components/dashboard/src/projects/Projects.tsx index f93d655fdbbe1d..2feb9298415fea 100644 --- a/components/dashboard/src/projects/Projects.tsx +++ b/components/dashboard/src/projects/Projects.tsx @@ -10,19 +10,16 @@ import Header from "../components/Header"; import projectsEmpty from "../images/projects-empty.svg"; import projectsEmptyDark from "../images/projects-empty-dark.svg"; import { useHistory, useLocation } from "react-router"; -import { useContext, useEffect, useState } from "react"; +import { useCallback, useContext, useEffect, useMemo, useState } from "react"; import { getGitpodService } from "../service/service"; import { getCurrentTeam, TeamsContext } from "../teams/teams-context"; import { ThemeContext } from "../theme-context"; import { PrebuildWithStatus, Project } from "@gitpod/gitpod-protocol"; -import { toRemoteURL } from "./render-utils"; -import ContextMenu from "../components/ContextMenu"; -import ConfirmationModal from "../components/ConfirmationModal"; -import { prebuildStatusIcon } from "./Prebuilds"; import Alert from "../components/Alert"; import { FeatureFlagContext } from "../contexts/FeatureFlagContext"; -import { listAllProjects, projectsService } from "../service/public-api"; +import { listAllProjects } from "../service/public-api"; import { UserContext } from "../user-context"; +import { ProjectListItem } from "./ProjectListItem"; export default function () { const location = useLocation(); @@ -32,6 +29,7 @@ export default function () { const { user } = useContext(UserContext); const { usePublicApiProjectsService } = useContext(FeatureFlagContext); const team = getCurrentTeam(location, teams); + const [projectsLoaded, setProjectsLoaded] = useState(false); const [projects, setProjects] = useState([]); const [lastPrebuilds, setLastPrebuilds] = useState>(new Map()); @@ -39,11 +37,7 @@ export default function () { const [searchFilter, setSearchFilter] = useState(); - useEffect(() => { - updateProjects(); - }, [teams]); - - const updateProjects = async () => { + const updateProjects = useCallback(async () => { if (!teams) { return; } @@ -59,6 +53,7 @@ export default function () { : await getGitpodService().server.getUserProjects(); } setProjects(infos); + setProjectsLoaded(true); const map = new Map(); await Promise.all( @@ -77,74 +72,39 @@ export default function () { }), ); setLastPrebuilds(map); - }; - - const newProjectUrl = !!team ? `/new?team=${team.slug}` : "/new?user=1"; - const onNewProject = () => { - history.push(newProjectUrl); - }; - - const onRemoveProject = async (p: Project) => { - setRemoveModalVisible(false); - usePublicApiProjectsService - ? await projectsService.deleteProject({ projectId: p.id }) - : await getGitpodService().server.deleteProject(p.id); - await updateProjects(); - }; - - const filter = (project: Project) => { - if (searchFilter && `${project.name}`.toLowerCase().includes(searchFilter.toLowerCase()) === false) { - return false; - } - return true; - }; - - function hasNewerPrebuild(p0: Project, p1: Project): number { - return dayjs(lastPrebuilds.get(p1.id)?.info?.startedAt || "1970-01-01").diff( - dayjs(lastPrebuilds.get(p0.id)?.info?.startedAt || "1970-01-01"), - ); - } - - let [isRemoveModalVisible, setRemoveModalVisible] = useState(false); - let [removeProjectHandler, setRemoveProjectHandler] = useState<() => void>(() => () => {}); - let [willRemoveProject, setWillRemoveProject] = useState(); + }, [team, teams, usePublicApiProjectsService, user?.id]); - function renderProjectLink(project: Project): React.ReactElement { - let slug = ""; - const name = project.name; - - if (project.slug) { - slug = project.slug; - } else { - // For existing GitLab projects that don't have a slug yet - slug = name; - } + // Reload projects if the team changes + useEffect(() => { + updateProjects(); + }, [teams, updateProjects]); - return ( - - {name} - - ); - } + const newProjectUrl = !!team ? `/new?team=${team.slug}` : "/new?user=1"; - const teamOrUserSlug = !!team ? "t/" + team.slug : "projects"; + const onNewProject = useCallback(() => { + history.push(newProjectUrl); + }, [history, newProjectUrl]); + + // sort/filter projects if anything related changes + const sortedFilteredProjects = useMemo(() => { + const filter = (project: Project) => { + if (searchFilter && `${project.name}`.toLowerCase().includes(searchFilter.toLowerCase()) === false) { + return false; + } + return true; + }; + + const hasNewerPrebuild = (p0: Project, p1: Project): number => { + return dayjs(lastPrebuilds.get(p1.id)?.info?.startedAt || "1970-01-01").diff( + dayjs(lastPrebuilds.get(p0.id)?.info?.startedAt || "1970-01-01"), + ); + }; + + return projects.filter(filter).sort(hasNewerPrebuild); + }, [lastPrebuilds, projects, searchFilter]); return ( <> - {isRemoveModalVisible && ( - setRemoveModalVisible(false)} - onConfirm={removeProjectHandler} - /> - )} {!team && (
@@ -156,7 +116,8 @@ export default function () {
)}
- {projects.length === 0 && ( + {/* only show if we're not still loading projects to avoid a content flash */} + {projectsLoaded && projects.length === 0 && (
Projects (empty)
- {projects - .filter(filter) - .sort(hasNewerPrebuild) - .map((p) => ( -
-
-
-
- {renderProjectLink(p)} - -
- { - setWillRemoveProject(p); - setRemoveProjectHandler(() => () => { - onRemoveProject(p); - }); - setRemoveModalVisible(true); - }, - }, - ]} - /> -
-
- -

- {toRemoteURL(p.cloneUrl)} -

-
-
-
- - Branches - - · - - - Prebuilds - - -
-
-
- {lastPrebuilds.get(p.id) ? ( -
- - {prebuildStatusIcon(lastPrebuilds.get(p.id))} -
- {lastPrebuilds.get(p.id)?.info?.branch} -
- - · - -
- {dayjs(lastPrebuilds.get(p.id)?.info?.startedAt).fromNow()} -
- - - View All → - -
- ) : ( -
-

No recent prebuilds

-
- )} -
-
- ))} + {sortedFilteredProjects.map((p) => ( + + ))} {!searchFilter && (
)} -

- The JetBrains desktop IDEs are currently in beta.{" "} +

+ JetBrains integration is currently in{" "} + + + Beta + + +  ·  - Send feedback - {" "} - ·{" "} - - Documentation + Send feedback

diff --git a/components/dashboard/src/teams/teams-context.tsx b/components/dashboard/src/teams/teams-context.tsx index 7d59dfcda9596e..c7f247dc443eda 100644 --- a/components/dashboard/src/teams/teams-context.tsx +++ b/components/dashboard/src/teams/teams-context.tsx @@ -5,8 +5,9 @@ */ import { Team } from "@gitpod/gitpod-protocol"; -import React, { createContext, useState } from "react"; +import React, { createContext, useContext, useState } from "react"; import { Location } from "history"; +import { useLocation } from "react-router"; export const TeamsContext = createContext<{ teams?: Team[]; @@ -36,3 +37,11 @@ export function getCurrentTeam(location: Location, teams?: Team[]): Team | export function getSelectedTeamSlug(): string { return localStorage.getItem("team-selection") || ""; } + +// Helper hook to return the current team if one is selected +export function useCurrentTeam(): Team | undefined { + const location = useLocation(); + const { teams } = useContext(TeamsContext); + + return getCurrentTeam(location, teams); +} diff --git a/components/gitpod-db/go/encryption.go b/components/gitpod-db/go/encryption.go new file mode 100644 index 00000000000000..539c0028db2a97 --- /dev/null +++ b/components/gitpod-db/go/encryption.go @@ -0,0 +1,130 @@ +// Copyright (c) 2022 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License.AGPL.txt in the project root for license information. + +package db + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "encoding/base64" + "errors" + "fmt" +) + +type Cipher interface { + Encrypt(data []byte) (EncryptedData, error) + Decrypt(data EncryptedData) ([]byte, error) +} + +func NewAES256CBCCipher(secret string, metadata CipherMetadata) (*AES256CBC, error) { + block, err := aes.NewCipher([]byte(secret)) + if err != nil { + return nil, fmt.Errorf("failed to initialize AES 256 CBC cipher block: %w", err) + } + + return &AES256CBC{ + block: block, + metadata: metadata, + }, nil +} + +type AES256CBC struct { + block cipher.Block + metadata CipherMetadata +} + +func (c *AES256CBC) Encrypt(data []byte) (EncryptedData, error) { + iv, err := generateInitializationVector(16) + if err != nil { + return EncryptedData{}, err + } + + // In CBC mode, the plaintext has to be padded to align with the cipher's block size + plaintext := pad(data, c.block.BlockSize()) + ciphertext := make([]byte, len(plaintext)) + + cbc := cipher.NewCBCEncrypter(c.block, iv) + cbc.CryptBlocks(ciphertext, plaintext) + + encoded := base64.StdEncoding.EncodeToString(ciphertext) + return EncryptedData{ + EncodedData: encoded, + Params: KeyParams{ + InitializationVector: base64.StdEncoding.EncodeToString(iv), + }, + Metadata: c.metadata, + }, nil +} + +func (c *AES256CBC) Decrypt(data EncryptedData) ([]byte, error) { + if data.Metadata != c.metadata { + return nil, errors.New("cipher metadata does not match") + } + + if data.Params.InitializationVector == "" { + return nil, errors.New("encrypted data does not contain an initialization vector") + } + + ciphertext, err := base64.StdEncoding.DecodeString(data.EncodedData) + if err != nil { + return nil, fmt.Errorf("failed to decode ciphertext: %w", err) + } + + plaintext := make([]byte, len(ciphertext)) + + iv, err := base64.StdEncoding.DecodeString(data.Params.InitializationVector) + if err != nil { + return nil, fmt.Errorf("failed to decode initialize vector from base64: %w", err) + } + + cbc := cipher.NewCBCDecrypter(c.block, iv) + cbc.CryptBlocks(plaintext, ciphertext) + + // In CBC mode, the plaintext was padded to align with the cipher's block size, we need to trim + trimmed := trim(plaintext) + return trimmed, nil +} + +type KeyParams struct { + InitializationVector string `json:"iv"` +} + +type CipherMetadata struct { + Name string `json:"name"` + Version int `json:"version"` +} + +// EncryptedData represents the data stored in an encrypted entry +// The JSON fields must match the existing implementation on server, in +// components/gitpod-protocol/src/encryption/encryption-engine.ts +type EncryptedData struct { + // EncodedData is base64 encoded + EncodedData string `json:"data"` + // Params contain additional data needed for encryption/decryption + Params KeyParams `json:"keyParams"` + // Metadata contains metadata about the cipher used to encrypt the data + Metadata CipherMetadata `json:"keyMetadata"` +} + +func generateInitializationVector(size int) ([]byte, error) { + buf := make([]byte, size) + _, err := rand.Read(buf) + if err != nil { + return nil, fmt.Errorf("failed to generate initialization vector: %w", err) + } + + return buf, nil +} + +func pad(ciphertext []byte, blockSize int) []byte { + padding := blockSize - len(ciphertext)%blockSize + padtext := bytes.Repeat([]byte{byte(padding)}, padding) + return append(ciphertext, padtext...) +} +func trim(encrypt []byte) []byte { + padding := encrypt[len(encrypt)-1] + return encrypt[:len(encrypt)-int(padding)] +} diff --git a/components/gitpod-db/go/encryption_test.go b/components/gitpod-db/go/encryption_test.go new file mode 100644 index 00000000000000..390e7e11ffc428 --- /dev/null +++ b/components/gitpod-db/go/encryption_test.go @@ -0,0 +1,72 @@ +// Copyright (c) 2022 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License.AGPL.txt in the project root for license information. + +package db + +import ( + "encoding/base64" + "fmt" + "github.com/stretchr/testify/require" + "testing" +) + +func TestAES256CBCCipher_Encrypt_Decrypt(t *testing.T) { + secret, err := generateInitializationVector(32) + require.NoError(t, err) + + metadata := CipherMetadata{ + Name: "general", + Version: 1, + } + + cipher, err := NewAES256CBCCipher(string(secret), metadata) + require.NoError(t, err) + + data := []byte(`{ "foo": "bar", "another": "one" }`) + + encrypted, err := cipher.Encrypt(data) + require.NoError(t, err) + + iv, err := base64.StdEncoding.DecodeString(encrypted.Params.InitializationVector) + require.NoError(t, err, "initialization vector must be stored as base64") + require.NotEmpty(t, iv, "initialization vector must not be empty") + + decodedCipherText, err := base64.StdEncoding.DecodeString(encrypted.EncodedData) + require.NoError(t, err, "encrypted data must be base64 encoded") + require.NotEmpty(t, decodedCipherText, "decoded cipher text must not be emtpy") + + require.Equal(t, metadata, encrypted.Metadata) + require.NotEmpty(t, encrypted.Params.InitializationVector) + + decrypted, err := cipher.Decrypt(encrypted) + require.NoError(t, err) + require.Equal(t, data, decrypted) +} + +func TestAES256CBCCipher_EncryptedByServer(t *testing.T) { + // This is a test key also used in server tests - see components/gitpod-protocol/src/encryption/encryption-engine.spec.ts + key, err := base64.StdEncoding.DecodeString("ZMaTPrF7s9gkLbY45zP59O0LTpLvDd/cgqPE9Ptghh8=") + require.NoError(t, err) + + metadata := CipherMetadata{ + Name: "general", + Version: 1, + } + encrypted := EncryptedData{ + + EncodedData: "YpgOY8ZNV64oG1DXiuCUXKy0thVySbN7uXTQxtC2j2A=", + Params: KeyParams{ + InitializationVector: "vpTOAFN5v4kOPsAHBKk+eg==", + }, + Metadata: metadata, + } + + cipher, err := NewAES256CBCCipher(string(key), metadata) + require.NoError(t, err) + + decrypted, err := cipher.Decrypt(encrypted) + fmt.Println(err) + require.NoError(t, err) + require.Equal(t, "12345678901234567890", string(decrypted)) +} diff --git a/components/gitpod-protocol/go/gitpod-service.go b/components/gitpod-protocol/go/gitpod-service.go index edc26fd97205eb..ce8c9175172bc1 100644 --- a/components/gitpod-protocol/go/gitpod-service.go +++ b/components/gitpod-protocol/go/gitpod-service.go @@ -1899,7 +1899,9 @@ type WorkspaceInstanceStatus struct { // StartWorkspaceOptions is the StartWorkspaceOptions message type type StartWorkspaceOptions struct { - ForceDefaultImage bool `json:"forceDefaultImage,omitempty"` + ForceDefaultImage bool `json:"forceDefaultImage,omitempty"` + WorkspaceClass string `json:"workspaceClass,omitempty"` + IdeSettings *IDESettings `json:"ideSettings,omitempty"` } // GetWorkspaceTimeoutResult is the GetWorkspaceTimeoutResult message type diff --git a/components/gitpod-protocol/src/gitpod-service.ts b/components/gitpod-protocol/src/gitpod-service.ts index d0affefd45bace..6d4438890b2a79 100644 --- a/components/gitpod-protocol/src/gitpod-service.ts +++ b/components/gitpod-protocol/src/gitpod-service.ts @@ -26,6 +26,7 @@ import { PrebuiltWorkspace, UserSSHPublicKeyValue, SSHPublicKeyValue, + IDESettings, } from "./protocol"; import { Team, @@ -414,16 +415,20 @@ export namespace GitpodServer { export interface GetAccountStatementOptions { date?: string; } - export interface CreateWorkspaceOptions { + export interface CreateWorkspaceOptions extends StartWorkspaceOptions { contextUrl: string; + // whether running workspaces on the same context should be ignored. If false (default) users will be asked. ignoreRunningWorkspaceOnSameCommit?: boolean; ignoreRunningPrebuild?: boolean; allowUsingPreviousPrebuilds?: boolean; forceDefaultConfig?: boolean; } + export interface StartWorkspaceOptions { - forceDefaultImage: boolean; + forceDefaultImage?: boolean; + workspaceClass?: string; + ideSettings?: IDESettings; } export interface TakeSnapshotOptions { workspaceId: string; diff --git a/components/iam/.vscode/launch.json b/components/iam/.vscode/launch.json new file mode 100644 index 00000000000000..adec351559f408 --- /dev/null +++ b/components/iam/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Debug client", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "/workspace/gitpod/components/iam/main.go", + "args": ["run"] + } + ] +} diff --git a/components/iam/go.mod b/components/iam/go.mod index 14c71a04c84e05..a133bba9d89ae5 100644 --- a/components/iam/go.mod +++ b/components/iam/go.mod @@ -3,10 +3,13 @@ module github.com/gitpod-io/gitpod/iam go 1.19 require ( + github.com/coreos/go-oidc/v3 v3.4.0 github.com/gitpod-io/gitpod/common-go v0.0.0-00010101000000-000000000000 github.com/go-chi/chi/v5 v5.0.8 github.com/sirupsen/logrus v1.8.1 github.com/spf13/cobra v1.4.0 + github.com/stretchr/testify v1.7.0 + golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094 ) require ( @@ -30,17 +33,19 @@ require ( github.com/prometheus/procfs v0.8.0 // indirect github.com/slok/go-http-metrics v0.10.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/testify v1.7.0 // indirect - golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect + golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b // indirect golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect - golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect + golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154 // indirect + golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90 // indirect google.golang.org/grpc v1.49.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect + gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/components/iam/go.sum b/components/iam/go.sum index a3da5af875f185..3c1ff0f69410ba 100644 --- a/components/iam/go.sum +++ b/components/iam/go.sum @@ -13,14 +13,36 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= +cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -30,19 +52,23 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -51,6 +77,16 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/coreos/go-oidc/v3 v3.4.0 h1:xz7elHb/LDwm/ERpwHd+5nb7wFHL32rsr6bBOgaeu6g= +github.com/coreos/go-oidc/v3 v3.4.0/go.mod h1:eHUXhZtXPQLgEaDrOVTgwbgmz1xGOkJNye6h3zkD2Pw= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -59,9 +95,16 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -88,6 +131,8 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -103,8 +148,10 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -114,12 +161,19 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -127,19 +181,36 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/heptiolabs/healthcheck v0.0.0-20211123025425-613501dd5deb h1:tsEKRC3PU9rMw18w/uAptoijhgG4EvlA5kfJPtwrMDk= github.com/heptiolabs/healthcheck v0.0.0-20211123025425-613501dd5deb/go.mod h1:NtmN9h8vrTveVQRLHcX2HQ5wIPBDCsZ351TGbZWgg38= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= @@ -206,6 +277,7 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -215,6 +287,7 @@ github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/slok/go-http-metrics v0.10.0 h1:rh0LaYEKza5eaYRGDXujKrOln57nHBi4TtVhmNEpbgM= github.com/slok/go-http-metrics v0.10.0/go.mod h1:lFqdaS4kWMfUKCSukjC47PdCeTk+hXDUVm8kLHRqJ38= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -225,17 +298,23 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= @@ -245,6 +324,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -267,6 +348,8 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -275,6 +358,9 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -304,17 +390,46 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b h1:ZmngSVLe/wycRns9MKikG9OWIEjGcGAkacif7oYQaUY= +golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094 h1:2o1E+E8TpNLklK9nHiPiK1uzIYrIHt+cQx3ynCwq9V8= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -325,6 +440,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8= golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -359,16 +475,44 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -376,6 +520,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -425,12 +571,26 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -447,12 +607,37 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= +google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -477,14 +662,62 @@ google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154 h1:bFFRpT+e8JJVY7lMMfvezL1ZIwqiwmPl2bsE2yx4HqM= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90 h1:4SPz2GL2CXJt28MTF8V6Ap/9ZiVbQlJeGSd9qtA7DLs= +google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -497,8 +730,28 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw= google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -511,6 +764,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 h1:FVCohIoYO7IJoDDVpV2pdq7SgrMH6wHnuTyrdrxJNoY= @@ -521,8 +776,11 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= +gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/components/iam/pkg/config/config.go b/components/iam/pkg/config/config.go index 304fa38f889850..179a977174ae68 100644 --- a/components/iam/pkg/config/config.go +++ b/components/iam/pkg/config/config.go @@ -13,4 +13,6 @@ type ServiceConfig struct { Server *baseserver.Configuration `json:"server"` DatabaseConfigPath string `json:"databaseConfigPath"` + + OIDCClientsConfigFile string `json:"oidcClientsConfigFile,omitempty"` } diff --git a/components/iam/pkg/oidc/demo.go b/components/iam/pkg/oidc/demo.go new file mode 100644 index 00000000000000..86fd87a3cb0249 --- /dev/null +++ b/components/iam/pkg/oidc/demo.go @@ -0,0 +1,39 @@ +// Copyright (c) 2022 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package oidc + +import ( + "encoding/json" + "fmt" + "os" +) + +// The demo config is used to setup a OIDC client with Google. +// +// This is a temporary way to boot the OIDC client service with a single +// configuration, e.g. mounted as secret into a preview environment. +// +// ‼️ This demo config will be removed once the configuration is read from DB. +type DemoConfig struct { + Issuer string `json:"issuer"` + ClientID string `json:"clientID"` + ClientSecret string `json:"clientSecret"` + RedirectURL string `json:"redirectURL"` +} + +func ReadDemoConfigFromFile(path string) (*DemoConfig, error) { + bytes, err := os.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("failed to read test config: %q %w", path, err) + } + + var config DemoConfig + err = json.Unmarshal(bytes, &config) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal config: %w", err) + } + + return &config, nil +} diff --git a/components/iam/pkg/oidc/oauth2.go b/components/iam/pkg/oidc/oauth2.go new file mode 100644 index 00000000000000..0356d63d54aa51 --- /dev/null +++ b/components/iam/pkg/oidc/oauth2.go @@ -0,0 +1,89 @@ +// Copyright (c) 2022 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package oidc + +import ( + "context" + "net/http" + + "golang.org/x/oauth2" +) + +type OAuth2Result struct { + ClientID string + OAuth2Token *oauth2.Token + ReturnToURL string +} + +type StateParam struct { + // Internal client ID + ClientConfigID string `json:"clientId"` + + ReturnToURL string `json:"returnTo"` +} + +type keyOAuth2Result struct{} + +func AttachOAuth2ResultToContext(parentContext context.Context, result *OAuth2Result) context.Context { + childContext := context.WithValue(parentContext, keyOAuth2Result{}, result) + return childContext +} + +func GetOAuth2ResultFromContext(ctx context.Context) *OAuth2Result { + return ctx.Value(keyOAuth2Result{}).(*OAuth2Result) +} + +func OAuth2Middleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + config := GetClientConfigFromContext(r.Context()) + if config == nil { + http.Error(rw, "config not found", http.StatusInternalServerError) + return + } + + // http-only cookie written during flow start request + stateCookie, err := r.Cookie(stateCookieName) + if err != nil { + http.Error(rw, "state cookie not found", http.StatusBadRequest) + return + } + // the starte param passed back from IdP + stateParam := r.URL.Query().Get("state") + if stateParam == "" { + http.Error(rw, "state param not found", http.StatusBadRequest) + return + } + // on mismatch, obviously there is a client side error + if stateParam != stateCookie.Value { + http.Error(rw, "state did not match", http.StatusBadRequest) + return + } + + state, err := decodeStateParam(stateParam) + if err != nil { + http.Error(rw, "bad state param", http.StatusBadRequest) + return + } + + code := r.URL.Query().Get("code") + if code == "" { + http.Error(rw, "code param not found", http.StatusBadRequest) + return + } + + oauth2Token, err := config.OAuth2Config.Exchange(r.Context(), code) + if err != nil { + http.Error(rw, "failed to exchange token: "+err.Error(), http.StatusInternalServerError) + return + } + + ctx := AttachOAuth2ResultToContext(r.Context(), &OAuth2Result{ + OAuth2Token: oauth2Token, + ReturnToURL: state.ReturnToURL, + ClientID: state.ClientConfigID, + }) + next.ServeHTTP(rw, r.WithContext(ctx)) + }) +} diff --git a/components/iam/pkg/oidc/router.go b/components/iam/pkg/oidc/router.go index 9e8c5556bf6425..c6b82944526e60 100644 --- a/components/iam/pkg/oidc/router.go +++ b/components/iam/pkg/oidc/router.go @@ -5,16 +5,131 @@ package oidc import ( - "github.com/go-chi/chi/v5" + "context" "net/http" + "time" + + "github.com/gitpod-io/gitpod/common-go/log" + + "github.com/go-chi/chi/v5" ) -func Router() *chi.Mux { - router := chi.NewMux() +func Router(s *Service) *chi.Mux { + router := chi.NewRouter() - router.HandleFunc("/start", func(writer http.ResponseWriter, request *http.Request) { - writer.Write([]byte(`hello`)) + router.Route("/start", func(r chi.Router) { + r.Use(s.clientConfigMiddleware()) + r.Get("/", s.getStartHandler()) + }) + router.Route("/callback", func(r chi.Router) { + r.Use(s.clientConfigMiddleware()) + r.Use(OAuth2Middleware) + r.Get("/", s.getCallbackHandler()) }) return router } + +type keyOIDCClientConfig struct{} + +const ( + stateCookieName = "state" + nonceCookieName = "nonce" +) + +func AttachClientConfigToContext(parentContext context.Context, config *ClientConfig) context.Context { + childContext := context.WithValue(parentContext, keyOIDCClientConfig{}, config) + return childContext +} + +func GetClientConfigFromContext(ctx context.Context) *ClientConfig { + return ctx.Value(keyOIDCClientConfig{}).(*ClientConfig) +} + +func (s *Service) getStartHandler() http.HandlerFunc { + return func(rw http.ResponseWriter, r *http.Request) { + config := GetClientConfigFromContext(r.Context()) + if config == nil { + http.Error(rw, "config not found", http.StatusInternalServerError) + return + } + + startParams, err := s.GetStartParams(config) + if err != nil { + http.Error(rw, "failed to start auth flow", http.StatusInternalServerError) + return + } + + http.SetCookie(rw, newCallbackCookie(r, nonceCookieName, startParams.Nonce)) + http.SetCookie(rw, newCallbackCookie(r, stateCookieName, startParams.State)) + + http.Redirect(rw, r, startParams.AuthCodeURL, http.StatusTemporaryRedirect) + } +} + +func newCallbackCookie(r *http.Request, name string, value string) *http.Cookie { + return &http.Cookie{ + Name: name, + Value: value, + MaxAge: int(10 * time.Minute.Seconds()), + Secure: r.TLS != nil, + SameSite: http.SameSiteLaxMode, + HttpOnly: true, + } +} + +// The config middleware is responsible to retrieve the client config suitable for request +func (s *Service) clientConfigMiddleware() func(http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + config, err := s.GetClientConfigFromRequest(r) + if err != nil { + log.Warn("client config not found: " + err.Error()) + http.Error(rw, "config not found", http.StatusNotFound) + return + } + + ctx := AttachClientConfigToContext(r.Context(), config) + next.ServeHTTP(rw, r.WithContext(ctx)) + }) + } +} + +// The OIDC callback handler depends on the state produced in the OAuth2 middleware +func (s *Service) getCallbackHandler() http.HandlerFunc { + return func(rw http.ResponseWriter, r *http.Request) { + config := GetClientConfigFromContext(r.Context()) + if config == nil { + http.Error(rw, "config not found", http.StatusInternalServerError) + return + } + oauth2Result := GetOAuth2ResultFromContext(r.Context()) + if oauth2Result == nil { + http.Error(rw, "OIDC precondition failure", http.StatusInternalServerError) + return + } + + // nonce = number used once + nonceCookie, err := r.Cookie(nonceCookieName) + if err != nil { + http.Error(rw, "nonce not found", http.StatusBadRequest) + return + } + result, err := s.Authenticate(r.Context(), AuthenticateParams{ + OAuth2Result: oauth2Result, + Issuer: config.Issuer, + NonceCookieValue: nonceCookie.Value, + }) + if err != nil { + log.Warn("OIDC authentication failed: " + err.Error()) + http.Error(rw, "OIDC authentication failed", http.StatusInternalServerError) + return + } + + // TODO(at) given the result of OIDC authN, let's proceed with the redirect + log.WithField("id_token", result.IDToken).Trace("user verification was successful") + + returnToURL := oauth2Result.ReturnToURL + http.Redirect(rw, r, returnToURL, http.StatusTemporaryRedirect) + } +} diff --git a/components/iam/pkg/oidc/router_test.go b/components/iam/pkg/oidc/router_test.go new file mode 100644 index 00000000000000..e06305a991f1ab --- /dev/null +++ b/components/iam/pkg/oidc/router_test.go @@ -0,0 +1,136 @@ +// Copyright (c) 2022 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License.AGPL.txt in the project root for license information. + +package oidc + +import ( + "io/ioutil" + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/go-chi/chi/v5" + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/require" + "golang.org/x/oauth2" + + goidc "github.com/coreos/go-oidc/v3/oidc" + + "github.com/gitpod-io/gitpod/common-go/log" +) + +func TestRoute_start(t *testing.T) { + log.Log.Logger.SetLevel(logrus.TraceLevel) + + // setup fake OIDC service + idpUrl := newFakeIdP(t) + + // setup test server with client routes + baseUrl, _ := newTestServer(t, testServerParams{ + issuer: idpUrl, + returnToURL: "", + clientConfigID: "R4ND0M1D", + }) + + // go to /start + client := &http.Client{Timeout: 10 * time.Second} + resp, err := client.Get(baseUrl + "/oidc/start?issuer=" + idpUrl) + require.NoError(t, err) + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + require.NoError(t, err) + + require.Equal(t, 200, resp.StatusCode) + require.NotEqual(t, "config not found", string(body)) +} + +func TestRoute_callback(t *testing.T) { + log.Log.Logger.SetLevel(logrus.TraceLevel) + + // setup fake OIDC service + idpUrl := newFakeIdP(t) + + // setup test server with client routes + baseUrl, stateParam := newTestServer(t, testServerParams{ + issuer: idpUrl, + returnToURL: "/relative/url/to/some/page", + clientConfigID: "R4ND0M1D", + }) + state, err := encodeStateParam(*stateParam) + require.NoError(t, err) + + // hit the /callback endpoint + client := &http.Client{ + Timeout: 10 * time.Second, + CheckRedirect: func(req *http.Request, via []*http.Request) error { + return http.ErrUseLastResponse + }, + } + req, err := http.NewRequest("GET", baseUrl+"/oidc/callback?code=123&state="+state, nil) + require.NoError(t, err) + req.AddCookie(&http.Cookie{ + Name: "state", Value: state, MaxAge: 60, + }) + req.AddCookie(&http.Cookie{ + Name: "nonce", Value: "111", MaxAge: 60, + }) + resp, err := client.Do(req) + require.NoError(t, err) + defer resp.Body.Close() + + require.NoError(t, err) + require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode, "callback should response with redirect (307)") + + url, err := resp.Location() + require.NoError(t, err) + require.Equal(t, "/relative/url/to/some/page", url.Path, "callback redirects properly") + +} + +type testServerParams struct { + issuer string + returnToURL string + clientConfigID string + clientID string +} + +func newTestServer(t *testing.T, params testServerParams) (url string, state *StateParam) { + router := chi.NewRouter() + oidcService := NewService() + router.Mount("/oidc", Router(oidcService)) + + ts := httptest.NewServer(router) + url = ts.URL + + stateParam := &StateParam{ + ClientConfigID: params.clientConfigID, + ReturnToURL: params.returnToURL, + } + + oidcConfig := &goidc.Config{ + ClientID: params.clientConfigID, + SkipClientIDCheck: true, + SkipIssuerCheck: true, + SkipExpiryCheck: true, + InsecureSkipSignatureCheck: true, + } + oauth2Config := &oauth2.Config{ + ClientID: params.clientID, + ClientSecret: "secret", + RedirectURL: url + "/callback", + Scopes: []string{goidc.ScopeOpenID, "profile", "email"}, + } + clientConfig := &ClientConfig{ + Issuer: params.issuer, + ID: params.clientConfigID, + OAuth2Config: oauth2Config, + VerifierConfig: oidcConfig, + } + err := oidcService.AddClientConfig(clientConfig) + require.NoError(t, err) + + return url, stateParam +} diff --git a/components/iam/pkg/oidc/service.go b/components/iam/pkg/oidc/service.go new file mode 100644 index 00000000000000..848872bfba5830 --- /dev/null +++ b/components/iam/pkg/oidc/service.go @@ -0,0 +1,182 @@ +// Copyright (c) 2022 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License.AGPL.txt in the project root for license information. + +package oidc + +import ( + "bytes" + "context" + "crypto/rand" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/coreos/go-oidc/v3/oidc" + "golang.org/x/oauth2" +) + +type Service struct { + configsById map[string]*ClientConfig + verifierByIssuer map[string]*oidc.IDTokenVerifier + providerByIssuer map[string]*oidc.Provider +} + +type ClientConfig struct { + ID string + Issuer string + OAuth2Config *oauth2.Config + VerifierConfig *oidc.Config +} + +type StartParams struct { + State string + Nonce string + AuthCodeURL string +} + +type AuthFlowResult struct { + IDToken *oidc.IDToken +} + +func NewService() *Service { + var s Service + s.configsById = make(map[string]*ClientConfig) + s.verifierByIssuer = make(map[string]*oidc.IDTokenVerifier) + s.providerByIssuer = make(map[string]*oidc.Provider) + return &s +} + +func (s *Service) AddClientConfig(config *ClientConfig) error { + if s.providerByIssuer[config.Issuer] == nil { + provider, err := oidc.NewProvider(context.Background(), config.Issuer) + if err != nil { + return fmt.Errorf("OIDC discovery failed: %w", err) + } + s.providerByIssuer[config.Issuer] = provider + s.verifierByIssuer[config.Issuer] = provider.Verifier(config.VerifierConfig) + } + + config.OAuth2Config.Endpoint = s.providerByIssuer[config.Issuer].Endpoint() + s.configsById[config.ID] = config + return nil +} + +func (s *Service) GetStartParams(config *ClientConfig) (*StartParams, error) { + // state is supposed to a) be present on client request as cookie header + // and b) to be mirrored by the IdP on callback requests. + stateParam := StateParam{ + ClientConfigID: config.ID, + + // TODO(at) read a relative URL from `returnTo` query param of the start request + ReturnToURL: "/", + } + state, err := encodeStateParam(stateParam) + if err != nil { + return nil, fmt.Errorf("failed to encode state") + } + + // number used once + nonce, err := randString(32) + if err != nil { + return nil, fmt.Errorf("failed to create nonce") + } + + // Nonce is the single option passed on to configure the consent page ATM. + authCodeURL := config.OAuth2Config.AuthCodeURL(state, oidc.Nonce(nonce)) + + return &StartParams{ + AuthCodeURL: authCodeURL, + State: state, + Nonce: nonce, + }, nil +} + +// TODO(at) state should be a JWT encoding a redirect location +// For now, just use base64 +func encodeStateParam(state StateParam) (string, error) { + var buf bytes.Buffer + encoder := base64.NewEncoder(base64.StdEncoding, &buf) + err := json.NewEncoder(encoder).Encode(state) + if err != nil { + return "", err + } + encoder.Close() + return buf.String(), nil +} + +func decodeStateParam(encoded string) (StateParam, error) { + var result StateParam + err := json.NewDecoder(base64.NewDecoder(base64.StdEncoding, strings.NewReader(encoded))).Decode(&result) + return result, err +} + +func randString(size int) (string, error) { + b := make([]byte, size) + if _, err := io.ReadFull(rand.Reader, b); err != nil { + return "", err + } + return base64.RawURLEncoding.EncodeToString(b), nil +} + +func (s *Service) GetClientConfigFromRequest(r *http.Request) (*ClientConfig, error) { + issuerParam := r.URL.Query().Get("issuer") + stateParam := r.URL.Query().Get("state") + if issuerParam == "" && stateParam == "" { + return nil, fmt.Errorf("missing request parameters") + } + + if issuerParam != "" { + for _, value := range s.configsById { + if value.Issuer == issuerParam { + return value, nil + } + } + } + + if stateParam != "" { + state, err := decodeStateParam(stateParam) + if err != nil { + return nil, fmt.Errorf("bad state param") + } + config := s.configsById[state.ClientConfigID] + if config != nil { + return config, nil + } + } + + return nil, fmt.Errorf("failed to find OIDC config for request") +} + +type AuthenticateParams struct { + OAuth2Result *OAuth2Result + Issuer string + NonceCookieValue string +} + +func (s *Service) Authenticate(ctx context.Context, params AuthenticateParams) (*AuthFlowResult, error) { + rawIDToken, ok := params.OAuth2Result.OAuth2Token.Extra("id_token").(string) + if !ok { + return nil, fmt.Errorf("id_token not found") + } + + verifier := s.verifierByIssuer[params.Issuer] + if verifier == nil { + return nil, fmt.Errorf("verifier not found") + } + + idToken, err := verifier.Verify(ctx, rawIDToken) + if err != nil { + return nil, fmt.Errorf("failed to verify id_token: %w", err) + } + + if idToken.Nonce != params.NonceCookieValue { + return nil, fmt.Errorf("nonce mismatch") + } + return &AuthFlowResult{ + IDToken: idToken, + }, nil +} diff --git a/components/iam/pkg/oidc/service_test.go b/components/iam/pkg/oidc/service_test.go new file mode 100644 index 00000000000000..8ec3e90c58d2e5 --- /dev/null +++ b/components/iam/pkg/oidc/service_test.go @@ -0,0 +1,274 @@ +// Copyright (c) 2022 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License.AGPL.txt in the project root for license information. + +package oidc + +import ( + "context" + "fmt" + "log" + "net/http" + "net/http/httptest" + "net/url" + "testing" + + "github.com/coreos/go-oidc/v3/oidc" + "github.com/go-chi/chi/v5" + "github.com/go-chi/chi/v5/middleware" + "github.com/stretchr/testify/require" + "golang.org/x/oauth2" +) + +func TestGetStartParams(t *testing.T) { + const ( + issuerG = "https://accounts.google.com" + clientID = "client-id-123" + ) + service := NewService() + config := &ClientConfig{ + ID: "google-1", + Issuer: issuerG, + VerifierConfig: &oidc.Config{}, + OAuth2Config: &oauth2.Config{ + ClientID: clientID, + Endpoint: oauth2.Endpoint{ + AuthURL: issuerG + "/o/oauth2/v2/auth", + }, + }, + } + + params, err := service.GetStartParams(config) + + require.NoError(t, err) + require.NotNil(t, params.Nonce) + require.NotNil(t, params.State) + + // AuthCodeURL example: + // https://accounts.google.com/o/oauth2/v2/auth + // ?client_id=client-id-123 + // &nonce=UFTMxxUtc5jVZbp2a2R9XEoRwpfzs-04FcmVQ-HdCsw + // &response_type=code + // &state=Q4XzRcdo4jtOYeRbF17T9LHHwX-4HacT1_5pZH8mXLI + require.NotNil(t, params.AuthCodeURL) + require.Contains(t, params.AuthCodeURL, issuerG) + require.Contains(t, params.AuthCodeURL, clientID) + require.Contains(t, params.AuthCodeURL, url.QueryEscape(params.Nonce)) + require.Contains(t, params.AuthCodeURL, url.QueryEscape(params.State)) +} + +func TestGetClientConfigFromRequest(t *testing.T) { + issuer := newFakeIdP(t) + + const ( + clientID = "google-1" + ) + + state, err := encodeStateParam(StateParam{ + ClientConfigID: clientID, + ReturnToURL: "", + }) + require.NoError(t, err, "failed encode state param") + + state_unknown, err := encodeStateParam(StateParam{ + ClientConfigID: "UNKNOWN", + ReturnToURL: "", + }) + require.NoError(t, err, "failed encode state param") + + testCases := []struct { + Location string + ExpectedError bool + ExpectedId string + }{ + { + Location: "/start?word=abc", + ExpectedError: true, + ExpectedId: "", + }, + { + Location: "/start?issuer=" + issuer, + ExpectedError: false, + ExpectedId: clientID, + }, + { + Location: "/start?issuer=UNKNOWN", + ExpectedError: true, + ExpectedId: "", + }, + { + Location: "/callback?state=BAD", + ExpectedError: true, + ExpectedId: "", + }, + { + Location: "/callback?state=" + state_unknown, + ExpectedError: true, + ExpectedId: "", + }, + { + Location: "/callback?state=" + state, + ExpectedError: false, + ExpectedId: clientID, + }, + } + + service := NewService() + err = service.AddClientConfig(&ClientConfig{ + ID: clientID, + Issuer: issuer, + VerifierConfig: &oidc.Config{}, + OAuth2Config: &oauth2.Config{}, + }) + require.NoError(t, err, "failed to initialize test") + + for _, tc := range testCases { + t.Run(tc.Location, func(t *testing.T) { + request := httptest.NewRequest(http.MethodGet, tc.Location, nil) + config, err := service.GetClientConfigFromRequest(request) + if tc.ExpectedError == true { + require.Error(t, err) + } + if tc.ExpectedError != true { + require.NoError(t, err) + require.NotNil(t, config) + require.Equal(t, tc.ExpectedId, config.ID) + } + }) + } +} + +func TestAuthenticate_nonce_check(t *testing.T) { + issuer := newFakeIdP(t) + + service := NewService() + err := service.AddClientConfig(&ClientConfig{ + ID: "google-1", + Issuer: issuer, + VerifierConfig: &oidc.Config{ + SkipClientIDCheck: true, + SkipIssuerCheck: true, + SkipExpiryCheck: true, + InsecureSkipSignatureCheck: true, + }, + OAuth2Config: &oauth2.Config{}, + }) + require.NoError(t, err, "failed to initialize test") + + token := oauth2.Token{} + extra := map[string]interface{}{ + "id_token": `eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkN1bXF1YXQgRG9wdGlnIiwibm9uY2UiOiIxMTEiLCJpYXQiOjE1MTYyMzkwMjJ9.NfbRZns-Sefhw6MT4ULWMj_7bX0vScklaZA2ObCYkStYlo2SvNu5Be79-5Lwcy4GY95vY_dFvLIKrZjfqv_duURSKLUbtH8VxskhcrW4sPAK2R5lzz62a6d_OnVydjNJRZf754TQZILAzMm81tEDNAJSDQjaTFl7t8Bp0iYapNyyH9ZoBrGAPaZkXHYoq4lNH88gCZj5JMRIbrZbsvhOuR3CAzbAMplOmKIWxhFVnHdm6aq6HRjz0ra6Y7yh0R9jEF3vWl2w5D3aN4XESPNBbyB3CHKQ5TG0WkbgdUpv1wwzbPfz4aFHOt--qLy7ZK0TOrS-A7YLFFsJKtoPGRjAPA`, + } + + result, err := service.Authenticate(context.Background(), AuthenticateParams{ + OAuth2Result: &OAuth2Result{ + OAuth2Token: token.WithExtra(extra), + }, + NonceCookieValue: "111", + Issuer: issuer, + }) + + require.NoError(t, err, "failed to authenticate") + require.NotNil(t, result) +} + +func newFakeIdP(t *testing.T) string { + router := chi.NewRouter() + ts := httptest.NewServer(router) + url := ts.URL + + router.Use(middleware.Logger) + router.Get("/oauth2/v3/certs", func(w http.ResponseWriter, r *http.Request) { + _, err := w.Write([]byte(`{ + "keys": [ + ] + }`)) + if err != nil { + log.Fatal(err) + } + }) + router.Get("/o/oauth2/v2/auth", func(w http.ResponseWriter, r *http.Request) { + _, err := w.Write([]byte(r.URL.RawQuery)) + if err != nil { + log.Fatal(err) + } + }) + router.Post("/token", func(w http.ResponseWriter, r *http.Request) { + w.Header().Add("Content-Type", "application/json") + _, err := w.Write([]byte(`{ + "access_token": "no-token-set", + "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkN1bXF1YXQgRG9wdGlnIiwibm9uY2UiOiIxMTEiLCJpYXQiOjE1MTYyMzkwMjJ9.NfbRZns-Sefhw6MT4ULWMj_7bX0vScklaZA2ObCYkStYlo2SvNu5Be79-5Lwcy4GY95vY_dFvLIKrZjfqv_duURSKLUbtH8VxskhcrW4sPAK2R5lzz62a6d_OnVydjNJRZf754TQZILAzMm81tEDNAJSDQjaTFl7t8Bp0iYapNyyH9ZoBrGAPaZkXHYoq4lNH88gCZj5JMRIbrZbsvhOuR3CAzbAMplOmKIWxhFVnHdm6aq6HRjz0ra6Y7yh0R9jEF3vWl2w5D3aN4XESPNBbyB3CHKQ5TG0WkbgdUpv1wwzbPfz4aFHOt--qLy7ZK0TOrS-A7YLFFsJKtoPGRjAPA" + }`)) + if err != nil { + log.Fatal(err) + } + }) + router.Get("/.well-known/openid-configuration", func(w http.ResponseWriter, r *http.Request) { + w.Header().Add("Content-Type", "application/json") + _, err := w.Write([]byte(fmt.Sprintf(`{ + "issuer": "%[1]s", + "authorization_endpoint": "%[1]s/o/oauth2/v2/auth", + "device_authorization_endpoint": "%[1]s/device/code", + "token_endpoint": "%[1]s/token", + "userinfo_endpoint": "%[1]s/v1/userinfo", + "revocation_endpoint": "%[1]s/revoke", + "jwks_uri": "%[1]s/oauth2/v3/certs", + "response_types_supported": [ + "code", + "token", + "id_token", + "code token", + "code id_token", + "token id_token", + "code token id_token", + "none" + ], + "subject_types_supported": [ + "public" + ], + "id_token_signing_alg_values_supported": [ + "RS256" + ], + "scopes_supported": [ + "openid", + "email", + "profile" + ], + "token_endpoint_auth_methods_supported": [ + "client_secret_post", + "client_secret_basic" + ], + "claims_supported": [ + "aud", + "email", + "email_verified", + "exp", + "family_name", + "given_name", + "iat", + "iss", + "locale", + "name", + "picture", + "sub" + ], + "code_challenge_methods_supported": [ + "plain", + "S256" + ], + "grant_types_supported": [ + "authorization_code", + "refresh_token", + "urn:ietf:params:oauth:grant-type:device_code", + "urn:ietf:params:oauth:grant-type:jwt-bearer" + ] + }`, url))) + if err != nil { + t.Error((err)) + t.FailNow() + } + }) + + t.Cleanup(ts.Close) + return url +} diff --git a/components/iam/pkg/server/server.go b/components/iam/pkg/server/server.go index b8865068bdce26..006667ef4f0bb7 100644 --- a/components/iam/pkg/server/server.go +++ b/components/iam/pkg/server/server.go @@ -7,30 +7,46 @@ package server import ( "fmt" + goidc "github.com/coreos/go-oidc/v3/oidc" "github.com/gitpod-io/gitpod/common-go/baseserver" "github.com/gitpod-io/gitpod/iam/pkg/config" "github.com/gitpod-io/gitpod/iam/pkg/oidc" "github.com/go-chi/chi/v5" "github.com/sirupsen/logrus" + "golang.org/x/oauth2" ) func Start(logger *logrus.Entry, version string, cfg *config.ServiceConfig) error { logger.WithField("config", cfg).Info("Starting IAM server.") + logger.Logger.SetLevel(logrus.TraceLevel) + srv, err := baseserver.New("iam", baseserver.WithLogger(logger), baseserver.WithConfig(cfg.Server), baseserver.WithVersion(version), ) if err != nil { - return fmt.Errorf("failed to initialize iam server: %w", err) + return fmt.Errorf("failed to initialize IAM server: %w", err) } - err = register(srv) + // All root requests are handled by our router + rootHandler, err := registerRootRouter(srv) if err != nil { return fmt.Errorf("failed to register services to iam server") } + // Requests to /oidc/* are handled by oidc.Router + oidcService := oidc.NewService() + rootHandler.Mount("/oidc", oidc.Router(oidcService)) + + // TODO(at) remove the demo config after start sync'ing with DB + err = loadTestConfig(oidcService, cfg) + if err != nil { + logger.Errorf("failed to load test config: " + err.Error()) + // return fmt.Errorf("failed to load test config: %w", err) + } + if listenErr := srv.ListenAndServe(); listenErr != nil { return fmt.Errorf("failed to serve iam server: %w", listenErr) } @@ -38,11 +54,34 @@ func Start(logger *logrus.Entry, version string, cfg *config.ServiceConfig) erro return nil } -func register(srv *baseserver.Server) error { - router := chi.NewMux() - router.Mount("/oidc", oidc.Router()) +func registerRootRouter(srv *baseserver.Server) (*chi.Mux, error) { + rootHandler := chi.NewRouter() - // All root requests are handled by our router - srv.HTTPMux().Handle("/", router) - return nil + srv.HTTPMux().Handle("/", rootHandler) + return rootHandler, nil +} + +// TODO(at) remove the demo config after start sync'ing with DB +func loadTestConfig(oidcService *oidc.Service, cfg *config.ServiceConfig) error { + testConfig, err := oidc.ReadDemoConfigFromFile(cfg.OIDCClientsConfigFile) + if err != nil { + return fmt.Errorf("failed to read test config: %w", err) + } + oidcConfig := &goidc.Config{ + ClientID: testConfig.ClientID, + } + oauth2Config := &oauth2.Config{ + ClientID: testConfig.ClientID, + ClientSecret: testConfig.ClientSecret, + RedirectURL: testConfig.RedirectURL, + Scopes: []string{goidc.ScopeOpenID, "profile", "email"}, + } + clientConfig := &oidc.ClientConfig{ + Issuer: testConfig.Issuer, + ID: "R4ND0M1D", + OAuth2Config: oauth2Config, + VerifierConfig: oidcConfig, + } + err = oidcService.AddClientConfig(clientConfig) + return err } diff --git a/components/iam/telepresence.sh b/components/iam/telepresence.sh new file mode 100755 index 00000000000000..911a0987be6abc --- /dev/null +++ b/components/iam/telepresence.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +# TODO(at) add config mounts + +telepresence --swap-deployment iam --expose 9002 --method vpn-tcp --run go run . run diff --git a/components/ide-service-api/go/ide.pb.go b/components/ide-service-api/go/ide.pb.go index fdbadd0c94bcea..de75561c04c1be 100644 --- a/components/ide-service-api/go/ide.pb.go +++ b/components/ide-service-api/go/ide.pb.go @@ -212,6 +212,53 @@ func (x *EnvironmentVariable) GetValue() string { return "" } +type User struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *User) Reset() { + *x = User{} + if protoimpl.UnsafeEnabled { + mi := &file_ide_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *User) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*User) ProtoMessage() {} + +func (x *User) ProtoReflect() protoreflect.Message { + mi := &file_ide_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use User.ProtoReflect.Descriptor instead. +func (*User) Descriptor() ([]byte, []int) { + return file_ide_proto_rawDescGZIP(), []int{3} +} + +func (x *User) GetId() string { + if x != nil { + return x.Id + } + return "" +} + type ResolveWorkspaceConfigRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -221,12 +268,13 @@ type ResolveWorkspaceConfigRequest struct { Context string `protobuf:"bytes,2,opt,name=context,proto3" json:"context,omitempty"` IdeSettings string `protobuf:"bytes,3,opt,name=ide_settings,json=ideSettings,proto3" json:"ide_settings,omitempty"` WorkspaceConfig string `protobuf:"bytes,4,opt,name=workspace_config,json=workspaceConfig,proto3" json:"workspace_config,omitempty"` + User *User `protobuf:"bytes,5,opt,name=user,proto3" json:"user,omitempty"` } func (x *ResolveWorkspaceConfigRequest) Reset() { *x = ResolveWorkspaceConfigRequest{} if protoimpl.UnsafeEnabled { - mi := &file_ide_proto_msgTypes[3] + mi := &file_ide_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -239,7 +287,7 @@ func (x *ResolveWorkspaceConfigRequest) String() string { func (*ResolveWorkspaceConfigRequest) ProtoMessage() {} func (x *ResolveWorkspaceConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_ide_proto_msgTypes[3] + mi := &file_ide_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -252,7 +300,7 @@ func (x *ResolveWorkspaceConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveWorkspaceConfigRequest.ProtoReflect.Descriptor instead. func (*ResolveWorkspaceConfigRequest) Descriptor() ([]byte, []int) { - return file_ide_proto_rawDescGZIP(), []int{3} + return file_ide_proto_rawDescGZIP(), []int{4} } func (x *ResolveWorkspaceConfigRequest) GetType() WorkspaceType { @@ -283,6 +331,13 @@ func (x *ResolveWorkspaceConfigRequest) GetWorkspaceConfig() string { return "" } +func (x *ResolveWorkspaceConfigRequest) GetUser() *User { + if x != nil { + return x.User + } + return nil +} + type ResolveWorkspaceConfigResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -300,7 +355,7 @@ type ResolveWorkspaceConfigResponse struct { func (x *ResolveWorkspaceConfigResponse) Reset() { *x = ResolveWorkspaceConfigResponse{} if protoimpl.UnsafeEnabled { - mi := &file_ide_proto_msgTypes[4] + mi := &file_ide_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -313,7 +368,7 @@ func (x *ResolveWorkspaceConfigResponse) String() string { func (*ResolveWorkspaceConfigResponse) ProtoMessage() {} func (x *ResolveWorkspaceConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_ide_proto_msgTypes[4] + mi := &file_ide_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -326,7 +381,7 @@ func (x *ResolveWorkspaceConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveWorkspaceConfigResponse.ProtoReflect.Descriptor instead. func (*ResolveWorkspaceConfigResponse) Descriptor() ([]byte, []int) { - return file_ide_proto_rawDescGZIP(), []int{4} + return file_ide_proto_rawDescGZIP(), []int{5} } func (x *ResolveWorkspaceConfigResponse) GetEnvvars() []*EnvironmentVariable { @@ -384,57 +439,62 @@ var file_ide_proto_rawDesc = []byte{ 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x22, 0xbb, 0x01, 0x0a, 0x1d, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x32, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x1e, 0x2e, 0x69, 0x64, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, - 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x64, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x64, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x77, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x89, - 0x02, 0x0a, 0x1e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x3e, 0x0a, 0x07, 0x65, 0x6e, 0x76, 0x76, 0x61, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x69, 0x64, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, - 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x07, 0x65, 0x6e, 0x76, 0x76, 0x61, 0x72, - 0x73, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x75, 0x70, 0x65, 0x72, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x5f, - 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x75, 0x70, - 0x65, 0x72, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, - 0x77, 0x65, 0x62, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x77, 0x65, 0x62, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x69, 0x64, 0x65, - 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x64, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x4c, 0x61, 0x79, - 0x65, 0x72, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, - 0x72, 0x49, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x2a, 0x2a, 0x0a, 0x0d, 0x57, 0x6f, - 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x52, - 0x45, 0x47, 0x55, 0x4c, 0x41, 0x52, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x52, 0x45, 0x42, - 0x55, 0x49, 0x4c, 0x44, 0x10, 0x01, 0x32, 0xdf, 0x01, 0x0a, 0x0a, 0x49, 0x44, 0x45, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x54, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x21, 0x2e, 0x69, 0x64, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x69, 0x64, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, + 0x22, 0x16, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0xe6, 0x01, 0x0a, 0x1d, 0x52, 0x65, 0x73, + 0x6f, 0x6c, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x69, 0x64, 0x65, 0x5f, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, + 0x70, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x64, 0x65, 0x5f, + 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x69, 0x64, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x77, + 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x29, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x69, 0x64, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, + 0x72, 0x22, 0x89, 0x02, 0x0a, 0x1e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x57, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x07, 0x65, 0x6e, 0x76, 0x76, 0x61, 0x72, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x69, 0x64, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, + 0x65, 0x6e, 0x74, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x07, 0x65, 0x6e, 0x76, + 0x76, 0x61, 0x72, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x73, 0x75, 0x70, 0x65, 0x72, 0x76, 0x69, 0x73, + 0x6f, 0x72, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, + 0x73, 0x75, 0x70, 0x65, 0x72, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, + 0x1b, 0x0a, 0x09, 0x77, 0x65, 0x62, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x77, 0x65, 0x62, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x10, + 0x69, 0x64, 0x65, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x64, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, + 0x4c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x66, + 0x65, 0x72, 0x65, 0x72, 0x49, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x2a, 0x2a, 0x0a, + 0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, + 0x0a, 0x07, 0x52, 0x45, 0x47, 0x55, 0x4c, 0x41, 0x52, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x50, + 0x52, 0x45, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x10, 0x01, 0x32, 0xe5, 0x01, 0x0a, 0x0a, 0x49, 0x44, + 0x45, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x57, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x21, 0x2e, 0x69, 0x64, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x7b, 0x0a, 0x16, 0x52, - 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e, 0x2e, 0x69, 0x64, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x57, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x69, 0x64, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x57, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x47, 0x0a, 0x18, 0x69, 0x6f, 0x2e, 0x67, - 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x69, 0x64, 0x65, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x2e, 0x61, 0x70, 0x69, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2d, 0x69, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, - 0x64, 0x2f, 0x69, 0x64, 0x65, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x61, 0x70, - 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x69, 0x64, 0x65, 0x5f, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, + 0x02, 0x12, 0x7e, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e, 0x2e, 0x69, 0x64, + 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, + 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x69, 0x64, + 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, + 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, + 0x02, 0x42, 0x47, 0x0a, 0x18, 0x69, 0x6f, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x69, + 0x64, 0x65, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x5a, 0x2b, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, + 0x2d, 0x69, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, 0x69, 0x64, 0x65, 0x2d, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -450,27 +510,29 @@ func file_ide_proto_rawDescGZIP() []byte { } var file_ide_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_ide_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_ide_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_ide_proto_goTypes = []interface{}{ (WorkspaceType)(0), // 0: ide_service_api.WorkspaceType (*GetConfigRequest)(nil), // 1: ide_service_api.GetConfigRequest (*GetConfigResponse)(nil), // 2: ide_service_api.GetConfigResponse (*EnvironmentVariable)(nil), // 3: ide_service_api.EnvironmentVariable - (*ResolveWorkspaceConfigRequest)(nil), // 4: ide_service_api.ResolveWorkspaceConfigRequest - (*ResolveWorkspaceConfigResponse)(nil), // 5: ide_service_api.ResolveWorkspaceConfigResponse + (*User)(nil), // 4: ide_service_api.User + (*ResolveWorkspaceConfigRequest)(nil), // 5: ide_service_api.ResolveWorkspaceConfigRequest + (*ResolveWorkspaceConfigResponse)(nil), // 6: ide_service_api.ResolveWorkspaceConfigResponse } var file_ide_proto_depIdxs = []int32{ 0, // 0: ide_service_api.ResolveWorkspaceConfigRequest.type:type_name -> ide_service_api.WorkspaceType - 3, // 1: ide_service_api.ResolveWorkspaceConfigResponse.envvars:type_name -> ide_service_api.EnvironmentVariable - 1, // 2: ide_service_api.IDEService.GetConfig:input_type -> ide_service_api.GetConfigRequest - 4, // 3: ide_service_api.IDEService.ResolveWorkspaceConfig:input_type -> ide_service_api.ResolveWorkspaceConfigRequest - 2, // 4: ide_service_api.IDEService.GetConfig:output_type -> ide_service_api.GetConfigResponse - 5, // 5: ide_service_api.IDEService.ResolveWorkspaceConfig:output_type -> ide_service_api.ResolveWorkspaceConfigResponse - 4, // [4:6] is the sub-list for method output_type - 2, // [2:4] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name + 4, // 1: ide_service_api.ResolveWorkspaceConfigRequest.user:type_name -> ide_service_api.User + 3, // 2: ide_service_api.ResolveWorkspaceConfigResponse.envvars:type_name -> ide_service_api.EnvironmentVariable + 1, // 3: ide_service_api.IDEService.GetConfig:input_type -> ide_service_api.GetConfigRequest + 5, // 4: ide_service_api.IDEService.ResolveWorkspaceConfig:input_type -> ide_service_api.ResolveWorkspaceConfigRequest + 2, // 5: ide_service_api.IDEService.GetConfig:output_type -> ide_service_api.GetConfigResponse + 6, // 6: ide_service_api.IDEService.ResolveWorkspaceConfig:output_type -> ide_service_api.ResolveWorkspaceConfigResponse + 5, // [5:7] is the sub-list for method output_type + 3, // [3:5] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name } func init() { file_ide_proto_init() } @@ -516,7 +578,7 @@ func file_ide_proto_init() { } } file_ide_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResolveWorkspaceConfigRequest); i { + switch v := v.(*User); i { case 0: return &v.state case 1: @@ -528,6 +590,18 @@ func file_ide_proto_init() { } } file_ide_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ResolveWorkspaceConfigRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ide_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ResolveWorkspaceConfigResponse); i { case 0: return &v.state @@ -546,7 +620,7 @@ func file_ide_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_ide_proto_rawDesc, NumEnums: 1, - NumMessages: 5, + NumMessages: 6, NumExtensions: 0, NumServices: 1, }, diff --git a/components/ide-service-api/ide.proto b/components/ide-service-api/ide.proto index 604eb4744a3e44..34df10b61a297f 100644 --- a/components/ide-service-api/ide.proto +++ b/components/ide-service-api/ide.proto @@ -10,8 +10,12 @@ option go_package = "github.com/gitpod-io/gitpod/ide-service/api"; option java_package = "io.gitpod.ideservice.api"; service IDEService { - rpc GetConfig(GetConfigRequest) returns (GetConfigResponse) {} - rpc ResolveWorkspaceConfig(ResolveWorkspaceConfigRequest) returns (ResolveWorkspaceConfigResponse) {} + rpc GetConfig(GetConfigRequest) returns (GetConfigResponse) { + option idempotency_level = IDEMPOTENT; + } + rpc ResolveWorkspaceConfig(ResolveWorkspaceConfigRequest) returns (ResolveWorkspaceConfigResponse) { + option idempotency_level = IDEMPOTENT; + } } message GetConfigRequest {} @@ -32,12 +36,16 @@ enum WorkspaceType { PREBUILD = 1; } +message User { + string id = 1; +} message ResolveWorkspaceConfigRequest { WorkspaceType type = 1; string context = 2; string ide_settings = 3; string workspace_config = 4; + User user = 5; } message ResolveWorkspaceConfigResponse { diff --git a/components/ide-service-api/typescript/src/ide.pb.ts b/components/ide-service-api/typescript/src/ide.pb.ts index 9e7c8a784ee582..5ea8f3a8b76e0d 100644 --- a/components/ide-service-api/typescript/src/ide.pb.ts +++ b/components/ide-service-api/typescript/src/ide.pb.ts @@ -11,54 +11,55 @@ import * as _m0 from "protobufjs/minimal"; export const protobufPackage = "ide_service_api"; export enum WorkspaceType { - REGULAR = "REGULAR", - PREBUILD = "PREBUILD", - UNRECOGNIZED = "UNRECOGNIZED", + REGULAR = "REGULAR", + PREBUILD = "PREBUILD", + UNRECOGNIZED = "UNRECOGNIZED", } export function workspaceTypeFromJSON(object: any): WorkspaceType { - switch (object) { - case 0: - case "REGULAR": - return WorkspaceType.REGULAR; - case 1: - case "PREBUILD": - return WorkspaceType.PREBUILD; - case -1: - case "UNRECOGNIZED": - default: - return WorkspaceType.UNRECOGNIZED; - } + switch (object) { + case 0: + case "REGULAR": + return WorkspaceType.REGULAR; + case 1: + case "PREBUILD": + return WorkspaceType.PREBUILD; + case -1: + case "UNRECOGNIZED": + default: + return WorkspaceType.UNRECOGNIZED; + } } export function workspaceTypeToJSON(object: WorkspaceType): string { - switch (object) { - case WorkspaceType.REGULAR: - return "REGULAR"; - case WorkspaceType.PREBUILD: - return "PREBUILD"; - case WorkspaceType.UNRECOGNIZED: - default: - return "UNRECOGNIZED"; - } + switch (object) { + case WorkspaceType.REGULAR: + return "REGULAR"; + case WorkspaceType.PREBUILD: + return "PREBUILD"; + case WorkspaceType.UNRECOGNIZED: + default: + return "UNRECOGNIZED"; + } } export function workspaceTypeToNumber(object: WorkspaceType): number { - switch (object) { - case WorkspaceType.REGULAR: - return 0; - case WorkspaceType.PREBUILD: - return 1; - case WorkspaceType.UNRECOGNIZED: - default: - return -1; - } + switch (object) { + case WorkspaceType.REGULAR: + return 0; + case WorkspaceType.PREBUILD: + return 1; + case WorkspaceType.UNRECOGNIZED: + default: + return -1; + } } -export interface GetConfigRequest {} +export interface GetConfigRequest { +} export interface GetConfigResponse { - content: string; + content: string; } /** @@ -66,420 +67,466 @@ export interface GetConfigResponse { * EnvironmentVariable describes an env var as key/value pair */ export interface EnvironmentVariable { - name: string; - value: string; + name: string; + value: string; +} + +export interface User { + id: string; } export interface ResolveWorkspaceConfigRequest { - type: WorkspaceType; - context: string; - ideSettings: string; - workspaceConfig: string; + type: WorkspaceType; + context: string; + ideSettings: string; + workspaceConfig: string; + user: User | undefined; } export interface ResolveWorkspaceConfigResponse { - envvars: EnvironmentVariable[]; - supervisorImage: string; - webImage: string; - ideImageLayers: string[]; - /** control whether to configure default IDE for a user */ - refererIde: string; - tasks: string; + envvars: EnvironmentVariable[]; + supervisorImage: string; + webImage: string; + ideImageLayers: string[]; + /** control whether to configure default IDE for a user */ + refererIde: string; + tasks: string; } function createBaseGetConfigRequest(): GetConfigRequest { - return {}; + return {}; } export const GetConfigRequest = { - encode(_: GetConfigRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - return writer; - }, + encode(_: GetConfigRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): GetConfigRequest { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseGetConfigRequest(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, - decode(input: _m0.Reader | Uint8Array, length?: number): GetConfigRequest { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseGetConfigRequest(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, + fromJSON(_: any): GetConfigRequest { + return {}; + }, - fromJSON(_: any): GetConfigRequest { - return {}; - }, + toJSON(_: GetConfigRequest): unknown { + const obj: any = {}; + return obj; + }, - toJSON(_: GetConfigRequest): unknown { - const obj: any = {}; - return obj; - }, - - fromPartial(_: DeepPartial): GetConfigRequest { - const message = createBaseGetConfigRequest(); - return message; - }, + fromPartial(_: DeepPartial): GetConfigRequest { + const message = createBaseGetConfigRequest(); + return message; + }, }; function createBaseGetConfigResponse(): GetConfigResponse { - return { content: "" }; + return { content: "" }; } export const GetConfigResponse = { - encode(message: GetConfigResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.content !== "") { - writer.uint32(10).string(message.content); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): GetConfigResponse { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseGetConfigResponse(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.content = reader.string(); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): GetConfigResponse { - return { content: isSet(object.content) ? String(object.content) : "" }; - }, - - toJSON(message: GetConfigResponse): unknown { - const obj: any = {}; - message.content !== undefined && (obj.content = message.content); - return obj; - }, - - fromPartial(object: DeepPartial): GetConfigResponse { - const message = createBaseGetConfigResponse(); - message.content = object.content ?? ""; - return message; - }, + encode(message: GetConfigResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.content !== "") { + writer.uint32(10).string(message.content); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): GetConfigResponse { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseGetConfigResponse(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.content = reader.string(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): GetConfigResponse { + return { content: isSet(object.content) ? String(object.content) : "" }; + }, + + toJSON(message: GetConfigResponse): unknown { + const obj: any = {}; + message.content !== undefined && (obj.content = message.content); + return obj; + }, + + fromPartial(object: DeepPartial): GetConfigResponse { + const message = createBaseGetConfigResponse(); + message.content = object.content ?? ""; + return message; + }, }; function createBaseEnvironmentVariable(): EnvironmentVariable { - return { name: "", value: "" }; + return { name: "", value: "" }; } export const EnvironmentVariable = { - encode(message: EnvironmentVariable, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.name !== "") { - writer.uint32(10).string(message.name); - } - if (message.value !== "") { - writer.uint32(18).string(message.value); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): EnvironmentVariable { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseEnvironmentVariable(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.name = reader.string(); - break; - case 2: - message.value = reader.string(); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): EnvironmentVariable { - return { - name: isSet(object.name) ? String(object.name) : "", - value: isSet(object.value) ? String(object.value) : "", - }; - }, + encode(message: EnvironmentVariable, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.name !== "") { + writer.uint32(10).string(message.name); + } + if (message.value !== "") { + writer.uint32(18).string(message.value); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): EnvironmentVariable { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseEnvironmentVariable(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.name = reader.string(); + break; + case 2: + message.value = reader.string(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): EnvironmentVariable { + return { + name: isSet(object.name) ? String(object.name) : "", + value: isSet(object.value) ? String(object.value) : "", + }; + }, + + toJSON(message: EnvironmentVariable): unknown { + const obj: any = {}; + message.name !== undefined && (obj.name = message.name); + message.value !== undefined && (obj.value = message.value); + return obj; + }, + + fromPartial(object: DeepPartial): EnvironmentVariable { + const message = createBaseEnvironmentVariable(); + message.name = object.name ?? ""; + message.value = object.value ?? ""; + return message; + }, +}; - toJSON(message: EnvironmentVariable): unknown { - const obj: any = {}; - message.name !== undefined && (obj.name = message.name); - message.value !== undefined && (obj.value = message.value); - return obj; - }, +function createBaseUser(): User { + return { id: "" }; +} - fromPartial(object: DeepPartial): EnvironmentVariable { - const message = createBaseEnvironmentVariable(); - message.name = object.name ?? ""; - message.value = object.value ?? ""; - return message; - }, +export const User = { + encode(message: User, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.id !== "") { + writer.uint32(10).string(message.id); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): User { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseUser(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.id = reader.string(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): User { + return { id: isSet(object.id) ? String(object.id) : "" }; + }, + + toJSON(message: User): unknown { + const obj: any = {}; + message.id !== undefined && (obj.id = message.id); + return obj; + }, + + fromPartial(object: DeepPartial): User { + const message = createBaseUser(); + message.id = object.id ?? ""; + return message; + }, }; function createBaseResolveWorkspaceConfigRequest(): ResolveWorkspaceConfigRequest { - return { type: WorkspaceType.REGULAR, context: "", ideSettings: "", workspaceConfig: "" }; + return { type: WorkspaceType.REGULAR, context: "", ideSettings: "", workspaceConfig: "", user: undefined }; } export const ResolveWorkspaceConfigRequest = { - encode(message: ResolveWorkspaceConfigRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.type !== WorkspaceType.REGULAR) { - writer.uint32(8).int32(workspaceTypeToNumber(message.type)); - } - if (message.context !== "") { - writer.uint32(18).string(message.context); - } - if (message.ideSettings !== "") { - writer.uint32(26).string(message.ideSettings); - } - if (message.workspaceConfig !== "") { - writer.uint32(34).string(message.workspaceConfig); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): ResolveWorkspaceConfigRequest { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseResolveWorkspaceConfigRequest(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.type = workspaceTypeFromJSON(reader.int32()); - break; - case 2: - message.context = reader.string(); - break; - case 3: - message.ideSettings = reader.string(); - break; - case 4: - message.workspaceConfig = reader.string(); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): ResolveWorkspaceConfigRequest { - return { - type: isSet(object.type) ? workspaceTypeFromJSON(object.type) : WorkspaceType.REGULAR, - context: isSet(object.context) ? String(object.context) : "", - ideSettings: isSet(object.ideSettings) ? String(object.ideSettings) : "", - workspaceConfig: isSet(object.workspaceConfig) ? String(object.workspaceConfig) : "", - }; - }, - - toJSON(message: ResolveWorkspaceConfigRequest): unknown { - const obj: any = {}; - message.type !== undefined && (obj.type = workspaceTypeToJSON(message.type)); - message.context !== undefined && (obj.context = message.context); - message.ideSettings !== undefined && (obj.ideSettings = message.ideSettings); - message.workspaceConfig !== undefined && (obj.workspaceConfig = message.workspaceConfig); - return obj; - }, - - fromPartial(object: DeepPartial): ResolveWorkspaceConfigRequest { - const message = createBaseResolveWorkspaceConfigRequest(); - message.type = object.type ?? WorkspaceType.REGULAR; - message.context = object.context ?? ""; - message.ideSettings = object.ideSettings ?? ""; - message.workspaceConfig = object.workspaceConfig ?? ""; - return message; - }, + encode(message: ResolveWorkspaceConfigRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.type !== WorkspaceType.REGULAR) { + writer.uint32(8).int32(workspaceTypeToNumber(message.type)); + } + if (message.context !== "") { + writer.uint32(18).string(message.context); + } + if (message.ideSettings !== "") { + writer.uint32(26).string(message.ideSettings); + } + if (message.workspaceConfig !== "") { + writer.uint32(34).string(message.workspaceConfig); + } + if (message.user !== undefined) { + User.encode(message.user, writer.uint32(42).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): ResolveWorkspaceConfigRequest { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseResolveWorkspaceConfigRequest(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.type = workspaceTypeFromJSON(reader.int32()); + break; + case 2: + message.context = reader.string(); + break; + case 3: + message.ideSettings = reader.string(); + break; + case 4: + message.workspaceConfig = reader.string(); + break; + case 5: + message.user = User.decode(reader, reader.uint32()); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): ResolveWorkspaceConfigRequest { + return { + type: isSet(object.type) ? workspaceTypeFromJSON(object.type) : WorkspaceType.REGULAR, + context: isSet(object.context) ? String(object.context) : "", + ideSettings: isSet(object.ideSettings) ? String(object.ideSettings) : "", + workspaceConfig: isSet(object.workspaceConfig) ? String(object.workspaceConfig) : "", + user: isSet(object.user) ? User.fromJSON(object.user) : undefined, + }; + }, + + toJSON(message: ResolveWorkspaceConfigRequest): unknown { + const obj: any = {}; + message.type !== undefined && (obj.type = workspaceTypeToJSON(message.type)); + message.context !== undefined && (obj.context = message.context); + message.ideSettings !== undefined && (obj.ideSettings = message.ideSettings); + message.workspaceConfig !== undefined && (obj.workspaceConfig = message.workspaceConfig); + message.user !== undefined && (obj.user = message.user ? User.toJSON(message.user) : undefined); + return obj; + }, + + fromPartial(object: DeepPartial): ResolveWorkspaceConfigRequest { + const message = createBaseResolveWorkspaceConfigRequest(); + message.type = object.type ?? WorkspaceType.REGULAR; + message.context = object.context ?? ""; + message.ideSettings = object.ideSettings ?? ""; + message.workspaceConfig = object.workspaceConfig ?? ""; + message.user = (object.user !== undefined && object.user !== null) ? User.fromPartial(object.user) : undefined; + return message; + }, }; function createBaseResolveWorkspaceConfigResponse(): ResolveWorkspaceConfigResponse { - return { envvars: [], supervisorImage: "", webImage: "", ideImageLayers: [], refererIde: "", tasks: "" }; + return { envvars: [], supervisorImage: "", webImage: "", ideImageLayers: [], refererIde: "", tasks: "" }; } export const ResolveWorkspaceConfigResponse = { - encode(message: ResolveWorkspaceConfigResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - for (const v of message.envvars) { - EnvironmentVariable.encode(v!, writer.uint32(10).fork()).ldelim(); - } - if (message.supervisorImage !== "") { - writer.uint32(18).string(message.supervisorImage); - } - if (message.webImage !== "") { - writer.uint32(26).string(message.webImage); - } - for (const v of message.ideImageLayers) { - writer.uint32(34).string(v!); - } - if (message.refererIde !== "") { - writer.uint32(42).string(message.refererIde); - } - if (message.tasks !== "") { - writer.uint32(50).string(message.tasks); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): ResolveWorkspaceConfigResponse { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseResolveWorkspaceConfigResponse(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.envvars.push(EnvironmentVariable.decode(reader, reader.uint32())); - break; - case 2: - message.supervisorImage = reader.string(); - break; - case 3: - message.webImage = reader.string(); - break; - case 4: - message.ideImageLayers.push(reader.string()); - break; - case 5: - message.refererIde = reader.string(); - break; - case 6: - message.tasks = reader.string(); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): ResolveWorkspaceConfigResponse { - return { - envvars: Array.isArray(object?.envvars) - ? object.envvars.map((e: any) => EnvironmentVariable.fromJSON(e)) - : [], - supervisorImage: isSet(object.supervisorImage) ? String(object.supervisorImage) : "", - webImage: isSet(object.webImage) ? String(object.webImage) : "", - ideImageLayers: Array.isArray(object?.ideImageLayers) - ? object.ideImageLayers.map((e: any) => String(e)) - : [], - refererIde: isSet(object.refererIde) ? String(object.refererIde) : "", - tasks: isSet(object.tasks) ? String(object.tasks) : "", - }; - }, - - toJSON(message: ResolveWorkspaceConfigResponse): unknown { - const obj: any = {}; - if (message.envvars) { - obj.envvars = message.envvars.map((e) => (e ? EnvironmentVariable.toJSON(e) : undefined)); - } else { - obj.envvars = []; - } - message.supervisorImage !== undefined && (obj.supervisorImage = message.supervisorImage); - message.webImage !== undefined && (obj.webImage = message.webImage); - if (message.ideImageLayers) { - obj.ideImageLayers = message.ideImageLayers.map((e) => e); - } else { - obj.ideImageLayers = []; - } - message.refererIde !== undefined && (obj.refererIde = message.refererIde); - message.tasks !== undefined && (obj.tasks = message.tasks); - return obj; - }, - - fromPartial(object: DeepPartial): ResolveWorkspaceConfigResponse { - const message = createBaseResolveWorkspaceConfigResponse(); - message.envvars = object.envvars?.map((e) => EnvironmentVariable.fromPartial(e)) || []; - message.supervisorImage = object.supervisorImage ?? ""; - message.webImage = object.webImage ?? ""; - message.ideImageLayers = object.ideImageLayers?.map((e) => e) || []; - message.refererIde = object.refererIde ?? ""; - message.tasks = object.tasks ?? ""; - return message; - }, + encode(message: ResolveWorkspaceConfigResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + for (const v of message.envvars) { + EnvironmentVariable.encode(v!, writer.uint32(10).fork()).ldelim(); + } + if (message.supervisorImage !== "") { + writer.uint32(18).string(message.supervisorImage); + } + if (message.webImage !== "") { + writer.uint32(26).string(message.webImage); + } + for (const v of message.ideImageLayers) { + writer.uint32(34).string(v!); + } + if (message.refererIde !== "") { + writer.uint32(42).string(message.refererIde); + } + if (message.tasks !== "") { + writer.uint32(50).string(message.tasks); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): ResolveWorkspaceConfigResponse { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseResolveWorkspaceConfigResponse(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.envvars.push(EnvironmentVariable.decode(reader, reader.uint32())); + break; + case 2: + message.supervisorImage = reader.string(); + break; + case 3: + message.webImage = reader.string(); + break; + case 4: + message.ideImageLayers.push(reader.string()); + break; + case 5: + message.refererIde = reader.string(); + break; + case 6: + message.tasks = reader.string(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): ResolveWorkspaceConfigResponse { + return { + envvars: Array.isArray(object?.envvars) ? object.envvars.map((e: any) => EnvironmentVariable.fromJSON(e)) : [], + supervisorImage: isSet(object.supervisorImage) ? String(object.supervisorImage) : "", + webImage: isSet(object.webImage) ? String(object.webImage) : "", + ideImageLayers: Array.isArray(object?.ideImageLayers) ? object.ideImageLayers.map((e: any) => String(e)) : [], + refererIde: isSet(object.refererIde) ? String(object.refererIde) : "", + tasks: isSet(object.tasks) ? String(object.tasks) : "", + }; + }, + + toJSON(message: ResolveWorkspaceConfigResponse): unknown { + const obj: any = {}; + if (message.envvars) { + obj.envvars = message.envvars.map((e) => e ? EnvironmentVariable.toJSON(e) : undefined); + } else { + obj.envvars = []; + } + message.supervisorImage !== undefined && (obj.supervisorImage = message.supervisorImage); + message.webImage !== undefined && (obj.webImage = message.webImage); + if (message.ideImageLayers) { + obj.ideImageLayers = message.ideImageLayers.map((e) => e); + } else { + obj.ideImageLayers = []; + } + message.refererIde !== undefined && (obj.refererIde = message.refererIde); + message.tasks !== undefined && (obj.tasks = message.tasks); + return obj; + }, + + fromPartial(object: DeepPartial): ResolveWorkspaceConfigResponse { + const message = createBaseResolveWorkspaceConfigResponse(); + message.envvars = object.envvars?.map((e) => EnvironmentVariable.fromPartial(e)) || []; + message.supervisorImage = object.supervisorImage ?? ""; + message.webImage = object.webImage ?? ""; + message.ideImageLayers = object.ideImageLayers?.map((e) => e) || []; + message.refererIde = object.refererIde ?? ""; + message.tasks = object.tasks ?? ""; + return message; + }, }; export type IDEServiceDefinition = typeof IDEServiceDefinition; export const IDEServiceDefinition = { - name: "IDEService", - fullName: "ide_service_api.IDEService", - methods: { - getConfig: { - name: "GetConfig", - requestType: GetConfigRequest, - requestStream: false, - responseType: GetConfigResponse, - responseStream: false, - options: {}, - }, - resolveWorkspaceConfig: { - name: "ResolveWorkspaceConfig", - requestType: ResolveWorkspaceConfigRequest, - requestStream: false, - responseType: ResolveWorkspaceConfigResponse, - responseStream: false, - options: {}, - }, + name: "IDEService", + fullName: "ide_service_api.IDEService", + methods: { + getConfig: { + name: "GetConfig", + requestType: GetConfigRequest, + requestStream: false, + responseType: GetConfigResponse, + responseStream: false, + options: { idempotencyLevel: "IDEMPOTENT" }, + }, + resolveWorkspaceConfig: { + name: "ResolveWorkspaceConfig", + requestType: ResolveWorkspaceConfigRequest, + requestStream: false, + responseType: ResolveWorkspaceConfigResponse, + responseStream: false, + options: { idempotencyLevel: "IDEMPOTENT" }, }, + }, } as const; export interface IDEServiceServiceImplementation { - getConfig( - request: GetConfigRequest, - context: CallContext & CallContextExt, - ): Promise>; - resolveWorkspaceConfig( - request: ResolveWorkspaceConfigRequest, - context: CallContext & CallContextExt, - ): Promise>; + getConfig(request: GetConfigRequest, context: CallContext & CallContextExt): Promise>; + resolveWorkspaceConfig( + request: ResolveWorkspaceConfigRequest, + context: CallContext & CallContextExt, + ): Promise>; } export interface IDEServiceClient { - getConfig( - request: DeepPartial, - options?: CallOptions & CallOptionsExt, - ): Promise; - resolveWorkspaceConfig( - request: DeepPartial, - options?: CallOptions & CallOptionsExt, - ): Promise; + getConfig(request: DeepPartial, options?: CallOptions & CallOptionsExt): Promise; + resolveWorkspaceConfig( + request: DeepPartial, + options?: CallOptions & CallOptionsExt, + ): Promise; } export interface DataLoaderOptions { - cache?: boolean; + cache?: boolean; } export interface DataLoaders { - rpcDataLoaderOptions?: DataLoaderOptions; - getDataLoader(identifier: string, constructorFn: () => T): T; + rpcDataLoaderOptions?: DataLoaderOptions; + getDataLoader(identifier: string, constructorFn: () => T): T; } type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; -export type DeepPartial = T extends Builtin - ? T - : T extends Array - ? Array> - : T extends ReadonlyArray - ? ReadonlyArray> - : T extends {} - ? { [K in keyof T]?: DeepPartial } - : Partial; +export type DeepPartial = T extends Builtin ? T + : T extends Array ? Array> : T extends ReadonlyArray ? ReadonlyArray> + : T extends {} ? { [K in keyof T]?: DeepPartial } + : Partial; function isSet(value: any): boolean { - return value !== null && value !== undefined; + return value !== null && value !== undefined; } diff --git a/components/ide-service/go.mod b/components/ide-service/go.mod index 00c50eda269c52..b93504001f4da8 100644 --- a/components/ide-service/go.mod +++ b/components/ide-service/go.mod @@ -9,7 +9,6 @@ require ( github.com/gitpod-io/gitpod/gitpod-protocol v0.0.0-00010101000000-000000000000 github.com/gitpod-io/gitpod/ide-service-api v0.0.0-00010101000000-000000000000 github.com/heptiolabs/healthcheck v0.0.0-20211123025425-613501dd5deb - github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.0.1 github.com/prometheus/client_golang v1.13.0 github.com/sirupsen/logrus v1.8.1 @@ -36,6 +35,7 @@ require ( github.com/klauspost/compress v1.13.6 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/moby/locker v1.0.1 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/components/ide/code/leeway.Dockerfile b/components/ide/code/leeway.Dockerfile index f12cf93ff84bfb..e8c1ddc1e03d84 100644 --- a/components/ide/code/leeway.Dockerfile +++ b/components/ide/code/leeway.Dockerfile @@ -22,7 +22,7 @@ ARG CODE_COMMIT ARG CODE_QUALITY ARG CODE_VERSION -ARG NODE_VERSION=16.16.0 +ARG NODE_VERSION=16.18.1 ARG NVM_DIR="/root/.nvm" RUN mkdir -p $NVM_DIR \ && curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | sh \ diff --git a/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodProjectManager.kt b/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodProjectManager.kt deleted file mode 100644 index 018afade32ef4d..00000000000000 --- a/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/GitpodProjectManager.kt +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) 2022 Gitpod GmbH. All rights reserved. -// Licensed under the GNU Affero General Public License (AGPL). -// See License.AGPL.txt in the project root for license information. - -package io.gitpod.jetbrains.remote - -import com.intellij.ProjectTopics -import com.intellij.openapi.diagnostic.thisLogger -import com.intellij.openapi.module.Module -import com.intellij.openapi.module.ModuleManager -import com.intellij.openapi.project.ModuleListener -import com.intellij.openapi.project.Project -import com.intellij.openapi.projectRoots.ProjectJdkTable -import com.intellij.openapi.projectRoots.Sdk -import com.intellij.openapi.projectRoots.SdkType -import com.intellij.openapi.projectRoots.impl.JavaHomeFinder -import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil -import com.intellij.openapi.roots.ModuleRootModificationUtil -import com.intellij.openapi.roots.ProjectRootManager -import com.intellij.openapi.util.registry.Registry -import com.intellij.util.application -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.future.await -import kotlinx.coroutines.launch -import java.util.concurrent.CompletableFuture - -@Suppress("UnstableApiUsage", "OPT_IN_USAGE") -class GitpodProjectManager( - private val project: Project -) { - - init { - configureSdks() - } - - /** - * It is a workaround for https://youtrack.jetbrains.com/issue/GTW-88 - */ - private fun configureSdks() { - if (application.isHeadlessEnvironment || Registry.get("gitpod.autoJdk.disabled").asBoolean()) { - return - } - val pendingSdk = CompletableFuture() - application.invokeLaterOnWriteThread { - application.runWriteAction { - try { - val jdkTable = ProjectJdkTable.getInstance() - jdkTable.preconfigure() - val preconfiguredJdk = ProjectRootManager.getInstance(project).projectSdk - val preferredJdkHomePath = JavaHomeFinder.getFinder().findExistingJdks().firstOrNull() - pendingSdk.complete( - when { - preconfiguredJdk != null -> preconfiguredJdk - preferredJdkHomePath != null -> - jdkTable.allJdks.find { sdk -> sdk.homePath == preferredJdkHomePath } - ?: SdkConfigurationUtil.createAndAddSDK( - preferredJdkHomePath, - SdkType.findByName(jdkTable.defaultSdkType.name)!! - ) - - else -> jdkTable.allJdks.firstOrNull() - } - ) - } catch (t: Throwable) { - pendingSdk.completeExceptionally(t) - } - } - } - GlobalScope.launch { - val sdk = pendingSdk.await() ?: return@launch - thisLogger().warn("gitpod: '${project.name}' project: SDK detected: $sdk") - project.messageBus.connect().subscribe(ProjectTopics.MODULES, object : ModuleListener { - override fun moduleAdded(project: Project, module: Module) { - configureSdk(sdk) - } - }) - configureSdk(sdk) - } - } - - private fun configureSdk(sdk: Sdk) { - application.invokeLaterOnWriteThread { - application.runWriteAction { - val projectRootManager = ProjectRootManager.getInstance(project) - if (projectRootManager.projectSdk == null) { - projectRootManager.projectSdk = sdk - thisLogger().warn("gitpod: '${project.name}' project: SDK was auto preconfigured: $sdk") - } - } - } - for (module in ModuleManager.getInstance(project).modules) { - ModuleRootModificationUtil.updateModel(module) { m -> - if (m.sdk == null) { - m.sdk = sdk - thisLogger().warn("gitpod: '${module.name}' module: SDK was auto preconfigured: $sdk") - } - } - } - } -} diff --git a/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/optional/GitpodForceUpdateMavenProjectsActivity.kt b/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/optional/GitpodForceUpdateMavenProjectsActivity.kt index c51dd60fb62039..352ff203dd3516 100644 --- a/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/optional/GitpodForceUpdateMavenProjectsActivity.kt +++ b/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/optional/GitpodForceUpdateMavenProjectsActivity.kt @@ -7,12 +7,16 @@ package io.gitpod.jetbrains.remote.optional import com.intellij.openapi.diagnostic.thisLogger import com.intellij.openapi.project.Project import com.intellij.openapi.startup.StartupActivity +import com.intellij.openapi.util.registry.Registry import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.util.application import org.jetbrains.idea.maven.project.MavenProjectsManager class GitpodForceUpdateMavenProjectsActivity : StartupActivity.RequiredForSmartMode { override fun runActivity(project: Project) { + if (application.isHeadlessEnvironment || Registry.get("gitpod.forceUpdateMavenProjects.disabled").asBoolean()) { + return + } application.invokeLater { VirtualFileManager.getInstance().asyncRefresh { MavenProjectsManager.getInstance(project).forceUpdateAllProjectsOrFindAllAvailablePomFiles() diff --git a/components/ide/jetbrains/backend-plugin/src/main/resources/META-INF/plugin.xml b/components/ide/jetbrains/backend-plugin/src/main/resources/META-INF/plugin.xml index 1aa4aaa80ca482..41430d159b5a4b 100644 --- a/components/ide/jetbrains/backend-plugin/src/main/resources/META-INF/plugin.xml +++ b/components/ide/jetbrains/backend-plugin/src/main/resources/META-INF/plugin.xml @@ -37,7 +37,6 @@ - - diff --git a/components/ide/jetbrains/launcher/hot-deploy.sh b/components/ide/jetbrains/launcher/hot-deploy.sh index 41c0fd2f99a6b1..85b9ec74271bde 100755 --- a/components/ide/jetbrains/launcher/hot-deploy.sh +++ b/components/ide/jetbrains/launcher/hot-deploy.sh @@ -19,13 +19,13 @@ dev_image="$(tar xfO "$bldfn" ./imgnames.txt | head -n1)" echo "Dev Image: $dev_image" cf_patch=$(kubectl get cm ide-config -o=json | jq '.data."config.json"' |jq -r) -# TODO: Findout how to update the ide config from .ideOptions.options.imageLayers and .ideOptions.options.latestImageLayers -# cf_patch=$(echo "$cf_patch" |jq ".ideOptions.options.intellij.$prop = \"$dev_image\"") -# cf_patch=$(echo "$cf_patch" |jq ".ideOptions.options.goland.$prop = \"$dev_image\"") -# cf_patch=$(echo "$cf_patch" |jq ".ideOptions.options.pycharm.$prop = \"$dev_image\"") -# cf_patch=$(echo "$cf_patch" |jq ".ideOptions.options.phpstorm.$prop = \"$dev_image\"") -# cf_patch=$(echo "$cf_patch" |jq ".ideOptions.options.rubymine.$prop = \"$dev_image\"") -# cf_patch=$(echo "$cf_patch" |jq ".ideOptions.options.webstorm.$prop = \"$dev_image\"") +ides=$(echo "$cf_patch" |jq '.ideOptions.clients."jetbrains-gateway".desktopIDEs') +for ide in $(echo "$ides" | jq -r '.[]'); do + # second image is always jb-launcher, if position is changed then this script should be updated as well + cf_patch=$(echo "$cf_patch" |jq ".ideOptions.options.${ide}.imageLayers[1] = \"$dev_image\"") + cf_patch=$(echo "$cf_patch" |jq ".ideOptions.options.${ide}.latestImageLayers[1] = \"$dev_image\"") +done + cf_patch=$(echo "$cf_patch" |jq tostring) cf_patch="{\"data\": {\"config.json\": $cf_patch}}" diff --git a/components/ide/jetbrains/launcher/main.go b/components/ide/jetbrains/launcher/main.go index 303adfe5ad7b73..78aaf5be8380e3 100644 --- a/components/ide/jetbrains/launcher/main.go +++ b/components/ide/jetbrains/launcher/main.go @@ -616,7 +616,11 @@ func updateVMOptions( return isEqual || isXmx || isXms || isXss || isXXOptions } // Gitpod's default customization - gitpodVMOptions := []string{"-Dgtw.disable.exit.dialog=true"} + var gitpodVMOptions []string + gitpodVMOptions = append(gitpodVMOptions, "-Dgtw.disable.exit.dialog=true") + if alias == "intellij" { + gitpodVMOptions = append(gitpodVMOptions, "-Djdk.configure.existing=true") + } vmoptions := deduplicateVMOption(ideaVMOptionsLines, gitpodVMOptions, filterFunc) // user-defined vmoptions (EnvVar) diff --git a/components/ide/jetbrains/launcher/main_test.go b/components/ide/jetbrains/launcher/main_test.go index 7b090beeea0618..a527399cd832a9 100644 --- a/components/ide/jetbrains/launcher/main_test.go +++ b/components/ide/jetbrains/launcher/main_test.go @@ -44,10 +44,10 @@ func TestUpdateVMOptions(t *testing.T) { Expectation string }{ {"goland64.vmoptions", "goland", nil, "-Xms128m\n-Xmx750m\n-Dsun.tools.attach.tmp.only=true", "-Xms128m\n-Xmx750m\n-Dsun.tools.attach.tmp.only=true\n-Dgtw.disable.exit.dialog=true"}, - {"idea64.vmoptions", "intellij", nil, "-Xms128m\n-Xmx750m\n-Dsun.tools.attach.tmp.only=true", "-Xms128m\n-Xmx750m\n-Dsun.tools.attach.tmp.only=true\n-Dgtw.disable.exit.dialog=true"}, - {"idea64.vmoptions (INTELLIJ_VMOPTIONS env set)", "intellij", map[string]string{"INTELLIJ_VMOPTIONS": "-Xmx2048m"}, "-Xms128m\n-Xmx750m\n-Dsun.tools.attach.tmp.only=true", "-Xms128m\n-Xmx2048m\n-Dsun.tools.attach.tmp.only=true\n-Dgtw.disable.exit.dialog=true"}, - {"idea64.vmoptions (INTELLIJ_VMOPTIONS env set)", "intellij", map[string]string{"INTELLIJ_VMOPTIONS": "-Xmx4096m"}, "-Xms128m\n-Xmx2g\n-Dsun.tools.attach.tmp.only=true", "-Xms128m\n-Xmx4096m\n-Dsun.tools.attach.tmp.only=true\n-Dgtw.disable.exit.dialog=true"}, - {"idea64.vmoptions (INTELLIJ_VMOPTIONS env set)", "intellij", map[string]string{"INTELLIJ_VMOPTIONS": "-Xmx4096m -XX:MaxRAMPercentage=75"}, "-Xms128m\n-Xmx2g\n-Dsun.tools.attach.tmp.only=true", "-Xms128m\n-Xmx4096m\n-XX:MaxRAMPercentage=75\n-Dsun.tools.attach.tmp.only=true\n-Dgtw.disable.exit.dialog=true"}, + {"idea64.vmoptions", "intellij", nil, "-Xms128m\n-Xmx750m\n-Dsun.tools.attach.tmp.only=true", "-Xms128m\n-Xmx750m\n-Dsun.tools.attach.tmp.only=true\n-Dgtw.disable.exit.dialog=true\n-Djdk.configure.existing=true"}, + {"idea64.vmoptions (INTELLIJ_VMOPTIONS env set)", "intellij", map[string]string{"INTELLIJ_VMOPTIONS": "-Xmx2048m"}, "-Xms128m\n-Xmx750m\n-Dsun.tools.attach.tmp.only=true", "-Xms128m\n-Xmx2048m\n-Dsun.tools.attach.tmp.only=true\n-Dgtw.disable.exit.dialog=true\n-Djdk.configure.existing=true"}, + {"idea64.vmoptions (INTELLIJ_VMOPTIONS env set)", "intellij", map[string]string{"INTELLIJ_VMOPTIONS": "-Xmx4096m"}, "-Xms128m\n-Xmx2g\n-Dsun.tools.attach.tmp.only=true", "-Xms128m\n-Xmx4096m\n-Dsun.tools.attach.tmp.only=true\n-Dgtw.disable.exit.dialog=true\n-Djdk.configure.existing=true"}, + {"idea64.vmoptions (INTELLIJ_VMOPTIONS env set)", "intellij", map[string]string{"INTELLIJ_VMOPTIONS": "-Xmx4096m -XX:MaxRAMPercentage=75"}, "-Xms128m\n-Xmx2g\n-Dsun.tools.attach.tmp.only=true", "-Xms128m\n-Xmx4096m\n-XX:MaxRAMPercentage=75\n-Dsun.tools.attach.tmp.only=true\n-Dgtw.disable.exit.dialog=true\n-Djdk.configure.existing=true"}, {"goland64.vmoptions (GOLAND_VMOPTIONS env set with conflicting options)", "goland", map[string]string{"GOLAND_VMOPTIONS": "-ea -XX:+IgnoreUnrecognizedVMOptions -XX:MaxRAMPercentage=75 -XX:MaxRAMPercentage=50"}, "-Xms128m\n-Xmx2g\n-Dsun.tools.attach.tmp.only=true", "-Xms128m\n-Xmx2g\n-Dsun.tools.attach.tmp.only=true\n-Dgtw.disable.exit.dialog=true\n-ea\n-XX:+IgnoreUnrecognizedVMOptions\n-XX:MaxRAMPercentage=50"}, } for _, test := range tests { diff --git a/components/image-builder-bob/README.md b/components/image-builder-bob/README.md index dab6116bed4704..5e8cb95f4d746a 100644 --- a/components/image-builder-bob/README.md +++ b/components/image-builder-bob/README.md @@ -61,3 +61,32 @@ BOB_BASE_REF=localhost:5000/source:latest BOB_TARGET_REF=localhost:5000/target:8 cd /workspace/gitpod/components/image-builder-bob go test -v ./... ``` + +# Required Permssion + +If you want it to work in a particular public cloud, you may need to grant some permissions. +Below is a reference for this. + +## AWS + +If you would like to use ECR as a container registry, please add the following IAM policy below. +Also, if you want to use ECR as public, you should add `ecr-public` too. + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "VisualEditor0", + "Effect": "Allow", + "Action": [ + "ecr:BatchGetImage", + "ecr:GetAuthorizationToken", + "ecr:BatchCheckLayerAvailability", + "ecr:PutImage" + ], + "Resource": "*" + } + ] +} +``` diff --git a/components/image-builder-mk3/README.md b/components/image-builder-mk3/README.md index 77bcae0e553e5c..b400fe4ff600f3 100644 --- a/components/image-builder-mk3/README.md +++ b/components/image-builder-mk3/README.md @@ -72,3 +72,32 @@ To run all `image-builder-mk3` tests: ```console go test -v ./... ``` + +# Required Permssion + +If you want it to work in a particular public cloud, you may need to grant some permissions. +Below is a reference for this. + +## AWS IAM Policy + +If you would like to use ECR as a container registry, please add the following IAM policy below. +Also, if you want to use ECR as public, you should add `ecr-public` too. + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "VisualEditor0", + "Effect": "Allow", + "Action": [ + "ecr:BatchGetImage", + "ecr:GetAuthorizationToken", + "ecr:BatchCheckLayerAvailability", + "ecr:PutImage" + ], + "Resource": "*" + } + ] +} +``` diff --git a/components/proxy/conf/Caddyfile b/components/proxy/conf/Caddyfile index 0c2b476c67c938..1938c66c4b53d5 100644 --- a/components/proxy/conf/Caddyfile +++ b/components/proxy/conf/Caddyfile @@ -280,6 +280,21 @@ https://{$GITPOD_DOMAIN} { } } + @iam path /iam/* + handle @iam { + + gitpod.cors_origin { + any_domain true + } + + uri strip_prefix /iam + + reverse_proxy iam.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:9002 { + import upstream_headers + import upstream_connection + } + } + @codesync path /code-sync* handle @codesync { gitpod.cors_origin { diff --git a/components/refresh-credential/go.mod b/components/refresh-credential/go.mod index 76179a2f510484..3e19be3237a22e 100644 --- a/components/refresh-credential/go.mod +++ b/components/refresh-credential/go.mod @@ -5,7 +5,6 @@ go 1.19 require ( github.com/aws/aws-sdk-go-v2 v1.17.2 github.com/aws/aws-sdk-go-v2/config v1.18.4 - github.com/aws/aws-sdk-go-v2/credentials v1.13.4 github.com/aws/aws-sdk-go-v2/service/ecr v1.17.24 github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.13.21 github.com/docker/cli v20.10.21+incompatible @@ -18,6 +17,7 @@ require ( ) require ( + github.com/aws/aws-sdk-go-v2/credentials v1.13.4 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.20 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.26 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.20 // indirect diff --git a/components/registry-facade/README.md b/components/registry-facade/README.md index 491b71daa33a07..6fe34a25c69f4a 100644 --- a/components/registry-facade/README.md +++ b/components/registry-facade/README.md @@ -12,3 +12,31 @@ Registry-facade modifies images as they are downloaded. It consults with `ws-man 6. Desktop IDE It also adds the `gp` cli to the workspace. Think of `registry-facade` as an image layer smuggler. + +# Required Permssion + +If you want it to work in a particular public cloud, you may need to grant some permissions. +Below is a reference for this. + +## AWS IAM Policy + +If you would like to use ECR as a container registry, please add the following IAM policy below. +Also, if you want to use ECR as public, you should add `ecr-public` too. + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "VisualEditor0", + "Effect": "Allow", + "Action": [ + "ecr:GetDownloadUrlForLayer", + "ecr:BatchGetImage", + "ecr:GetAuthorizationToken" + ], + "Resource": "*" + } + ] +} +``` diff --git a/components/server/package.json b/components/server/package.json index f9e751a8e5bf14..b5c0cda790ae72 100644 --- a/components/server/package.json +++ b/components/server/package.json @@ -69,6 +69,7 @@ "lodash.debounce": "^4.0.8", "longjohn": "^0.2.12", "minio": "^7.0.12", + "nice-grpc-client-middleware-retry": "^2.0.1", "node-fetch": "^2.6.7", "opentracing": "^0.14.4", "p-throttle": "^4.1.1", diff --git a/components/server/src/container-module.ts b/components/server/src/container-module.ts index f1c3a5d851e3ea..c84cd1332b7e2f 100644 --- a/components/server/src/container-module.ts +++ b/components/server/src/container-module.ts @@ -115,6 +115,7 @@ import { UsageService, UsageServiceImpl } from "./user/usage-service"; import { OpenPrebuildPrefixContextParser } from "./workspace/open-prebuild-prefix-context-parser"; import { contentServiceBinder } from "./util/content-service-sugar"; import { UbpResetOnCancel } from "@gitpod/gitpod-payment-endpoint/lib/chargebee/ubp-reset-on-cancel"; +import { retryMiddleware } from "nice-grpc-client-middleware-retry"; export const productionContainerModule = new ContainerModule((bind, unbind, isBound, rebind) => { bind(Config).toConstantValue(ConfigFile.fromFile()); @@ -282,9 +283,18 @@ export const productionContainerModule = new ContainerModule((bind, unbind, isBo .toDynamicValue((ctx) => { const config = ctx.container.get(Config); const metricsClient = ctx.container.get(IClientCallMetrics); + const options: grpc.ClientOptions = { + ...defaultGRPCOptions, + }; return createClientFactory() .use(prometheusClientMiddleware(metricsClient)) - .create(IDEServiceDefinition, createChannel(config.ideServiceAddr)); + .use(retryMiddleware) + .create(IDEServiceDefinition, createChannel(config.ideServiceAddr, undefined, options), { + "*": { + retryBaseDelayMs: 200, + retryMaxAttempts: 15, + }, + }); }) .inSingletonScope(); diff --git a/components/server/src/ide-service.ts b/components/server/src/ide-service.ts index 66031e800f18fc..97627555c2ae25 100644 --- a/components/server/src/ide-service.ts +++ b/components/server/src/ide-service.ts @@ -84,18 +84,22 @@ export class IDEService { return newIDESettings; } - async resolveWorkspaceConfig(workspace: Workspace, user: User): Promise { + async resolveWorkspaceConfig( + workspace: Workspace, + user: User, + userSelectedIdeSettings?: IDESettings, + ): Promise { const use = await this.configCatClientFactory().getValueAsync("use_IDEService_ResolveWorkspaceConfig", false, { user, }); if (use) { - return this.doResolveWorkspaceConfig(workspace, user); + return this.doResolveWorkspaceConfig(workspace, user, userSelectedIdeSettings); } const deprecated = await this.resolveDeprecated(workspace, user); // assert against ide-service (async () => { - const config = await this.doResolveWorkspaceConfig(workspace, user); + const config = await this.doResolveWorkspaceConfig(workspace, user, userSelectedIdeSettings); const { tasks: configTasks, ...newConfig } = config; const { tasks: deprecatedTasks, ...newDeprecated } = deprecated; // we omit tasks because we're going to rewrite them soon and the deepEqual was failing @@ -104,23 +108,29 @@ export class IDEService { return deprecated; } - private async doResolveWorkspaceConfig(workspace: Workspace, user: User): Promise { + private async doResolveWorkspaceConfig( + workspace: Workspace, + user: User, + userSelectedIdeSettings?: IDESettings, + ): Promise { const workspaceType = workspace.type === "prebuild" ? IdeServiceApi.WorkspaceType.PREBUILD : IdeServiceApi.WorkspaceType.REGULAR; const req: IdeServiceApi.ResolveWorkspaceConfigRequest = { type: workspaceType, context: JSON.stringify(workspace.context), - ideSettings: JSON.stringify(user.additionalData?.ideSettings), + ideSettings: JSON.stringify(userSelectedIdeSettings || user.additionalData?.ideSettings), workspaceConfig: JSON.stringify(workspace.config), + user: { + id: user.id, + }, }; for (let attempt = 0; attempt < 15; attempt++) { if (attempt != 0) { await new Promise((resolve) => setTimeout(resolve, 1000)); } try { - const resp = await this.tryResolveWorkspaceConfig(req); - return resp; + return await this.ideService.resolveWorkspaceConfig(req); } catch (e) { console.error("ide-service: failed to resolve workspace config: ", e); } @@ -128,16 +138,6 @@ export class IDEService { throw new Error("failed to resolve workspace IDE configuration"); } - private tryResolveWorkspaceConfig( - req: IdeServiceApi.ResolveWorkspaceConfigRequest, - ): Promise { - const controller = new AbortController(); - setTimeout(() => controller.abort(), 5000); - return this.ideService.resolveWorkspaceConfig(req, { - signal: controller.signal, - }); - } - resolveGitpodTasks(ws: Workspace, ideConfig: ResolveWorkspaceConfigResponse): TaskConfig[] { const tasks: TaskConfig[] = []; if (ws.config.tasks) { diff --git a/components/server/src/workspace/gitpod-server-impl.ts b/components/server/src/workspace/gitpod-server-impl.ts index 8153070162ce43..7d3623e81d6763 100644 --- a/components/server/src/workspace/gitpod-server-impl.ts +++ b/components/server/src/workspace/gitpod-server-impl.ts @@ -734,9 +734,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable { await projectPromise, await userEnvVars, await projectEnvVarsPromise, - { - forceDefaultImage: !!options.forceDefaultImage, - }, + options, ); traceWI(ctx, { instanceId: result.instanceID }); return result; @@ -1207,6 +1205,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable { project, await envVars, await projectEnvVarsPromise, + options, ); ctx.span?.log({ event: "startWorkspaceComplete", ...startWorkspaceResult }); diff --git a/components/server/src/workspace/workspace-starter.ts b/components/server/src/workspace/workspace-starter.ts index 1d9e94fdb50d41..9b92d9f846af40 100644 --- a/components/server/src/workspace/workspace-starter.ts +++ b/components/server/src/workspace/workspace-starter.ts @@ -60,6 +60,8 @@ import { EnvVarWithValue, BillingTier, Project, + GitpodServer, + IDESettings, } from "@gitpod/gitpod-protocol"; import { IAnalyticsWriter } from "@gitpod/gitpod-protocol/lib/analytics"; import { log } from "@gitpod/gitpod-protocol/lib/util/logging"; @@ -127,9 +129,8 @@ import { AttributionId } from "@gitpod/gitpod-protocol/lib/attribution"; import { LogContext } from "@gitpod/gitpod-protocol/lib/util/logging"; import { repeat } from "@gitpod/gitpod-protocol/lib/util/repeat"; -export interface StartWorkspaceOptions { +export interface StartWorkspaceOptions extends GitpodServer.StartWorkspaceOptions { rethrow?: boolean; - forceDefaultImage?: boolean; excludeFeatureFlags?: NamedWorkspaceFeatureFlag[]; } @@ -139,21 +140,31 @@ const INSTANCE_START_RETRY_INTERVAL_SECONDS = 2; export async function getWorkspaceClassForInstance( ctx: TraceContext, workspace: Workspace, + previousInstance: WorkspaceInstance | undefined, user: User, project: Project | undefined, + workspaceClassOverride: string | undefined, entitlementService: EntitlementService, config: WorkspaceClassesConfig, ): Promise { const span = TraceContext.startSpan("getWorkspaceClassForInstance", ctx); try { let workspaceClass: string | undefined; - switch (workspace.type) { - case "prebuild": - workspaceClass = project?.settings?.workspaceClasses?.prebuild; - break; - case "regular": - workspaceClass = project?.settings?.workspaceClasses?.regular; - break; + if (workspaceClassOverride) { + workspaceClass = workspaceClassOverride; + } + if (!workspaceClass && previousInstance) { + workspaceClass = previousInstance.workspaceClass; + } + if (!workspaceClass) { + switch (workspace.type) { + case "prebuild": + workspaceClass = project?.settings?.workspaceClasses?.prebuild; + break; + case "regular": + workspaceClass = project?.settings?.workspaceClasses?.regular; + break; + } } if (!workspaceClass && (await entitlementService.userGetsMoreResources(user))) { workspaceClass = config.find((c) => !!c.marker?.moreResources)?.id; @@ -269,7 +280,7 @@ export class WorkspaceStarter { } } - const ideConfig = await this.resolveIDEConfiguration(ctx, workspace, user); + const ideConfig = await this.resolveIDEConfiguration(ctx, workspace, user, options.ideSettings); // create and store instance let instance = await this.workspaceDb @@ -283,6 +294,7 @@ export class WorkspaceStarter { project, options.excludeFeatureFlags || [], ideConfig, + options.workspaceClass, ), ); span.log({ newInstance: instance.id }); @@ -350,7 +362,12 @@ export class WorkspaceStarter { } } - private async resolveIDEConfiguration(ctx: TraceContext, workspace: Workspace, user: User) { + private async resolveIDEConfiguration( + ctx: TraceContext, + workspace: Workspace, + user: User, + userSelectedIdeSettings?: IDESettings, + ) { const span = TraceContext.startSpan("resolveIDEConfiguration", ctx); try { const migrated = this.ideService.migrateSettings(user); @@ -358,7 +375,7 @@ export class WorkspaceStarter { user.additionalData.ideSettings = migrated; } - const resp = await this.ideService.resolveWorkspaceConfig(workspace, user); + const resp = await this.ideService.resolveWorkspaceConfig(workspace, user, userSelectedIdeSettings); if (!user.additionalData?.ideSettings && resp.refererIde) { // A user does not have IDE settings configured yet configure it with a referrer ide as default. const additionalData = user?.additionalData || {}; @@ -770,6 +787,7 @@ export class WorkspaceStarter { project: Project | undefined, excludeFeatureFlags: NamedWorkspaceFeatureFlag[], ideConfig: IdeServiceApi.ResolveWorkspaceConfigResponse, + workspaceClassOverride?: string, ): Promise { const span = TraceContext.startSpan("newInstance", ctx); try { @@ -814,8 +832,10 @@ export class WorkspaceStarter { let workspaceClass = await getWorkspaceClassForInstance( ctx, workspace, + previousInstance, user, project, + workspaceClassOverride, this.entitlementService, this.config.workspaceClasses, ); diff --git a/components/ws-manager/pkg/manager/manager.go b/components/ws-manager/pkg/manager/manager.go index 471c01e439332f..acc403d2e68b28 100644 --- a/components/ws-manager/pkg/manager/manager.go +++ b/components/ws-manager/pkg/manager/manager.go @@ -354,6 +354,11 @@ func (m *Manager) StartWorkspace(ctx context.Context, req *api.StartWorkspaceReq return nil, xerrors.Errorf("cannot create secret for workspace pod: %w", err) } + err = waitForSecretInNamespace(m.Clientset, m.Config.Namespace, podName(startContext.Request)) + if err != nil && !k8serr.IsAlreadyExists(err) { + return nil, xerrors.Errorf("timeout waiting for secret required by workspace pod: %w", err) + } + err = m.Clientset.Create(ctx, pod) if err != nil { m, _ := json.Marshal(pod) @@ -1727,3 +1732,23 @@ func extractExposedPorts(pod *corev1.Pod) *api.ExposedPorts { return &api.ExposedPorts{} } + +func waitForSecretInNamespace(client client.Client, namespace, name string) error { + return wait.Poll(200*time.Millisecond, 1*time.Minute, secretInNamespace(client, namespace, name)) +} + +func secretInNamespace(client client.Client, namespace, name string) wait.ConditionFunc { + return func() (bool, error) { + var secret corev1.Secret + err := client.Get(context.TODO(), types.NamespacedName{Namespace: namespace, Name: name}, &secret) + if k8serr.IsNotFound(err) { + return false, nil + } + + if err != nil { + return false, err + } + + return true, nil + } +} diff --git a/dev/image/Dockerfile b/dev/image/Dockerfile index e750fd9cb3dd1c..daa094d717017d 100644 --- a/dev/image/Dockerfile +++ b/dev/image/Dockerfile @@ -136,7 +136,7 @@ RUN install-packages netcat USER gitpod # Fix node version we develop against -ARG GITPOD_NODE_VERSION=16.16.0 +ARG GITPOD_NODE_VERSION=16.18.1 RUN bash -c ". .nvm/nvm.sh \ && nvm install $GITPOD_NODE_VERSION \ && npm install -g typescript yarn" diff --git a/dev/preview/workflow/preview/deploy-gitpod.sh b/dev/preview/workflow/preview/deploy-gitpod.sh index e26e995972abf2..f48a5da05748b4 100755 --- a/dev/preview/workflow/preview/deploy-gitpod.sh +++ b/dev/preview/workflow/preview/deploy-gitpod.sh @@ -446,6 +446,25 @@ yq w -i "${INSTALLER_CONFIG_PATH}" "experimental.webapp.server.chargebeeSecret" yq w -i "${INSTALLER_CONFIG_PATH}" "experimental.webapp.server.stripeSecret" "stripe-api-keys" yq w -i "${INSTALLER_CONFIG_PATH}" "experimental.webapp.server.stripeConfig" "stripe-config" +# +# IAM +# + +# copy secret from werft's space +kubectl --kubeconfig "${DEV_KUBE_PATH}" --context "${DEV_KUBE_CONTEXT}" -n werft get secret preview-envs-oidc-clients-config-secret -o yaml > preview-envs-oidc-clients-config-secret.secret.yaml +yq d -i preview-envs-oidc-clients-config-secret.secret.yaml metadata.name +yq d -i preview-envs-oidc-clients-config-secret.secret.yaml metadata.creationTimestamp +yq d -i preview-envs-oidc-clients-config-secret.secret.yaml metadata.uid +yq d -i preview-envs-oidc-clients-config-secret.secret.yaml metadata.resourceVersion +yq w -i preview-envs-oidc-clients-config-secret.secret.yaml metadata.name "oidc-clients-config-secret" +yq w -i preview-envs-oidc-clients-config-secret.secret.yaml metadata.namespace "default" +kubectl --kubeconfig "${PREVIEW_K3S_KUBE_PATH}" --context "${PREVIEW_K3S_KUBE_CONTEXT}" apply -f preview-envs-oidc-clients-config-secret.secret.yaml +rm -f preview-envs-oidc-clients-config-secret.secret.yaml + +# enable config +yq w -i "${INSTALLER_CONFIG_PATH}" "experimental.webapp.iam.oidsClientsConfigSecret" "oidc-clients-config-secret" + + log_success "Generated config at $INSTALLER_CONFIG_PATH" # ======== diff --git a/install/installer/cmd/testdata/render/aws-setup/output.golden b/install/installer/cmd/testdata/render/aws-setup/output.golden index b4fb78da053431..e1b1c9969624e9 100644 --- a/install/installer/cmd/testdata/render/aws-setup/output.golden +++ b/install/installer/cmd/testdata/render/aws-setup/output.golden @@ -86,6 +86,35 @@ spec: policyTypes: - Ingress +--- +# networking.k8s.io/v1/NetworkPolicy iam +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default +spec: + ingress: + - from: + - podSelector: + matchLabels: + component: proxy + ports: + - port: 9001 + protocol: TCP + - port: 9002 + protocol: TCP + podSelector: + matchLabels: + app: gitpod + component: iam + policyTypes: + - Ingress + --- # networking.k8s.io/v1/NetworkPolicy ide-metrics apiVersion: networking.k8s.io/v1 @@ -2117,6 +2146,16 @@ data: name: iam namespace: default --- + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default + --- apiVersion: v1 kind: ConfigMap metadata: @@ -3459,7 +3498,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { @@ -5092,7 +5131,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { diff --git a/install/installer/cmd/testdata/render/azure-setup/output.golden b/install/installer/cmd/testdata/render/azure-setup/output.golden index b6fcc786df4c15..695bf309d179fb 100644 --- a/install/installer/cmd/testdata/render/azure-setup/output.golden +++ b/install/installer/cmd/testdata/render/azure-setup/output.golden @@ -86,6 +86,35 @@ spec: policyTypes: - Ingress +--- +# networking.k8s.io/v1/NetworkPolicy iam +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default +spec: + ingress: + - from: + - podSelector: + matchLabels: + component: proxy + ports: + - port: 9001 + protocol: TCP + - port: 9002 + protocol: TCP + podSelector: + matchLabels: + app: gitpod + component: iam + policyTypes: + - Ingress + --- # networking.k8s.io/v1/NetworkPolicy ide-metrics apiVersion: networking.k8s.io/v1 @@ -2123,6 +2152,16 @@ data: name: iam namespace: default --- + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default + --- apiVersion: v1 kind: ConfigMap metadata: @@ -3463,7 +3502,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { @@ -5076,7 +5115,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { diff --git a/install/installer/cmd/testdata/render/customization/output.golden b/install/installer/cmd/testdata/render/customization/output.golden index 3bc5c0ce6b0e71..27ac1e24ce1008 100644 --- a/install/installer/cmd/testdata/render/customization/output.golden +++ b/install/installer/cmd/testdata/render/customization/output.golden @@ -86,6 +86,35 @@ spec: policyTypes: - Ingress +--- +# networking.k8s.io/v1/NetworkPolicy iam +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default +spec: + ingress: + - from: + - podSelector: + matchLabels: + component: proxy + ports: + - port: 9001 + protocol: TCP + - port: 9002 + protocol: TCP + podSelector: + matchLabels: + app: gitpod + component: iam + policyTypes: + - Ingress + --- # networking.k8s.io/v1/NetworkPolicy ide-metrics apiVersion: networking.k8s.io/v1 @@ -2569,6 +2598,16 @@ data: name: iam namespace: default --- + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default + --- apiVersion: v1 kind: ConfigMap metadata: @@ -4328,7 +4367,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { @@ -6086,7 +6125,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { diff --git a/install/installer/cmd/testdata/render/external-registry/output.golden b/install/installer/cmd/testdata/render/external-registry/output.golden index 37c05f795c1a97..15d8579d94c75f 100644 --- a/install/installer/cmd/testdata/render/external-registry/output.golden +++ b/install/installer/cmd/testdata/render/external-registry/output.golden @@ -86,6 +86,35 @@ spec: policyTypes: - Ingress +--- +# networking.k8s.io/v1/NetworkPolicy iam +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default +spec: + ingress: + - from: + - podSelector: + matchLabels: + component: proxy + ports: + - port: 9001 + protocol: TCP + - port: 9002 + protocol: TCP + podSelector: + matchLabels: + app: gitpod + component: iam + policyTypes: + - Ingress + --- # networking.k8s.io/v1/NetworkPolicy ide-metrics apiVersion: networking.k8s.io/v1 @@ -2170,6 +2199,16 @@ data: name: iam namespace: default --- + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default + --- apiVersion: v1 kind: ConfigMap metadata: @@ -3604,7 +3643,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { @@ -5263,7 +5302,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { diff --git a/install/installer/cmd/testdata/render/gcp-setup/output.golden b/install/installer/cmd/testdata/render/gcp-setup/output.golden index e80f899a54aa3f..8c6abb5b5e037c 100644 --- a/install/installer/cmd/testdata/render/gcp-setup/output.golden +++ b/install/installer/cmd/testdata/render/gcp-setup/output.golden @@ -86,6 +86,35 @@ spec: policyTypes: - Ingress +--- +# networking.k8s.io/v1/NetworkPolicy iam +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default +spec: + ingress: + - from: + - podSelector: + matchLabels: + component: proxy + ports: + - port: 9001 + protocol: TCP + - port: 9002 + protocol: TCP + podSelector: + matchLabels: + app: gitpod + component: iam + policyTypes: + - Ingress + --- # networking.k8s.io/v1/NetworkPolicy ide-metrics apiVersion: networking.k8s.io/v1 @@ -2101,6 +2130,16 @@ data: name: iam namespace: default --- + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default + --- apiVersion: v1 kind: ConfigMap metadata: @@ -3434,7 +3473,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { @@ -5037,7 +5076,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { diff --git a/install/installer/cmd/testdata/render/http-proxy/output.golden b/install/installer/cmd/testdata/render/http-proxy/output.golden index 20d32da2b27434..29e668dd8614f7 100644 --- a/install/installer/cmd/testdata/render/http-proxy/output.golden +++ b/install/installer/cmd/testdata/render/http-proxy/output.golden @@ -86,6 +86,35 @@ spec: policyTypes: - Ingress +--- +# networking.k8s.io/v1/NetworkPolicy iam +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default +spec: + ingress: + - from: + - podSelector: + matchLabels: + component: proxy + ports: + - port: 9001 + protocol: TCP + - port: 9002 + protocol: TCP + podSelector: + matchLabels: + app: gitpod + component: iam + policyTypes: + - Ingress + --- # networking.k8s.io/v1/NetworkPolicy ide-metrics apiVersion: networking.k8s.io/v1 @@ -2279,6 +2308,16 @@ data: name: iam namespace: default --- + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default + --- apiVersion: v1 kind: ConfigMap metadata: @@ -3773,7 +3812,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { @@ -5486,7 +5525,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { diff --git a/install/installer/cmd/testdata/render/kind-ide/output.golden b/install/installer/cmd/testdata/render/kind-ide/output.golden index 0fafeddc2e9279..2f1d349a4727ce 100644 --- a/install/installer/cmd/testdata/render/kind-ide/output.golden +++ b/install/installer/cmd/testdata/render/kind-ide/output.golden @@ -1290,7 +1290,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { @@ -2609,7 +2609,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { diff --git a/install/installer/cmd/testdata/render/kind-meta/output.golden b/install/installer/cmd/testdata/render/kind-meta/output.golden index e2b98128fea338..e74fe4b49e0f8d 100644 --- a/install/installer/cmd/testdata/render/kind-meta/output.golden +++ b/install/installer/cmd/testdata/render/kind-meta/output.golden @@ -67,6 +67,35 @@ spec: policyTypes: - Ingress +--- +# networking.k8s.io/v1/NetworkPolicy iam +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default +spec: + ingress: + - from: + - podSelector: + matchLabels: + component: proxy + ports: + - port: 9001 + protocol: TCP + - port: 9002 + protocol: TCP + podSelector: + matchLabels: + app: gitpod + component: iam + policyTypes: + - Ingress + --- # networking.k8s.io/v1/NetworkPolicy ide-metrics apiVersion: networking.k8s.io/v1 @@ -1824,6 +1853,16 @@ data: name: iam namespace: default --- + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default + --- apiVersion: v1 kind: ConfigMap metadata: @@ -2742,7 +2781,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { @@ -4360,7 +4399,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { diff --git a/install/installer/cmd/testdata/render/kind-webapp/output.golden b/install/installer/cmd/testdata/render/kind-webapp/output.golden index 02bfb36e05bcc3..6b292928afe863 100644 --- a/install/installer/cmd/testdata/render/kind-webapp/output.golden +++ b/install/installer/cmd/testdata/render/kind-webapp/output.golden @@ -46,6 +46,35 @@ spec: policyTypes: - Ingress +--- +# networking.k8s.io/v1/NetworkPolicy iam +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default +spec: + ingress: + - from: + - podSelector: + matchLabels: + component: proxy + ports: + - port: 9001 + protocol: TCP + - port: 9002 + protocol: TCP + podSelector: + matchLabels: + app: gitpod + component: iam + policyTypes: + - Ingress + --- # networking.k8s.io/v1/NetworkPolicy messagebus # Source: rabbitmq/charts/rabbitmq/templates/networkpolicy.yaml @@ -1203,6 +1232,16 @@ data: name: iam namespace: default --- + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default + --- apiVersion: v1 kind: ConfigMap metadata: diff --git a/install/installer/cmd/testdata/render/minimal/output.golden b/install/installer/cmd/testdata/render/minimal/output.golden index 861c5bc1a54e41..d728171bf60d8f 100644 --- a/install/installer/cmd/testdata/render/minimal/output.golden +++ b/install/installer/cmd/testdata/render/minimal/output.golden @@ -86,6 +86,35 @@ spec: policyTypes: - Ingress +--- +# networking.k8s.io/v1/NetworkPolicy iam +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default +spec: + ingress: + - from: + - podSelector: + matchLabels: + component: proxy + ports: + - port: 9001 + protocol: TCP + - port: 9002 + protocol: TCP + podSelector: + matchLabels: + app: gitpod + component: iam + policyTypes: + - Ingress + --- # networking.k8s.io/v1/NetworkPolicy ide-metrics apiVersion: networking.k8s.io/v1 @@ -2276,6 +2305,16 @@ data: name: iam namespace: default --- + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default + --- apiVersion: v1 kind: ConfigMap metadata: @@ -3770,7 +3809,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { @@ -5483,7 +5522,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { diff --git a/install/installer/cmd/testdata/render/shortname/output.golden b/install/installer/cmd/testdata/render/shortname/output.golden index 83eecf80e0ef28..90b2be4d7a574f 100644 --- a/install/installer/cmd/testdata/render/shortname/output.golden +++ b/install/installer/cmd/testdata/render/shortname/output.golden @@ -86,6 +86,35 @@ spec: policyTypes: - Ingress +--- +# networking.k8s.io/v1/NetworkPolicy iam +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default +spec: + ingress: + - from: + - podSelector: + matchLabels: + component: proxy + ports: + - port: 9001 + protocol: TCP + - port: 9002 + protocol: TCP + podSelector: + matchLabels: + app: gitpod + component: iam + policyTypes: + - Ingress + --- # networking.k8s.io/v1/NetworkPolicy ide-metrics apiVersion: networking.k8s.io/v1 @@ -2276,6 +2305,16 @@ data: name: iam namespace: default --- + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default + --- apiVersion: v1 kind: ConfigMap metadata: @@ -3770,7 +3809,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { @@ -5483,7 +5522,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { diff --git a/install/installer/cmd/testdata/render/statefulset-customization/output.golden b/install/installer/cmd/testdata/render/statefulset-customization/output.golden index 74c5e595f0a585..11efaa78148ebc 100644 --- a/install/installer/cmd/testdata/render/statefulset-customization/output.golden +++ b/install/installer/cmd/testdata/render/statefulset-customization/output.golden @@ -86,6 +86,35 @@ spec: policyTypes: - Ingress +--- +# networking.k8s.io/v1/NetworkPolicy iam +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default +spec: + ingress: + - from: + - podSelector: + matchLabels: + component: proxy + ports: + - port: 9001 + protocol: TCP + - port: 9002 + protocol: TCP + podSelector: + matchLabels: + app: gitpod + component: iam + policyTypes: + - Ingress + --- # networking.k8s.io/v1/NetworkPolicy ide-metrics apiVersion: networking.k8s.io/v1 @@ -2288,6 +2317,16 @@ data: name: iam namespace: default --- + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default + --- apiVersion: v1 kind: ConfigMap metadata: @@ -3782,7 +3821,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { @@ -5495,7 +5534,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { diff --git a/install/installer/cmd/testdata/render/use-pod-security-policies/output.golden b/install/installer/cmd/testdata/render/use-pod-security-policies/output.golden index f08cabfd8e4a33..4dfb164a789498 100644 --- a/install/installer/cmd/testdata/render/use-pod-security-policies/output.golden +++ b/install/installer/cmd/testdata/render/use-pod-security-policies/output.golden @@ -86,6 +86,35 @@ spec: policyTypes: - Ingress +--- +# networking.k8s.io/v1/NetworkPolicy iam +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default +spec: + ingress: + - from: + - podSelector: + matchLabels: + component: proxy + ports: + - port: 9001 + protocol: TCP + - port: 9002 + protocol: TCP + podSelector: + matchLabels: + app: gitpod + component: iam + policyTypes: + - Ingress + --- # networking.k8s.io/v1/NetworkPolicy ide-metrics apiVersion: networking.k8s.io/v1 @@ -2564,6 +2593,16 @@ data: name: iam namespace: default --- + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default + --- apiVersion: v1 kind: ConfigMap metadata: @@ -4103,7 +4142,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { @@ -5816,7 +5855,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { diff --git a/install/installer/cmd/testdata/render/vsxproxy-pvc/output.golden b/install/installer/cmd/testdata/render/vsxproxy-pvc/output.golden index b93c282294a3fa..7b4e4885bac9be 100644 --- a/install/installer/cmd/testdata/render/vsxproxy-pvc/output.golden +++ b/install/installer/cmd/testdata/render/vsxproxy-pvc/output.golden @@ -86,6 +86,35 @@ spec: policyTypes: - Ingress +--- +# networking.k8s.io/v1/NetworkPolicy iam +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default +spec: + ingress: + - from: + - podSelector: + matchLabels: + component: proxy + ports: + - port: 9001 + protocol: TCP + - port: 9002 + protocol: TCP + podSelector: + matchLabels: + app: gitpod + component: iam + policyTypes: + - Ingress + --- # networking.k8s.io/v1/NetworkPolicy ide-metrics apiVersion: networking.k8s.io/v1 @@ -2278,6 +2307,16 @@ data: name: iam namespace: default --- + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default + --- apiVersion: v1 kind: ConfigMap metadata: @@ -3772,7 +3811,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { @@ -5485,7 +5524,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { diff --git a/install/installer/cmd/testdata/render/workspace-requests-limits/output.golden b/install/installer/cmd/testdata/render/workspace-requests-limits/output.golden index 2261920ae1f0bc..a525644c5f5227 100644 --- a/install/installer/cmd/testdata/render/workspace-requests-limits/output.golden +++ b/install/installer/cmd/testdata/render/workspace-requests-limits/output.golden @@ -86,6 +86,35 @@ spec: policyTypes: - Ingress +--- +# networking.k8s.io/v1/NetworkPolicy iam +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default +spec: + ingress: + - from: + - podSelector: + matchLabels: + component: proxy + ports: + - port: 9001 + protocol: TCP + - port: 9002 + protocol: TCP + podSelector: + matchLabels: + app: gitpod + component: iam + policyTypes: + - Ingress + --- # networking.k8s.io/v1/NetworkPolicy ide-metrics apiVersion: networking.k8s.io/v1 @@ -2279,6 +2308,16 @@ data: name: iam namespace: default --- + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + creationTimestamp: null + labels: + app: gitpod + component: iam + name: iam + namespace: default + --- apiVersion: v1 kind: ConfigMap metadata: @@ -3773,7 +3812,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { @@ -5486,7 +5525,7 @@ data: "type": "browser", "logo": "https://ide.gitpod.example.com/image/ide-logo/vscode.svg", "label": "Browser", - "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c", + "image": "eu.gcr.io/gitpod-core-dev/build/ide/code:commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5", "latestImage": "eu.gcr.io/gitpod-core-dev/build/ide/code:nightly" }, "code-desktop": { diff --git a/install/installer/pkg/components/iam/configmap.go b/install/installer/pkg/components/iam/configmap.go index e6c64529106efd..b32b3155bf01ac 100644 --- a/install/installer/pkg/components/iam/configmap.go +++ b/install/installer/pkg/components/iam/configmap.go @@ -11,6 +11,7 @@ import ( "github.com/gitpod-io/gitpod/iam/pkg/config" "github.com/gitpod-io/gitpod/installer/pkg/common" + "github.com/gitpod-io/gitpod/installer/pkg/config/v1/experimental" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -39,6 +40,16 @@ func configmap(ctx *common.RenderContext) ([]runtime.Object, error) { DatabaseConfigPath: databaseSecretMountPath, } + _ = ctx.WithExperimental(func(ucfg *experimental.Config) error { + _, _, path, ok := getOIDCClientsConfig(ucfg) + if !ok { + return nil + } + + cfg.OIDCClientsConfigFile = path + return nil + }) + fc, err := common.ToJSONString(cfg) if err != nil { return nil, fmt.Errorf("failed to marshal config: %w", err) diff --git a/install/installer/pkg/components/iam/constants.go b/install/installer/pkg/components/iam/constants.go index d680c5432200cf..fc21b16dbc4a40 100644 --- a/install/installer/pkg/components/iam/constants.go +++ b/install/installer/pkg/components/iam/constants.go @@ -7,10 +7,12 @@ package iam const ( Component = "iam" - GRPCPortName = "grpc" - GRPCContainerPort = 9001 - GRPCServicePort = 9001 - HTTPContainerPort = 9002 - HTTPServicePort = 9002 - HTTPPortName = "http" + GRPCPortName = "grpc" + GRPCContainerPort = 9001 + GRPCServicePort = 9001 + HTTPContainerPort = 9002 + HTTPServicePort = 9002 + HTTPPortName = "http" + oidcClientsSecretMountPath = "oidc-clients-secret" + oidcClientsSecretFilename = "config.json" ) diff --git a/install/installer/pkg/components/iam/deployment.go b/install/installer/pkg/components/iam/deployment.go index 51e5075b751b18..93c8b9759209e2 100644 --- a/install/installer/pkg/components/iam/deployment.go +++ b/install/installer/pkg/components/iam/deployment.go @@ -11,6 +11,7 @@ import ( "github.com/gitpod-io/gitpod/installer/pkg/cluster" "github.com/gitpod-io/gitpod/installer/pkg/common" + "github.com/gitpod-io/gitpod/installer/pkg/config/v1/experimental" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -55,6 +56,17 @@ func deployment(ctx *common.RenderContext) ([]runtime.Object, error) { databaseSecretMount, } + _ = ctx.WithExperimental(func(cfg *experimental.Config) error { + volume, mount, _, ok := getOIDCClientsConfig(cfg) + if !ok { + return nil + } + + volumes = append(volumes, volume) + volumeMounts = append(volumeMounts, mount) + return nil + }) + labels := common.CustomizeLabel(ctx, Component, common.TypeMetaDeployment) return []runtime.Object{ &appsv1.Deployment{ diff --git a/install/installer/pkg/components/iam/networkpolicy.go b/install/installer/pkg/components/iam/networkpolicy.go new file mode 100644 index 00000000000000..813f7796d3f961 --- /dev/null +++ b/install/installer/pkg/components/iam/networkpolicy.go @@ -0,0 +1,55 @@ +// Copyright (c) 2021 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package iam + +import ( + "github.com/gitpod-io/gitpod/installer/pkg/common" + networkingv1 "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/intstr" +) + +func networkpolicy(ctx *common.RenderContext) ([]runtime.Object, error) { + labels := common.DefaultLabels(Component) + + return []runtime.Object{ + &networkingv1.NetworkPolicy{ + TypeMeta: common.TypeMetaNetworkPolicy, + ObjectMeta: metav1.ObjectMeta{ + Name: Component, + Namespace: ctx.Namespace, + Labels: labels, + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{MatchLabels: labels}, + PolicyTypes: []networkingv1.PolicyType{"Ingress"}, + Ingress: []networkingv1.NetworkPolicyIngressRule{ + { + Ports: []networkingv1.NetworkPolicyPort{ + { + Protocol: common.TCPProtocol, + Port: &intstr.IntOrString{IntVal: GRPCContainerPort}, + }, + { + Protocol: common.TCPProtocol, + Port: &intstr.IntOrString{IntVal: HTTPContainerPort}, + }, + }, + From: []networkingv1.NetworkPolicyPeer{ + { + PodSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "component": common.ProxyComponent, + }, + }, + }, + }, + }, + }, + }, + }, + }, nil +} diff --git a/install/installer/pkg/components/iam/objects.go b/install/installer/pkg/components/iam/objects.go index 9e861886b9f91c..83f99ecc7b2d47 100644 --- a/install/installer/pkg/components/iam/objects.go +++ b/install/installer/pkg/components/iam/objects.go @@ -16,5 +16,6 @@ func Objects(ctx *common.RenderContext) ([]runtime.Object, error) { rolebinding, common.DefaultServiceAccount(Component), service, + networkpolicy, )(ctx) } diff --git a/install/installer/pkg/components/iam/oidc.go b/install/installer/pkg/components/iam/oidc.go new file mode 100644 index 00000000000000..1e3280a130bb02 --- /dev/null +++ b/install/installer/pkg/components/iam/oidc.go @@ -0,0 +1,43 @@ +// Copyright (c) 2022 Gitpod GmbH. All rights reserved. +// Licensed under the MIT License. See License-MIT.txt in the project root for license information. + +package iam + +import ( + "path/filepath" + + "github.com/gitpod-io/gitpod/installer/pkg/config/v1/experimental" + corev1 "k8s.io/api/core/v1" + "k8s.io/utils/pointer" +) + +func getOIDCClientsConfig(cfg *experimental.Config) (corev1.Volume, corev1.VolumeMount, string, bool) { + var volume corev1.Volume + var mount corev1.VolumeMount + var path string + + if cfg == nil || cfg.WebApp == nil || cfg.WebApp.IAM == nil || cfg.WebApp.IAM.OIDCClientsSecretName == "" { + return volume, mount, path, false + } + + secretName := cfg.WebApp.IAM.OIDCClientsSecretName + + volume = corev1.Volume{ + Name: "oidc-clients-secret", + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: secretName, + Optional: pointer.Bool(true), + }, + }, + } + + mount = corev1.VolumeMount{ + Name: "oidc-clients-secret", + MountPath: oidcClientsSecretMountPath, + ReadOnly: true, + } + path = filepath.Join(oidcClientsSecretMountPath, oidcClientsSecretFilename) + + return volume, mount, path, true +} diff --git a/install/installer/pkg/components/refresh-credential/configmap.go b/install/installer/pkg/components/refresh-credential/configmap.go index 544cea2d8430df..5b7348afc73636 100644 --- a/install/installer/pkg/components/refresh-credential/configmap.go +++ b/install/installer/pkg/components/refresh-credential/configmap.go @@ -1,5 +1,6 @@ // Copyright (c) 2022 Gitpod GmbH. All rights reserved. -// Licensed under the MIT License. See License-MIT.txt in the project root for license information. +// Licensed under the GNU Affero General Public License (AGPL). +// See License.AGPL.txt in the project root for license information. package refresh_credential diff --git a/install/installer/pkg/components/workspace/ide/constants.go b/install/installer/pkg/components/workspace/ide/constants.go index 8fdae2996098a9..45f927a5d68085 100644 --- a/install/installer/pkg/components/workspace/ide/constants.go +++ b/install/installer/pkg/components/workspace/ide/constants.go @@ -6,7 +6,7 @@ package ide const ( CodeIDEImage = "ide/code" - CodeIDEImageStableVersion = "commit-8335b0de46d748b9d12119bc7cbdf8554a9e121c" // stable version that will be updated manually on demand + CodeIDEImageStableVersion = "commit-73b9682c5040a9fec5a02e066aa48faa635f5ca5" // stable version that will be updated manually on demand CodeDesktopIDEImage = "ide/code-desktop" CodeDesktopInsidersIDEImage = "ide/code-desktop-insiders" IntelliJDesktopIDEImage = "ide/intellij" diff --git a/install/installer/pkg/config/v1/experimental/experimental.go b/install/installer/pkg/config/v1/experimental/experimental.go index 83562e6edb2ef5..3dcf1d4acbfa97 100644 --- a/install/installer/pkg/config/v1/experimental/experimental.go +++ b/install/installer/pkg/config/v1/experimental/experimental.go @@ -185,6 +185,7 @@ type StripeConfig struct { } type IAMConfig struct { + OIDCClientsSecretName string `json:"oidsClientsConfigSecret,omitempty"` } type WebAppConfig struct { diff --git a/test/README.md b/test/README.md index 865220fc4269e0..e655c1778607d3 100644 --- a/test/README.md +++ b/test/README.md @@ -58,7 +58,10 @@ If you want to run an entire test suite, the easiest is to use `./test/run.sh`: ./test/run.sh # This will run only the webapp test suite -./test/run.sh webapp +./test/run.sh -s webapp + +# This will run only the webapp test suite with the report +./test/run.sh -s webapp -r report.csv ``` If you're iterating on a single test, the easiest is to use `go test` directly. diff --git a/test/pkg/report/features.go b/test/pkg/report/features.go new file mode 100644 index 00000000000000..215d2547763536 --- /dev/null +++ b/test/pkg/report/features.go @@ -0,0 +1,17 @@ +// Copyright (c) 2022 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License.AGPL.txt in the project root for license information. + +package report + +type Feature string + +const ( + FeatureExample Feature = "example" + FeatureResourceLimit Feature = "resource limit" + FeatureContentInit Feature = "content init" + FeatureDocker Feature = "docker" + FeatureDotfiles Feature = "dotfiles" + FeatureMultiRepos Feature = "multi repos" + FeaturePrebuild Feature = "prebuild" +) diff --git a/test/pkg/report/report.go b/test/pkg/report/report.go new file mode 100644 index 00000000000000..fa46e3b54973d4 --- /dev/null +++ b/test/pkg/report/report.go @@ -0,0 +1,14 @@ +// Copyright (c) 2022 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License.AGPL.txt in the project root for license information. + +package report + +import "testing" + +func SetupReport(t *testing.T, feat Feature, desc string) { + // Output the feature type of this test for the Quality Assurance Report + t.Log(feat) + // Output the description of this test for the Quality Assurance Report + t.Log(desc) +} diff --git a/test/run.sh b/test/run.sh index 832b8b759d5fd1..3cbefa9586102d 100755 --- a/test/run.sh +++ b/test/run.sh @@ -4,18 +4,40 @@ # # Usage: # -# run.sh [suite] +# run.sh --suite [suite] --report [report_file] # # Examples # -# run.sh This will run all test suites -# run.sh ide This will run just the 'ide' test suite +# run.sh This will run all test suites +# run.sh -s ide This will run just the 'ide' test suite +# run.sh -s ide -r report.csv This will run just the 'ide' test suite with the report for the quality assurance # set -euo pipefail +REPORT="" +TEST_SUITE=all +opt="" +optarg="" +while getopts rs-: opt; do + optarg="${!OPTIND}" + [[ "$opt" = - ]] && opt="-$OPTARG" + + case "-$opt" in + -r|--report) + REPORT=${optarg} + shift + ;; + -s|--suit) + TEST_SUITE=${optarg} + shift + ;; + *) ;; + esac +done +shift $((OPTIND - 1)) + THIS_DIR="$(dirname "$0")" -TEST_SUITE=${1:-'all'} FAILURE_COUNT=0 LOGS_DIR=$(mktemp -d) @@ -54,6 +76,9 @@ case $TEST_SUITE in esac args=() +if [ "${REPORT}" != "" ]; then + args+=( "--json" ) +fi args+=( "-kubeconfig=${KUBECONFIG:-/home/gitpod/.kube/config}" ) args+=( "-namespace=${NAMESPACE:-default}" ) args+=( "-timeout=60m" ) @@ -98,7 +123,7 @@ if [ "$TEST_SUITE" == "workspace" ]; then echo "running integration for ${TEST_NAME} - log file at ${LOG_FILE}" | werft log slice "test-${TEST_NAME}-serial-only" set +e # shellcheck disable=SC2086 - go test -v $TEST_LIST "${args[@]}" -run '.*SerialOnly$' -p 1 2>&1 | tee "${LOG_FILE}" | werft log slice "test-${TEST_NAME}-serial-only" + go test -v $TEST_LIST "${args[@]}" -run '.*SerialOnly$' -p 1 2>&1 | tee -a "${LOG_FILE}" | werft log slice "test-${TEST_NAME}-serial-only" RC=${PIPESTATUS[0]} set -e @@ -110,6 +135,9 @@ if [ "$TEST_SUITE" == "workspace" ]; then fi cd - + if [ "${REPORT}" != "" ]; then + ./report.sh "${LOG_FILE}" > "$REPORT" + fi else for TEST_PATH in ${TEST_LIST} do diff --git a/test/tests/workspace/cgroup_v2_test.go b/test/tests/workspace/cgroup_v2_test.go index 5186d1254e7aa4..6005ad87909d64 100644 --- a/test/tests/workspace/cgroup_v2_test.go +++ b/test/tests/workspace/cgroup_v2_test.go @@ -19,12 +19,14 @@ import ( agent "github.com/gitpod-io/gitpod/test/pkg/agent/workspace/api" "github.com/gitpod-io/gitpod/test/pkg/integration" + "github.com/gitpod-io/gitpod/test/pkg/report" ) func TestCgroupV2(t *testing.T) { f := features.New("cgroup v2"). WithLabel("component", "workspace"). Assess("it should create a new cgroup when cgroup v2 is enabled", func(_ context.Context, t *testing.T, cfg *envconf.Config) context.Context { + report.SetupReport(t, report.FeatureResourceLimit, "this is the test for cgroup v2") t.Parallel() ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) diff --git a/test/tests/workspace/contexts_test.go b/test/tests/workspace/contexts_test.go index 10a7a65e5174ef..c8393332f2cb11 100644 --- a/test/tests/workspace/contexts_test.go +++ b/test/tests/workspace/contexts_test.go @@ -6,6 +6,7 @@ package workspace import ( "context" + "fmt" "os" "testing" "time" @@ -14,6 +15,7 @@ import ( "sigs.k8s.io/e2e-framework/pkg/features" "github.com/gitpod-io/gitpod/test/pkg/integration" + "github.com/gitpod-io/gitpod/test/pkg/report" ) type ContextTest struct { @@ -144,6 +146,7 @@ func runContextTests(t *testing.T, tests []ContextTest) { for _, ff := range ffs { for _, test := range tests { t.Run(test.ContextURL+"_"+ff.Name, func(t *testing.T) { + report.SetupReport(t, report.FeatureContentInit, fmt.Sprintf("Test to open %v", test.ContextURL)) if test.Skip { t.SkipNow() } diff --git a/test/tests/workspace/example_test.go b/test/tests/workspace/example_test.go index 3e9fae40eae14f..eec7d98c2dbdec 100644 --- a/test/tests/workspace/example_test.go +++ b/test/tests/workspace/example_test.go @@ -15,6 +15,7 @@ import ( agent "github.com/gitpod-io/gitpod/test/pkg/agent/workspace/api" "github.com/gitpod-io/gitpod/test/pkg/integration" + "github.com/gitpod-io/gitpod/test/pkg/report" ) func TestWorkspaceInstrumentation(t *testing.T) { @@ -38,6 +39,8 @@ func TestWorkspaceInstrumentation(t *testing.T) { Assess("it can instrument a workspace", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context { for _, test := range tests { t.Run(test.ContextURL, func(t *testing.T) { + report.SetupReport(t, report.FeatureExample, "this is the example test for instrumenting a workspace") + t.Parallel() ctx, cancel := context.WithTimeout(context.Background(), time.Duration(5*len(tests))*time.Minute) diff --git a/yarn.lock b/yarn.lock index c0be8e35150fde..9a228b90e7486e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12311,6 +12311,14 @@ next-tick@~1.0.0: resolved "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz" integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= +nice-grpc-client-middleware-retry@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/nice-grpc-client-middleware-retry/-/nice-grpc-client-middleware-retry-2.0.1.tgz#2b70d606baa6360acf8e216348ee761be20b34b2" + integrity sha512-U3oWOkSXw2VnBRUOduMYq6pwJ358HjbbhEzupOypIY9UhCHfyT7CxFs49Fd7v0zdV+EsxxowlkheM1v30vmTxw== + dependencies: + abort-controller-x "^0.4.0" + nice-grpc-common "^2.0.0" + nice-grpc-common@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/nice-grpc-common/-/nice-grpc-common-2.0.0.tgz#36c9b9cdc38d3b4aa8ad7abf120fd4737eff70ea"