diff --git a/Makefile.core.mk b/Makefile.core.mk index b1715989b8f..da44cddfcd3 100644 --- a/Makefile.core.mk +++ b/Makefile.core.mk @@ -343,7 +343,6 @@ gen: \ proto \ copy-templates \ gen-kustomize \ - maistra-gen \ update-golden ## Update all generated code. gen-check: gen check-clean-repo @@ -523,4 +522,7 @@ include tests/integration/tests.mk include common/Makefile.common.mk -include pkg/servicemesh/maistra.mk +#----------------------------------------------------------------------------- +# Maistra +#----------------------------------------------------------------------------- +include maistra.mk diff --git a/bin/update_maistra_deps.sh b/bin/update_maistra_deps.sh index 595c4fcb59e..18494c732f7 100755 --- a/bin/update_maistra_deps.sh +++ b/bin/update_maistra_deps.sh @@ -36,9 +36,9 @@ popd # rm -f manifests/charts/base/crds/maistra* # cp "${dir}"/manifests/* manifests/charts/base/crds -cp "${dir}"/manifests/maistra.io_meshfederations.yaml manifests/charts/base/crds -cp "${dir}"/manifests/maistra.io_serviceexports.yaml manifests/charts/base/crds -cp "${dir}"/manifests/maistra.io_servicemeshextensions.yaml manifests/charts/base/crds +cp "${dir}"/manifests/federation.maistra.io_servicemeshpeers.yaml manifests/charts/base/crds +cp "${dir}"/manifests/federation.maistra.io_exportedservicesets.yaml manifests/charts/base/crds +cp "${dir}"/manifests/federation.maistra.io_importedservicesets.yaml manifests/charts/base/crds rm -rf "${dir}" diff --git a/common/config/.golangci-format.yml b/common/config/.golangci-format.yml index 15da25a3005..9ff1bbf03ee 100644 --- a/common/config/.golangci-format.yml +++ b/common/config/.golangci-format.yml @@ -30,6 +30,8 @@ run: skip-files: - ".*\\.pb\\.go" - ".*\\.gen\\.go" + # This file requires a custom import order for side effects (https://github.com/grpc/grpc-go/issues/4124) + - pilot/pkg/networking/grpcgen/grpcgen_test.go linters: disable-all: true diff --git a/go.mod b/go.mod index 28dcc37e79e..ae0a538d392 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( contrib.go.opencensus.io/exporter/prometheus v0.4.1 github.com/AdaLogics/go-fuzz-headers v0.0.0-20220408101031-f1761e18c0c6 github.com/Masterminds/sprig/v3 v3.2.2 + github.com/cenkalti/backoff v2.2.1+incompatible github.com/cenkalti/backoff/v4 v4.1.3 github.com/census-instrumentation/opencensus-proto v0.3.0 github.com/cheggaaa/pb/v3 v3.0.8 @@ -53,10 +54,12 @@ require ( github.com/miekg/dns v1.1.48 github.com/mitchellh/copystructure v1.2.0 github.com/mitchellh/go-homedir v1.1.0 - github.com/moby/buildkit v0.10.1 + github.com/mitchellh/hashstructure/v2 v2.0.2 + github.com/moby/buildkit v0.10.4 github.com/onsi/gomega v1.19.0 github.com/openshift/api v0.0.0-20200929171550-c99a4deebbe5 github.com/openshift/client-go v0.0.0-20200929181438-91d71ef2122c + github.com/pkg/errors v0.9.1 github.com/pmezard/go-difflib v1.0.0 github.com/prometheus/client_golang v1.12.1 github.com/prometheus/client_model v0.2.0 @@ -85,7 +88,7 @@ require ( google.golang.org/protobuf v1.28.0 gopkg.in/square/go-jose.v2 v2.6.0 gopkg.in/yaml.v2 v2.4.0 - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b + gopkg.in/yaml.v3 v3.0.0 helm.sh/helm/v3 v3.8.2 istio.io/api v0.0.0-20220728184806-7837c4e62d82 istio.io/client-go v1.14.3-0.20220728185607-9117649b5a7f @@ -205,7 +208,6 @@ require ( github.com/pelletier/go-toml v1.9.4 // indirect github.com/pelletier/go-toml/v2 v2.0.0-beta.8 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect github.com/prometheus/prom2json v1.3.0 // indirect github.com/prometheus/statsd_exporter v0.21.0 // indirect diff --git a/go.sum b/go.sum index 5941bddecc5..fed1aa29ffd 100644 --- a/go.sum +++ b/go.sum @@ -335,6 +335,8 @@ github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacM github.com/caarlos0/ctrlc v1.0.0/go.mod h1:CdXpj4rmq0q/1Eb44M9zi2nKB0QraNKuRGYGrrHhcQw= github.com/campoy/unique v0.0.0-20180121183637-88950e537e7e/go.mod h1:9IOqJGCPMSc6E5ydlp5NIonxObaeu/Iub/X03EKPVYo= github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e/go.mod h1:oDpT4efm8tSYHXV5tHSdRvBet/b/QzxZ+XyyPehvm3A= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= @@ -585,7 +587,6 @@ github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TT github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.8.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v0.0.0-20200511152416-a93e9eb0e95c/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= @@ -689,6 +690,7 @@ github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYis github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= @@ -1144,7 +1146,6 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ= github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= -github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg= github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw= github.com/jaguilar/vt100 v0.0.0-20150826170717-2703a27b14ea/go.mod h1:QMdK4dGB3YhEW2BmA1wgGpPYI3HZy/5gD705PXKUVSg= @@ -1406,7 +1407,9 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y= github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= +github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -1422,8 +1425,8 @@ github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/buildkit v0.8.1/go.mod h1:/kyU1hKy/aYCuP39GZA9MaKioovHku57N6cqlKZIaiQ= -github.com/moby/buildkit v0.10.1 h1:jB0xuJU0ehDxDnzKal6R7BUHxXZ/EOA1CCuD+24fBvU= -github.com/moby/buildkit v0.10.1/go.mod h1:jxeOuly98l9gWHai0Ojrbnczrk/rf+o9/JqNhY+UCSo= +github.com/moby/buildkit v0.10.4 h1:FvC+buO8isGpUFZ1abdSLdGHZVqg9sqI4BbFL8tlzP4= +github.com/moby/buildkit v0.10.4/go.mod h1:Yajz9vt1Zw5q9Pp4pdb3TCSUXJBIroIQGQ3TTs/sLug= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= @@ -2921,8 +2924,9 @@ gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= diff --git a/licenses/github.com/cenkalti/backoff/LICENSE b/licenses/github.com/cenkalti/backoff/LICENSE new file mode 100644 index 00000000000..89b81799655 --- /dev/null +++ b/licenses/github.com/cenkalti/backoff/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Cenk Altı + +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/licenses/github.com/mitchellh/hashstructure/v2/LICENSE b/licenses/github.com/mitchellh/hashstructure/v2/LICENSE new file mode 100644 index 00000000000..a3866a291fd --- /dev/null +++ b/licenses/github.com/mitchellh/hashstructure/v2/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Mitchell Hashimoto + +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/licenses/maistra.io/api/LICENSE b/licenses/maistra.io/api/LICENSE new file mode 100644 index 00000000000..b085857dfb7 --- /dev/null +++ b/licenses/maistra.io/api/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 Red Hat Inc + + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/maistra.mk b/maistra.mk new file mode 100644 index 00000000000..9c1ab66a579 --- /dev/null +++ b/maistra.mk @@ -0,0 +1,7 @@ +.PHONY: vendor +vendor: + @echo "updating vendor" + @go mod vendor + @echo "done updating vendor" + +gen: vendor diff --git a/manifests/charts/base/crds/federation.maistra.io_exportedservicesets.yaml b/manifests/charts/base/crds/federation.maistra.io_exportedservicesets.yaml new file mode 100644 index 00000000000..b695c3f84fe --- /dev/null +++ b/manifests/charts/base/crds/federation.maistra.io_exportedservicesets.yaml @@ -0,0 +1,221 @@ + +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: exportedservicesets.federation.maistra.io +spec: + group: federation.maistra.io + names: + kind: ExportedServiceSet + listKind: ExportedServiceSetList + plural: exportedservicesets + singular: exportedserviceset + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: ExportedServiceSet is the Schema for configuring exported services. + It must be created in the same namespace as the control plane. The name + of the ExportedServiceSet resource must match the name of a ServiceMeshPeer + resource defining the remote mesh to which the services will be exported. + This implies there will be at most one ExportedServiceSet resource per peer + and control plane. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines rules for matching services to be exported. + properties: + exportRules: + description: ExportRules are the rules that determine which services + are exported from the mesh. The list is processed in order and + the first spec in the list that applies to a service is the one + that will be applied. This allows more specific selectors to be + placed before more general selectors. + items: + properties: + labelSelector: + description: LabelSelector provides a mechanism for selecting + services to export by using a label selector to match Service + resources for export. + properties: + aliases: + description: 'Aliases is a map of aliases to apply to exported + services. If a name is not found in the map, the original + service name is exported. A ''*'' will match any name. + The Aliases list will be processed in order, with the + first match found being applied to the exported service. + Examples: */foo->*/bar will match foo service in any namesapce, + exporting it as bar from its original namespace. */foo->bar/bar + will match foo service in any namespace, exporting it + as bar/bar. foo/*->bar/* will match any service in foo + namespace, exporting it from the bar namespace with its + original name */*->bar/* will match any service and export + it from the bar namespace with its original name. */*->*/* + is the same as not specifying anything' + items: + properties: + alias: + properties: + name: + type: string + namespace: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + type: array + namespace: + description: Namespace specifies to which namespace the + selector applies. An empty value applies to all namespaces + in the mesh. + type: string + selector: + description: Selector used to select Service resources in + the namespace/mesh. An empty selector selects all services. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists + or DoesNotExist, the values array must be empty. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + type: object + nameSelector: + description: NameSelector provides a simple name matcher for + exporting services in the mesh. + properties: + alias: + properties: + name: + type: string + namespace: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + type: + description: Type of rule. One of NameSelector or LabelSelector. + type: string + required: + - type + type: object + type: array + type: object + status: + properties: + exportedServices: + description: Exports provides details about the services exported + by this mesh. + items: + description: PeerServiceMapping represents the name mapping between + an exported service and its local counterpart. + properties: + exportedName: + description: ExportedName represents the fully qualified domain + name (FQDN) of an exported service. For an exporting mesh, + this is the name that is exported to the remote mesh. For + an importing mesh, this would be the name of the service exported + by the remote mesh. + type: string + localService: + description: LocalService represents the service in the local + (i.e. this) mesh. For an exporting mesh, this would be the + service being exported. For an importing mesh, this would + be the imported service. + properties: + hostname: + description: Hostname represents fully qualified domain + name (FQDN) used to access the service. + type: string + name: + description: Name represents the simple name of the service, + e.g. the metadata.name field of a kubernetes Service. + type: string + namespace: + description: Namespace represents the namespace within which + the service resides. + type: string + required: + - hostname + - name + - namespace + type: object + required: + - exportedName + - localService + type: object + type: array + x-kubernetes-list-map-keys: + - exportedName + x-kubernetes-list-type: map + required: + - exportedServices + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/manifests/charts/base/crds/federation.maistra.io_importedservicesets.yaml b/manifests/charts/base/crds/federation.maistra.io_importedservicesets.yaml new file mode 100644 index 00000000000..8dcb552e14b --- /dev/null +++ b/manifests/charts/base/crds/federation.maistra.io_importedservicesets.yaml @@ -0,0 +1,171 @@ + +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: importedservicesets.federation.maistra.io +spec: + group: federation.maistra.io + names: + kind: ImportedServiceSet + listKind: ImportedServiceSetList + plural: importedservicesets + singular: importedserviceset + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: ImportedServiceSet is the Schema for configuring imported services. + It must be created in the same namespace as the control plane. The name + of the ImportedServiceSet resource must match the name of a ServiceMeshPeer + resource defining the remote mesh from which the services will be imported. + This implies there will be at most one ImportedServiceSet resource per peer + and control plane. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines rules for matching services to be imported. + properties: + domainSuffix: + description: 'DomainSuffix specifies the domain suffix to be applies + to imported services. If no domain suffix is specified, imported + services will be named as follows: ..svc.-imports.local + If a domain suffix is specified, imported services will be named + as follows: ..' + type: string + importRules: + description: ImportRules are the rules that determine which services + are imported to the mesh. The list is processed in order and the + first spec in the list that applies to a service is the one that + will be applied. This allows more specific selectors to be placed + before more general selectors. + items: + properties: + domainSuffix: + description: DomainSuffix applies the specified suffix to services + imported by this rule. The behavior is identical to that + of ImportedServiceSetSpec.DomainSuffix. + type: string + importAsLocal: + description: ImportAsLocal imports the service as a local service + in the mesh. For example, if an exported service, foo/bar + is imported as some-ns/service, the service will be imported + as service.some-ns.svc.cluster.local in the some-ns namespace. If + a service of this name already exists in the mesh, the imported + service's endpoints will be aggregated with any other workloads + associated with the service. This setting overrides DomainSuffix. + type: boolean + nameSelector: + description: NameSelector provides a simple name matcher for + importing services in the mesh. + properties: + alias: + properties: + name: + type: string + namespace: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + type: + description: Type of rule. Only NameSelector type is supported. + type: string + required: + - type + type: object + type: array + locality: + description: Locality within which imported services should be associated. + properties: + region: + description: Region within which imported services are located. + type: string + subzone: + description: Subzone within which imported services are located. If + Subzone is specified, Zone must also be specified. + type: string + zone: + description: Zone within which imported services are located. If + Zone is specified, Region must also be specified. + type: string + type: object + type: object + status: + properties: + importedServices: + description: Imports provides details about the services imported + by this mesh. + items: + description: PeerServiceMapping represents the name mapping between + an exported service and its local counterpart. + properties: + exportedName: + description: ExportedName represents the fully qualified domain + name (FQDN) of an exported service. For an exporting mesh, + this is the name that is exported to the remote mesh. For + an importing mesh, this would be the name of the service exported + by the remote mesh. + type: string + localService: + description: LocalService represents the service in the local + (i.e. this) mesh. For an exporting mesh, this would be the + service being exported. For an importing mesh, this would + be the imported service. + properties: + hostname: + description: Hostname represents fully qualified domain + name (FQDN) used to access the service. + type: string + name: + description: Name represents the simple name of the service, + e.g. the metadata.name field of a kubernetes Service. + type: string + namespace: + description: Namespace represents the namespace within which + the service resides. + type: string + required: + - hostname + - name + - namespace + type: object + required: + - exportedName + - localService + type: object + type: array + x-kubernetes-list-map-keys: + - exportedName + x-kubernetes-list-type: map + required: + - importedServices + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/manifests/charts/base/crds/federation.maistra.io_servicemeshpeers.yaml b/manifests/charts/base/crds/federation.maistra.io_servicemeshpeers.yaml new file mode 100644 index 00000000000..ca43fe99494 --- /dev/null +++ b/manifests/charts/base/crds/federation.maistra.io_servicemeshpeers.yaml @@ -0,0 +1,353 @@ + +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: servicemeshpeers.federation.maistra.io +spec: + group: federation.maistra.io + names: + categories: + - maistra-io + kind: ServiceMeshPeer + listKind: ServiceMeshPeerList + plural: servicemeshpeers + singular: servicemeshpeer + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: ServiceMeshPeer is the Schema for joining two meshes together. The + resource name will be used to identify the 'cluster' to which imported services + belong. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ServiceMeshPeerSpec configures details required to support + federation with another service mesh. + properties: + gateways: + description: Gateways configures the gateways used to facilitate ingress + and egress with the other mesh. + properties: + egress: + description: Gateway through which outbound federated service + traffic will travel. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + ingress: + description: Gateway through which inbound federated service traffic + will travel. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: object + remote: + description: Remote configures details related to the remote mesh + with which this mesh is federating. + properties: + addresses: + description: Addresses are the addresses to which discovery and + service requests should be sent (i.e. the addresses of ingress + gateways on the remote mesh). These may be specified as resolveable + DNS names or IP addresses. + items: + type: string + type: array + discoveryPort: + description: DiscoveryPort is the port on which the addresses + are handling discovery requests. Defaults to 8188, if unspecified. + format: int32 + type: integer + servicePort: + description: ServicePort is the port on which the addresses are + handling service requests. Defaults to 15443, if unspecified. + format: int32 + type: integer + type: object + security: + description: Security configures details for securing communication + with the other mesh. + properties: + certificateChain: + description: Name of ConfigMap containing certificate chain to + be used to validate the remote. This is also used to validate + certificates used by the remote services (both client and server + certificates). The name of the entry should be root-cert.pem. If + unspecified, it will look for a ConfigMap named -ca-root-cert, + e.g. if this resource is named mesh1, it will look for a ConfigMap + named mesh1-ca-root-cert. + properties: + apiGroup: + description: APIGroup is the group for the resource being + referenced. If APIGroup is not specified, the specified + Kind must be in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + clientID: + description: ClientID of the remote mesh. This is used to authenticate + incoming requrests from the remote mesh's discovery client. + type: string + trustDomain: + description: TrustDomain of remote mesh. + type: string + type: object + type: object + status: + description: ServiceMeshPeerStatus provides information related to the + other mesh. + properties: + discoveryStatus: + description: DiscoveryStatus represents the discovery status of each + pilot/istiod pod in the mesh. + properties: + active: + description: Active represents the pilot/istiod pods actively + watching the other mesh for discovery. + items: + description: PodPeerDiscoveryStatus provides discovery details + related to a specific pilot/istiod pod. + properties: + pod: + description: Pod is the pod name to which these details + apply. This maps to a a pilot/istiod pod. + type: string + remotes: + description: Remotes represents details related to the inbound + connections from remote meshes. + items: + description: DiscoveryRemoteStatus represents details + related to an inbound connection from a remote mesh. + properties: + connected: + description: Connected identfies an active connection + with the remote mesh. + type: boolean + lastConnected: + description: LastConnected represents the last time + a connection with the remote mesh was successful. + format: date-time + type: string + lastDisconnect: + description: LastDisconnect represents the last time + the connection with the remote mesh was disconnected. + format: date-time + type: string + lastDisconnectStatus: + description: LastDisconnectStatus is the status returned + the last time the connection with the remote mesh + was terminated. + type: string + lastEvent: + description: LastEvent represents the last time an + event was received from the remote mesh. + format: date-time + type: string + lastFullSync: + description: LastFullSync represents the last time + a full sync was performed with the remote mesh. + format: date-time + type: string + source: + description: Source represents the source of the remote + watch. + type: string + required: + - connected + - source + type: object + type: array + x-kubernetes-list-map-keys: + - source + x-kubernetes-list-type: map + watch: + description: Watch represents details related to the outbound + connection to the remote mesh. + properties: + connected: + description: Connected identfies an active connection + with the remote mesh. + type: boolean + lastConnected: + description: LastConnected represents the last time + a connection with the remote mesh was successful. + format: date-time + type: string + lastDisconnect: + description: LastDisconnect represents the last time + the connection with the remote mesh was disconnected. + format: date-time + type: string + lastDisconnectStatus: + description: LastDisconnectStatus is the status returned + the last time the connection with the remote mesh + was terminated. + type: string + lastEvent: + description: LastEvent represents the last time an event + was received from the remote mesh. + format: date-time + type: string + lastFullSync: + description: LastFullSync represents the last time a + full sync was performed with the remote mesh. + format: date-time + type: string + required: + - connected + type: object + required: + - pod + type: object + nullable: true + type: array + x-kubernetes-list-map-keys: + - pod + x-kubernetes-list-type: map + inactive: + description: Inactive represents the pilot/istiod pods not actively + watching the other mesh for discovery. + items: + description: PodPeerDiscoveryStatus provides discovery details + related to a specific pilot/istiod pod. + properties: + pod: + description: Pod is the pod name to which these details + apply. This maps to a a pilot/istiod pod. + type: string + remotes: + description: Remotes represents details related to the inbound + connections from remote meshes. + items: + description: DiscoveryRemoteStatus represents details + related to an inbound connection from a remote mesh. + properties: + connected: + description: Connected identfies an active connection + with the remote mesh. + type: boolean + lastConnected: + description: LastConnected represents the last time + a connection with the remote mesh was successful. + format: date-time + type: string + lastDisconnect: + description: LastDisconnect represents the last time + the connection with the remote mesh was disconnected. + format: date-time + type: string + lastDisconnectStatus: + description: LastDisconnectStatus is the status returned + the last time the connection with the remote mesh + was terminated. + type: string + lastEvent: + description: LastEvent represents the last time an + event was received from the remote mesh. + format: date-time + type: string + lastFullSync: + description: LastFullSync represents the last time + a full sync was performed with the remote mesh. + format: date-time + type: string + source: + description: Source represents the source of the remote + watch. + type: string + required: + - connected + - source + type: object + type: array + x-kubernetes-list-map-keys: + - source + x-kubernetes-list-type: map + watch: + description: Watch represents details related to the outbound + connection to the remote mesh. + properties: + connected: + description: Connected identfies an active connection + with the remote mesh. + type: boolean + lastConnected: + description: LastConnected represents the last time + a connection with the remote mesh was successful. + format: date-time + type: string + lastDisconnect: + description: LastDisconnect represents the last time + the connection with the remote mesh was disconnected. + format: date-time + type: string + lastDisconnectStatus: + description: LastDisconnectStatus is the status returned + the last time the connection with the remote mesh + was terminated. + type: string + lastEvent: + description: LastEvent represents the last time an event + was received from the remote mesh. + format: date-time + type: string + lastFullSync: + description: LastFullSync represents the last time a + full sync was performed with the remote mesh. + format: date-time + type: string + required: + - connected + type: object + required: + - pod + type: object + nullable: true + type: array + x-kubernetes-list-map-keys: + - pod + x-kubernetes-list-type: map + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/manifests/charts/base/files/gen-istio-cluster.yaml b/manifests/charts/base/files/gen-istio-cluster.yaml index b1513695c1b..6a2f93ebf08 100644 --- a/manifests/charts/base/files/gen-istio-cluster.yaml +++ b/manifests/charts/base/files/gen-istio-cluster.yaml @@ -6505,6 +6505,760 @@ spec: storage: true --- +--- +# Source: crds/federation.maistra.io_exportedservicesets.yaml + +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: exportedservicesets.federation.maistra.io +spec: + group: federation.maistra.io + names: + kind: ExportedServiceSet + listKind: ExportedServiceSetList + plural: exportedservicesets + singular: exportedserviceset + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: ExportedServiceSet is the Schema for configuring exported services. + It must be created in the same namespace as the control plane. The name + of the ExportedServiceSet resource must match the name of a ServiceMeshPeer + resource defining the remote mesh to which the services will be exported. + This implies there will be at most one ExportedServiceSet resource per peer + and control plane. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines rules for matching services to be exported. + properties: + exportRules: + description: ExportRules are the rules that determine which services + are exported from the mesh. The list is processed in order and + the first spec in the list that applies to a service is the one + that will be applied. This allows more specific selectors to be + placed before more general selectors. + items: + properties: + labelSelector: + description: LabelSelector provides a mechanism for selecting + services to export by using a label selector to match Service + resources for export. + properties: + aliases: + description: 'Aliases is a map of aliases to apply to exported + services. If a name is not found in the map, the original + service name is exported. A ''*'' will match any name. + The Aliases list will be processed in order, with the + first match found being applied to the exported service. + Examples: */foo->*/bar will match foo service in any namesapce, + exporting it as bar from its original namespace. */foo->bar/bar + will match foo service in any namespace, exporting it + as bar/bar. foo/*->bar/* will match any service in foo + namespace, exporting it from the bar namespace with its + original name */*->bar/* will match any service and export + it from the bar namespace with its original name. */*->*/* + is the same as not specifying anything' + items: + properties: + alias: + properties: + name: + type: string + namespace: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + type: array + namespace: + description: Namespace specifies to which namespace the + selector applies. An empty value applies to all namespaces + in the mesh. + type: string + selector: + description: Selector used to select Service resources in + the namespace/mesh. An empty selector selects all services. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists + or DoesNotExist, the values array must be empty. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + type: object + nameSelector: + description: NameSelector provides a simple name matcher for + exporting services in the mesh. + properties: + alias: + properties: + name: + type: string + namespace: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + type: + description: Type of rule. One of NameSelector or LabelSelector. + type: string + required: + - type + type: object + type: array + type: object + status: + properties: + exportedServices: + description: Exports provides details about the services exported + by this mesh. + items: + description: PeerServiceMapping represents the name mapping between + an exported service and its local counterpart. + properties: + exportedName: + description: ExportedName represents the fully qualified domain + name (FQDN) of an exported service. For an exporting mesh, + this is the name that is exported to the remote mesh. For + an importing mesh, this would be the name of the service exported + by the remote mesh. + type: string + localService: + description: LocalService represents the service in the local + (i.e. this) mesh. For an exporting mesh, this would be the + service being exported. For an importing mesh, this would + be the imported service. + properties: + hostname: + description: Hostname represents fully qualified domain + name (FQDN) used to access the service. + type: string + name: + description: Name represents the simple name of the service, + e.g. the metadata.name field of a kubernetes Service. + type: string + namespace: + description: Namespace represents the namespace within which + the service resides. + type: string + required: + - hostname + - name + - namespace + type: object + required: + - exportedName + - localService + type: object + type: array + x-kubernetes-list-map-keys: + - exportedName + x-kubernetes-list-type: map + required: + - exportedServices + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/federation.maistra.io_importedservicesets.yaml + +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: importedservicesets.federation.maistra.io +spec: + group: federation.maistra.io + names: + kind: ImportedServiceSet + listKind: ImportedServiceSetList + plural: importedservicesets + singular: importedserviceset + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: ImportedServiceSet is the Schema for configuring imported services. + It must be created in the same namespace as the control plane. The name + of the ImportedServiceSet resource must match the name of a ServiceMeshPeer + resource defining the remote mesh from which the services will be imported. + This implies there will be at most one ImportedServiceSet resource per peer + and control plane. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines rules for matching services to be imported. + properties: + domainSuffix: + description: 'DomainSuffix specifies the domain suffix to be applies + to imported services. If no domain suffix is specified, imported + services will be named as follows: ..svc.-imports.local + If a domain suffix is specified, imported services will be named + as follows: ..' + type: string + importRules: + description: ImportRules are the rules that determine which services + are imported to the mesh. The list is processed in order and the + first spec in the list that applies to a service is the one that + will be applied. This allows more specific selectors to be placed + before more general selectors. + items: + properties: + domainSuffix: + description: DomainSuffix applies the specified suffix to services + imported by this rule. The behavior is identical to that + of ImportedServiceSetSpec.DomainSuffix. + type: string + importAsLocal: + description: ImportAsLocal imports the service as a local service + in the mesh. For example, if an exported service, foo/bar + is imported as some-ns/service, the service will be imported + as service.some-ns.svc.cluster.local in the some-ns namespace. If + a service of this name already exists in the mesh, the imported + service's endpoints will be aggregated with any other workloads + associated with the service. This setting overrides DomainSuffix. + type: boolean + nameSelector: + description: NameSelector provides a simple name matcher for + importing services in the mesh. + properties: + alias: + properties: + name: + type: string + namespace: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + type: + description: Type of rule. Only NameSelector type is supported. + type: string + required: + - type + type: object + type: array + locality: + description: Locality within which imported services should be associated. + properties: + region: + description: Region within which imported services are located. + type: string + subzone: + description: Subzone within which imported services are located. If + Subzone is specified, Zone must also be specified. + type: string + zone: + description: Zone within which imported services are located. If + Zone is specified, Region must also be specified. + type: string + type: object + type: object + status: + properties: + importedServices: + description: Imports provides details about the services imported + by this mesh. + items: + description: PeerServiceMapping represents the name mapping between + an exported service and its local counterpart. + properties: + exportedName: + description: ExportedName represents the fully qualified domain + name (FQDN) of an exported service. For an exporting mesh, + this is the name that is exported to the remote mesh. For + an importing mesh, this would be the name of the service exported + by the remote mesh. + type: string + localService: + description: LocalService represents the service in the local + (i.e. this) mesh. For an exporting mesh, this would be the + service being exported. For an importing mesh, this would + be the imported service. + properties: + hostname: + description: Hostname represents fully qualified domain + name (FQDN) used to access the service. + type: string + name: + description: Name represents the simple name of the service, + e.g. the metadata.name field of a kubernetes Service. + type: string + namespace: + description: Namespace represents the namespace within which + the service resides. + type: string + required: + - hostname + - name + - namespace + type: object + required: + - exportedName + - localService + type: object + type: array + x-kubernetes-list-map-keys: + - exportedName + x-kubernetes-list-type: map + required: + - importedServices + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/federation.maistra.io_servicemeshpeers.yaml + +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: servicemeshpeers.federation.maistra.io +spec: + group: federation.maistra.io + names: + categories: + - maistra-io + kind: ServiceMeshPeer + listKind: ServiceMeshPeerList + plural: servicemeshpeers + singular: servicemeshpeer + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: ServiceMeshPeer is the Schema for joining two meshes together. The + resource name will be used to identify the 'cluster' to which imported services + belong. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ServiceMeshPeerSpec configures details required to support + federation with another service mesh. + properties: + gateways: + description: Gateways configures the gateways used to facilitate ingress + and egress with the other mesh. + properties: + egress: + description: Gateway through which outbound federated service + traffic will travel. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + ingress: + description: Gateway through which inbound federated service traffic + will travel. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: object + remote: + description: Remote configures details related to the remote mesh + with which this mesh is federating. + properties: + addresses: + description: Addresses are the addresses to which discovery and + service requests should be sent (i.e. the addresses of ingress + gateways on the remote mesh). These may be specified as resolveable + DNS names or IP addresses. + items: + type: string + type: array + discoveryPort: + description: DiscoveryPort is the port on which the addresses + are handling discovery requests. Defaults to 8188, if unspecified. + format: int32 + type: integer + servicePort: + description: ServicePort is the port on which the addresses are + handling service requests. Defaults to 15443, if unspecified. + format: int32 + type: integer + type: object + security: + description: Security configures details for securing communication + with the other mesh. + properties: + certificateChain: + description: Name of ConfigMap containing certificate chain to + be used to validate the remote. This is also used to validate + certificates used by the remote services (both client and server + certificates). The name of the entry should be root-cert.pem. If + unspecified, it will look for a ConfigMap named -ca-root-cert, + e.g. if this resource is named mesh1, it will look for a ConfigMap + named mesh1-ca-root-cert. + properties: + apiGroup: + description: APIGroup is the group for the resource being + referenced. If APIGroup is not specified, the specified + Kind must be in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + clientID: + description: ClientID of the remote mesh. This is used to authenticate + incoming requrests from the remote mesh's discovery client. + type: string + trustDomain: + description: TrustDomain of remote mesh. + type: string + type: object + type: object + status: + description: ServiceMeshPeerStatus provides information related to the + other mesh. + properties: + discoveryStatus: + description: DiscoveryStatus represents the discovery status of each + pilot/istiod pod in the mesh. + properties: + active: + description: Active represents the pilot/istiod pods actively + watching the other mesh for discovery. + items: + description: PodPeerDiscoveryStatus provides discovery details + related to a specific pilot/istiod pod. + properties: + pod: + description: Pod is the pod name to which these details + apply. This maps to a a pilot/istiod pod. + type: string + remotes: + description: Remotes represents details related to the inbound + connections from remote meshes. + items: + description: DiscoveryRemoteStatus represents details + related to an inbound connection from a remote mesh. + properties: + connected: + description: Connected identfies an active connection + with the remote mesh. + type: boolean + lastConnected: + description: LastConnected represents the last time + a connection with the remote mesh was successful. + format: date-time + type: string + lastDisconnect: + description: LastDisconnect represents the last time + the connection with the remote mesh was disconnected. + format: date-time + type: string + lastDisconnectStatus: + description: LastDisconnectStatus is the status returned + the last time the connection with the remote mesh + was terminated. + type: string + lastEvent: + description: LastEvent represents the last time an + event was received from the remote mesh. + format: date-time + type: string + lastFullSync: + description: LastFullSync represents the last time + a full sync was performed with the remote mesh. + format: date-time + type: string + source: + description: Source represents the source of the remote + watch. + type: string + required: + - connected + - source + type: object + type: array + x-kubernetes-list-map-keys: + - source + x-kubernetes-list-type: map + watch: + description: Watch represents details related to the outbound + connection to the remote mesh. + properties: + connected: + description: Connected identfies an active connection + with the remote mesh. + type: boolean + lastConnected: + description: LastConnected represents the last time + a connection with the remote mesh was successful. + format: date-time + type: string + lastDisconnect: + description: LastDisconnect represents the last time + the connection with the remote mesh was disconnected. + format: date-time + type: string + lastDisconnectStatus: + description: LastDisconnectStatus is the status returned + the last time the connection with the remote mesh + was terminated. + type: string + lastEvent: + description: LastEvent represents the last time an event + was received from the remote mesh. + format: date-time + type: string + lastFullSync: + description: LastFullSync represents the last time a + full sync was performed with the remote mesh. + format: date-time + type: string + required: + - connected + type: object + required: + - pod + type: object + nullable: true + type: array + x-kubernetes-list-map-keys: + - pod + x-kubernetes-list-type: map + inactive: + description: Inactive represents the pilot/istiod pods not actively + watching the other mesh for discovery. + items: + description: PodPeerDiscoveryStatus provides discovery details + related to a specific pilot/istiod pod. + properties: + pod: + description: Pod is the pod name to which these details + apply. This maps to a a pilot/istiod pod. + type: string + remotes: + description: Remotes represents details related to the inbound + connections from remote meshes. + items: + description: DiscoveryRemoteStatus represents details + related to an inbound connection from a remote mesh. + properties: + connected: + description: Connected identfies an active connection + with the remote mesh. + type: boolean + lastConnected: + description: LastConnected represents the last time + a connection with the remote mesh was successful. + format: date-time + type: string + lastDisconnect: + description: LastDisconnect represents the last time + the connection with the remote mesh was disconnected. + format: date-time + type: string + lastDisconnectStatus: + description: LastDisconnectStatus is the status returned + the last time the connection with the remote mesh + was terminated. + type: string + lastEvent: + description: LastEvent represents the last time an + event was received from the remote mesh. + format: date-time + type: string + lastFullSync: + description: LastFullSync represents the last time + a full sync was performed with the remote mesh. + format: date-time + type: string + source: + description: Source represents the source of the remote + watch. + type: string + required: + - connected + - source + type: object + type: array + x-kubernetes-list-map-keys: + - source + x-kubernetes-list-type: map + watch: + description: Watch represents details related to the outbound + connection to the remote mesh. + properties: + connected: + description: Connected identfies an active connection + with the remote mesh. + type: boolean + lastConnected: + description: LastConnected represents the last time + a connection with the remote mesh was successful. + format: date-time + type: string + lastDisconnect: + description: LastDisconnect represents the last time + the connection with the remote mesh was disconnected. + format: date-time + type: string + lastDisconnectStatus: + description: LastDisconnectStatus is the status returned + the last time the connection with the remote mesh + was terminated. + type: string + lastEvent: + description: LastEvent represents the last time an event + was received from the remote mesh. + format: date-time + type: string + lastFullSync: + description: LastFullSync represents the last time a + full sync was performed with the remote mesh. + format: date-time + type: string + required: + - connected + type: object + required: + - pod + type: object + nullable: true + type: array + x-kubernetes-list-map-keys: + - pod + x-kubernetes-list-type: map + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + --- # Source: base/templates/reader-serviceaccount.yaml # This service account aggregates reader permissions for the revisions in a given cluster @@ -6756,6 +7510,11 @@ rules: resources: ["secrets"] # TODO lock this down to istio-ca-cert if not using the DNS cert mesh config verbs: ["create", "get", "watch", "list", "update", "delete"] + +# For MeshFederation support +- apiGroups: ["federation.maistra.io"] + resources: ["servicemeshpeers", "servicemeshpeers/status", "exportedservicesets", "exportedservicesets/status", "importedservicesets", "importedservicesets/status"] + verbs: ["get", "list", "watch", "patch", "update"] --- # Source: base/templates/rolebinding.yaml # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- diff --git a/manifests/charts/base/templates/crds.yaml b/manifests/charts/base/templates/crds.yaml index 871ee2a6b44..fd3553e6704 100644 --- a/manifests/charts/base/templates/crds.yaml +++ b/manifests/charts/base/templates/crds.yaml @@ -1,4 +1,8 @@ {{- if .Values.base.enableCRDTemplates }} {{ .Files.Get "crds/crd-all.gen.yaml" }} {{ .Files.Get "crds/crd-operator.yaml" }} +{{ .Files.Get "crds/maistra.io_meshfederations.yaml" }} +{{ .Files.Get "crds/maistra.io_federationstatuses.yaml" }} +{{ .Files.Get "crds/maistra.io_serviceexports.yaml" }} +{{ .Files.Get "crds/maistra.io_serviceimports.yaml" }} {{- end }} diff --git a/manifests/charts/base/templates/role.yaml b/manifests/charts/base/templates/role.yaml index ca1a4243f0b..3b3376bba6c 100644 --- a/manifests/charts/base/templates/role.yaml +++ b/manifests/charts/base/templates/role.yaml @@ -23,3 +23,8 @@ rules: resources: ["secrets"] # TODO lock this down to istio-ca-cert if not using the DNS cert mesh config verbs: ["create", "get", "watch", "list", "update", "delete"] + +# For MeshFederation support +- apiGroups: ["federation.maistra.io"] + resources: ["servicemeshpeers", "servicemeshpeers/status", "exportedservicesets", "exportedservicesets/status", "importedservicesets", "importedservicesets/status"] + verbs: ["get", "list", "watch", "patch", "update"] diff --git a/manifests/charts/istio-control/istio-discovery/files/gen-istio.yaml b/manifests/charts/istio-control/istio-discovery/files/gen-istio.yaml index 37be2947779..b68ed108264 100644 --- a/manifests/charts/istio-control/istio-discovery/files/gen-istio.yaml +++ b/manifests/charts/istio-control/istio-discovery/files/gen-istio.yaml @@ -1507,6 +1507,11 @@ rules: resources: ["secrets"] # TODO lock this down to istio-ca-cert if not using the DNS cert mesh config verbs: ["create", "get", "watch", "list", "update", "delete"] + +# For MeshFederation support +- apiGroups: ["federation.maistra.io"] + resources: ["servicemeshpeers", "servicemeshpeers/status", "exportedservicesets", "exportedservicesets/status", "importedservicesets", "importedservicesets/status"] + verbs: ["get", "list", "watch", "patch", "update"] --- # Source: istiod/templates/rolebinding.yaml apiVersion: rbac.authorization.k8s.io/v1 @@ -1554,6 +1559,9 @@ spec: - port: 15014 name: http-monitoring # prometheus stats protocol: TCP + - port: 8188 + name: http-discovery # federation discovery + protocol: TCP selector: app: istiod # Label used by the 'default' service. For versioned deployments we match with app and version. @@ -1616,6 +1624,8 @@ spec: protocol: TCP - containerPort: 15017 protocol: TCP + - containerPort: 8188 + protocol: TCP readinessProbe: httpGet: path: /ready @@ -1647,6 +1657,8 @@ spec: fieldPath: spec.serviceAccountName - name: KUBECONFIG value: /var/run/secrets/remote/config + - name: PILOT_ENABLE_FEDERATION + value: "true" - name: PILOT_TRACE_SAMPLING value: "1" - name: PILOT_ENABLE_PROTOCOL_SNIFFING_FOR_OUTBOUND @@ -1774,6 +1786,28 @@ spec: # Removed paths for legacy and default selectors since a revision tag # is inherently created from a specific revision --- +# Source: istiod/templates/federation.yaml +apiVersion: networking.istio.io/v1beta1 +kind: DestinationRule +metadata: + name: istiod + namespace: istio-system + labels: + istio.io/rev: default + install.operator.istio.io/owning-resource: unknown + operator.istio.io/component: "Pilot" + app: istiod + istio: pilot + release: istio +spec: + host: istiod.istio-system.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 8188 + tls: + mode: SIMPLE +--- # Source: istiod/templates/telemetryv2_1.11.yaml # Note: http stats filter is wasm enabled only in sidecars. apiVersion: networking.istio.io/v1alpha3 diff --git a/manifests/charts/istio-control/istio-discovery/templates/deployment.yaml b/manifests/charts/istio-control/istio-discovery/templates/deployment.yaml index 6e3afc0d4ff..3ee1b9d724a 100644 --- a/manifests/charts/istio-control/istio-discovery/templates/deployment.yaml +++ b/manifests/charts/istio-control/istio-discovery/templates/deployment.yaml @@ -115,6 +115,8 @@ spec: protocol: TCP - containerPort: 15017 protocol: TCP + - containerPort: 8188 + protocol: TCP readinessProbe: httpGet: path: /ready @@ -152,6 +154,8 @@ spec: value: "{{ $val }}" {{- end }} {{- end }} + - name: PILOT_ENABLE_FEDERATION + value: "{{ .Values.pilot.enableFederation }}" {{- if .Values.pilot.traceSampling }} - name: PILOT_TRACE_SAMPLING value: "{{ .Values.pilot.traceSampling }}" diff --git a/manifests/charts/istio-control/istio-discovery/templates/federation.yaml b/manifests/charts/istio-control/istio-discovery/templates/federation.yaml new file mode 100644 index 00000000000..ed7ed59aa86 --- /dev/null +++ b/manifests/charts/istio-control/istio-discovery/templates/federation.yaml @@ -0,0 +1,21 @@ +apiVersion: networking.istio.io/v1beta1 +kind: DestinationRule +metadata: + name: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }} + namespace: {{ .Release.Namespace }} + labels: + istio.io/rev: {{ .Values.revision | default "default" }} + install.operator.istio.io/owning-resource: {{ .Values.ownerName | default "unknown" }} + operator.istio.io/component: "Pilot" + app: istiod + istio: pilot + release: {{ .Release.Name }} +spec: + host: istiod{{- if not (eq .Values.revision "") }}-{{ .Values.revision }}{{- end }}.{{ .Release.Namespace }}.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 8188 + tls: + mode: SIMPLE +--- diff --git a/manifests/charts/istio-control/istio-discovery/templates/role.yaml b/manifests/charts/istio-control/istio-discovery/templates/role.yaml index 25c4f5c3b88..91e529ce4d4 100644 --- a/manifests/charts/istio-control/istio-discovery/templates/role.yaml +++ b/manifests/charts/istio-control/istio-discovery/templates/role.yaml @@ -18,3 +18,8 @@ rules: resources: ["secrets"] # TODO lock this down to istio-ca-cert if not using the DNS cert mesh config verbs: ["create", "get", "watch", "list", "update", "delete"] + +# For MeshFederation support +- apiGroups: ["federation.maistra.io"] + resources: ["servicemeshpeers", "servicemeshpeers/status", "exportedservicesets", "exportedservicesets/status", "importedservicesets", "importedservicesets/status"] + verbs: ["get", "list", "watch", "patch", "update"] diff --git a/manifests/charts/istio-control/istio-discovery/templates/service.yaml b/manifests/charts/istio-control/istio-discovery/templates/service.yaml index b5ddf5b6e54..6fb94b93374 100644 --- a/manifests/charts/istio-control/istio-discovery/templates/service.yaml +++ b/manifests/charts/istio-control/istio-discovery/templates/service.yaml @@ -29,6 +29,9 @@ spec: - port: 15014 name: http-monitoring # prometheus stats protocol: TCP + - port: 8188 + name: http-discovery # federation discovery + protocol: TCP selector: app: istiod {{- if ne .Values.revision "" }} diff --git a/manifests/charts/istio-control/istio-discovery/values.yaml b/manifests/charts/istio-control/istio-discovery/values.yaml index b33303b9b6c..0bfa57b1d54 100644 --- a/manifests/charts/istio-control/istio-discovery/values.yaml +++ b/manifests/charts/istio-control/istio-discovery/values.yaml @@ -2,6 +2,7 @@ ## Discovery Settings pilot: + enableFederation: true autoscaleEnabled: true autoscaleMin: 1 autoscaleMax: 5 diff --git a/manifests/charts/istiod-remote/templates/role.yaml b/manifests/charts/istiod-remote/templates/role.yaml index 69949127513..a61a9d29267 100644 --- a/manifests/charts/istiod-remote/templates/role.yaml +++ b/manifests/charts/istiod-remote/templates/role.yaml @@ -19,4 +19,9 @@ rules: resources: ["secrets"] # TODO lock this down to istio-ca-cert if not using the DNS cert mesh config verbs: ["create", "get", "watch", "list", "update", "delete"] + +# For MeshFederation support +- apiGroups: ["federation.maistra.io"] + resources: ["servicemeshpeers", "servicemeshpeers/status", "exportedservicesets", "exportedservicesets/status", "importedservicesets", "importedservicesets/status"] + verbs: ["get", "list", "watch", "patch", "update"] {{- end }} diff --git a/manifests/charts/istiod-remote/values.yaml b/manifests/charts/istiod-remote/values.yaml index 0af7b9efa4c..76a730c574e 100644 --- a/manifests/charts/istiod-remote/values.yaml +++ b/manifests/charts/istiod-remote/values.yaml @@ -2,6 +2,7 @@ ## Discovery Settings pilot: + enableFederation: true autoscaleEnabled: true autoscaleMin: 1 autoscaleMax: 5 diff --git a/pilot/cmd/pilot-discovery/app/cmd.go b/pilot/cmd/pilot-discovery/app/cmd.go index ac415b2a1cf..b6893a75f08 100644 --- a/pilot/cmd/pilot-discovery/app/cmd.go +++ b/pilot/cmd/pilot-discovery/app/cmd.go @@ -146,6 +146,8 @@ func addFlags(c *cobra.Command) { "Directory to watch for updates to config yaml files. If specified, the files will be used as the source of config, rather than a CRD client.") c.PersistentFlags().StringVar(&serverArgs.RegistryOptions.KubeOptions.DomainSuffix, "domain", constants.DefaultKubernetesDomain, "DNS domain suffix") + c.PersistentFlags().DurationVar(&serverArgs.RegistryOptions.KubeOptions.ResyncPeriod, "resync", 60*time.Second, + "Controller resync interval") c.PersistentFlags().StringVar((*string)(&serverArgs.RegistryOptions.KubeOptions.ClusterID), "clusterID", features.ClusterName, "The ID of the cluster that this Istiod instance resides") c.PersistentFlags().StringToStringVar(&serverArgs.RegistryOptions.KubeOptions.ClusterAliases, "clusterAliases", map[string]string{}, @@ -159,6 +161,8 @@ func addFlags(c *cobra.Command) { "Whether to prevent istiod watching Node objects") c.PersistentFlags().BoolVar(&serverArgs.RegistryOptions.KubeOptions.EnableIngressClassName, "enableIngressClassName", true, "Whether support processing Ingress resources that use the new ingressClassName field in their spec") + c.PersistentFlags().StringVar(&serverArgs.ServerOptions.FederationAddr, "federationAddr", ":8188", + "Federation Service Discovery HTTP address") // using address, so it can be configured as localhost:.. (possibly UDS in future) c.PersistentFlags().StringVar(&serverArgs.ServerOptions.HTTPAddr, "httpAddr", ":8080", diff --git a/pilot/pkg/bootstrap/configcontroller.go b/pilot/pkg/bootstrap/configcontroller.go index 100e5c667fb..4e3a749f8da 100644 --- a/pilot/pkg/bootstrap/configcontroller.go +++ b/pilot/pkg/bootstrap/configcontroller.go @@ -131,6 +131,14 @@ func (s *Server) initConfigController(args *PilotArgs) error { }) } + if features.EnableFederation { + if s.federation == nil { + log.Errorf("Federation support disabled: federation not initialized") + } else { + s.ConfigStores = append(s.ConfigStores, s.federation.ConfigStore()) + } + } + // Wrap the config controller with a cache. aggregateConfigController, err := configaggregate.MakeCache(s.ConfigStores) if err != nil { diff --git a/pilot/pkg/bootstrap/options.go b/pilot/pkg/bootstrap/options.go index bee4ccd7c3b..6624e4fc1e0 100644 --- a/pilot/pkg/bootstrap/options.go +++ b/pilot/pkg/bootstrap/options.go @@ -57,6 +57,7 @@ type PilotArgs struct { Namespace string Revision string MeshConfigFile string + Network string NetworksConfigFile string RegistryOptions RegistryOptions CtrlZOptions *ctrlz.Options @@ -94,6 +95,10 @@ type DiscoveryServerOptions struct { // The listening address for secured gRPC. If the port in the address is empty or "0" (as in "127.0.0.1:" or "[::1]:0") // a port number is automatically chosen. SecureGRPCAddr string + + // The listening address for federation service discovery. If the port in the address is empty or "0" (as in "127.0.0.1:" or "[::1]:0") + // a port number is automatically chosen. + FederationAddr string } type InjectionOptions struct { diff --git a/pilot/pkg/bootstrap/server.go b/pilot/pkg/bootstrap/server.go index 98bbd3ce72d..0fad29bcbd3 100644 --- a/pilot/pkg/bootstrap/server.go +++ b/pilot/pkg/bootstrap/server.go @@ -68,6 +68,7 @@ import ( "istio.io/istio/pkg/kube/inject" "istio.io/istio/pkg/kube/multicluster" "istio.io/istio/pkg/security" + "istio.io/istio/pkg/servicemesh/federation" "istio.io/istio/pkg/spiffe" "istio.io/istio/security/pkg/k8s/chiron" "istio.io/istio/security/pkg/pki/ca" @@ -120,6 +121,8 @@ type Server struct { httpsServer *http.Server // webhooks HTTPS Server. httpsReadyClient *http.Client + federation *federation.Federation + grpcServer *grpc.Server grpcAddress string secureGrpcServer *grpc.Server @@ -248,25 +251,25 @@ func NewServer(args *PilotArgs, initFuncs ...func(*Server)) (*Server, error) { return nil, err } - if err := s.initControllers(args); err != nil { + // Parse and validate Istiod Address. + istiodHost, _, err := e.GetDiscoveryAddress() + if err != nil { return nil, err } - s.XDSServer.InitGenerators(e, args.Namespace) - - // Initialize workloadTrustBundle after CA has been initialized - if err := s.initWorkloadTrustBundle(args); err != nil { + // Create Istiod certs and setup watches. + if err := s.initIstiodCerts(args, string(istiodHost)); err != nil { return nil, err } - // Parse and validate Istiod Address. - istiodHost, _, err := e.GetDiscoveryAddress() - if err != nil { + if err := s.initControllers(args); err != nil { return nil, err } - // Create Istiod certs and setup watches. - if err := s.initIstiodCerts(args, string(istiodHost)); err != nil { + s.XDSServer.InitGenerators(e, args.Namespace) + + // Initialize workloadTrustBundle after CA has been initialized + if err := s.initWorkloadTrustBundle(args); err != nil { return nil, err } @@ -490,6 +493,10 @@ func (s *Server) Start(stop <-chan struct{}) error { }() } + if s.federation != nil { + go s.federation.StartServer(stop) + } + s.waitForShutdown(stop) return nil @@ -858,6 +865,9 @@ func (s *Server) cachesSynced() bool { if !s.configController.HasSynced() { return false } + if s.federation != nil && !s.federation.HasSynced() { + return false + } return true } @@ -879,6 +889,10 @@ func (s *Server) initRegistryEventHandlers() { } s.ServiceController().AppendServiceHandler(serviceHandler) + if s.federation != nil { + s.federation.RegisterServiceHandlers(s.ServiceController()) + } + if s.configController != nil { configHandler := func(prev config.Config, curr config.Config, event model.Event) { defer func() { @@ -1085,6 +1099,10 @@ func (s *Server) getIstiodCertificate(*tls.ClientHelloInfo) (*tls.Certificate, e // initControllers initializes the controllers. func (s *Server) initControllers(args *PilotArgs) error { log.Info("initializing controllers") + // federation support must be initialized before config and service controllers + if err := s.initFederationControllers(args); err != nil { + return fmt.Errorf("error initializing federation controller: %v", err) + } s.initMulticluster(args) // Certificate controller is created before MCP controller in case MCP server pod // waits to mount a certificate to be provisioned by the certificate controller. @@ -1100,6 +1118,67 @@ func (s *Server) initControllers(args *PilotArgs) error { return nil } +func (s *Server) initFederationControllers(args *PilotArgs) error { + if !features.EnableFederation { + return nil + } + + if s.kubeClient == nil { + log.Errorf("could not initialize federation discovery server: kubeClient is nil") + return nil + } + + peerCertVerifier, err := s.createPeerCertVerifier(args.ServerOptions.TLSOptions) + if err != nil { + return err + } + if peerCertVerifier == nil { + panic("No peerCertVerifier") + } + tlsCfg := &tls.Config{ + GetCertificate: s.getIstiodCertificate, + ClientAuth: tls.VerifyClientCertIfGiven, + ClientCAs: peerCertVerifier.GetGeneralCertPool(), + VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { + err := peerCertVerifier.VerifyPeerCert(rawCerts, verifiedChains) + if err != nil { + log.Infof("Could not verify certificate: %v", err) + } + return err + }, + MinVersion: tls_features.TLSMinProtocolVersion.GetGoTLSProtocolVersion(), + MaxVersion: tls_features.TLSMaxProtocolVersion.GetGoTLSProtocolVersion(), + CipherSuites: tls_features.TLSCipherSuites.GetGoTLSCipherSuites(), + CurvePreferences: tls_features.TLSECDHCurves.GetGoTLSECDHCurves(), + } + + s.federation, err = federation.New(federation.Options{ + KubeClient: s.kubeClient, + ResyncPeriod: args.RegistryOptions.KubeOptions.ResyncPeriod, + FederationNamespace: args.RegistryOptions.ClusterRegistriesNamespace, + LocalClusterID: s.clusterID.String(), + LocalNetwork: features.NetworkName, + BindAddress: args.ServerOptions.FederationAddr, + Env: s.environment, + XDSUpdater: s.XDSServer, + ServiceController: s.ServiceController(), + IstiodNamespace: args.Namespace, + IstiodPodName: args.PodName, + TLSConfig: tlsCfg, + }) + s.XDSServer.Generators[v3.TrustBundleType] = &xds.TbdsGenerator{TrustBundleProvider: s.federation} + + if err != nil { + return fmt.Errorf("error initializing federation: %v", err) + } + + s.addStartFunc(func(stop <-chan struct{}) error { + go s.federation.StartControllers(stop) + return nil + }) + return nil +} + func (s *Server) initMulticluster(args *PilotArgs) { if s.kubeClient == nil { return diff --git a/pilot/pkg/features/pilot.go b/pilot/pkg/features/pilot.go index b2fc81b8ebb..ad8f8fd2547 100644 --- a/pilot/pkg/features/pilot.go +++ b/pilot/pkg/features/pilot.go @@ -389,6 +389,9 @@ var ( ExternalIstiod = env.RegisterBoolVar("EXTERNAL_ISTIOD", false, "If this is set to true, one Istiod will control remote clusters including CA.").Get() + NetworkName = env.RegisterStringVar("NETWORK_NAME", "Kubernetes", + "Defines the network that this Istiod instance belongs to").Get() + EnableCAServer = env.RegisterBoolVar("ENABLE_CA_SERVER", true, "If this is set to false, will not create CA server in istiod.").Get() @@ -636,6 +639,8 @@ var ( EnableIOR = env.RegisterBoolVar("ENABLE_IOR", false, "Whether to enable IOR component, which provides integration between Istio Gateways and OpenShift Routes").Get() + + EnableFederation = env.RegisterBoolVar("PILOT_ENABLE_FEDERATION", false, "").Get() ) // EnableEndpointSliceController returns the value of the feature flag and whether it was actually specified. diff --git a/pilot/pkg/networking/grpcgen/testdata/xds_bootstrap.json b/pilot/pkg/networking/grpcgen/testdata/xds_bootstrap.json index 5457e65da6b..d5212a87351 100644 --- a/pilot/pkg/networking/grpcgen/testdata/xds_bootstrap.json +++ b/pilot/pkg/networking/grpcgen/testdata/xds_bootstrap.json @@ -31,4 +31,4 @@ } }, "server_listener_resource_name_template": "xds.istio.io/grpc/lds/inbound/%s" -} +} \ No newline at end of file diff --git a/pilot/pkg/security/trustdomain/bundle.go b/pilot/pkg/security/trustdomain/bundle.go index 6bdc7d7b965..f04ff322a48 100644 --- a/pilot/pkg/security/trustdomain/bundle.go +++ b/pilot/pkg/security/trustdomain/bundle.go @@ -72,7 +72,7 @@ func (t Bundle) ReplaceTrustDomainAliases(principals []string) []string { principalsIncludingAliases = append(principalsIncludingAliases, t.replaceTrustDomains(principal, trustDomainFromPrincipal)...) } else { authzLog.Warnf("Trust domain %s from principal %s does not match the current trust "+ - "domain or its aliases", trustDomainFromPrincipal, principal) + "domain or its aliases: %v", trustDomainFromPrincipal, principal, t.TrustDomains) // If the trust domain from the existing doesn't match with the new trust domain aliases or "cluster.local", // keep the policy as it is. principalsIncludingAliases = append(principalsIncludingAliases, principal) diff --git a/pilot/pkg/serviceregistry/aggregate/controller.go b/pilot/pkg/serviceregistry/aggregate/controller.go index ceeba99a076..4670b0b7d15 100644 --- a/pilot/pkg/serviceregistry/aggregate/controller.go +++ b/pilot/pkg/serviceregistry/aggregate/controller.go @@ -169,8 +169,8 @@ func (c *Controller) Services() []*model.Service { // Locking Registries list while walking it to prevent inconsistent results for _, r := range c.GetRegistries() { svcs := r.Services() - if r.Provider() != provider.Kubernetes { - index += len(svcs) + // The second condition is required for merging Services and Service Accounts from federation controllers + if r.Provider() != provider.Kubernetes && r.Provider() != provider.Federation { services = append(services, svcs...) } else { for _, s := range svcs { @@ -208,7 +208,7 @@ func (c *Controller) GetService(hostname host.Name) *model.Service { if service == nil { continue } - if r.Provider() != provider.Kubernetes { + if r.Provider() != provider.Kubernetes && r.Provider() != provider.Federation { return service } if out == nil { @@ -224,7 +224,7 @@ func (c *Controller) GetService(hostname host.Name) *model.Service { func mergeService(dst, src *model.Service, srcRegistry serviceregistry.Instance) { // Prefer the k8s HostVIPs where possible clusterID := srcRegistry.Cluster() - if srcRegistry.Provider() == provider.Kubernetes || len(dst.ClusterVIPs.GetAddressesFor(clusterID)) == 0 { + if srcRegistry.Provider() == provider.Kubernetes || srcRegistry.Provider() == provider.Federation || len(dst.ClusterVIPs.GetAddressesFor(clusterID)) == 0 { newAddresses := src.ClusterVIPs.GetAddressesFor(clusterID) dst.ClusterVIPs.SetAddressesFor(clusterID, newAddresses) } @@ -423,3 +423,10 @@ func (c *Controller) GetIstioServiceAccounts(svc *model.Service, ports []int) [] sort.Strings(result) return result } + +func (c *Controller) Unwrap(registry serviceregistry.Instance) serviceregistry.Instance { + if registryEntry, ok := registry.(*registryEntry); ok { + return registryEntry.Instance + } + return registry +} diff --git a/pilot/pkg/serviceregistry/aggregate/controller_test.go b/pilot/pkg/serviceregistry/aggregate/controller_test.go index 64b3b2ee9fc..330cfcc6679 100644 --- a/pilot/pkg/serviceregistry/aggregate/controller_test.go +++ b/pilot/pkg/serviceregistry/aggregate/controller_test.go @@ -26,6 +26,7 @@ import ( meshconfig "istio.io/api/mesh/v1alpha1" "istio.io/istio/pilot/pkg/model" "istio.io/istio/pilot/pkg/serviceregistry" + "istio.io/istio/pilot/pkg/serviceregistry/federation" "istio.io/istio/pilot/pkg/serviceregistry/memory" "istio.io/istio/pilot/pkg/serviceregistry/mock" "istio.io/istio/pilot/pkg/serviceregistry/provider" @@ -44,8 +45,14 @@ func (mh mockMeshConfigHolder) Mesh() *meshconfig.MeshConfig { } } +var ( + meshHolder mockMeshConfigHolder + discovery1 *memory.ServiceDiscovery + discovery2 *memory.ServiceDiscovery +) + func buildMockController() *Controller { - discovery1 := memory.NewServiceDiscovery(mock.ReplicatedFooServiceV1.DeepCopy(), + discovery1 = memory.NewServiceDiscovery(mock.ReplicatedFooServiceV1.DeepCopy(), mock.HelloService.DeepCopy(), mock.ExtHTTPService.DeepCopy(), ) @@ -54,7 +61,7 @@ func buildMockController() *Controller { discovery1.AddInstance(mock.HelloService.Hostname, mock.MakeServiceInstance(mock.HelloService, port, 1, model.Locality{})) } - discovery2 := memory.NewServiceDiscovery(mock.ReplicatedFooServiceV2.DeepCopy(), + discovery2 = memory.NewServiceDiscovery(mock.ReplicatedFooServiceV2.DeepCopy(), mock.WorldService.DeepCopy(), mock.ExtHTTPSService.DeepCopy(), ) @@ -74,7 +81,7 @@ func buildMockController() *Controller { Controller: &mock.Controller{}, } - ctls := NewController(Options{&mockMeshConfigHolder{}}) + ctls := NewController(Options{&meshHolder}) ctls.AddRegistry(registry1) ctls.AddRegistry(registry2) @@ -83,9 +90,9 @@ func buildMockController() *Controller { // return aggregator and cluster1 and cluster2 service discovery func buildMockControllerForMultiCluster() (*Controller, *memory.ServiceDiscovery, *memory.ServiceDiscovery) { - discovery1 := memory.NewServiceDiscovery(mock.HelloService) + discovery1 = memory.NewServiceDiscovery(mock.HelloService) - discovery2 := memory.NewServiceDiscovery(mock.MakeService(mock.ServiceArgs{ + discovery2 = memory.NewServiceDiscovery(mock.MakeService(mock.ServiceArgs{ Hostname: mock.HelloService.Hostname, Address: "10.1.2.0", ServiceAccounts: []string{}, @@ -113,6 +120,47 @@ func buildMockControllerForMultiCluster() (*Controller, *memory.ServiceDiscovery return ctls, discovery1, discovery2 } +func buildMockControllerForFederation() *Controller { + discovery1 = memory.NewServiceDiscovery( + mock.MakeService(mock.ServiceArgs{ + Hostname: "hello.default.svc.cluster.local", + Address: "10.1.1.0", + ServiceAccounts: []string{}, + ClusterID: "cluster-1", + }), + ) + + discovery2 = memory.NewServiceDiscovery( + mock.MakeService(mock.ServiceArgs{ + Hostname: "hello.default.svc.cluster.local", + Address: "10.1.2.0", + ServiceAccounts: []string{}, + ClusterID: "cluster-2", + }), + mock.WorldService.DeepCopy(), + ) + + registry1 := serviceregistry.Simple{ + ProviderID: provider.Kubernetes, + ClusterID: "cluster-1", + ServiceDiscovery: discovery1, + Controller: &mock.Controller{}, + } + + registry2 := serviceregistry.Simple{ + ProviderID: provider.Federation, + ClusterID: "cluster-2", + ServiceDiscovery: discovery2, + Controller: &federation.Controller{}, + } + + ctls := NewController(Options{}) + ctls.AddRegistry(registry1) + ctls.AddRegistry(registry2) + + return ctls +} + func TestServicesForMultiCluster(t *testing.T) { originalHelloService := mock.HelloService.DeepCopy() aggregateCtl, _, registry2 := buildMockControllerForMultiCluster() @@ -351,6 +399,40 @@ func TestGetIstioServiceAccounts(t *testing.T) { } } +// Test the aggregate controller with federation providers +func TestFederationGetIstioServiceAccounts(t *testing.T) { + federationCtl := buildMockControllerForFederation() + testCases := []struct { + name string + svc *model.Service + trustDomainAliases []string + want []string + }{ + { + name: "HelloEmpty", + svc: mock.HelloService, + want: []string{}, + }, + { + name: "World", + svc: mock.WorldService, + want: []string{ + "spiffe://cluster.local/ns/default/sa/world1", + "spiffe://cluster.local/ns/default/sa/world2", + }, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + meshHolder.trustDomainAliases = tc.trustDomainAliases + accounts := federationCtl.GetIstioServiceAccounts(tc.svc, []int{}) + if diff := cmp.Diff(accounts, tc.want); diff != "" { + t.Errorf("unexpected service account, diff %v", diff) + } + }) + } +} + func TestAddRegistry(t *testing.T) { registries := []serviceregistry.Simple{ { diff --git a/pilot/pkg/serviceregistry/federation/controller.go b/pilot/pkg/serviceregistry/federation/controller.go new file mode 100644 index 00000000000..198935dd772 --- /dev/null +++ b/pilot/pkg/serviceregistry/federation/controller.go @@ -0,0 +1,1130 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package federation + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net" + "net/http" + "reflect" + "strings" + "sync" + "sync/atomic" + "time" + + "github.com/cenkalti/backoff" + corev1 "k8s.io/api/core/v1" + v1 "maistra.io/api/federation/v1" + + "istio.io/api/label" + "istio.io/istio/pilot/pkg/model" + "istio.io/istio/pilot/pkg/serviceregistry" + "istio.io/istio/pilot/pkg/serviceregistry/provider" + "istio.io/istio/pkg/cluster" + "istio.io/istio/pkg/config/constants" + "istio.io/istio/pkg/config/host" + "istio.io/istio/pkg/config/labels" + "istio.io/istio/pkg/config/protocol" + "istio.io/istio/pkg/config/schema/gvk" + "istio.io/istio/pkg/config/visibility" + "istio.io/istio/pkg/kube" + "istio.io/istio/pkg/network" + "istio.io/istio/pkg/servicemesh/federation/common" + federationmodel "istio.io/istio/pkg/servicemesh/federation/model" + "istio.io/istio/pkg/servicemesh/federation/status" + "istio.io/istio/pkg/test/util/retry" + "istio.io/pkg/log" +) + +var ( + _ model.ServiceDiscovery = &Controller{} + _ model.Controller = &Controller{} + _ serviceregistry.Instance = &Controller{} +) + +// Controller aggregates data across different registries and monitors for changes +type Controller struct { + model.NetworkGatewaysHandler + + remote v1.ServiceMeshPeerRemote + egressService string + egressName string + discoveryURL string + discoveryServiceName string + useDirectCalls bool + namespace string + localClusterID cluster.ID + localNetworkID network.ID + clusterID cluster.ID + networkID network.ID + resyncPeriod time.Duration + backoffPolicy *backoff.ExponentialBackOff + + logger *log.Scope + + kubeClient kube.Client + statusHandler status.Handler + configStore model.ConfigStoreController + xdsUpdater model.XDSUpdater + + localDomainSuffix string + defaultDomainSuffix string + importNameMapper common.NameMapper + defaultLocality *v1.ImportedServiceLocality + importLocality *v1.ImportedServiceLocality + locality *v1.ImportedServiceLocality + + storeLock sync.RWMutex + imports map[federationmodel.ServiceKey]*existingImport + serviceStore map[host.Name]*model.Service + instanceStore map[host.Name][]*model.ServiceInstance + gatewayStore []model.NetworkGateway + egressGateways []model.NetworkGateway + egressSAs []string + + lastMessage *federationmodel.ServiceListMessage + started int32 + + cancelWatch context.CancelFunc + watchEvents chan *federationmodel.WatchEvent + + peerConfigGeneration int64 + importConfigGeneration int64 +} + +type existingImport struct { + *federationmodel.ServiceMessage + localName federationmodel.ServiceKey +} + +type Options struct { + DomainSuffix string + LocalClusterID string + LocalNetwork string + ClusterID string + Network string + KubeClient kube.Client + StatusHandler status.Handler + ConfigStore model.ConfigStoreController + XDSUpdater model.XDSUpdater + ResyncPeriod time.Duration +} + +func defaultDomainSuffixForMesh(mesh *v1.ServiceMeshPeer) string { + return fmt.Sprintf("svc.%s-imports.local", mesh.Name) +} + +func localDomainSuffix(domainSuffix string) string { + if domainSuffix == "" { + return "svc.cluster.local" + } + return "svc." + domainSuffix +} + +func mergeLocality(locality *v1.ImportedServiceLocality, defaults *v1.ImportedServiceLocality) *v1.ImportedServiceLocality { + merged := v1.ImportedServiceLocality{} + if defaults == nil { + defaults = &v1.ImportedServiceLocality{} + if locality == nil { + // If default and imported locality are all empty, return nil + // Otherwise, return imported locality. + return nil + } + } + if locality != nil { + merged = *locality + } + if merged.Subzone == "" && defaults.Subzone != "" { + merged.Subzone = defaults.Subzone + } + if merged.Zone == "" && defaults.Zone != "" { + merged.Zone = defaults.Zone + } + if merged.Region == "" && defaults.Region != "" { + merged.Region = defaults.Region + } + if merged.Subzone != "" && (merged.Zone == "" || merged.Region == "") { + // cannot have subzone specified without region and zone + return nil + } else if merged.Zone != "" && merged.Region == "" { + // cannot have zone specified without region + return nil + } + return &merged +} + +// NewController creates a new Aggregate controller +func NewController(opt Options, mesh *v1.ServiceMeshPeer, importConfig *v1.ImportedServiceSet) *Controller { + backoffPolicy := backoff.NewExponentialBackOff() + backoffPolicy.MaxElapsedTime = 0 + localDomainSuffix := localDomainSuffix(opt.DomainSuffix) + c := &Controller{ + localClusterID: cluster.ID(opt.LocalClusterID), + localNetworkID: network.ID(opt.LocalNetwork), + clusterID: cluster.ID(opt.ClusterID), + networkID: network.ID(opt.Network), + localDomainSuffix: localDomainSuffix, + imports: map[federationmodel.ServiceKey]*existingImport{}, + serviceStore: map[host.Name]*model.Service{}, + instanceStore: map[host.Name][]*model.ServiceInstance{}, + kubeClient: opt.KubeClient, + statusHandler: opt.StatusHandler, + configStore: opt.ConfigStore, + xdsUpdater: opt.XDSUpdater, + resyncPeriod: opt.ResyncPeriod, + backoffPolicy: backoffPolicy, + logger: common.Logger.WithLabels("component", "federation-registry"), + watchEvents: make(chan *federationmodel.WatchEvent), + } + c.UpdatePeerConfig(mesh) + c.UpdateImportConfig(importConfig) + return c +} + +// UpdatePeerConfig updates all settings derived from the ServiceMeshPeer resource. +// It will also restart the watch if the controller is already running. +func (c *Controller) UpdatePeerConfig(peerConfig *v1.ServiceMeshPeer) { + if func() bool { + c.storeLock.RLock() + defer c.storeLock.RUnlock() + return c.peerConfigGeneration == peerConfig.Generation + }() { + return + } + + restartWatch := func() bool { + c.storeLock.Lock() + defer c.storeLock.Unlock() + + restartWatch := false + + c.discoveryServiceName = common.DiscoveryServiceHostname(peerConfig) + c.defaultDomainSuffix = defaultDomainSuffixForMesh(peerConfig) + c.namespace = peerConfig.Namespace + c.useDirectCalls = peerConfig.Spec.Security.AllowDirectOutbound + if c.egressName != peerConfig.Spec.Gateways.Egress.Name { + c.egressName = peerConfig.Spec.Gateways.Egress.Name + c.egressService = fmt.Sprintf("%s.%s.%s", + peerConfig.Spec.Gateways.Egress.Name, c.namespace, c.localDomainSuffix) + c.discoveryURL = fmt.Sprintf("%s://%s:%d", common.DiscoveryScheme, c.egressService, common.DefaultDiscoveryPort) + restartWatch = true + } + + if !reflect.DeepEqual(c.remote, peerConfig.Spec.Remote) { + c.remote = peerConfig.Spec.Remote + restartWatch = true + } + + c.peerConfigGeneration = peerConfig.Generation + + return restartWatch + }() + if c.hasStarted() && restartWatch { + c.RestartWatch() + } +} + +// UpdateImportConfig updates the import rules that are used to select services for +// import into the mesh and rewrite their names. +func (c *Controller) UpdateImportConfig(importConfig *v1.ImportedServiceSet) { + if func() bool { + if importConfig == nil { + return false + } + c.storeLock.RLock() + defer c.storeLock.RUnlock() + return c.importConfigGeneration == importConfig.Generation + }() { + return + } + func() { + c.storeLock.Lock() + defer c.storeLock.Unlock() + c.importNameMapper = common.NewServiceImporter(importConfig, nil, c.defaultDomainSuffix, c.localDomainSuffix) + if importConfig == nil { + c.importLocality = nil + } else { + c.importLocality = importConfig.Spec.Locality + c.importConfigGeneration = importConfig.Generation + } + c.locality = mergeLocality(c.importLocality, c.defaultLocality) + }() +} + +func (c *Controller) Cluster() cluster.ID { + return c.clusterID +} + +func (c *Controller) Provider() provider.ID { + return provider.Federation +} + +func (c *Controller) pollServices() (*federationmodel.ServiceListMessage, error) { + url := c.discoveryURL + "/v1/services/" + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return nil, fmt.Errorf("failed to create request: '%s': %s", url, err) + } + req.Header.Add("discovery-service", c.discoveryServiceName) + req.Header.Add("remote", fmt.Sprint(common.RemoteChecksum(c.remote))) + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, fmt.Errorf("failed to GET URL: '%s': %s", url, err) + } + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("status code is not OK: %v (%s)", resp.StatusCode, resp.Status) + } + + respBytes := []byte{} + _, err = resp.Body.Read(respBytes) + if err != nil { + return nil, fmt.Errorf("failed to read response body from URL '%s': %s", url, err) + } + + var serviceList federationmodel.ServiceListMessage + err = json.NewDecoder(resp.Body).Decode(&serviceList) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal response bytes: %s", err) + } + return &serviceList, nil +} + +func (c *Controller) convertExportedService(s *federationmodel.ServiceMessage) (*model.Service, []*model.ServiceInstance) { + serviceVisibility := visibility.Private + if c.useDirectCalls { + serviceVisibility = visibility.Public + } + serviceName := fmt.Sprintf("%s.%s.%s.remote", s.Name, s.Namespace, c.clusterID) + return c.createService(createServiceOptions{ + service: s, + serviceName: serviceName, + serviceNamespace: c.namespace, + hostname: s.Hostname, + clusterID: c.clusterID, + networkID: c.networkID, + serviceVisibility: serviceVisibility, + networkGateways: c.gatewayStore, + sas: s.ServiceAccounts, + }) +} + +func (c *Controller) convertToLocalService(s *federationmodel.ServiceMessage, + importedName federationmodel.ServiceKey, +) (*model.Service, []*model.ServiceInstance) { + serviceName := fmt.Sprintf("%s.%s.%s.local", importedName.Name, importedName.Namespace, c.clusterID) + serviceNamespace := importedName.Namespace + if !strings.HasSuffix(importedName.Hostname, c.localDomainSuffix) { + // not importing as a local service + serviceNamespace = c.namespace + } + // XXX: make this configurable + serviceVisibility := visibility.Public + return c.createService(createServiceOptions{ + service: s, + serviceName: serviceName, + serviceNamespace: serviceNamespace, + hostname: importedName.Hostname, + clusterID: c.clusterID, + networkID: c.localNetworkID, + serviceVisibility: serviceVisibility, + networkGateways: c.egressGateways, + sas: c.egressSAs, + locality: c.locality, + }) +} + +type createServiceOptions struct { + service *federationmodel.ServiceMessage + serviceName string + serviceNamespace string + hostname string + clusterID cluster.ID + networkID network.ID + serviceVisibility visibility.Instance + networkGateways []model.NetworkGateway + sas []string + locality *v1.ImportedServiceLocality +} + +func (c *Controller) createService(opts createServiceOptions) (*model.Service, []*model.ServiceInstance) { + var instances []*model.ServiceInstance + svc := &model.Service{ + Attributes: model.ServiceAttributes{ + ServiceRegistry: provider.Federation, + Name: opts.serviceName, + Namespace: opts.serviceNamespace, + ExportTo: map[visibility.Instance]bool{ + opts.serviceVisibility: true, + }, + Labels: labels.Instance{ + label.TopologyCluster.Name: opts.clusterID.String(), + label.TopologyNetwork.Name: opts.networkID.String(), + model.IstioCanonicalServiceLabelName: opts.serviceName, + }, + }, + CreationTime: time.Now(), + Resolution: model.ClientSideLB, + DefaultAddress: constants.UnspecifiedIP, + Hostname: host.Name(opts.hostname), + Ports: model.PortList{}, + ServiceAccounts: append([]string(nil), opts.sas...), + } + for _, port := range opts.service.ServicePorts { + svc.Ports = append(svc.Ports, &model.Port{ + Name: port.Name, + Port: port.Port, + Protocol: protocol.Instance(port.Protocol), + }) + } + + baseWorkloadName := opts.serviceName + if !strings.Contains(opts.serviceName, c.clusterID.String()) { + baseWorkloadName = fmt.Sprintf("%s-%s", opts.serviceName, c.clusterID) + } + localityLabel := "" + if opts.locality != nil && opts.locality.Region != "" { + localityLabel = fmt.Sprintf("%s/%s/%s", opts.locality.Region, opts.locality.Zone, opts.locality.Subzone) + } + for _, port := range svc.Ports { + for gatewayIndex, networkGateway := range opts.networkGateways { + c.logger.Debugf("adding endpoint for imported service: addr=%s, port=%d, host=%s", + networkGateway.Addr, networkGateway.Port, svc.Hostname) + instance := &model.ServiceInstance{ + Service: svc, + ServicePort: port, + Endpoint: &model.IstioEndpoint{ + Address: networkGateway.Addr, + EndpointPort: networkGateway.Port, + Labels: labels.Instance{ + label.TopologyCluster.Name: opts.clusterID.String(), + label.TopologyNetwork.Name: opts.networkID.String(), + model.IstioCanonicalServiceLabelName: opts.serviceName, + model.IstioCanonicalServiceRevisionLabelName: opts.clusterID.String(), + }, + Network: opts.networkID, + Locality: model.Locality{ + ClusterID: opts.clusterID, + }, + ServicePortName: port.Name, + TLSMode: model.IstioMutualTLSModeLabel, + Namespace: opts.serviceNamespace, + WorkloadName: fmt.Sprintf("%s-%d", baseWorkloadName, gatewayIndex), + }, + } + if opts.locality != nil { + instance.Endpoint.Labels[label.TopologySubzone.Name] = opts.locality.Subzone + instance.Endpoint.Labels[corev1.LabelZoneFailureDomainStable] = opts.locality.Zone + instance.Endpoint.Labels[corev1.LabelZoneRegionStable] = opts.locality.Region + instance.Endpoint.Locality.Label = localityLabel + } + instances = append(instances, instance) + } + } + return svc, instances +} + +func (c *Controller) gatewayForNetworkAddress() []model.NetworkGateway { + var gateways []model.NetworkGateway + remotePort := c.remote.ServicePort + if remotePort == 0 { + remotePort = common.DefaultFederationPort + } + for _, address := range c.remote.Addresses { + addrs, err := c.getIPAddrsForHostOrIP(address) + if err != nil { + c.logger.Errorf("error resolving IP addr for federation network %s: %v", address, err) + } else { + c.logger.Debugf("adding gateway %s endpoints for cluster %s", address, c.clusterID) + for _, ip := range addrs { + c.logger.Debugf("adding gateway %s endpoint %s for cluster %s", address, ip, c.clusterID) + gateways = append(gateways, model.NetworkGateway{ + Addr: ip, + Port: uint32(remotePort), + }) + } + } + } + return gateways +} + +func (c *Controller) getIPAddrsForHostOrIP(host string) ([]string, error) { + gwIP := net.ParseIP(host) + if gwIP != nil { + return []string{gwIP.String()}, nil + } + return net.LookupHost(host) +} + +// store has to be Lock()ed +func (c *Controller) getImportNameForService(exportedService *model.Service) *federationmodel.ServiceKey { + // XXX: integrate ServiceImports CRD functionality here + // for now, hardcoding values for all services + return c.importNameMapper.NameForService(exportedService) +} + +func (c *Controller) updateGateways(serviceList *federationmodel.ServiceListMessage) { + c.gatewayStore = c.gatewayForNetworkAddress() + if serviceList != nil { + for _, gateway := range serviceList.NetworkGatewayEndpoints { + c.gatewayStore = append(c.gatewayStore, model.NetworkGateway{ + Addr: gateway.Hostname, + Port: uint32(gateway.Port), + }) + } + } + c.egressGateways, c.egressSAs = c.getEgressServiceAddrs() +} + +func (c *Controller) getEgressServiceAddrs() ([]model.NetworkGateway, []string) { + endpoints, err := common.EndpointsForService(c.kubeClient, c.egressName, c.namespace) + if err != nil { + c.logger.Errorf("unabled to retrieve endpoints for federation egress gateway %s: %s", c.egressName, err) + return nil, nil + } + serviceAccountByIP := map[string]string{} + if !c.useDirectCalls { + serviceAccountByIP, err = common.ServiceAccountsForService(c.kubeClient, c.egressName, c.namespace) + if err != nil { + c.logger.Warnf("unable to retrieve ServiceAccount information for imported services accessed through %s: %s", + c.egressName, err) + } + } + var addrs []model.NetworkGateway + var sas []string + for _, subset := range endpoints.Subsets { + for index, address := range subset.Addresses { + if subset.Ports[index].Port == common.DefaultFederationPort { + ips, err := c.getIPAddrsForHostOrIP(address.IP) + if err != nil { + c.logger.Errorf("error converting to IP address from %s: %s", address.IP, err) + continue + } + for _, ip := range ips { + addrs = append(addrs, model.NetworkGateway{ + Addr: ip, + Port: uint32(common.DefaultFederationPort), + }) + sas = append(sas, serviceAccountByIP[ip]) + } + } + } + } + return addrs, sas +} + +func (c *Controller) convertServices(serviceList *federationmodel.ServiceListMessage) { + oldImports := c.imports + c.imports = map[federationmodel.ServiceKey]*existingImport{} + allUpdatedConfigs := map[model.ConfigKey]struct{}{} + for _, s := range serviceList.Services { + var updatedConfigs map[model.ConfigKey]struct{} + var err error + if existing, update := oldImports[s.ServiceKey]; update { + if updatedConfigs, err = c.updateService(s, existing); err != nil { + // XXX: just log for now, we can't really recover + c.logger.Errorf("error updating configuration for federated service %+v from mesh %s: %s", s.ServiceKey, c.clusterID, err) + } + } else { + if updatedConfigs, err = c.addService(s); err != nil { + // XXX: just log for now, we can't really recover + c.logger.Errorf("error adding configuration for federated service %+v from mesh %s: %s", s.ServiceKey, c.clusterID, err) + } + } + for key, value := range updatedConfigs { + allUpdatedConfigs[key] = value + } + } + for key, existing := range oldImports { + if _, exists := c.imports[key]; !exists { + updatedConfigs := c.deleteService(&federationmodel.ServiceMessage{ServiceKey: key}, existing) + c.statusHandler.ImportRemoved(key.Hostname) + for key, value := range updatedConfigs { + allUpdatedConfigs[key] = value + } + } + } + if len(allUpdatedConfigs) > 0 { + c.logger.Debugf("pushing XDS config for services: %+v", allUpdatedConfigs) + c.xdsUpdater.ConfigUpdate(&model.PushRequest{ + Full: true, + ConfigsUpdated: allUpdatedConfigs, + }) + } +} + +func (c *Controller) autoAllocateIPs(serviceStore map[host.Name]*model.Service) []*model.Service { + var services []*model.Service + // i is everything from 240.241.0.(j) to 240.241.255.(j) + // j is everything from 240.241.(i).1 to 240.241.(i).254 + // we can capture this in one integer variable. + // given X, we can compute i by X/255, and j is X%255 + // To avoid allocating 240.241.(i).255, if X % 255 is 0, increment X. + // For example, when X=510, the resulting IP would be 240.241.2.0 (invalid) + // So we bump X to 511, so that the resulting IP is 240.241.2.1 + maxIPs := 255 * 255 // are we going to exceeed this limit by processing 64K services? + x := 0 + for _, svc := range serviceStore { + services = append(services, svc) + // we can allocate IPs only if + // 1. the service has resolution set to static/dns. We cannot allocate + // for NONE because we will not know the original DST IP that the application requested. + // 2. the address is not set (0.0.0.0) + // 3. the hostname is not a wildcard + if svc.DefaultAddress == constants.UnspecifiedIP && !svc.Hostname.IsWildCarded() && + svc.Resolution != model.Passthrough { + x++ + if x%255 == 0 { + x++ + } + if x >= maxIPs { + c.logger.Errorf("could not allocate VIP for %s: out of IPs to allocate for service entries", svc.Hostname) + continue + } + thirdOctet := x / 255 + fourthOctet := x % 255 + svc.AutoAllocatedIPv4Address = fmt.Sprintf("240.241.%d.%d", thirdOctet, fourthOctet) + } + } + return services +} + +// Services lists services +func (c *Controller) Services() []*model.Service { + c.storeLock.RLock() + defer c.storeLock.RUnlock() + return c.autoAllocateIPs(c.serviceStore) +} + +// GetService retrieves a service by hostname if exists +func (c *Controller) GetService(hostname host.Name) *model.Service { + c.storeLock.RLock() + defer c.storeLock.RUnlock() + if svc, found := c.serviceStore[hostname]; found { + return svc + } + return nil +} + +// NetworkGateways merges the service-based cross-network gateways from each registry. +func (c *Controller) NetworkGateways() []model.NetworkGateway { + c.storeLock.RLock() + defer c.storeLock.RUnlock() + return c.gatewayStore +} + +func (c *Controller) MCSServices() []model.MCSServiceInfo { + return nil // TODO: Implement +} + +// InstancesByPort retrieves instances for a service on a given port that match +// any of the supplied labels. All instances match an empty label list. +func (c *Controller) InstancesByPort(svc *model.Service, port int, _ labels.Instance) []*model.ServiceInstance { + instances := []*model.ServiceInstance{} + c.storeLock.RLock() + defer c.storeLock.RUnlock() + for _, instance := range c.instanceStore[svc.Hostname] { + if instance.ServicePort.Port == port { + instances = append(instances, instance.DeepCopy()) + } + } + return instances +} + +// GetProxyServiceInstances lists service instances co-located with a given proxy +func (c *Controller) GetProxyServiceInstances(_ *model.Proxy) []*model.ServiceInstance { + return make([]*model.ServiceInstance, 0) +} + +func (c *Controller) GetProxyWorkloadLabels(_ *model.Proxy) labels.Instance { + return labels.Instance{} +} + +// Run starts all the controllers +func (c *Controller) Run(stop <-chan struct{}) { + refreshTicker := time.NewTicker(c.resyncPeriod) + defer refreshTicker.Stop() + c.startWatch() + atomic.StoreInt32(&c.started, 1) + for { + select { + case <-stop: + c.logger.Info("Federation Controller terminated") + c.stopWatch() + c.stop() + return + case e := <-c.watchEvents: + c.logger.Debugf("watch event received: %v", e) + c.handleEvent(e) + case <-refreshTicker.C: + c.logger.Debugf("performing full resync for cluster %s", c.clusterID) + _ = c.resync() + } + } +} + +func (c *Controller) RestartWatch() { + c.logger.Infof("restarting watch for cluster %s", c.clusterID) + c.stopWatch() + c.startWatch() +} + +func (c *Controller) stop() { + atomic.StoreInt32(&c.started, 0) +} + +func (c *Controller) hasStarted() bool { + return atomic.LoadInt32(&c.started) == 1 +} + +func (c *Controller) handleEvent(e *federationmodel.WatchEvent) { + if e.Service == nil || c.lastMessage == nil { + checksum := c.resync() + if checksum != e.Checksum { + // this shouldn't happen + c.logger.Error("checksum mismatch after resync") + } + return + } + + c.statusHandler.WatchEventReceived() + + unlockIt := true + c.storeLock.Lock() + defer func() { + if unlockIt { + c.storeLock.Unlock() + } + }() + // verify we're up to date + lastReceivedMessage := *c.lastMessage + switch e.Action { + case federationmodel.ActionAdd: + lastReceivedMessage.Services = append(c.lastMessage.Services, e.Service) + case federationmodel.ActionUpdate: + for i, s := range lastReceivedMessage.Services { + if s.Name == e.Service.Name { + lastReceivedMessage.Services[i] = e.Service + break + } + } + case federationmodel.ActionDelete: + for i, s := range lastReceivedMessage.Services { + if s.Name == e.Service.Name { + lastReceivedMessage.Services[i] = c.lastMessage.Services[len(c.lastMessage.Services)-1] + lastReceivedMessage.Services = c.lastMessage.Services[:len(c.lastMessage.Services)-1] + break + } + } + default: + c.logger.Errorf("unknown Action from federation watch: %s", e.Action) + return + } + + lastReceivedMessage.Checksum = lastReceivedMessage.GenerateChecksum() + if lastReceivedMessage.Checksum != e.Checksum { + c.logger.Warnf("checksums don't match. resyncing") + unlockIt = false + c.storeLock.Unlock() + c.resync() + return + } + + c.lastMessage = &lastReceivedMessage + + existing := c.imports[e.Service.ServiceKey] + var updatedConfigs map[model.ConfigKey]struct{} + var err error + switch e.Action { + case federationmodel.ActionAdd: + if updatedConfigs, err = c.addService(e.Service); err != nil { + // XXX: just log for now, we can't really recover + c.logger.Errorf("error adding configuration for federated service %+v from mesh %s: %s", e.Service.ServiceKey, c.clusterID, err) + } + case federationmodel.ActionUpdate: + if updatedConfigs, err = c.updateService(e.Service, existing); err != nil { + // XXX: just log for now, we can't really recover + c.logger.Errorf("error updating configuration for federated service %+v from mesh %s: %s", e.Service.ServiceKey, c.clusterID, err) + } + case federationmodel.ActionDelete: + updatedConfigs = c.deleteService(e.Service, existing) + c.statusHandler.ImportRemoved(e.Service.Hostname) + } + if len(updatedConfigs) > 0 { + c.logger.Debugf("pushing XDS config for services: %+v", updatedConfigs) + c.xdsUpdater.ConfigUpdate(&model.PushRequest{ + Full: true, + ConfigsUpdated: updatedConfigs, + }) + } +} + +// store has to be Lock()ed +func (c *Controller) updateXDS(hostname, namespace string, instances []*model.ServiceInstance, event model.Event) { + endpoints := []*model.IstioEndpoint{} + for _, instance := range instances { + endpoints = append(endpoints, instance.Endpoint) + } + c.xdsUpdater.SvcUpdate(model.ShardKeyFromRegistry(c), hostname, namespace, event) + c.xdsUpdater.EDSCacheUpdate(model.ShardKeyFromRegistry(c), hostname, namespace, endpoints) +} + +// store has to be Lock()ed +func (c *Controller) addService(service *federationmodel.ServiceMessage) (map[model.ConfigKey]struct{}, error) { + c.logger.Debugf("handling new exported service %+v", service.ServiceKey) + + importedName := c.getImportNameForService(&model.Service{ + Hostname: host.Name(service.Hostname), + Attributes: model.ServiceAttributes{Name: service.Name, Namespace: service.Namespace}, + }) + if importedName == nil { + c.statusHandler.ImportAdded(federationmodel.ServiceKey{}, service.Hostname) + c.logger.Debugf("skipping import of service %+v, as it does not match an import filter", service.ServiceKey) + return nil, nil + } + + c.logger.Debugf("adding import for service %+v as %+v", service.ServiceKey, *importedName) + updatedConfigs := map[model.ConfigKey]struct{}{} + exportedService, exportedInstances := c.convertExportedService(service) + localService, localInstances := c.convertToLocalService(service, *importedName) + + if err := c.createRoutingResources(service.ServiceKey, *importedName); err != nil { + return nil, err + } + + c.imports[service.ServiceKey] = &existingImport{ServiceMessage: service, localName: *importedName} + + c.addServiceToStore(exportedService, exportedInstances) + updatedConfigs[model.ConfigKey{ + Kind: gvk.ServiceEntry, + Name: string(exportedService.Hostname), + Namespace: exportedService.Attributes.Namespace, + }] = struct{}{} + + c.addServiceToStore(localService, localInstances) + updatedConfigs[model.ConfigKey{ + Kind: gvk.ServiceEntry, + Name: string(localService.Hostname), + Namespace: localService.Attributes.Namespace, + }] = struct{}{} + + c.statusHandler.ImportAdded(*importedName, service.Hostname) + + return updatedConfigs, nil +} + +// store has to be Lock()ed +func (c *Controller) updateService(service *federationmodel.ServiceMessage, existing *existingImport) (map[model.ConfigKey]struct{}, error) { + c.logger.Debugf("handling update for exported service %+v", service.ServiceKey) + + // XXX: exported service name is name.namespace, while it's namespace is c.namespace + importedName := c.getImportNameForService(&model.Service{ + Hostname: host.Name(service.Hostname), + Attributes: model.ServiceAttributes{Name: service.Name, Namespace: service.Namespace}, + }) + if importedName == nil { + c.statusHandler.ImportUpdated(federationmodel.ServiceKey{}, service.Hostname) + if existing != nil { + c.logger.Debugf("deleting import for service %+v, as it no longer matches an import filter", service.ServiceKey) + return c.deleteService(service, existing), nil + } + c.logger.Debugf("skipping import for service %+v, as it does not match any import filter", service.ServiceKey) + return nil, nil + } + + updatedConfigs := map[model.ConfigKey]struct{}{} + exportedService, exportedInstances := c.convertExportedService(service) + localService, localInstances := c.convertToLocalService(service, *importedName) + + if existing == nil { + // this may have been previously filtered out + c.logger.Debugf("importing service %+v as %+v", service.ServiceKey, *importedName) + if err := c.createRoutingResources(service.ServiceKey, *importedName); err != nil { + return nil, err + } + // TODO: optimize service and instance updates + } else if importedName.Hostname != existing.localName.Hostname { + c.logger.Debugf("service %+v has been reimported as %+v (was %+v)", service.ServiceKey, *importedName, existing.localName) + // update the routing + if err := c.createRoutingResources(service.ServiceKey, *importedName); err != nil { + return nil, err + } + + // delete the old imported service + c.removeServiceFromStore(existing.localName) + updatedConfigs[model.ConfigKey{ + Kind: gvk.ServiceEntry, + Name: existing.localName.Hostname, + Namespace: existing.Namespace, + }] = struct{}{} + } + + // TODO: be smart and see if anything changed, so we don't push unnecessarily + + c.imports[service.ServiceKey] = &existingImport{ServiceMessage: service, localName: *importedName} + + c.updateServiceInStore(exportedService, exportedInstances) + updatedConfigs[model.ConfigKey{ + Kind: gvk.ServiceEntry, + Name: string(exportedService.Hostname), + Namespace: exportedService.Attributes.Namespace, + }] = struct{}{} + + c.updateServiceInStore(localService, localInstances) + updatedConfigs[model.ConfigKey{ + Kind: gvk.ServiceEntry, + Name: string(localService.Hostname), + Namespace: localService.Attributes.Namespace, + }] = struct{}{} + + c.statusHandler.ImportUpdated(*importedName, service.Hostname) + + return updatedConfigs, nil +} + +// store has to be Lock()ed +func (c *Controller) deleteService(service *federationmodel.ServiceMessage, existing *existingImport) map[model.ConfigKey]struct{} { + if existing != nil { + c.logger.Debugf("deleting import for service %+v, known locally as %+v", service.ServiceKey, existing.localName) + } else { + c.logger.Debugf("deleting import for service %+v, with unknown local name", service.ServiceKey) + } + _ = c.deleteRoutingResources(service.ServiceKey) + updatedConfigs := map[model.ConfigKey]struct{}{} + + delete(c.imports, service.ServiceKey) + + svc := c.removeServiceFromStore(service.ServiceKey) + if svc != nil { + updatedConfigs[model.ConfigKey{ + Kind: gvk.ServiceEntry, + Name: service.Hostname, + Namespace: svc.Attributes.Namespace, + }] = struct{}{} + } + + if existing != nil { + c.removeServiceFromStore(existing.localName) + if svc != nil { + updatedConfigs[model.ConfigKey{ + Kind: gvk.ServiceEntry, + Name: existing.localName.Hostname, + Namespace: svc.Attributes.Namespace, + }] = struct{}{} + } + } + + return updatedConfigs +} + +func (c *Controller) addServiceToStore(service *model.Service, instances []*model.ServiceInstance) { + // Check existing services in the serviceStore, those can be created before importing services from a federation peer. + eventType := model.EventAdd + for i, s := range c.serviceStore { + if s.Hostname == service.Hostname { + c.serviceStore[i] = service + c.logger.Debugf("Update service %s to the registry", service.Hostname) + eventType = model.EventUpdate + break + } + } + + c.serviceStore[service.Hostname] = service + c.instanceStore[service.Hostname] = instances + c.updateXDS(string(service.Hostname), service.Attributes.Namespace, instances, eventType) +} + +func (c *Controller) updateServiceInStore(service *model.Service, instances []*model.ServiceInstance) { + eventType := model.EventUpdate + found := false + for i, s := range c.serviceStore { + if s.Hostname == service.Hostname { + c.serviceStore[i] = service + found = true + break + } + } + if !found { + c.logger.Warnf("trying to update unknown service %s, adding it to the registry", service.Hostname) + c.serviceStore[service.Hostname] = service + eventType = model.EventAdd + } + c.instanceStore[service.Hostname] = instances + c.updateXDS(string(service.Hostname), service.Attributes.Namespace, instances, eventType) +} + +func (c *Controller) removeServiceFromStore(service federationmodel.ServiceKey) *model.Service { + svc := c.serviceStore[host.Name(service.Hostname)] + if svc != nil { + delete(c.serviceStore, host.Name(service.Hostname)) + delete(c.instanceStore, host.Name(service.Hostname)) + c.xdsUpdater.SvcUpdate(model.ShardKeyFromRegistry(c), service.Hostname, svc.Attributes.Namespace, model.EventDelete) + c.xdsUpdater.EDSCacheUpdate(model.ShardKeyFromRegistry(c), service.Hostname, svc.Attributes.Namespace, nil) + } + return svc +} + +func (c *Controller) startWatch() { + var ctx context.Context + var cancelCtx context.CancelFunc + ctx, cancelCtx = context.WithCancel(context.Background()) + c.cancelWatch = cancelCtx + go func() { + defer func() { + cancelCtx() // cleans up resources when watch is closed gracefully + c.logger.Info("watch stopped") + }() + for ctx.Err() != context.Canceled { + c.logger.Info("starting watch") + err := c.watch(ctx, c.watchEvents) + if err != nil { + if err == context.Canceled { + c.logger.Info("watch cancelled") + return + } + c.logger.Errorf("watch failed: %s", err) + + // sleep, but still honor context cancellation + select { + case <-ctx.Done(): + c.logger.Info("watch cancelled") + return + case <-time.After(c.backoffPolicy.NextBackOff()): + // start watch again after backoff + } + } else { + c.backoffPolicy.Reset() + c.logger.Info("watch closed") + } + } + }() +} + +func (c *Controller) stopWatch() { + if c.cancelWatch != nil { + c.cancelWatch() + } +} + +func (c *Controller) watch(ctx context.Context, eventCh chan *federationmodel.WatchEvent) error { + c.statusHandler.WatchInitiated() + url := c.discoveryURL + "/v1/watch" + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + c.logger.Errorf("Failed to create request: '%s': %s", url, err) + return nil + } + req.Header.Add("discovery-service", c.discoveryServiceName) + req.Header.Add("remote", fmt.Sprint(common.RemoteChecksum(c.remote))) + resp, err := http.DefaultClient.Do(req.WithContext(ctx)) + defer func() { + status := "" + if resp != nil { + status = resp.Status + } else if err != nil { + status = err.Error() + } + c.statusHandler.WatchTerminated(status) + }() + if err != nil { + return err + } + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("status code is not OK: %v (%s)", resp.StatusCode, resp.Status) + } + + c.statusHandler.Watching() + + // connection was established successfully. reset backoffPolicy and resync + c.backoffPolicy.Reset() + c.resync() + + dec := json.NewDecoder(resp.Body) + defer resp.Body.Close() + for { + var e federationmodel.WatchEvent + err := dec.Decode(&e) + if err != nil { + if err == io.EOF { + return nil // server closed the connection gracefully + } + return err + } + eventCh <- &e + } +} + +func (c *Controller) resync() uint64 { + c.storeLock.Lock() + defer c.storeLock.Unlock() + c.logger.Debugf("performing full resync") + var err error + var svcList *federationmodel.ServiceListMessage + err = retry.UntilSuccess(func() error { + svcList, err = c.pollServices() + return err + }, retry.Delay(time.Second), retry.Timeout(2*time.Minute)) + if err != nil { + c.logger.Warnf("resync failed: %s", err) + return 0 + } + c.updateGateways(svcList) + if svcList != nil { + c.convertServices(svcList) + c.statusHandler.FullSyncComplete() + return svcList.Checksum + } + return 0 +} + +// HasSynced always returns true so not to stall istiod on a broken federation connection +func (c *Controller) HasSynced() bool { + return true +} + +// AppendServiceHandler implements a service catalog operation +func (c *Controller) AppendServiceHandler(f func(*model.Service, model.Event)) { + // TODO +} + +func (c *Controller) AppendWorkloadHandler(f func(*model.WorkloadInstance, model.Event)) { + // TODO +} + +// GetIstioServiceAccounts implements model.ServiceAccounts operation. +// The returned list contains all SPIFFE based identities that backs the service. +// This method also expand the results from different registries based on the mesh config trust domain aliases. +// To retain such trust domain expansion behavior, the xDS server implementation should wrap any (even if single) +// service registry by this aggreated one. +// For example, +// - { "spiffe://cluster.local/bar@iam.gserviceaccount.com"}; when annotation is used on corresponding workloads. +// - { "spiffe://cluster.local/ns/default/sa/foo" }; normal kubernetes cases +// - { "spiffe://cluster.local/ns/default/sa/foo", "spiffe://trust-domain-alias/ns/default/sa/foo" }; +// if the trust domain alias is configured. +func (c *Controller) GetIstioServiceAccounts(svc *model.Service, ports []int) []string { + if svc == nil { + return nil + } + c.storeLock.RLock() + defer c.storeLock.RUnlock() + // we don't have different workloads for different ports, so we just need to + // return the SAs associated with our service. + if ourSVC, ok := c.serviceStore[svc.Hostname]; ok { + return append([]string(nil), ourSVC.ServiceAccounts...) + } + return nil +} diff --git a/pilot/pkg/serviceregistry/federation/controller_test.go b/pilot/pkg/serviceregistry/federation/controller_test.go new file mode 100644 index 00000000000..c50b5569b9d --- /dev/null +++ b/pilot/pkg/serviceregistry/federation/controller_test.go @@ -0,0 +1,62 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package federation + +import ( + "testing" + + v1 "maistra.io/api/federation/v1" +) + +// TestMergeLocality tests the federation mergeLocality function +func TestMergeLocality(t *testing.T) { + remoteLocality := v1.ImportedServiceLocality{ + Region: "region1", + Zone: "zone1", + Subzone: "subzone1", + } + merged := mergeLocality(&remoteLocality, nil) + if merged.Region != "region1" { + t.Fatalf("Federation controller should initialize importConfig locality region. Actual %v, expected %v", + merged.Region, "region1") + } + if merged.Zone != "zone1" { + t.Fatalf("Federation controller should initialize importConfig locality zone. Actual %v, expected %v", + merged.Zone, "zone1") + } + if merged.Subzone != "subzone1" { + t.Fatalf("Federation controller should initialize importConfig locality subzone Actual %v, expected %v", + merged.Subzone, "subzone1") + } + + updatedLocality := v1.ImportedServiceLocality{ + Region: "region2", + Zone: "zone2", + Subzone: "subzone2", + } + merged = mergeLocality(&updatedLocality, &remoteLocality) + if merged.Region != "region2" { + t.Fatalf("Federation controller should update importConfig locality region. Actual %v, expected %v", + merged.Region, "region2") + } + if merged.Zone != "zone2" { + t.Fatalf("Federation controller should update importConfig locality zone. Actual %v, expected %v", + merged.Zone, "zone2") + } + if merged.Subzone != "subzone2" { + t.Fatalf("Federation controller should update importConfig locality subzone Actual %v, expected %v", + merged.Subzone, "subzone2") + } +} diff --git a/pilot/pkg/serviceregistry/federation/routing.go b/pilot/pkg/serviceregistry/federation/routing.go new file mode 100644 index 00000000000..7613d3d270c --- /dev/null +++ b/pilot/pkg/serviceregistry/federation/routing.go @@ -0,0 +1,177 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package federation + +import ( + "fmt" + "strings" + "time" + + "github.com/pkg/errors" + + rawnetworking "istio.io/api/networking/v1alpha3" + "istio.io/istio/pkg/cluster" + "istio.io/istio/pkg/config" + "istio.io/istio/pkg/config/schema/gvk" + "istio.io/istio/pkg/servicemesh/federation/common" + federationmodel "istio.io/istio/pkg/servicemesh/federation/model" +) + +// ensure our config gets ignored if the user wants to change routing for +// exported services +var armageddonTime = time.Unix(1<<62-1, 0) + +func createResourceName(mesh cluster.ID, source federationmodel.ServiceKey) string { + return fmt.Sprintf("federation-imports-%s-%s-%s", mesh, source.Name, source.Namespace) +} + +func (c *Controller) deleteRoutingResources(remote federationmodel.ServiceKey) error { + resourceName := createResourceName(c.clusterID, remote) + // Delete() is always successful + _ = c.configStore.Delete(gvk.Gateway, resourceName, c.namespace, nil) + return c.configStore.Delete(gvk.VirtualService, resourceName, c.namespace, nil) +} + +func (c *Controller) createRoutingResources(remote, local federationmodel.ServiceKey) error { + resourceName := createResourceName(c.clusterID, remote) + gateway := c.gatewayForImport(remote, local) + if rawGateway := c.configStore.Get(gvk.Gateway, gateway.Name, c.namespace); rawGateway == nil { + if gateway != nil { + if _, err := c.configStore.Create(*gateway); err != nil { + return errors.Wrapf(err, "error creating Gateway resource") + } + } + } else if gateway == nil { + _ = c.configStore.Delete(gvk.Gateway, resourceName, c.namespace, nil) + } else { + existingGateway := rawGateway.Spec.(*rawnetworking.Gateway) + if len(existingGateway.Servers) > 0 && len(existingGateway.Servers[0].Hosts) > 0 && existingGateway.Servers[0].Hosts[0] != local.Hostname { + // overwrite whatever's there + c.logger.Warnf("Gateway resource %s already exists for exported service (%s => %s). It will be overwritten.", + gateway.Name, remote.Hostname, local.Hostname) + if _, err := c.configStore.Update(*gateway); err != nil { + return errors.Wrapf(err, "error updating Gateway resource") + } + } + } + vs := c.virtualServiceForImport(remote, local) + if rawVS := c.configStore.Get(gvk.VirtualService, vs.Name, c.namespace); rawVS == nil { + if _, err := c.configStore.Create(*vs); err != nil { + return errors.Wrapf(err, "error creating VirtualService resource") + } + } else { + existingVS := rawVS.Spec.(*rawnetworking.VirtualService) + if (len(existingVS.Hosts) > 0 && !strings.HasSuffix(existingVS.Hosts[0], "/"+local.Hostname)) || + (len(existingVS.ExportTo) > 0 && existingVS.ExportTo[0] != vs.Spec.(*rawnetworking.VirtualService).ExportTo[0]) { + // overwrite whatever's there + c.logger.Warnf("VirtualService resource %s already exists for exported service (%s => %s). It will be overwritten.", + vs.Name, remote.Hostname, local.Hostname) + if _, err := c.configStore.Update(*vs); err != nil { + return errors.Wrapf(err, "error updating VirtualService resource") + } + } + } + return nil +} + +func (c *Controller) gatewayForImport(remote, local federationmodel.ServiceKey) *config.Config { + resourceName := createResourceName(c.clusterID, remote) + mode := rawnetworking.ServerTLSSettings_ISTIO_MUTUAL + if c.useDirectCalls { + // no gateway when directly accessing services + return nil + } + gateway := &config.Config{ + Meta: config.Meta{ + GroupVersionKind: gvk.Gateway, + Name: resourceName, + Namespace: c.namespace, + }, + Spec: &rawnetworking.Gateway{ + Selector: map[string]string{ + "service.istio.io/canonical-name": c.egressName, + }, + Servers: []*rawnetworking.Server{ + { + Name: resourceName, + Hosts: []string{ + local.Hostname, + "*." + local.Hostname, + }, + Port: &rawnetworking.Port{ + Name: "tls-federation", + Number: uint32(common.DefaultFederationPort), + Protocol: "TLS", + }, + Tls: &rawnetworking.ServerTLSSettings{ + Mode: mode, + }, + }, + }, + }, + } + return gateway +} + +func (c *Controller) virtualServiceForImport(remote, local federationmodel.ServiceKey) *config.Config { + // VirtualService used to route inbound requests to the service. + name := createResourceName(c.clusterID, remote) + egressGatewayName := fmt.Sprintf("%s/%s", c.namespace, name) + exportTo := "." + creationTime := time.Now() + if c.useDirectCalls { + exportTo = "*" + creationTime = armageddonTime + } + vs := &config.Config{ + Meta: config.Meta{ + GroupVersionKind: gvk.VirtualService, + Name: name, + Namespace: c.namespace, + CreationTimestamp: creationTime, + }, + Spec: &rawnetworking.VirtualService{ + Hosts: []string{ + local.Hostname, + "*." + local.Hostname, + }, + Gateways: []string{ + egressGatewayName, + }, + ExportTo: []string{ + exportTo, + }, + Tcp: []*rawnetworking.TCPRoute{ + { + Match: []*rawnetworking.L4MatchAttributes{ + { + Gateways: []string{ + egressGatewayName, + }, + }, + }, + Route: []*rawnetworking.RouteDestination{ + { + Destination: &rawnetworking.Destination{ + Host: remote.Hostname, + }, + }, + }, + }, + }, + }, + } + return vs +} diff --git a/pilot/pkg/serviceregistry/kube/controller/controller.go b/pilot/pkg/serviceregistry/kube/controller/controller.go index 8e4490b0fba..87e5ef38813 100644 --- a/pilot/pkg/serviceregistry/kube/controller/controller.go +++ b/pilot/pkg/serviceregistry/kube/controller/controller.go @@ -109,6 +109,7 @@ type Options struct { // MeshServiceController is a mesh-wide service Controller. MeshServiceController *aggregate.Controller + ResyncPeriod time.Duration DomainSuffix string // Name of the Maistra MemberRoll resource. diff --git a/pilot/pkg/serviceregistry/provider/providers.go b/pilot/pkg/serviceregistry/provider/providers.go index 7c38b85d4ab..db23e29c718 100644 --- a/pilot/pkg/serviceregistry/provider/providers.go +++ b/pilot/pkg/serviceregistry/provider/providers.go @@ -22,6 +22,8 @@ const ( Mock ID = "Mock" // Kubernetes is a service registry backed by k8s API server Kubernetes ID = "Kubernetes" + // Federation is a service registry backed by Federation + Federation ID = "Federation" // External is a service registry for externally provided ServiceEntries External ID = "External" ) diff --git a/pilot/pkg/xds/tbds.go b/pilot/pkg/xds/tbds.go new file mode 100644 index 00000000000..e1e0c531824 --- /dev/null +++ b/pilot/pkg/xds/tbds.go @@ -0,0 +1,71 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package xds + +import ( + discovery "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" + v1 "maistra.io/api/security/v1" + + "istio.io/istio/pilot/pkg/model" + fedmodel "istio.io/istio/pkg/servicemesh/federation/model" + "istio.io/istio/pkg/util/gogo" +) + +// TbdsGenerator generates trust bundle configuration for proxies to consume +type TbdsGenerator struct { + TrustBundleProvider fedmodel.TrustBundleProvider +} + +var _ model.XdsResourceGenerator = &TbdsGenerator{} + +func tbdsNeedsPush(req *model.PushRequest) bool { + if req == nil { + return true + } + + if !req.Full { + return false + } + + if len(req.ConfigsUpdated) == 0 { + return true + } + + return false +} + +// Generate returns protobuf containing TrustBundle for given proxy +func (e *TbdsGenerator) Generate(_ *model.Proxy, _ *model.WatchedResource, req *model.PushRequest) (model.Resources, model.XdsLogDetails, error) { + if !tbdsNeedsPush(req) { + return nil, model.DefaultXdsLogDetails, nil + } + if e.TrustBundleProvider == nil { + return nil, model.DefaultXdsLogDetails, nil + } + tb := &v1.TrustBundleResponse{} + trustBundles := e.TrustBundleProvider.GetTrustBundles() + if len(trustBundles) == 0 { + return nil, model.DefaultXdsLogDetails, nil + } + for td, cert := range trustBundles { + tb.TrustBundles = append(tb.TrustBundles, &v1.TrustBundle{ + TrustDomain: td, + RootCert: cert, + }) + } + // TODO: Remove package gogo and use MassageToAny from "istio.io/istio/pilot/pkg/networking/util" + resources := model.Resources{&discovery.Resource{Resource: gogo.MessageToAny(tb)}} + return resources, model.DefaultXdsLogDetails, nil +} diff --git a/pilot/pkg/xds/v3/model.go b/pilot/pkg/xds/v3/model.go index f34e5a9816f..d76757b0f72 100644 --- a/pilot/pkg/xds/v3/model.go +++ b/pilot/pkg/xds/v3/model.go @@ -30,6 +30,9 @@ const ( SecretType = resource.SecretType ExtensionConfigurationType = resource.ExtensionConfigType + // maistra xDS + TrustBundleType = "type.googleapis.com/maistra.security.v1.TrustBundleResponse" + NameTableType = resource.APITypePrefix + "istio.networking.nds.v1.NameTable" HealthInfoType = resource.APITypePrefix + "istio.v1.HealthInformation" ProxyConfigType = resource.APITypePrefix + "istio.mesh.v1alpha1.ProxyConfig" @@ -60,6 +63,8 @@ func GetShortType(typeURL string) string { return "PCDS" case ExtensionConfigurationType: return "ECDS" + case TrustBundleType: + return "TBDS" default: return typeURL } @@ -86,6 +91,8 @@ func GetMetricType(typeURL string) string { return "ecds" case BootstrapType: return "bds" + case TrustBundleType: + return "tbds" default: return typeURL } diff --git a/pkg/istio-agent/xds_proxy.go b/pkg/istio-agent/xds_proxy.go index bab19df2a0f..574223a75b0 100644 --- a/pkg/istio-agent/xds_proxy.go +++ b/pkg/istio-agent/xds_proxy.go @@ -30,6 +30,7 @@ import ( "time" discovery "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" + "github.com/golang/protobuf/ptypes" "go.uber.org/atomic" google_rpc "google.golang.org/genproto/googleapis/rpc/status" "google.golang.org/grpc" @@ -40,6 +41,7 @@ import ( "google.golang.org/grpc/metadata" "google.golang.org/grpc/reflection" any "google.golang.org/protobuf/types/known/anypb" + v1 "maistra.io/api/security/v1" meshconfig "istio.io/api/mesh/v1alpha1" "istio.io/istio/pilot/cmd/pilot-agent/status/ready" @@ -55,7 +57,9 @@ import ( "istio.io/istio/pkg/uds" "istio.io/istio/pkg/util/protomarshal" "istio.io/istio/pkg/wasm" + "istio.io/istio/security/pkg/nodeagent/cache" "istio.io/istio/security/pkg/nodeagent/caclient" + nodeagentutil "istio.io/istio/security/pkg/nodeagent/util" "istio.io/istio/security/pkg/pki/util" "istio.io/pkg/log" ) @@ -107,6 +111,8 @@ type XdsProxy struct { // Wasm cache and ecds channel are used to replace wasm remote load with local file. wasmCache wasm.Cache + secretCache *cache.SecretManagerClient + // ecds version and nonce uses atomic only to prevent race in testing. // In reality there should not be race as istiod will only have one // in flight update for each type of resource. @@ -151,6 +157,7 @@ func initXdsProxy(ia *Agent) (*XdsProxy, error) { xdsHeaders: ia.cfg.XDSHeaders, xdsUdsPath: ia.cfg.XdsUdsPath, wasmCache: cache, + secretCache: ia.secretCache, proxyAddresses: ia.cfg.ProxyIPAddresses, downstreamGrpcOptions: ia.cfg.DownstreamGrpcOptions, } @@ -459,6 +466,10 @@ func (p *XdsProxy) handleUpstreamRequest(con *ProxyConnection) { if initialRequest != nil { con.sendRequest(initialRequest) } + // fire off an initial TBDS request + con.requestsChan <- &discovery.DiscoveryRequest{ + TypeUrl: v3.TrustBundleType, + } p.connectedMutex.RUnlock() } } @@ -538,6 +549,46 @@ func (p *XdsProxy) handleUpstreamResponse(con *ProxyConnection) { // Otherwise, forward ECDS resource update directly to Envoy. forwardToEnvoy(con, resp) } + case v3.TrustBundleType: + if len(resp.Resources) == 0 { + log.Error("empty response") + continue + } + var tb v1.TrustBundleResponse + if err := ptypes.UnmarshalAny(resp.Resources[0], &tb); err != nil { // nolint + proxyLog.Errorf("failed to unmarshall trust bundles: %v", err) + continue + } + trustBundles := map[string][]byte{} + proxyLog.Debugf("received new trust bundles: %v", tb.TrustBundles) + expireTime := time.Date(3000, 1, 1, 1, 1, 1, 1, time.Now().Location()) + for _, bundle := range tb.TrustBundles { + certBytes := []byte(bundle.RootCert) + certExpireTime, err := nodeagentutil.ParseCertAndGetExpiryTimestamp(certBytes) + if err != nil { + proxyLog.Errorf("failed to extract expiration time in the certificate loaded from file: %v", err) + } else if certExpireTime.Before(expireTime) { + expireTime = certExpireTime + } + trustBundles[bundle.TrustDomain] = certBytes + } + + if p.secretCache == nil { + proxyLog.Error("failed to access secret cache") + continue + } + if len(trustBundles) == 0 { + trustBundles = nil + } + p.secretCache.SetTrustBundles(trustBundles, expireTime) + + // Send ACK + con.requestsChan <- &discovery.DiscoveryRequest{ + VersionInfo: resp.VersionInfo, + TypeUrl: v3.TrustBundleType, + ResponseNonce: resp.Nonce, + } + default: if strings.HasPrefix(resp.TypeUrl, "istio.io/debug") { p.forwardToTap(resp) diff --git a/pkg/kube/controller/controller.go b/pkg/kube/controller/controller.go new file mode 100644 index 00000000000..95f584deb7f --- /dev/null +++ b/pkg/kube/controller/controller.go @@ -0,0 +1,151 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package controller + +import ( + "time" + + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + + "istio.io/pkg/log" +) + +const ( + maxRetries = 5 +) + +type ( + ReconcilerFunc func(name string) error + Options struct { + ResyncPeriod time.Duration + Informer cache.SharedIndexInformer + Reconciler ReconcilerFunc + Logger *log.Scope + } +) + +type Controller struct { + Logger *log.Scope + informer cache.SharedIndexInformer + queue workqueue.RateLimitingInterface + resyncPeriod time.Duration + reconcile ReconcilerFunc +} + +// NewController creates a new Aggregate controller +func NewController(opt Options) *Controller { + queue := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()) + + if opt.Logger == nil { + opt.Logger = log.RegisterScope("kube-controller", "kube-controller", 0) + } + if opt.ResyncPeriod == 0 { + opt.ResyncPeriod = 60 * time.Second + } + controller := &Controller{ + informer: opt.Informer, + queue: queue, + Logger: opt.Logger, + resyncPeriod: opt.ResyncPeriod, + reconcile: opt.Reconciler, + } + + controller.informer.AddEventHandler( + cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + key, err := cache.MetaNamespaceKeyFunc(obj) + controller.Logger.Debugf("Processing add: %s", key) + if err == nil { + queue.Add(key) + } else { + controller.Logger.Errorf("error retrieving key for object %T", obj) + } + }, + UpdateFunc: func(oldObj, newObj interface{}) { + key, err := cache.MetaNamespaceKeyFunc(newObj) + controller.Logger.Debugf("Processing update: %s", key) + if err == nil { + queue.Add(key) + } else { + controller.Logger.Errorf("error retrieving key for object %T", newObj) + } + }, + DeleteFunc: func(obj interface{}) { + key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj) + controller.Logger.Debugf("Processing delete: %s", key) + if err == nil { + queue.Add(key) + } else { + controller.Logger.Errorf("error retrieving key for object %T", obj) + } + }, + }) + + return controller +} + +func (c *Controller) Start(stopChan <-chan struct{}) { + defer utilruntime.HandleCrash() + defer c.queue.ShutDown() + + t0 := time.Now() + c.Logger.Info("Starting controller") + + c.RunInformer(stopChan) + + cache.WaitForCacheSync(stopChan, c.HasSynced) + c.Logger.Infof("Controller synced in %s", time.Since(t0)) + + c.Logger.Info("Starting workers") + wait.Until(c.worker, c.resyncPeriod, stopChan) +} + +func (c *Controller) RunInformer(stopChan <-chan struct{}) { + go c.informer.Run(stopChan) +} + +func (c *Controller) HasSynced() bool { + return c.informer.HasSynced() +} + +func (c *Controller) worker() { + for c.processNextItem() { + } +} + +func (c *Controller) processNextItem() bool { + resourceName, quit := c.queue.Get() + if quit { + return false + } + defer c.queue.Done(resourceName) + + err := c.reconcile(resourceName.(string)) + if err == nil { + // No error, reset the ratelimit counters + c.queue.Forget(resourceName) + } else if c.queue.NumRequeues(resourceName) < maxRetries { + c.Logger.Errorf("Error processing %s (will retry): %v", resourceName, err) + c.queue.AddRateLimited(resourceName) + } else { + c.Logger.Errorf("Error processing %s (giving up): %v", resourceName, err) + c.queue.Forget(resourceName) + utilruntime.HandleError(err) + } + + return true +} diff --git a/pkg/security/security.go b/pkg/security/security.go index 16e92ce49b6..1280ac423be 100644 --- a/pkg/security/security.go +++ b/pkg/security/security.go @@ -316,6 +316,8 @@ type SecretItem struct { RootCert []byte + TrustBundles map[string][]byte + // ResourceName passed from envoy SDS discovery request. // "ROOTCA" for root cert request, "default" for key/cert request. ResourceName string diff --git a/pkg/servicemesh/apis/servicemesh/v1/register.go b/pkg/servicemesh/apis/servicemesh/v1/register.go deleted file mode 100644 index 12c37d57af4..00000000000 --- a/pkg/servicemesh/apis/servicemesh/v1/register.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -var SchemeGroupVersion = schema.GroupVersion{ - Group: "maistra.io", - Version: "v1", -} - -var InternalSchemeGroupVersion = schema.GroupVersion{ - Group: "maistra.io", - Version: runtime.APIVersionInternal, -} - -var ( - SchemeBuilder runtime.SchemeBuilder - localSchemeBuilder = &SchemeBuilder - AddToScheme = localSchemeBuilder.AddToScheme -) - -func init() { - // We only register manually written functions here. The registration of the - // generated functions takes place in the generated files. The separation - // makes the code compile even when the generated files are missing. - localSchemeBuilder.Register(addKnownTypes) - localSchemeBuilder.Register(addKnownInternalTypes) -} - -// Resource takes an unqualified resource and returns a Group qualified GroupResource -func Resource(resource string) schema.GroupResource { - return SchemeGroupVersion.WithResource(resource).GroupResource() -} - -// Adds the list of known types to the given scheme. -func addKnownTypes(scheme *runtime.Scheme) error { - scheme.AddKnownTypes( - SchemeGroupVersion, - &ServiceMeshMemberRoll{}, - &ServiceMeshMemberRollList{}, - ) - - metav1.AddToGroupVersion( - scheme, - SchemeGroupVersion, - ) - - return nil -} - -func addKnownInternalTypes(scheme *runtime.Scheme) error { - scheme.AddKnownTypes( - InternalSchemeGroupVersion, - &ServiceMeshMemberRoll{}, - &ServiceMeshMemberRollList{}, - ) - - return nil -} diff --git a/pkg/servicemesh/apis/servicemesh/v1/servicemesh.go b/pkg/servicemesh/apis/servicemesh/v1/servicemesh.go deleted file mode 100644 index cf7b2f11901..00000000000 --- a/pkg/servicemesh/apis/servicemesh/v1/servicemesh.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package v1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +genclient -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// ServiceMeshMemberRoll is the Schema for the servicemeshmemberrolls API -// +k8s:openapi-gen=true -type ServiceMeshMemberRoll struct { - metav1.TypeMeta `json:""` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec ServiceMeshMemberRollSpec `json:"spec,omitempty"` - Status ServiceMeshMemberRollStatus `json:"status,omitempty"` -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// ServiceMeshMemberRollList contains a list of ServiceMeshMemberRoll -type ServiceMeshMemberRollList struct { - metav1.TypeMeta `json:""` - metav1.ListMeta `json:"metadata,omitempty"` - Items []ServiceMeshMemberRoll `json:"items"` -} - -// ServiceMeshMemberRollSpec defines the members of the mesh -type ServiceMeshMemberRollSpec struct { - Members []string `json:"members,omitempty"` -} - -// ServiceMeshMemberRollStatus contains the state last used to reconcile the list -type ServiceMeshMemberRollStatus struct { - ObservedGeneration int64 `json:"observedGeneration,omitempty"` - ServiceMeshGeneration int64 `json:"meshGeneration,omitempty"` - ConfiguredMembers []string `json:"configuredMembers,omitempty"` -} diff --git a/pkg/servicemesh/apis/servicemesh/v1/zz_generated.deepcopy.go b/pkg/servicemesh/apis/servicemesh/v1/zz_generated.deepcopy.go deleted file mode 100644 index 871f3ad4a67..00000000000 --- a/pkg/servicemesh/apis/servicemesh/v1/zz_generated.deepcopy.go +++ /dev/null @@ -1,128 +0,0 @@ -// +build !ignore_autogenerated - -/* -Copyright The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by deepcopy-gen. DO NOT EDIT. - -package v1 - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServiceMeshMemberRoll) DeepCopyInto(out *ServiceMeshMemberRoll) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberRoll. -func (in *ServiceMeshMemberRoll) DeepCopy() *ServiceMeshMemberRoll { - if in == nil { - return nil - } - out := new(ServiceMeshMemberRoll) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ServiceMeshMemberRoll) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServiceMeshMemberRollList) DeepCopyInto(out *ServiceMeshMemberRollList) { - *out = *in - out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]ServiceMeshMemberRoll, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberRollList. -func (in *ServiceMeshMemberRollList) DeepCopy() *ServiceMeshMemberRollList { - if in == nil { - return nil - } - out := new(ServiceMeshMemberRollList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ServiceMeshMemberRollList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServiceMeshMemberRollSpec) DeepCopyInto(out *ServiceMeshMemberRollSpec) { - *out = *in - if in.Members != nil { - in, out := &in.Members, &out.Members - *out = make([]string, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberRollSpec. -func (in *ServiceMeshMemberRollSpec) DeepCopy() *ServiceMeshMemberRollSpec { - if in == nil { - return nil - } - out := new(ServiceMeshMemberRollSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ServiceMeshMemberRollStatus) DeepCopyInto(out *ServiceMeshMemberRollStatus) { - *out = *in - if in.ConfiguredMembers != nil { - in, out := &in.ConfiguredMembers, &out.ConfiguredMembers - *out = make([]string, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberRollStatus. -func (in *ServiceMeshMemberRollStatus) DeepCopy() *ServiceMeshMemberRollStatus { - if in == nil { - return nil - } - out := new(ServiceMeshMemberRollStatus) - in.DeepCopyInto(out) - return out -} diff --git a/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/servicemesh_client.go b/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/servicemesh_client.go deleted file mode 100644 index 3089a89a356..00000000000 --- a/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/servicemesh_client.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by client-gen. DO NOT EDIT. - -package v1 - -import ( - "net/http" - - v1 "istio.io/istio/pkg/servicemesh/apis/servicemesh/v1" - "istio.io/istio/pkg/servicemesh/client/clientset/versioned/scheme" - rest "k8s.io/client-go/rest" -) - -type MaistraV1Interface interface { - RESTClient() rest.Interface - ServiceMeshMemberRollsGetter -} - -// MaistraV1Client is used to interact with features provided by the maistra.io group. -type MaistraV1Client struct { - restClient rest.Interface -} - -func (c *MaistraV1Client) ServiceMeshMemberRolls(namespace string) ServiceMeshMemberRollInterface { - return newServiceMeshMemberRolls(c, namespace) -} - -// NewForConfig creates a new MaistraV1Client for the given config. -// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), -// where httpClient was generated with rest.HTTPClientFor(c). -func NewForConfig(c *rest.Config) (*MaistraV1Client, error) { - config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } - httpClient, err := rest.HTTPClientFor(&config) - if err != nil { - return nil, err - } - return NewForConfigAndClient(&config, httpClient) -} - -// NewForConfigAndClient creates a new MaistraV1Client for the given config and http client. -// Note the http client provided takes precedence over the configured transport values. -func NewForConfigAndClient(c *rest.Config, h *http.Client) (*MaistraV1Client, error) { - config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } - client, err := rest.RESTClientForConfigAndClient(&config, h) - if err != nil { - return nil, err - } - return &MaistraV1Client{client}, nil -} - -// NewForConfigOrDie creates a new MaistraV1Client for the given config and -// panics if there is an error in the config. -func NewForConfigOrDie(c *rest.Config) *MaistraV1Client { - client, err := NewForConfig(c) - if err != nil { - panic(err) - } - return client -} - -// New creates a new MaistraV1Client for the given RESTClient. -func New(c rest.Interface) *MaistraV1Client { - return &MaistraV1Client{c} -} - -func setConfigDefaults(config *rest.Config) error { - gv := v1.SchemeGroupVersion - config.GroupVersion = &gv - config.APIPath = "/apis" - config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() - - if config.UserAgent == "" { - config.UserAgent = rest.DefaultKubernetesUserAgent() - } - - return nil -} - -// RESTClient returns a RESTClient that is used to communicate -// with API server by this client implementation. -func (c *MaistraV1Client) RESTClient() rest.Interface { - if c == nil { - return nil - } - return c.restClient -} diff --git a/pkg/servicemesh/client/informers/externalversions/generic.go b/pkg/servicemesh/client/informers/externalversions/generic.go deleted file mode 100644 index 528bcc7f268..00000000000 --- a/pkg/servicemesh/client/informers/externalversions/generic.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright Red Hat, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by informer-gen. DO NOT EDIT. - -package externalversions - -import ( - "fmt" - - v1 "istio.io/istio/pkg/servicemesh/apis/servicemesh/v1" - schema "k8s.io/apimachinery/pkg/runtime/schema" - cache "k8s.io/client-go/tools/cache" -) - -// GenericInformer is type of SharedIndexInformer which will locate and delegate to other -// sharedInformers based on type -type GenericInformer interface { - Informer() cache.SharedIndexInformer - Lister() cache.GenericLister -} - -type genericInformer struct { - informer cache.SharedIndexInformer - resource schema.GroupResource -} - -// Informer returns the SharedIndexInformer. -func (f *genericInformer) Informer() cache.SharedIndexInformer { - return f.informer -} - -// Lister returns the GenericLister. -func (f *genericInformer) Lister() cache.GenericLister { - return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) -} - -// ForResource gives generic access to a shared informer of the matching type -// TODO extend this to unknown resources with a client pool -func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { - switch resource { - // Group=maistra.io, Version=v1 - case v1.SchemeGroupVersion.WithResource("servicemeshmemberrolls"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Maistra().V1().ServiceMeshMemberRolls().Informer()}, nil - - } - - return nil, fmt.Errorf("no informer found for %v", resource) -} diff --git a/pkg/servicemesh/controller/controller.go b/pkg/servicemesh/controller/controller.go index f9fdb3461c9..86852223732 100644 --- a/pkg/servicemesh/controller/controller.go +++ b/pkg/servicemesh/controller/controller.go @@ -22,11 +22,11 @@ import ( "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" + "maistra.io/api/client/informers/externalversions" + "maistra.io/api/client/versioned" + versioned_v1 "maistra.io/api/client/versioned/typed/core/v1" + v1 "maistra.io/api/core/v1" - v1 "istio.io/istio/pkg/servicemesh/apis/servicemesh/v1" - "istio.io/istio/pkg/servicemesh/client/clientset/versioned" - versioned_v1 "istio.io/istio/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1" - "istio.io/istio/pkg/servicemesh/client/informers/externalversions" "istio.io/pkg/log" ) @@ -69,7 +69,7 @@ func NewMemberRollController(config *rest.Config, namespace string, memberRollNa func newMemberRollSharedInformer(restClient rest.Interface, namespace string, resync time.Duration) cache.SharedIndexInformer { client := versioned.New(restClient) return externalversions.NewSharedInformerFactoryWithOptions(client, resync, - externalversions.WithNamespace(namespace)).Maistra().V1().ServiceMeshMemberRolls().Informer() + externalversions.WithNamespace(namespace)).Core().V1().ServiceMeshMemberRolls().Informer() } func (smmrc *serviceMeshMemberRollController) Start(stopCh <-chan struct{}) { diff --git a/pkg/servicemesh/federation/common/const.go b/pkg/servicemesh/federation/common/const.go new file mode 100644 index 00000000000..720be138737 --- /dev/null +++ b/pkg/servicemesh/federation/common/const.go @@ -0,0 +1,31 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "time" + + "istio.io/pkg/log" +) + +const ( + DiscoveryScheme = "http" + DefaultDiscoveryPort = 8188 + DefaultResyncPeriod = 60 * time.Second + DefaultFederationPort = 15443 + DefaultFederationRootCertName = "root-cert.pem" +) + +var Logger = log.RegisterScope("federation", "federation", 0) diff --git a/pkg/servicemesh/federation/common/exports.go b/pkg/servicemesh/federation/common/exports.go new file mode 100644 index 00000000000..36f60d02697 --- /dev/null +++ b/pkg/servicemesh/federation/common/exports.go @@ -0,0 +1,106 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "sync" + + v1 "maistra.io/api/federation/v1" + + "istio.io/istio/pilot/pkg/model" + "istio.io/istio/pilot/pkg/serviceregistry/provider" + federationmodel "istio.io/istio/pkg/servicemesh/federation/model" +) + +type ServiceExporter struct { + mu sync.RWMutex + domainSuffix string + exportConfig []NameMapper + defaultMapper NameMapper +} + +var _ NameMapper = (*ServiceExporter)(nil) + +func NewServiceExporter(exportConfig *v1.ExportedServiceSet, defaultMapper *ServiceExporter, domainSuffix string) *ServiceExporter { + return &ServiceExporter{ + domainSuffix: domainSuffix, + exportConfig: convertServiceExportsToNameMapper(exportConfig, domainSuffix), + defaultMapper: defaultMapper, + } +} + +func convertServiceExportsToNameMapper(serviceExports *v1.ExportedServiceSet, domainSuffix string) []NameMapper { + if serviceExports == nil { + return nil + } + var exportConfig []NameMapper + for index, rule := range serviceExports.Spec.ExportRules { + switch rule.Type { + case v1.LabelSelectorType: + if rule.LabelSelector == nil { + Logger.Errorf("skipping rule %d in ServiceExports %s/%s: null labelSelector", index, serviceExports.Namespace, serviceExports.Name) + continue + } + var matcher NameMapper + var err error + if matcher, err = newLabelMatcher(rule.LabelSelector, domainSuffix); err != nil { + Logger.Errorf("skipping rule %d in ServiceExports %s/%s: error creating matcher: %s", + index, serviceExports.Namespace, serviceExports.Name, err) + continue + } + exportConfig = append(exportConfig, matcher) + case v1.NameSelectorType: + if rule.NameSelector == nil { + Logger.Errorf("skipping rule %d in ServiceExports %s/%s: null nameSelector", index, serviceExports.Namespace, serviceExports.Name) + continue + } + exportConfig = append(exportConfig, newNameMatcher(rule.NameSelector, domainSuffix)) + default: + // unknown selector type + Logger.Errorf("skipping rule %d in ServiceExports %s/%s: unknown selector type %s", + rule.Type, index, serviceExports.Namespace, serviceExports.Name) + } + } + return exportConfig +} + +func (se *ServiceExporter) NameForService(svc *model.Service) *federationmodel.ServiceKey { + if se == nil { + return nil + } + // don't reexport federated services + if svc.Attributes.ServiceRegistry == provider.Federation || svc.MeshExternal { + return nil + } + se.mu.RLock() + defer se.mu.RUnlock() + for _, matcher := range se.exportConfig { + if name := matcher.NameForService(svc); name != nil { + return name + } + } + if se.defaultMapper != nil { + if name := se.defaultMapper.NameForService(svc); name != nil { + return name + } + } + return nil +} + +func (se *ServiceExporter) UpdateDefaultMapper(defaults NameMapper) { + se.mu.Lock() + defer se.mu.Unlock() + se.defaultMapper = defaults +} diff --git a/pkg/servicemesh/federation/common/imports.go b/pkg/servicemesh/federation/common/imports.go new file mode 100644 index 00000000000..7b572fba5c9 --- /dev/null +++ b/pkg/servicemesh/federation/common/imports.go @@ -0,0 +1,106 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "sync" + + v1 "maistra.io/api/federation/v1" + + "istio.io/istio/pilot/pkg/model" + federationmodel "istio.io/istio/pkg/servicemesh/federation/model" +) + +type ServiceImporter struct { + mu sync.RWMutex + domainSuffix string + importConfig []NameMapper + defaultMapper NameMapper +} + +var _ NameMapper = (*ServiceImporter)(nil) + +func NewServiceImporter(importConfig *v1.ImportedServiceSet, defaultMapper NameMapper, defaultDomainSuffix, localDomainSuffix string) *ServiceImporter { + return &ServiceImporter{ + domainSuffix: defaultDomainSuffix, + importConfig: convertServiceImportsToNameMapper(importConfig, defaultDomainSuffix, localDomainSuffix), + defaultMapper: defaultMapper, + } +} + +func convertServiceImportsToNameMapper(serviceImports *v1.ImportedServiceSet, defaultDomainSuffix, localDomainSuffix string) []NameMapper { + if serviceImports == nil { + return nil + } + if serviceImports.Spec.DomainSuffix != "" { + defaultDomainSuffix = serviceImports.Spec.DomainSuffix + } + var importConfig []NameMapper + for index, rule := range serviceImports.Spec.ImportRules { + if rule.Type != v1.NameSelectorType { + Logger.Errorf("skipping rule %d in ServiceImports %s/%s: unknown selector type %s", + rule.Type, index, serviceImports.Namespace, serviceImports.Name) + continue + } + if rule.NameSelector == nil { + Logger.Errorf("skipping rule %d in ServiceImports %s/%s: null nameSelector", index, serviceImports.Namespace, serviceImports.Name) + continue + } + ruleDomainSuffix := rule.DomainSuffix + if rule.ImportAsLocal { + if rule.NameSelector.Alias == nil || rule.NameSelector.Alias.Namespace == "" || rule.NameSelector.Alias.Namespace == v1.MatchAny { + Logger.Errorf("skipping rule %d in ServiceImports %s/%s: cannot use importAsLocal without setting a fixed namespace alias", + index, serviceImports.Namespace, serviceImports.Name) + continue + } + ruleDomainSuffix = localDomainSuffix + } else { + if ruleDomainSuffix == "" { + ruleDomainSuffix = defaultDomainSuffix + } + if ruleDomainSuffix == localDomainSuffix { + Logger.Errorf("skipping rule %d in ServiceImports %s/%s: "+ + "cannot use domainSuffix that matches the cluster domain suffix, use importAsLocal instead", + index, serviceImports.Namespace, serviceImports.Name) + continue + } + } + importConfig = append(importConfig, newNameMatcher(rule.NameSelector, ruleDomainSuffix)) + } + return importConfig +} + +func (si *ServiceImporter) NameForService(svc *model.Service) *federationmodel.ServiceKey { + if si == nil { + return nil + } + si.mu.RLock() + defer si.mu.RUnlock() + for _, matcher := range si.importConfig { + if name := matcher.NameForService(svc); name != nil { + return name + } + } + if si.defaultMapper != nil { + return si.defaultMapper.NameForService(svc) + } + return nil +} + +func (si *ServiceImporter) UpdateDefaultMapper(defaults NameMapper) { + si.mu.Lock() + defer si.mu.Unlock() + si.defaultMapper = defaults +} diff --git a/pkg/servicemesh/federation/common/namemapping.go b/pkg/servicemesh/federation/common/namemapping.go new file mode 100644 index 00000000000..e3d4fec1366 --- /dev/null +++ b/pkg/servicemesh/federation/common/namemapping.go @@ -0,0 +1,133 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + v1 "maistra.io/api/federation/v1" + + "istio.io/istio/pilot/pkg/model" + federationmodel "istio.io/istio/pkg/servicemesh/federation/model" +) + +func setHostname(name *federationmodel.ServiceKey, domainSuffix string) { + if name == nil { + return + } + name.Hostname = fmt.Sprintf("%s.%s.%s", name.Name, name.Namespace, domainSuffix) +} + +type NameMapper interface { + NameForService(svc *model.Service) *federationmodel.ServiceKey +} + +type nameMatcher struct { + domainSuffix string + match v1.ServiceName + alias *v1.ServiceName +} + +var _ NameMapper = (*nameMatcher)(nil) + +func newNameMatcher(mapping *v1.ServiceNameMapping, domainSuffix string) NameMapper { + var alias *v1.ServiceName + // if it's nil or matches anything, it may as well be nil + if mapping.Alias == nil || + ((mapping.Alias.Namespace == v1.MatchAny || mapping.Alias.Namespace == "") && + (mapping.Alias.Name == v1.MatchAny || mapping.Alias.Name == "")) { + alias = nil + } else { + alias = mapping.Alias.DeepCopy() + } + return &nameMatcher{ + domainSuffix: domainSuffix, + match: mapping.ServiceName, + alias: alias, + } +} + +func (m *nameMatcher) NameForService(svc *model.Service) *federationmodel.ServiceKey { + if (m.match.Namespace == "" || m.match.Namespace == v1.MatchAny || m.match.Namespace == svc.Attributes.Namespace) && + (m.match.Name == "" || m.match.Name == v1.MatchAny || m.match.Name == svc.Attributes.Name) { + name := &federationmodel.ServiceKey{} + if m.alias == nil { + name.Namespace = svc.Attributes.Namespace + name.Name = svc.Attributes.Name + } else { + if m.alias.Namespace == v1.MatchAny || m.alias.Namespace == "" { + name.Namespace = svc.Attributes.Namespace + } else { + name.Namespace = m.alias.Namespace + } + if m.alias.Name == v1.MatchAny || m.alias.Name == "" { + name.Name = svc.Attributes.Name + } else { + name.Name = m.alias.Name + } + } + setHostname(name, m.domainSuffix) + return name + } + return nil +} + +type labelMatcher struct { + domainSuffix string + namespace string + selector labels.Selector + aliases []NameMapper +} + +var _ NameMapper = (*labelMatcher)(nil) + +func newLabelMatcher(labelSelector *v1.ServiceImportExportLabelSelector, domainSuffix string) (NameMapper, error) { + selector, err := metav1.LabelSelectorAsSelector(&labelSelector.Selector) + if err != nil { + return nil, err + } + aliases := make([]NameMapper, len(labelSelector.Aliases)) + for index, alias := range labelSelector.Aliases { + aliases[index] = newNameMatcher(&alias, domainSuffix) + } + return &labelMatcher{ + domainSuffix: domainSuffix, + namespace: labelSelector.Namespace, + selector: selector, + aliases: aliases, + }, nil +} + +func (m *labelMatcher) NameForService(svc *model.Service) *federationmodel.ServiceKey { + if (m.namespace == "" || m.namespace == v1.MatchAny || m.namespace == svc.Attributes.Namespace) && + m.selector.Matches(labels.Set(svc.Attributes.Labels)) { + for _, alias := range m.aliases { + if name := alias.NameForService(svc); name != nil { + setHostname(name, m.domainSuffix) + return name + } + } + // if there's no alias, we return the original service name + name := &federationmodel.ServiceKey{ + Namespace: svc.Attributes.Namespace, + Name: svc.Attributes.Name, + } + setHostname(name, m.domainSuffix) + return name + } + return nil +} diff --git a/pkg/servicemesh/federation/common/options.go b/pkg/servicemesh/federation/common/options.go new file mode 100644 index 00000000000..75de691b939 --- /dev/null +++ b/pkg/servicemesh/federation/common/options.go @@ -0,0 +1,47 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "fmt" + "time" + + "k8s.io/apimachinery/pkg/util/errors" + maistraclient "maistra.io/api/client/versioned" + + "istio.io/istio/pkg/kube" +) + +type ControllerOptions struct { + KubeClient kube.Client + MaistraCS maistraclient.Interface + ResyncPeriod time.Duration + Namespace string +} + +func (opt ControllerOptions) validate() error { + var allErrors []error + if opt.KubeClient == nil { + allErrors = append(allErrors, fmt.Errorf("the KubeClient field must not be nil")) + } + if opt.MaistraCS == nil { + allErrors = append(allErrors, fmt.Errorf("the MaistraCS field must not be nil")) + } + if opt.ResyncPeriod == 0 { + opt.ResyncPeriod = DefaultResyncPeriod + Logger.WithLabels("component", "ControllerOptions").Infof("ResyncPeriod not specified, defaulting to %s", opt.ResyncPeriod) + } + return errors.NewAggregate(allErrors) +} diff --git a/pkg/servicemesh/federation/common/resources.go b/pkg/servicemesh/federation/common/resources.go new file mode 100644 index 00000000000..c0163be11e6 --- /dev/null +++ b/pkg/servicemesh/federation/common/resources.go @@ -0,0 +1,109 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "reflect" + + maistrainformersfederationv1 "maistra.io/api/client/informers/externalversions/federation/v1" + maistraclient "maistra.io/api/client/versioned" + maistraxnsinformer "maistra.io/api/client/xnsinformer" + + "istio.io/istio/pkg/kube" + memberroll "istio.io/istio/pkg/servicemesh/controller" +) + +type ResourceManager interface { + MaistraClientSet() maistraclient.Interface + KubeClient() kube.Client + PeerInformer() maistrainformersfederationv1.ServiceMeshPeerInformer + ExportsInformer() maistrainformersfederationv1.ExportedServiceSetInformer + ImportsInformer() maistrainformersfederationv1.ImportedServiceSetInformer + Start(stopCh <-chan struct{}) + HasSynced() bool + WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool +} + +func NewResourceManager(opts ControllerOptions, mrc memberroll.MemberRollController) (ResourceManager, error) { + if err := opts.validate(); err != nil { + return nil, err + } + + var informerFactory maistraxnsinformer.SharedInformerFactory + // Currently, we only watch istio system namespace for MeshFederation resources, which is why this block is disabled. + //nolint:revive + if mrc != nil && false { + informerFactory = maistraxnsinformer.NewSharedInformerFactoryWithOptions(opts.MaistraCS, opts.ResyncPeriod, maistraxnsinformer.WithNamespaces()) + mrc.Register(informerFactory, "federation") + } else { + informerFactory = maistraxnsinformer.NewSharedInformerFactoryWithOptions(opts.MaistraCS, opts.ResyncPeriod, maistraxnsinformer.WithNamespaces(opts.Namespace)) + } + rm := &resourceManager{ + mcs: opts.MaistraCS, + kc: opts.KubeClient, + inff: informerFactory, + pi: informerFactory.Federation().V1().ServiceMeshPeers(), + sei: informerFactory.Federation().V1().ExportedServiceSets(), + sii: informerFactory.Federation().V1().ImportedServiceSets(), + } + // create the informers now, so they're registered with the factory + rm.pi.Informer() + rm.sei.Informer() + rm.sii.Informer() + return rm, nil +} + +type resourceManager struct { + mcs maistraclient.Interface + kc kube.Client + inff maistraxnsinformer.SharedInformerFactory + pi maistrainformersfederationv1.ServiceMeshPeerInformer + sei maistrainformersfederationv1.ExportedServiceSetInformer + sii maistrainformersfederationv1.ImportedServiceSetInformer +} + +var _ ResourceManager = (*resourceManager)(nil) + +func (rm *resourceManager) MaistraClientSet() maistraclient.Interface { + return rm.mcs +} + +func (rm *resourceManager) KubeClient() kube.Client { + return rm.kc +} + +func (rm *resourceManager) Start(stopCh <-chan struct{}) { + rm.inff.Start(stopCh) +} + +func (rm *resourceManager) HasSynced() bool { + return rm.pi.Informer().HasSynced() && rm.sei.Informer().HasSynced() && rm.sii.Informer().HasSynced() +} + +func (rm *resourceManager) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + return rm.inff.WaitForCacheSync(stopCh) +} + +func (rm *resourceManager) PeerInformer() maistrainformersfederationv1.ServiceMeshPeerInformer { + return rm.pi +} + +func (rm *resourceManager) ExportsInformer() maistrainformersfederationv1.ExportedServiceSetInformer { + return rm.sei +} + +func (rm *resourceManager) ImportsInformer() maistrainformersfederationv1.ImportedServiceSetInformer { + return rm.sii +} diff --git a/pkg/servicemesh/federation/common/testing.go b/pkg/servicemesh/federation/common/testing.go new file mode 100644 index 00000000000..52565363a85 --- /dev/null +++ b/pkg/servicemesh/federation/common/testing.go @@ -0,0 +1,73 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import federationmodel "istio.io/istio/pkg/servicemesh/federation/model" + +type FakeStatusHandler struct{} + +// Outbound connections +func (m *FakeStatusHandler) WatchInitiated() { +} + +func (m *FakeStatusHandler) Watching() { +} + +func (m *FakeStatusHandler) WatchEventReceived() { +} + +func (m *FakeStatusHandler) FullSyncComplete() { +} + +func (m *FakeStatusHandler) WatchTerminated(status string) { +} + +// Inbound connections +func (m *FakeStatusHandler) RemoteWatchAccepted(source string) { +} + +func (m *FakeStatusHandler) WatchEventSent(source string) { +} + +func (m *FakeStatusHandler) FullSyncSent(source string) { +} + +func (m *FakeStatusHandler) RemoteWatchTerminated(source string) { +} + +// Exports +func (m *FakeStatusHandler) ExportAdded(service federationmodel.ServiceKey, exportedName string) { +} + +func (m *FakeStatusHandler) ExportUpdated(service federationmodel.ServiceKey, exportedName string) { +} + +func (m *FakeStatusHandler) ExportRemoved(service federationmodel.ServiceKey) { +} + +// Imports +func (m *FakeStatusHandler) ImportAdded(service federationmodel.ServiceKey, exportedName string) { +} + +func (m *FakeStatusHandler) ImportUpdated(service federationmodel.ServiceKey, exportedName string) { +} + +func (m *FakeStatusHandler) ImportRemoved(exportedName string) { +} + +// Write status +func (m *FakeStatusHandler) Flush() error { + return nil +} diff --git a/pkg/servicemesh/federation/common/util.go b/pkg/servicemesh/federation/common/util.go new file mode 100644 index 00000000000..ce128e85e14 --- /dev/null +++ b/pkg/servicemesh/federation/common/util.go @@ -0,0 +1,82 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package common + +import ( + "fmt" + + "github.com/mitchellh/hashstructure/v2" + corev1 "k8s.io/api/core/v1" + kubelabels "k8s.io/apimachinery/pkg/labels" + v1 "maistra.io/api/federation/v1" + + "istio.io/istio/pkg/kube" + "istio.io/istio/pkg/spiffe" +) + +// DiscoveryServiceHostname returns the hostname used to represent a remote's +// discovery service in the local mesh. +func DiscoveryServiceHostname(instance *v1.ServiceMeshPeer) string { + return fmt.Sprintf("discovery.%s.svc.%s.local", instance.Namespace, instance.Name) +} + +// DefaultFederationCARootResourceName is the default name used for the resource +// containing the root CA for a remote mesh. +func DefaultFederationCARootResourceName(instance *v1.ServiceMeshPeer) string { + return fmt.Sprintf("%s-ca-root-cert", instance.Name) +} + +// EndpointsForService returns the Endpoints for the named service. +func EndpointsForService(client kube.Client, name, namespace string) (*corev1.Endpoints, error) { + return client.KubeInformer().Core().V1().Endpoints().Lister().Endpoints(namespace).Get(name) +} + +// ServiceAccountsForService returns a list of service account names used by all +// pods implementing the service. +func ServiceAccountsForService(client kube.Client, name, namespace string) (map[string]string, error) { + serviceAccountByIP := map[string]string{} + service, err := client.KubeInformer().Core().V1().Services().Lister().Services(namespace).Get(name) + if err != nil { + return serviceAccountByIP, err + } + + pods, err := client.KubeInformer().Core().V1().Pods().Lister().Pods(namespace). + List(kubelabels.Set(service.Spec.Selector).AsSelector()) + if err != nil { + return serviceAccountByIP, err + } + + for _, pod := range pods { + if pod.Status.PodIP == "" { + continue + } + sa := pod.Spec.ServiceAccountName + if sa == "" { + sa = "default" + } + sa = spiffe.MustGenSpiffeURI(namespace, sa) + serviceAccountByIP[pod.Status.PodIP] = sa + Logger.Debugf("using ServiceAccount %s for gateway pod %s/%s", sa, pod.Namespace, pod.Name) + } + return serviceAccountByIP, nil +} + +func RemoteChecksum(remote v1.ServiceMeshPeerRemote) uint64 { + checksum, err := hashstructure.Hash(remote, hashstructure.FormatV2, &hashstructure.HashOptions{SlicesAsSets: true}) + if err != nil { + return 0 + } + return checksum +} diff --git a/pkg/servicemesh/federation/discovery/controller.go b/pkg/servicemesh/federation/discovery/controller.go new file mode 100644 index 00000000000..087b974bfb1 --- /dev/null +++ b/pkg/servicemesh/federation/discovery/controller.go @@ -0,0 +1,362 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package discovery + +import ( + "context" + "fmt" + "sync" + "time" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/federation/v1" + + "istio.io/istio/pilot/pkg/model" + "istio.io/istio/pilot/pkg/serviceregistry" + "istio.io/istio/pilot/pkg/serviceregistry/aggregate" + federationregistry "istio.io/istio/pilot/pkg/serviceregistry/federation" + "istio.io/istio/pilot/pkg/serviceregistry/provider" + "istio.io/istio/pkg/cluster" + kubecontroller "istio.io/istio/pkg/kube/controller" + "istio.io/istio/pkg/servicemesh/federation/common" + "istio.io/istio/pkg/servicemesh/federation/server" + "istio.io/istio/pkg/servicemesh/federation/status" +) + +const controllerName = "federation-discovery-controller" + +type Options struct { + ResourceManager common.ResourceManager + ResyncPeriod time.Duration + ServiceController *aggregate.Controller + XDSUpdater model.XDSUpdater + Env *model.Environment + ConfigStore model.ConfigStoreController + FederationManager server.FederationManager + StatusManager status.Manager + LocalNetwork string + LocalClusterID string +} + +type Controller struct { + *kubecontroller.Controller + model.ConfigStoreController + localNetwork string + localClusterID string + rm common.ResourceManager + env *model.Environment + federationManager server.FederationManager + statusManager status.Manager + sc *aggregate.Controller + xds model.XDSUpdater + mu sync.Mutex + stopChannels map[cluster.ID]chan struct{} + trustBundles map[string]string +} + +var ( + _ model.ConfigStore = (*Controller)(nil) + _ model.ConfigStoreController = (*Controller)(nil) +) + +// NewController creates a new Aggregate controller +func NewController(opt Options) (*Controller, error) { + if err := opt.validate(); err != nil { + return nil, err + } + + logger := common.Logger.WithLabels("component", controllerName) + + controller := &Controller{ + ConfigStoreController: opt.ConfigStore, + localClusterID: opt.LocalClusterID, + localNetwork: opt.LocalNetwork, + rm: opt.ResourceManager, + env: opt.Env, + sc: opt.ServiceController, + stopChannels: make(map[cluster.ID]chan struct{}), + xds: opt.XDSUpdater, + federationManager: opt.FederationManager, + statusManager: opt.StatusManager, + trustBundles: map[string]string{}, + } + internalController := kubecontroller.NewController(kubecontroller.Options{ + Informer: opt.ResourceManager.PeerInformer().Informer(), + Logger: logger, + ResyncPeriod: opt.ResyncPeriod, + Reconciler: controller.reconcile, + }) + controller.Controller = internalController + + return controller, nil +} + +func (c *Controller) Run(stopChan <-chan struct{}) { + c.Controller.Start(stopChan) + c.mu.Lock() + defer c.mu.Unlock() + for _, registryStopCh := range c.stopChannels { + close(registryStopCh) + } +} + +func (c *Controller) HasSynced() bool { + return c.Controller.HasSynced() +} + +func (c *Controller) RunInformer(_ <-chan struct{}) { + // no-op, informer is started by the shared factory in Federation.Start() +} + +func (c *Controller) reconcile(resourceName string) error { + c.Logger.Debugf("Reconciling ServiceMeshPeer %s", resourceName) + defer func() { + if err := c.statusManager.PushStatus(); err != nil { + c.Logger.Errorf("error pushing FederationStatus for mesh %s: %s", resourceName, err) + } + c.Logger.Debugf("Completed reconciliation of ServiceMeshPeer %s", resourceName) + }() + + ctx := context.TODO() + + namespace, name, err := cache.SplitMetaNamespaceKey(resourceName) + if err != nil { + c.Logger.Errorf("error splitting resource name: %s", resourceName) + } + instance, err := c.rm.PeerInformer().Lister().ServiceMeshPeers(namespace).Get(name) + if err != nil { + if apierrors.IsNotFound(err) || apierrors.IsGone(err) { + // Request object not found, could have been deleted after reconcile request. + // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. + // Return and don't requeue + err = c.delete(ctx, &v1.ServiceMeshPeer{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + }) + if err == nil { + c.Logger.Info("ServiceMeshPeer deleted") + } + } + // Error reading the object + return err + } + + return c.update(ctx, instance) +} + +func (c *Controller) update(ctx context.Context, instance *v1.ServiceMeshPeer) error { + registry := c.getRegistry(cluster.ID(instance.Name)) + if instance.Spec.Security.TrustDomain != "" && instance.Spec.Security.TrustDomain != c.env.Mesh().GetTrustDomain() { + rootCert, err := c.getRootCertForMesh(instance) + if err != nil { + return fmt.Errorf("could not get root cert for mesh %s: %v", instance.Name, err.Error()) + } + c.updateRootCert(instance.Spec.Security.TrustDomain, rootCert) + } + + if err := c.createDiscoveryResources(ctx, instance, c.env.Mesh()); err != nil { + return err + } + + importConfig, err := c.rm.ImportsInformer().Lister().ImportedServiceSets(instance.Namespace).Get(instance.Name) + if err != nil && !(apierrors.IsNotFound(err) || apierrors.IsGone(err)) { + c.Logger.Errorf("error retrieving ServiceImports associated with ServiceMeshPeer %s: %s", instance.Name, err) + return err + } + + // check for existing registry + if registry != nil { + // if there's an existing registry, make sure it's one of ours + if registry.Provider() != provider.Federation { + return fmt.Errorf( + "cannot create Federation registry for %s, registry exists and belongs to another provider (%s)", + instance.Name, registry.Provider()) + } + if federationRegistry, ok := registry.(*federationregistry.Controller); ok { + c.Logger.Debugf("updating settings for ServiceMeshPeer %s", instance.Name) + federationRegistry.UpdatePeerConfig(instance) + federationRegistry.UpdateImportConfig(importConfig) + } else { + return fmt.Errorf("registry %s is not a Federation registry (type=%T)", instance.Name, registry) + } + } else { + // if there's no existing registry + exportConfig, err := c.rm.ExportsInformer().Lister().ExportedServiceSets(instance.Namespace).Get(instance.Name) + if err != nil && !(apierrors.IsNotFound(err) || apierrors.IsGone(err)) { + c.Logger.Errorf("error retrieving ServiceExports associated with ServiceMeshPeer %s: %s", instance.Name, err) + return err + } + statusHandler := c.statusManager.PeerAdded(types.NamespacedName{Name: instance.Name, Namespace: instance.Namespace}) + if err := c.federationManager.AddPeer(instance, exportConfig, statusHandler); err != nil { + return err + } + c.Logger.Infof("initializing Federation service registry for %q at %s", instance.Name, instance.Spec.Remote.Addresses) + // create a registry instance + options := federationregistry.Options{ + KubeClient: c.rm.KubeClient(), + ConfigStore: c.ConfigStoreController, + StatusHandler: statusHandler, + XDSUpdater: c.xds, + ResyncPeriod: time.Minute * 5, + DomainSuffix: c.env.DomainSuffix, + LocalClusterID: c.localClusterID, + LocalNetwork: c.localNetwork, + ClusterID: instance.Name, + Network: fmt.Sprintf("network-%s", instance.Name), + } + registry = federationregistry.NewController(options, instance, importConfig) + // register the new instance + c.sc.AddRegistry(registry) + + stopCh := make(chan struct{}) + c.mu.Lock() + defer c.mu.Unlock() + c.stopChannels[cluster.ID(instance.Name)] = stopCh + go registry.Run(stopCh) + } + + return nil +} + +func (c *Controller) delete(ctx context.Context, instance *v1.ServiceMeshPeer) error { + var allErrors []error + // delete the server + c.federationManager.DeletePeer(instance.Name) + + // delete trust bundle + if instance.Spec.Security.TrustDomain != "" { + c.updateRootCert(instance.Spec.Security.TrustDomain, "") + } + + // delete the registry + registry := c.getRegistry(cluster.ID(instance.Name)) + if registry != nil { + // make sure it's one of ours + if registry.Provider() == provider.Federation { + // unregister federation registry + c.Logger.Infof("Removing registry for Federation cluster %s", instance.Name) + c.sc.DeleteRegistry(registry.Cluster(), provider.Federation) + c.mu.Lock() + defer c.mu.Unlock() + if registryStopCh := c.stopChannels[registry.Cluster()]; registryStopCh != nil { + close(registryStopCh) + delete(c.stopChannels, registry.Cluster()) + } + } else { + allErrors = append(allErrors, + fmt.Errorf("cannot delete Federation registry for %s, registry belongs to another provider (%s)", + instance.Name, registry.Provider())) + } + } + + if err := c.deleteDiscoveryResources(ctx, instance); err != nil { + allErrors = append(allErrors, err) + } + + c.statusManager.PeerDeleted(types.NamespacedName{Name: instance.Name, Namespace: instance.Namespace}) + + return utilerrors.NewAggregate(allErrors) +} + +func (c *Controller) getRegistry(clusterID cluster.ID) serviceregistry.Instance { + for _, registry := range c.sc.GetRegistries() { + if registry.Cluster() == clusterID { + return c.sc.Unwrap(registry) + } + } + return nil +} + +func (opt Options) validate() error { + var allErrors []error + if opt.ResourceManager == nil { + allErrors = append(allErrors, fmt.Errorf("the ResourceManager field must not be nil")) + } + if opt.ServiceController == nil { + allErrors = append(allErrors, fmt.Errorf("the ServiceController field must not be nil")) + } + if opt.XDSUpdater == nil { + allErrors = append(allErrors, fmt.Errorf("the XDSUpdater field must not be nil")) + } + if opt.Env == nil { + allErrors = append(allErrors, fmt.Errorf("the Env field must not be nil")) + } + if opt.FederationManager == nil { + allErrors = append(allErrors, fmt.Errorf("the FederationManager field must not be nil")) + } + if opt.ResyncPeriod == 0 { + opt.ResyncPeriod = common.DefaultResyncPeriod + common.Logger.WithLabels("component", controllerName).Warnf("ResyncPeriod not specified, defaulting to %s", opt.ResyncPeriod) + } + return utilerrors.NewAggregate(allErrors) +} + +func (c *Controller) getRootCertForMesh(instance *v1.ServiceMeshPeer) (string, error) { + if instance == nil { + return "", nil + } + name := instance.Spec.Security.CertificateChain.Name + if name == "" { + name = common.DefaultFederationCARootResourceName(instance) + } + entryKey := common.DefaultFederationRootCertName + switch instance.Spec.Security.CertificateChain.Kind { + case "", "ConfigMap": + cm, err := c.rm.KubeClient().KubeInformer().Core().V1().ConfigMaps().Lister().ConfigMaps(instance.Namespace).Get(name) + if err != nil { + return "", fmt.Errorf("error getting configmap %s in namespace %s: %v", name, instance.Namespace, err) + } + if cert, exists := cm.Data[entryKey]; exists { + return cert, nil + } + return "", fmt.Errorf("missing entry %s in ConfigMap %s/%s", entryKey, instance.Namespace, name) + default: + return "", fmt.Errorf("unknown Kind for CertificateChain object reference: %s", instance.Spec.Security.CertificateChain.Kind) + } +} + +func (c *Controller) updateRootCert(trustDomain string, rootCert string) { + c.mu.Lock() + defer c.mu.Unlock() + if rootCert == "" { + delete(c.trustBundles, trustDomain) + } else if existingCert, ok := c.trustBundles[trustDomain]; !ok || existingCert != rootCert { + c.trustBundles[trustDomain] = rootCert + } else { + // we didn't update the trust bundles, so we return early without pushing + return + } + c.xds.ConfigUpdate(&model.PushRequest{ + Full: true, + Reason: []model.TriggerReason{model.GlobalUpdate}, + }) +} + +func (c *Controller) GetTrustBundles() map[string]string { + c.mu.Lock() + defer c.mu.Unlock() + // make a copy + ret := map[string]string{} + for td, cert := range c.trustBundles { + ret[td] = cert + } + return ret +} diff --git a/pkg/servicemesh/federation/discovery/controller_test.go b/pkg/servicemesh/federation/discovery/controller_test.go new file mode 100644 index 00000000000..b0b8f53efd3 --- /dev/null +++ b/pkg/servicemesh/federation/discovery/controller_test.go @@ -0,0 +1,383 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package discovery + +import ( + "context" + "fmt" + "reflect" + "testing" + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/cache" + maistrainformersfederationv1 "maistra.io/api/client/informers/externalversions/federation/v1" + maistraclient "maistra.io/api/client/versioned" + "maistra.io/api/client/versioned/fake" + v1 "maistra.io/api/federation/v1" + + "istio.io/api/mesh/v1alpha1" + configmemory "istio.io/istio/pilot/pkg/config/memory" + "istio.io/istio/pilot/pkg/model" + "istio.io/istio/pilot/pkg/networking/core/v1alpha3" + "istio.io/istio/pilot/pkg/serviceregistry/aggregate" + "istio.io/istio/pkg/cluster" + "istio.io/istio/pkg/config/mesh" + "istio.io/istio/pkg/config/schema/collections" + "istio.io/istio/pkg/kube" + "istio.io/istio/pkg/servicemesh/federation/common" + "istio.io/istio/pkg/servicemesh/federation/status" +) + +type fakeManager struct{} + +func (m *fakeManager) AddPeer(_ *v1.ServiceMeshPeer, _ *v1.ExportedServiceSet, _ status.Handler) error { + return nil +} +func (m *fakeManager) DeletePeer(_ string) {} +func (m *fakeManager) UpdateExportsForMesh(_ *v1.ExportedServiceSet) error { + return nil +} +func (m *fakeManager) DeleteExportsForMesh(_ string) {} + +type fakeStatusManager struct{} + +func (m *fakeStatusManager) IsLeader() bool { + return true +} + +func (m *fakeStatusManager) PeerAdded(mesh types.NamespacedName) status.Handler { + return &common.FakeStatusHandler{} +} + +func (m *fakeStatusManager) PeerDeleted(mesh types.NamespacedName) { +} + +func (m *fakeStatusManager) HandlerFor(mesh types.NamespacedName) status.Handler { + return &common.FakeStatusHandler{} +} + +func (m *fakeStatusManager) PushStatus() error { + return nil +} + +type fakeResourceManager struct{} + +func (m *fakeResourceManager) MaistraClientSet() maistraclient.Interface { + panic("not implemented") // TODO: Implement +} + +func (m *fakeResourceManager) KubeClient() kube.Client { + panic("not implemented") // TODO: Implement +} + +func (m *fakeResourceManager) PeerInformer() maistrainformersfederationv1.ServiceMeshPeerInformer { + panic("not implemented") // TODO: Implement +} + +func (m *fakeResourceManager) ExportsInformer() maistrainformersfederationv1.ExportedServiceSetInformer { + panic("not implemented") // TODO: Implement +} + +func (m *fakeResourceManager) ImportsInformer() maistrainformersfederationv1.ImportedServiceSetInformer { + panic("not implemented") // TODO: Implement +} + +func (m *fakeResourceManager) Start(stopCh <-chan struct{}) { + panic("not implemented") // TODO: Implement +} + +func (m *fakeResourceManager) HasSynced() bool { + panic("not implemented") // TODO: Implement +} + +func (m *fakeResourceManager) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + panic("not implemented") // TODO: Implement +} + +func TestValidOptions(t *testing.T) { + opt := Options{ + ResourceManager: &fakeResourceManager{}, + ServiceController: &aggregate.Controller{}, + XDSUpdater: &v1alpha3.FakeXdsUpdater{}, + Env: &model.Environment{}, + FederationManager: &fakeManager{}, + } + if err := opt.validate(); err != nil { + t.Errorf("unexpected error") + } +} + +func TestInvalidOptions(t *testing.T) { + testCases := []struct { + name string + opt Options + }{ + { + name: "resource-manager", + opt: Options{ + ResourceManager: nil, + ServiceController: &aggregate.Controller{}, + XDSUpdater: &v1alpha3.FakeXdsUpdater{}, + Env: &model.Environment{}, + }, + }, + { + name: "service-controller", + opt: Options{ + ResourceManager: &fakeResourceManager{}, + ServiceController: nil, + XDSUpdater: &v1alpha3.FakeXdsUpdater{}, + Env: &model.Environment{}, + }, + }, + { + name: "xds-updater", + opt: Options{ + ResourceManager: &fakeResourceManager{}, + ServiceController: &aggregate.Controller{}, + XDSUpdater: nil, + Env: &model.Environment{}, + }, + }, + { + name: "env", + opt: Options{ + ResourceManager: &fakeResourceManager{}, + ServiceController: &aggregate.Controller{}, + XDSUpdater: &v1alpha3.FakeXdsUpdater{}, + Env: nil, + }, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if _, err := NewController(tc.opt); err == nil { + t.Errorf("expected error") + } + }) + } +} + +type options struct { + client kube.Client + serviceController *aggregate.Controller + xdsUpdater *v1alpha3.FakeXdsUpdater + env *model.Environment +} + +func newTestOptions(discoveryAddress string) options { + client := kube.NewFakeClient() + meshConfig := &v1alpha1.MeshConfig{ + DefaultConfig: &v1alpha1.ProxyConfig{ + DiscoveryAddress: discoveryAddress, + }, + } + meshWatcher := mesh.NewFixedWatcher(meshConfig) + serviceController := aggregate.NewController(aggregate.Options{ + MeshHolder: meshWatcher, + }) + xdsUpdater := &v1alpha3.FakeXdsUpdater{} + env := &model.Environment{ + ServiceDiscovery: serviceController, + Watcher: meshWatcher, + } + return options{ + client: client, + serviceController: serviceController, + xdsUpdater: xdsUpdater, + env: env, + } +} + +func TestReconcile(t *testing.T) { + name := "test" + namespace := "test" + resyncPeriod := 30 * time.Second + options := newTestOptions("test.address") + kubeClient := kube.NewFakeClient( + &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "dummy", + Namespace: namespace, + }, + Data: map[string]string{ + "root-cert.pem": "dummy-cert-pem", + }, + }, + ) + rm, err := common.NewResourceManager(common.ControllerOptions{ + KubeClient: kubeClient, + MaistraCS: fake.NewSimpleClientset(), + ResyncPeriod: resyncPeriod, + Namespace: namespace, + }, nil) + if err != nil { + t.Fatalf("unable to create ResourceManager: %s", err) + } + controller, err := NewController(Options{ + ResourceManager: rm, + ResyncPeriod: resyncPeriod, + ServiceController: options.serviceController, + XDSUpdater: options.xdsUpdater, + Env: options.env, + FederationManager: &fakeManager{}, + StatusManager: &fakeStatusManager{}, + ConfigStore: configmemory.NewController(configmemory.Make(Schemas)), + }) + if err != nil { + t.Fatalf("unable to create Controller: %s", err) + } + + federation := &v1.ServiceMeshPeer{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Spec: v1.ServiceMeshPeerSpec{ + Remote: v1.ServiceMeshPeerRemote{ + Addresses: []string{"test.mesh"}, + }, + Gateways: v1.ServiceMeshPeerGateways{ + Ingress: corev1.LocalObjectReference{ + Name: "test-ingress", + }, + Egress: corev1.LocalObjectReference{ + Name: "test-egress", + }, + }, + Security: v1.ServiceMeshPeerSecurity{ + ClientID: "cluster.local/ns/test-mesh/sa/test-egress-service-account", + TrustDomain: "test.local", + CertificateChain: corev1.TypedLocalObjectReference{ + Name: "dummy", + }, + AllowDirectInbound: false, + AllowDirectOutbound: false, + }, + }, + } + stopCh := make(chan struct{}) + defer close(stopCh) + go rm.Start(stopCh) + go kubeClient.KubeInformer().Core().V1().ConfigMaps().Informer().Run(stopCh) + for !kubeClient.KubeInformer().Core().V1().ConfigMaps().Informer().HasSynced() { + } + fedAdded := make(chan struct{}) + fedDeleted := make(chan struct{}) + rm.PeerInformer().Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + close(fedAdded) + }, + DeleteFunc: func(obj interface{}) { + close(fedDeleted) + }, + }) + cs := rm.MaistraClientSet() + newFederation, err := cs.FederationV1().ServiceMeshPeers(namespace).Create(context.TODO(), federation, metav1.CreateOptions{}) + if err != nil { + t.Errorf("failed to create ServiceMeshPeer") + return + } + // wait for object to show up + select { + case <-fedAdded: + case <-time.After(5 * time.Second): + t.Fatalf("timed out waiting for watch event") + } + if err := controller.reconcile(fmt.Sprintf("%s/%s", namespace, name)); err != nil { + t.Fatalf("unexpected error reconciling new ServiceMeshPeer: %s", err) + } + // verify registry has been created + if controller.getRegistry(cluster.ID(newFederation.Name)) == nil { + t.Errorf("failed to create service registry for federation") + } + // verify resources have been created + if resource := controller.Get(collections.IstioNetworkingV1Alpha3Serviceentries.Resource().GroupVersionKind(), + discoveryResourceName(federation), namespace); resource == nil { + t.Errorf("resource doesn't exist") + } + if resource := controller.Get(collections.IstioNetworkingV1Alpha3Virtualservices.Resource().GroupVersionKind(), + discoveryEgressResourceName(federation), namespace); resource == nil { + t.Errorf("resource doesn't exist") + } + if resource := controller.Get(collections.IstioNetworkingV1Alpha3Virtualservices.Resource().GroupVersionKind(), + discoveryIngressResourceName(federation), namespace); resource == nil { + t.Errorf("resource doesn't exist") + } + if resource := controller.Get(collections.IstioNetworkingV1Alpha3Gateways.Resource().GroupVersionKind(), + discoveryIngressResourceName(federation), namespace); resource == nil { + t.Errorf("resource doesn't exist") + } + if resource := controller.Get(collections.IstioNetworkingV1Alpha3Gateways.Resource().GroupVersionKind(), + discoveryEgressResourceName(federation), namespace); resource == nil { + t.Errorf("resource doesn't exist") + } + if resource := controller.Get(collections.IstioNetworkingV1Alpha3Destinationrules.Resource().GroupVersionKind(), + discoveryEgressResourceName(federation), namespace); resource == nil { + t.Errorf("resource doesn't exist") + } + if resource := controller.Get(collections.IstioSecurityV1Beta1Authorizationpolicies.Resource().GroupVersionKind(), + discoveryResourceName(federation), namespace); resource == nil { + t.Errorf("resource doesn't exist") + } + + // now delete + if err = cs.FederationV1().ServiceMeshPeers(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{}); err != nil { + t.Errorf("error deleting ServiceMeshPeer") + return + } + + // wait for deletion to show up + select { + case <-fedDeleted: + case <-time.After(5 * time.Second): + t.Fatalf("timed out waiting for watch event") + } + + if err := controller.reconcile(fmt.Sprintf("%s/%s", namespace, name)); err != nil { + t.Errorf("unexpected error reconciling new ServiceMeshPeer: %#v", err) + } + // verify registry has been deleted + if controller.getRegistry(cluster.ID(newFederation.Name)) != nil { + t.Errorf("failed to delete service registry for federation") + } + // verify resources have been deleted + if resource := controller.Get(collections.IstioNetworkingV1Alpha3Serviceentries.Resource().GroupVersionKind(), + discoveryResourceName(federation), namespace); resource != nil { + t.Errorf("resource not deleted") + } + if resource := controller.Get(collections.IstioNetworkingV1Alpha3Virtualservices.Resource().GroupVersionKind(), + discoveryResourceName(federation), namespace); resource != nil { + t.Errorf("resource not deleted") + } + if resource := controller.Get(collections.IstioNetworkingV1Alpha3Gateways.Resource().GroupVersionKind(), + discoveryIngressResourceName(federation), namespace); resource != nil { + t.Errorf("resource not deleted") + } + if resource := controller.Get(collections.IstioNetworkingV1Alpha3Gateways.Resource().GroupVersionKind(), + discoveryEgressResourceName(federation), namespace); resource != nil { + t.Errorf("resource not deleted") + } + if resource := controller.Get(collections.IstioNetworkingV1Alpha3Destinationrules.Resource().GroupVersionKind(), + discoveryResourceName(federation), namespace); resource != nil { + t.Errorf("resource not deleted") + } + if resource := controller.Get(collections.IstioSecurityV1Beta1Authorizationpolicies.Resource().GroupVersionKind(), + discoveryResourceName(federation), namespace); resource != nil { + t.Errorf("resource not deleted") + } +} diff --git a/pkg/servicemesh/federation/discovery/discovery.go b/pkg/servicemesh/federation/discovery/discovery.go new file mode 100644 index 00000000000..359df3796f9 --- /dev/null +++ b/pkg/servicemesh/federation/discovery/discovery.go @@ -0,0 +1,664 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package discovery + +import ( + "context" + "errors" + "fmt" + "strconv" + "strings" + + utilerrors "k8s.io/apimachinery/pkg/util/errors" + v1 "maistra.io/api/federation/v1" + + meshv1alpha1 "istio.io/api/mesh/v1alpha1" + rawnetworking "istio.io/api/networking/v1alpha3" + rawsecurity "istio.io/api/security/v1beta1" + rawtype "istio.io/api/type/v1beta1" + "istio.io/istio/pilot/pkg/config/kube/ior" + "istio.io/istio/pkg/config" + "istio.io/istio/pkg/config/schema/collection" + "istio.io/istio/pkg/config/schema/collections" + "istio.io/istio/pkg/servicemesh/federation/common" +) + +func init() { + schemasBuilder := collection.NewSchemasBuilder() + schemasBuilder.MustAdd(collections.IstioNetworkingV1Alpha3Destinationrules) + schemasBuilder.MustAdd(collections.IstioNetworkingV1Alpha3Virtualservices) + schemasBuilder.MustAdd(collections.IstioNetworkingV1Alpha3Gateways) + schemasBuilder.MustAdd(collections.IstioSecurityV1Beta1Authorizationpolicies) + // XXX: we should consider adding this directly to the service registry + schemasBuilder.MustAdd(collections.IstioNetworkingV1Alpha3Serviceentries) + Schemas = schemasBuilder.Build() +} + +const generationAnnotation = "reconciledGeneration" + +var Schemas collection.Schemas + +// only to facilitate processing errors from the store +type notFoundErrorChecker struct{} + +func (e *notFoundErrorChecker) Error() string { + return "item not found" +} + +func (e *notFoundErrorChecker) Is(other error) bool { + return other.Error() == "item not found" || strings.HasSuffix(other.Error(), "does not exist") +} + +var memoryStoreErrNotFound = ¬FoundErrorChecker{} + +func (c *Controller) deleteDiscoveryResources( + _ context.Context, instance *v1.ServiceMeshPeer, +) error { + c.Logger.Infof("deleting discovery resources for Federation cluster %s", instance.Name) + var allErrors []error + rootName := discoveryResourceName(instance) + egressName := discoveryEgressResourceName(instance) + ingressName := discoveryIngressResourceName(instance) + // XXX: the only errors possible on delete are "does not exist" and "unknown + // type", so maybe we should just skip error checking? + if err := c.Delete(collections.IstioNetworkingV1Alpha3Serviceentries.Resource().GroupVersionKind(), + rootName, instance.Namespace, nil); err != nil && !errors.Is(memoryStoreErrNotFound, err) { + c.Logger.Errorf("error deleting discovery Service %s for Federation cluster %s: %s", + rootName, instance.Name, err) + allErrors = append(allErrors, err) + } + if err := c.Delete(collections.IstioNetworkingV1Alpha3Virtualservices.Resource().GroupVersionKind(), + ingressName, instance.Namespace, nil); err != nil && !errors.Is(err, memoryStoreErrNotFound) { + c.Logger.Errorf("error deleting discovery ingress VirtualService %s for Federation cluster %s: %s", + ingressName, instance.Name, err) + allErrors = append(allErrors, err) + } + if err := c.Delete(collections.IstioNetworkingV1Alpha3Virtualservices.Resource().GroupVersionKind(), + egressName, instance.Namespace, nil); err != nil && !errors.Is(err, memoryStoreErrNotFound) { + c.Logger.Errorf("error deleting discovery egress VirtualService %s for Federation cluster %s: %s", + egressName, instance.Name, err) + allErrors = append(allErrors, err) + } + if err := c.Delete(collections.IstioNetworkingV1Alpha3Gateways.Resource().GroupVersionKind(), + ingressName, instance.Namespace, nil); err != nil && !errors.Is(memoryStoreErrNotFound, err) { + c.Logger.Errorf("error deleting discovery ingress Gateway %s for Federation cluster %s: %s", + ingressName, instance.Name, err) + allErrors = append(allErrors, err) + } + if err := c.Delete(collections.IstioNetworkingV1Alpha3Gateways.Resource().GroupVersionKind(), + egressName, instance.Namespace, nil); err != nil && !errors.Is(memoryStoreErrNotFound, err) { + c.Logger.Errorf("error deleting discovery egress Gateway %s for Federation cluster %s: %s", + egressName, instance.Name, err) + allErrors = append(allErrors, err) + } + if err := c.Delete(collections.IstioNetworkingV1Alpha3Destinationrules.Resource().GroupVersionKind(), + egressName, instance.Namespace, nil); err != nil && !errors.Is(err, memoryStoreErrNotFound) { + c.Logger.Errorf("error deleting discovery DestinationRule %s for Federation cluster %s: %s", + egressName, instance.Name, err) + allErrors = append(allErrors, err) + } + if err := c.Delete(collections.IstioSecurityV1Beta1Authorizationpolicies.Resource().GroupVersionKind(), + rootName, instance.Namespace, nil); err != nil && !errors.Is(memoryStoreErrNotFound, err) { + c.Logger.Errorf("error deleting discovery AuthorizationPolicy %s for Federation cluster %s: %s", + rootName, instance.Name, err) + allErrors = append(allErrors, err) + } + return utilerrors.NewAggregate(allErrors) +} + +func (c *Controller) createDiscoveryResources( + _ context.Context, instance *v1.ServiceMeshPeer, meshConfig *meshv1alpha1.MeshConfig, +) (err error) { + var s, ap, dr, ig, eg, evs, ivs *config.Config + + defer func() { + if err != nil { + c.Logger.Errorf("error creating discovery configuration for Federation cluster %s: %s", instance.Name, err) + c.Logger.Infof("rolling back discovery Service for %s", instance.Name) + if s != nil { + if newErr := c.Delete(collections.IstioNetworkingV1Alpha3Serviceentries.Resource().GroupVersionKind(), + s.Name, s.Namespace, nil); newErr != nil && !errors.Is(newErr, memoryStoreErrNotFound) { + c.Logger.Errorf("error deleting discovery Service %s: %s", s.Name, newErr) + } + } + c.Logger.Infof("rolling back discovery AuthorizationPolicy for Federation cluster %s", instance.Name) + if ap != nil { + if newErr := c.Delete(collections.IstioSecurityV1Beta1Authorizationpolicies.Resource().GroupVersionKind(), + ap.Name, ap.Namespace, nil); newErr != nil && !errors.Is(newErr, memoryStoreErrNotFound) { + c.Logger.Errorf("error deleting discovery AuthorizationPolicy %s: %s", ap.Name, newErr) + } + } + if dr != nil { + c.Logger.Infof("rolling back discovery DestinationRule for Federation cluster %s", instance.Name) + if newErr := c.Delete(collections.IstioNetworkingV1Alpha3Destinationrules.Resource().GroupVersionKind(), + dr.Name, dr.Namespace, nil); newErr != nil && !errors.Is(newErr, memoryStoreErrNotFound) { + c.Logger.Errorf("error deleting discovery DestinationRule %s: %s", dr.Name, newErr) + } + } + if ig != nil { + c.Logger.Infof("rolling back discovery ingress Gateway for Federation cluster %s", instance.Name) + if newErr := c.Delete(collections.IstioNetworkingV1Alpha3Gateways.Resource().GroupVersionKind(), + ig.Name, ig.Namespace, nil); newErr != nil && !errors.Is(newErr, memoryStoreErrNotFound) { + c.Logger.Errorf("error deleting discovery ingress Gateway %s: %s", ig.Name, newErr) + } + } + if eg != nil { + c.Logger.Infof("rolling back discovery egress Gateway for Federation cluster %s", instance.Name) + if newErr := c.Delete(collections.IstioNetworkingV1Alpha3Gateways.Resource().GroupVersionKind(), + eg.Name, eg.Namespace, nil); newErr != nil && !errors.Is(newErr, memoryStoreErrNotFound) { + c.Logger.Errorf("error deleting discovery egress Gateway %s: %s", eg.Name, newErr) + } + } + if evs != nil { + c.Logger.Infof("rolling back discovery egress VirtualService for Federation cluster %s", instance.Name) + if newErr := c.Delete(collections.IstioNetworkingV1Alpha3Virtualservices.Resource().GroupVersionKind(), + evs.Name, evs.Namespace, nil); newErr != nil && !errors.Is(newErr, memoryStoreErrNotFound) { + c.Logger.Errorf("error deleting discovery egress VirtualService %s: %s", evs.Name, newErr) + } + } + if ivs != nil { + c.Logger.Infof("rolling back discovery ingress VirtualService for Federation cluster %s", instance.Name) + if newErr := c.Delete(collections.IstioNetworkingV1Alpha3Virtualservices.Resource().GroupVersionKind(), + ivs.Name, ivs.Namespace, nil); newErr != nil && !errors.Is(newErr, memoryStoreErrNotFound) { + c.Logger.Errorf("error deleting discovery ingress VirtualService %s: %s", ivs.Name, newErr) + } + } + } + }() + + s = c.discoveryService(instance) + err = c.upsertConfig(*s) + if err != nil { + s = nil + } + + ap = c.discoveryAuthorizationPolicy(instance) + err = c.upsertConfig(*ap) + if err != nil { + ap = nil + } + + dr = c.discoveryDestinationRule(instance) + err = c.upsertConfig(*dr) + if err != nil { + dr = nil + } + + ig = c.discoveryIngressGateway(instance) + err = c.upsertConfig(*ig) + if err != nil { + ig = nil + } + + eg = c.discoveryEgressGateway(instance) + err = c.upsertConfig(*eg) + if err != nil { + eg = nil + } + + evs = c.discoveryVirtualService(instance) + err = c.upsertConfig(*evs) + if err != nil { + evs = nil + } + + ivs = c.discoveryIngressVirtualService(instance, meshConfig) + err = c.upsertConfig(*ivs) + if err != nil { + ivs = nil + } + return +} + +func (c *Controller) upsertConfig(cfg config.Config) (err error) { + existing := c.Get(cfg.GroupVersionKind, cfg.Name, cfg.Namespace) + if existing == nil { + _, err = c.Create(cfg) + if err != nil { + return err + } + } else if existing.Annotations[generationAnnotation] != cfg.Annotations[generationAnnotation] { + _, err = c.Update(cfg) + if err != nil { + // don't trigger roll back + c.Logger.Errorf("error updating resource %s: %s", cfg.Name, err) + err = nil + } + } + return err +} + +func discoveryResourceName(instance *v1.ServiceMeshPeer) string { + return fmt.Sprintf("federation-discovery-%s", instance.Name) +} + +func discoveryEgressResourceName(instance *v1.ServiceMeshPeer) string { + return fmt.Sprintf("%s-egress", discoveryResourceName(instance)) +} + +func discoveryIngressResourceName(instance *v1.ServiceMeshPeer) string { + return fmt.Sprintf("%s-ingress", discoveryResourceName(instance)) +} + +func federationIngressLabels(instance *v1.ServiceMeshPeer) map[string]string { + return map[string]string{ + "service.istio.io/canonical-name": instance.Spec.Gateways.Ingress.Name, + } +} + +func federationEgressLabels(instance *v1.ServiceMeshPeer) map[string]string { + return map[string]string{ + "service.istio.io/canonical-name": instance.Spec.Gateways.Egress.Name, + } +} + +func istiodServiceAddress(addr string) string { + portIndex := strings.Index(addr, ":") + if portIndex >= 0 { + return addr[:portIndex] + } + return addr +} + +func (c *Controller) discoveryService(instance *v1.ServiceMeshPeer) *config.Config { + // This is used for routing out of the egress gateway, primarily to configure mtls for discovery and + // to give the gateway an endpoint to route to (i.e. it creates a cluster with an endpoint in the gateway). + // This should turn into a service entry for the other mesh's network. + name := discoveryResourceName(instance) + discoveryPort := instance.Spec.Remote.DiscoveryPort + if discoveryPort == 0 { + discoveryPort = common.DefaultDiscoveryPort + } + serviceSpec := &rawnetworking.ServiceEntry{ + Hosts: []string{ + common.DiscoveryServiceHostname(instance), + }, + Location: rawnetworking.ServiceEntry_MESH_EXTERNAL, + Ports: []*rawnetworking.Port{ + { + Name: "https-discovery", + Number: uint32(discoveryPort), + Protocol: "HTTPS", + TargetPort: uint32(discoveryPort), + }, + }, + Resolution: rawnetworking.ServiceEntry_DNS, + ExportTo: []string{ + ".", + }, + } + for _, address := range instance.Spec.Remote.Addresses { + serviceSpec.Endpoints = append(serviceSpec.Endpoints, &rawnetworking.WorkloadEntry{ + Address: address, + Ports: map[string]uint32{ + "https-discovery": uint32(discoveryPort), + }, + }) + } + service := &config.Config{ + Meta: config.Meta{ + GroupVersionKind: collections.IstioNetworkingV1Alpha3Serviceentries.Resource().GroupVersionKind(), + Name: name, + Namespace: instance.Namespace, + Labels: map[string]string{ + "topology.istio.io/network": fmt.Sprintf("network-%s", instance.Name), + }, + Annotations: map[string]string{ + generationAnnotation: fmt.Sprintf("%d", instance.Generation), + }, + }, + Spec: serviceSpec, + } + return service +} + +func (c *Controller) discoveryIngressGateway(instance *v1.ServiceMeshPeer) *config.Config { + // Gateway definition for handling inbound discovery requests + name := discoveryIngressResourceName(instance) + discoveryPort := common.DefaultDiscoveryPort + gateway := &config.Config{ + Meta: config.Meta{ + GroupVersionKind: collections.IstioNetworkingV1Alpha3Gateways.Resource().GroupVersionKind(), + Name: name, + Namespace: instance.Namespace, + Annotations: map[string]string{ + generationAnnotation: fmt.Sprintf("%d", instance.Generation), + ior.ShouldManageRouteAnnotation: "false", + }, + }, + Spec: &rawnetworking.Gateway{ + Selector: federationIngressLabels(instance), + Servers: []*rawnetworking.Server{ + { + Name: name, + Hosts: []string{ + "*", + }, + Port: &rawnetworking.Port{ + Name: "https-discovery", + Number: uint32(discoveryPort), + Protocol: "HTTPS", + }, + Tls: &rawnetworking.ServerTLSSettings{ + Mode: rawnetworking.ServerTLSSettings_ISTIO_MUTUAL, + }, + }, + }, + }, + } + return gateway +} + +func (c *Controller) discoveryEgressGateway(instance *v1.ServiceMeshPeer) *config.Config { + // Gateway definition for routing outbound discovery. This is used to terminate source mtls for discovery. + name := discoveryEgressResourceName(instance) + egressGatewayServiceName := fmt.Sprintf("%s.%s.svc.%s", + instance.Spec.Gateways.Egress.Name, instance.Namespace, c.env.DomainSuffix) + discoveryPort := common.DefaultDiscoveryPort + gateway := &config.Config{ + Meta: config.Meta{ + GroupVersionKind: collections.IstioNetworkingV1Alpha3Gateways.Resource().GroupVersionKind(), + Name: name, + Namespace: instance.Namespace, + Annotations: map[string]string{ + generationAnnotation: fmt.Sprintf("%d", instance.Generation), + ior.ShouldManageRouteAnnotation: "false", + }, + }, + Spec: &rawnetworking.Gateway{ + Selector: federationEgressLabels(instance), + Servers: []*rawnetworking.Server{ + { + Name: name, + Hosts: []string{ + egressGatewayServiceName, + }, + Port: &rawnetworking.Port{ + // XXX: this will eventually be encrypted + Name: "http-discovery", + Number: uint32(discoveryPort), + Protocol: "HTTP", + }, + }, + }, + }, + } + return gateway +} + +func (c *Controller) discoveryAuthorizationPolicy(instance *v1.ServiceMeshPeer) *config.Config { + // AuthorizationPolicy used to restrict inbound discovery requests to known clients. + name := discoveryResourceName(instance) + discoveryPort := common.DefaultDiscoveryPort + ap := &config.Config{ + Meta: config.Meta{ + GroupVersionKind: collections.IstioSecurityV1Beta1Authorizationpolicies.Resource().GroupVersionKind(), + Name: name, + Namespace: instance.Namespace, + Annotations: map[string]string{ + generationAnnotation: fmt.Sprintf("%d", instance.Generation), + }, + }, + Spec: &rawsecurity.AuthorizationPolicy{ + Selector: &rawtype.WorkloadSelector{ + MatchLabels: federationIngressLabels(instance), + }, + Action: rawsecurity.AuthorizationPolicy_DENY, + Rules: []*rawsecurity.Rule{ + { + From: []*rawsecurity.Rule_From{ + { + Source: &rawsecurity.Source{ + NotPrincipals: []string{ + instance.Spec.Security.ClientID, + }, + }, + }, + }, + To: []*rawsecurity.Rule_To{ + { + Operation: &rawsecurity.Operation{ + Ports: []string{ + strconv.FormatInt(int64(discoveryPort), 10), + }, + }, + }, + }, + }, + }, + }, + } + return ap +} + +func (c *Controller) discoveryVirtualService(instance *v1.ServiceMeshPeer) *config.Config { + // VirtualService used to route inbound and outbound discovery requests. + name := discoveryEgressResourceName(instance) + egressGatewayName := fmt.Sprintf("%s/%s", instance.Namespace, name) + egressGatewayService := fmt.Sprintf("%s.%s.svc.%s", instance.Spec.Gateways.Egress.Name, instance.Namespace, c.env.DomainSuffix) + discoveryService := common.DiscoveryServiceHostname(instance) + discoveryPort := common.DefaultDiscoveryPort + remoteDiscoveryPort := discoveryPort + if instance.Spec.Remote.DiscoveryPort > 0 { + remoteDiscoveryPort = int(instance.Spec.Remote.DiscoveryPort) + } + vs := &config.Config{ + Meta: config.Meta{ + GroupVersionKind: collections.IstioNetworkingV1Alpha3Virtualservices.Resource().GroupVersionKind(), + Name: name, + Namespace: instance.Namespace, + Annotations: map[string]string{ + generationAnnotation: fmt.Sprintf("%d", instance.Generation), + }, + }, + Spec: &rawnetworking.VirtualService{ + Hosts: []string{ + egressGatewayService, + }, + Gateways: []string{ + egressGatewayName, + }, + ExportTo: []string{ + ".", + }, + Http: []*rawnetworking.HTTPRoute{ + { + // Outbound discovery requests + Name: name, + Match: []*rawnetworking.HTTPMatchRequest{ + { + Port: uint32(discoveryPort), + Headers: map[string]*rawnetworking.StringMatch{ + "discovery-service": { + MatchType: &rawnetworking.StringMatch_Exact{ + Exact: discoveryService, + }, + }, + "remote": { + MatchType: &rawnetworking.StringMatch_Exact{ + Exact: fmt.Sprint(common.RemoteChecksum(instance.Spec.Remote)), + }, + }, + }, + }, + }, + Rewrite: &rawnetworking.HTTPRewrite{ + // Allows us to get the correct endpoint for outbound + Authority: discoveryService, + }, + Route: []*rawnetworking.HTTPRouteDestination{ + { + Destination: &rawnetworking.Destination{ + Host: discoveryService, + Port: &rawnetworking.PortSelector{ + Number: uint32(remoteDiscoveryPort), + }, + // to configure mtls appropriately + Subset: name, + }, + }, + }, + }, + }, + }, + } + return vs +} + +func (c *Controller) discoveryIngressVirtualService( + instance *v1.ServiceMeshPeer, + meshConfig *meshv1alpha1.MeshConfig, +) *config.Config { + // VirtualService used to route inbound and outbound discovery requests. + name := discoveryIngressResourceName(instance) + istiodService := istiodServiceAddress(meshConfig.DefaultConfig.DiscoveryAddress) + if svcIndex := strings.LastIndex(istiodService, ".svc"); svcIndex >= 0 { + istiodService = istiodService[:svcIndex] + ".svc." + c.env.DomainSuffix + } + ingressGatewayName := fmt.Sprintf("%s/%s", instance.Namespace, name) + discoveryPort := common.DefaultDiscoveryPort + vs := &config.Config{ + Meta: config.Meta{ + GroupVersionKind: collections.IstioNetworkingV1Alpha3Virtualservices.Resource().GroupVersionKind(), + Name: name, + Namespace: instance.Namespace, + Annotations: map[string]string{ + generationAnnotation: fmt.Sprintf("%d", instance.Generation), + }, + }, + Spec: &rawnetworking.VirtualService{ + Hosts: []string{ + "*", + }, + Gateways: []string{ + ingressGatewayName, + }, + ExportTo: []string{ + ".", + }, + Http: []*rawnetworking.HTTPRoute{ + { + // inbound descovery /services/ requests + Name: fmt.Sprintf("%s-ingress-services", name), + Match: []*rawnetworking.HTTPMatchRequest{ + { + Gateways: []string{ + ingressGatewayName, + }, + Port: uint32(discoveryPort), + Uri: &rawnetworking.StringMatch{ + MatchType: &rawnetworking.StringMatch_Exact{ + Exact: "/v1/services/", + }, + }, + }, + }, + Rewrite: &rawnetworking.HTTPRewrite{ + Authority: istiodService, + Uri: "/v1/services/" + instance.Name, + }, + Route: []*rawnetworking.HTTPRouteDestination{ + { + Destination: &rawnetworking.Destination{ + Host: istiodService, + Port: &rawnetworking.PortSelector{ + Number: uint32(discoveryPort), + }, + }, + }, + }, + }, + { + // inbound discovery /watch requests + Name: fmt.Sprintf("%s-ingress-watch", name), + Match: []*rawnetworking.HTTPMatchRequest{ + { + Gateways: []string{ + ingressGatewayName, + }, + Port: uint32(discoveryPort), + Uri: &rawnetworking.StringMatch{ + MatchType: &rawnetworking.StringMatch_Exact{ + Exact: "/v1/watch", + }, + }, + }, + }, + Rewrite: &rawnetworking.HTTPRewrite{ + Authority: istiodService, + Uri: "/v1/watch/" + instance.Name, + }, + Route: []*rawnetworking.HTTPRouteDestination{ + { + Destination: &rawnetworking.Destination{ + Host: istiodService, + Port: &rawnetworking.PortSelector{ + Number: uint32(discoveryPort), + }, + }, + }, + }, + }, + }, + }, + } + return vs +} + +func (c *Controller) discoveryDestinationRule(instance *v1.ServiceMeshPeer) *config.Config { + // DestinationRule to configure mTLS for outbound discovery requests + name := discoveryEgressResourceName(instance) + discoveryHost := common.DiscoveryServiceHostname(instance) + discoveryPort := instance.Spec.Remote.DiscoveryPort + if discoveryPort == 0 { + discoveryPort = common.DefaultDiscoveryPort + } + dr := &config.Config{ + Meta: config.Meta{ + GroupVersionKind: collections.IstioNetworkingV1Alpha3Destinationrules.Resource().GroupVersionKind(), + Name: name, + Namespace: instance.Namespace, + Annotations: map[string]string{ + generationAnnotation: fmt.Sprintf("%d", instance.Generation), + }, + }, + Spec: &rawnetworking.DestinationRule{ + // the "fake" discovery service + Host: discoveryHost, + ExportTo: []string{ + ".", + }, + Subsets: []*rawnetworking.Subset{ + { + Name: name, + TrafficPolicy: &rawnetworking.TrafficPolicy{ + PortLevelSettings: []*rawnetworking.TrafficPolicy_PortTrafficPolicy{ + { + Port: &rawnetworking.PortSelector{ + Number: uint32(discoveryPort), + }, + Tls: &rawnetworking.ClientTLSSettings{ + Mode: rawnetworking.ClientTLSSettings_ISTIO_MUTUAL, + Sni: discoveryHost, + }, + }, + }, + }, + }, + }, + }, + } + return dr +} diff --git a/pkg/servicemesh/federation/example/config-poc/README.md b/pkg/servicemesh/federation/example/config-poc/README.md new file mode 100644 index 00000000000..55a054cf017 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/README.md @@ -0,0 +1,63 @@ +# Service Mesh Federation Example + +In this directory, you'll find a Service Mesh Federation example in which two meshes are connected to each other. + +## About + +One mesh control plane is installed in the `mesh1-system` Namespace by creating a `ServiceMeshControlPlane` resource named `fed-export`, the other is installed in the `mesh2-system` Namespace using a `ServiceMeshControlPlane` named `fed-import`. When using two clusters, the `fed-export` mesh is installed in the cluster pointed to by `MESH1_KUBECONFIG`, whereas the `fed-import` mesh is installed in the cluster pointed to by `MESH2_KUBECONFIG`. `ServiceMeshPeer` resources named `mesh2` and `mesh1` are created in the first mesh and the second mesh, respectively. + +The script also installs two instances of the Bookinfo application in namespaces `mesh1-bookinfo` and `mesh2-bookinfo`. + +The first mesh exports the `ratings` and `mongodb` Services, while the second mesh imports them. + +The meshes are configured to split the `ratings` Service traffic in `mesh2-bookinfo` between +*mesh1* and *mesh2*. Furthermore, the `ratings` service in *mesh2* is configured to use the +`mongodb` service in *mesh1*. + +## Running the example + +Everything can be setup by running `./install.sh`. You must point the `MESH1_KUBECONFIG` and `MESH2_KUBECONFIG` environment variables to the `KUBECONFIG` files of the *mesh1* and *mesh2* cluster, respectively. To use a single cluster, point both to the same `KUBECONFIG` file. + +The installation script deploys two meshes and registers each mesh in the other as a peer. The meshes are installed in a single or in two separate clusters, depending on the values of the `MESH1_KUBECONFIG` and `MESH2_KUBECONFIG` environment variables. + +When the script finishes, run the following command in the *mesh1* cluster to check the connection status: + +```shell +oc -n mesh1-system get servicemeshpeer mesh2 -o json | jq .status +``` + +Run the following command to check the connection status in *mesh2*: + +```shell +oc -n mesh2-system get servicemeshpeer mesh1 -o json | jq .status +``` + +Check if services from *mesh1* are imported into *mesh2*: + +```shell +oc -n mesh2-system get importedservicesets mesh1 -o json | jq .status +``` + +To see federation in action, use the bookinfo app in *mesh2* as follows: + +1. Stream the logs of the `ratings` Pods in the *mesh1* cluster as follows + + ```shell + oc logs -n mesh1-bookinfo svc/ratings -f + ``` + +1. Stream the logs of the `ratings` Pods in the *mesh2* cluster: + + ```shell + `oc logs -n mesh2-bookinfo svc/ratings -f` + ``` + +1. Send many requests to the Bookinfo productpage endpoint using `siege` or repeated `curl` commands: + + ```shell + siege http://$(oc -n mesh2-system get route istio-ingressgateway -o json | jq -r .spec.host)/productpage + ``` + +1. Inspect the `ratings` Service log output to see requests hitting the Service in either the *mesh1* or the *mesh2* cluster. + + diff --git a/pkg/servicemesh/federation/example/config-poc/cacerts/README.md b/pkg/servicemesh/federation/example/config-poc/cacerts/README.md new file mode 100644 index 00000000000..38621dfafd0 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/cacerts/README.md @@ -0,0 +1,20 @@ +# Istio plugin CA sample certificates + +This directory contains sample pre-generated certificate and keys to demonstrate how an operator could configure Citadel with an existing root certificate, signing certificates and keys. In such +a deployment, Citadel acts as an intermediate certificate authority (CA), under the given root CA. +Instructions are available [here](https://istio.io/docs/tasks/security/cert-management/plugin-ca-cert/). + +The included sample files are: + +- `root-cert.pem`: root CA certificate. +- `ca-[cert|key].pem`: Citadel intermediate certificate and corresponding private key. +- `cert-chain.pem`: certificate trust chain. +- `workload-foo-[cert|key].pem`: workload certificate and key for URI SAN `spiffe://trust-domain-foo/ns/foo/sa/foo` signed by `ca-cert.key`. +- `workload-bar-[cert|key].pem`: workload certificate and key for URI SAN `spiffe://trust-domain-bar/ns/bar/sa/bar` signed by `ca-cert.key`. + +The workload cert and key are generated by: + +```shell script + ./generate-workload.sh foo + ./generate-workload.sh bar +``` diff --git a/pkg/servicemesh/federation/example/config-poc/cacerts/ca-cert.pem b/pkg/servicemesh/federation/example/config-poc/cacerts/ca-cert.pem new file mode 100644 index 00000000000..a460e036b3f --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/cacerts/ca-cert.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDnzCCAoegAwIBAgIJAON1ifrBZ2/BMA0GCSqGSIb3DQEBCwUAMIGLMQswCQYD +VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJU3Vubnl2YWxl +MQ4wDAYDVQQKDAVJc3RpbzENMAsGA1UECwwEVGVzdDEQMA4GA1UEAwwHUm9vdCBD +QTEiMCAGCSqGSIb3DQEJARYTdGVzdHJvb3RjYUBpc3Rpby5pbzAgFw0xODAxMjQx +OTE1NTFaGA8yMTE3MTIzMTE5MTU1MVowWTELMAkGA1UEBhMCVVMxEzARBgNVBAgT +CkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTEOMAwGA1UEChMFSXN0aW8x +ETAPBgNVBAMTCElzdGlvIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAyzCxr/xu0zy5rVBiso9ffgl00bRKvB/HF4AX9/ytmZ6Hqsy13XIQk8/u/By9 +iCvVwXIMvyT0CbiJq/aPEj5mJUy0lzbrUs13oneXqrPXf7ir3HzdRw+SBhXlsh9z +APZJXcF93DJU3GabPKwBvGJ0IVMJPIFCuDIPwW4kFAI7R/8A5LSdPrFx6EyMXl7K +M8jekC0y9DnTj83/fY72WcWX7YTpgZeBHAeeQOPTZ2KYbFal2gLsar69PgFS0Tom +ESO9M14Yit7mzB1WDK2z9g3r+zLxENdJ5JG/ZskKe+TO4Diqi5OJt/h8yspS1ck8 +LJtCole9919umByg5oruflqIlQIDAQABozUwMzALBgNVHQ8EBAMCAgQwDAYDVR0T +BAUwAwEB/zAWBgNVHREEDzANggtjYS5pc3Rpby5pbzANBgkqhkiG9w0BAQsFAAOC +AQEAltHEhhyAsve4K4bLgBXtHwWzo6SpFzdAfXpLShpOJNtQNERb3qg6iUGQdY+w +A2BpmSkKr3Rw/6ClP5+cCG7fGocPaZh+c+4Nxm9suMuZBZCtNOeYOMIfvCPcCS+8 +PQ/0hC4/0J3WJKzGBssaaMufJxzgFPPtDJ998kY8rlROghdSaVt423/jXIAYnP3Y +05n8TGERBj7TLdtIVbtUIx3JHAo3PWJywA6mEDovFMJhJERp9sDHIr1BbhXK1TFN +Z6HNH6gInkSSMtvC4Ptejb749PTaePRPF7ID//eq/3AH8UK50F3TQcLjEqWUsJUn +aFKltOc+RAjzDklcUPeG4Y6eMA== +-----END CERTIFICATE----- diff --git a/pkg/servicemesh/federation/example/config-poc/cacerts/ca-key.pem b/pkg/servicemesh/federation/example/config-poc/cacerts/ca-key.pem new file mode 100644 index 00000000000..faa77f3882a --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/cacerts/ca-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAyzCxr/xu0zy5rVBiso9ffgl00bRKvB/HF4AX9/ytmZ6Hqsy1 +3XIQk8/u/By9iCvVwXIMvyT0CbiJq/aPEj5mJUy0lzbrUs13oneXqrPXf7ir3Hzd +Rw+SBhXlsh9zAPZJXcF93DJU3GabPKwBvGJ0IVMJPIFCuDIPwW4kFAI7R/8A5LSd +PrFx6EyMXl7KM8jekC0y9DnTj83/fY72WcWX7YTpgZeBHAeeQOPTZ2KYbFal2gLs +ar69PgFS0TomESO9M14Yit7mzB1WDK2z9g3r+zLxENdJ5JG/ZskKe+TO4Diqi5OJ +t/h8yspS1ck8LJtCole9919umByg5oruflqIlQIDAQABAoIBAGZI8fnUinmd5R6B +C941XG3XFs6GAuUm3hNPcUFuGnntmv/5I0gBpqSyFO0nDqYg4u8Jma8TTCIkmnFN +ogIeFU+LiJFinR3GvwWzTE8rTz1FWoaY+M9P4ENd/I4pVLxUPuSKhfA2ChAVOupU +8F7D9Q/dfBXQQCT3VoUaC+FiqjL4HvIhji1zIqaqpK7fChGPraC/4WHwLMNzI0Zg +oDdAanwVygettvm6KD7AeKzhK94gX1PcnsOi3KuzQYvkenQE1M6/K7YtEc5qXCYf +QETj0UCzB55btgdF36BGoZXf0LwHqxys9ubfHuhwKBpY0xg2z4/4RXZNhfIDih3w +J3mihcECgYEA6FtQ0cfh0Zm03OPDpBGc6sdKxTw6aBDtE3KztfI2hl26xHQoeFqp +FmV/TbnExnppw+gWJtwx7IfvowUD8uRR2P0M2wGctWrMpnaEYTiLAPhXsj69HSM/ +CYrh54KM0YWyjwNhtUzwbOTrh1jWtT9HV5e7ay9Atk3UWljuR74CFMUCgYEA392e +DVoDLE0XtbysmdlfSffhiQLP9sT8+bf/zYnr8Eq/4LWQoOtjEARbuCj3Oq7bP8IE +Vz45gT1mEE3IacC9neGwuEa6icBiuQi86NW8ilY/ZbOWrRPLOhk3zLiZ+yqkt+sN +cqWx0JkIh7IMKWI4dVQgk4I0jcFP7vNG/So4AZECgYEA426eSPgxHQwqcBuwn6Nt +yJCRq0UsljgbFfIr3Wfb3uFXsntQMZ3r67QlS1sONIgVhmBhbmARrcfQ0+xQ1SqO +wqnOL4AAd8K11iojoVXLGYP7ssieKysYxKpgPE8Yru0CveE9fkx0+OGJeM2IO5hY +qHAoTt3NpaPAuz5Y3XgqaVECgYA0TONS/TeGjxA9/jFY1Cbl8gp35vdNEKKFeM5D +Z7h+cAg56FE8tyFyqYIAGVoBFL7WO26mLzxiDEUfA/0Rb90c2JBfzO5hpleqIPd5 +cg3VR+cRzI4kK16sWR3nLy2SN1k6OqjuovVS5Z3PjfI3bOIBz0C5FY9Pmt0g1yc7 +mDRzcQKBgQCXWCZStbdjewaLd5u5Hhbw8tIWImMVfcfs3H1FN669LLpbARM8RtAa +8dYwDVHmWmevb/WX03LiSE+GCjCBO79fa1qc5RKAalqH/1OYxTuvYOeTUebSrg8+ +lQFlP2OC4GGolKrN6HVWdxtf+F+SdjwX6qGCfYkXJRLYXIFSFjFeuw== +-----END RSA PRIVATE KEY----- diff --git a/pkg/servicemesh/federation/example/config-poc/cacerts/cert-chain.pem b/pkg/servicemesh/federation/example/config-poc/cacerts/cert-chain.pem new file mode 100644 index 00000000000..a460e036b3f --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/cacerts/cert-chain.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDnzCCAoegAwIBAgIJAON1ifrBZ2/BMA0GCSqGSIb3DQEBCwUAMIGLMQswCQYD +VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJU3Vubnl2YWxl +MQ4wDAYDVQQKDAVJc3RpbzENMAsGA1UECwwEVGVzdDEQMA4GA1UEAwwHUm9vdCBD +QTEiMCAGCSqGSIb3DQEJARYTdGVzdHJvb3RjYUBpc3Rpby5pbzAgFw0xODAxMjQx +OTE1NTFaGA8yMTE3MTIzMTE5MTU1MVowWTELMAkGA1UEBhMCVVMxEzARBgNVBAgT +CkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTEOMAwGA1UEChMFSXN0aW8x +ETAPBgNVBAMTCElzdGlvIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAyzCxr/xu0zy5rVBiso9ffgl00bRKvB/HF4AX9/ytmZ6Hqsy13XIQk8/u/By9 +iCvVwXIMvyT0CbiJq/aPEj5mJUy0lzbrUs13oneXqrPXf7ir3HzdRw+SBhXlsh9z +APZJXcF93DJU3GabPKwBvGJ0IVMJPIFCuDIPwW4kFAI7R/8A5LSdPrFx6EyMXl7K +M8jekC0y9DnTj83/fY72WcWX7YTpgZeBHAeeQOPTZ2KYbFal2gLsar69PgFS0Tom +ESO9M14Yit7mzB1WDK2z9g3r+zLxENdJ5JG/ZskKe+TO4Diqi5OJt/h8yspS1ck8 +LJtCole9919umByg5oruflqIlQIDAQABozUwMzALBgNVHQ8EBAMCAgQwDAYDVR0T +BAUwAwEB/zAWBgNVHREEDzANggtjYS5pc3Rpby5pbzANBgkqhkiG9w0BAQsFAAOC +AQEAltHEhhyAsve4K4bLgBXtHwWzo6SpFzdAfXpLShpOJNtQNERb3qg6iUGQdY+w +A2BpmSkKr3Rw/6ClP5+cCG7fGocPaZh+c+4Nxm9suMuZBZCtNOeYOMIfvCPcCS+8 +PQ/0hC4/0J3WJKzGBssaaMufJxzgFPPtDJ998kY8rlROghdSaVt423/jXIAYnP3Y +05n8TGERBj7TLdtIVbtUIx3JHAo3PWJywA6mEDovFMJhJERp9sDHIr1BbhXK1TFN +Z6HNH6gInkSSMtvC4Ptejb749PTaePRPF7ID//eq/3AH8UK50F3TQcLjEqWUsJUn +aFKltOc+RAjzDklcUPeG4Y6eMA== +-----END CERTIFICATE----- diff --git a/pkg/servicemesh/federation/example/config-poc/cacerts/generate-workload.sh b/pkg/servicemesh/federation/example/config-poc/cacerts/generate-workload.sh new file mode 100755 index 00000000000..e3befaf565e --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/cacerts/generate-workload.sh @@ -0,0 +1,65 @@ +#!/bin/bash +# +# Copyright Istio Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name=${1:-foo} +ns=${2:-$name} +sa=${3:-$name} +tmp=${4:-""} +san="spiffe://trust-domain-$name/ns/$ns/sa/$sa" + +DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +if [ ! -d "$DIR/$tmp" ]; then + mkdir "$DIR/$tmp" +fi + +openssl genrsa -out "$DIR/$tmp/workload-$name-key.pem" 2048 + +cat > "$DIR"/workload.cfg <> "$DIR/$tmp/workload-$name-cert.pem" + +echo "Generated workload-$name-[cert|key].pem with URI SAN $san" +openssl verify -CAfile <(cat "$DIR"/cert-chain.pem "$DIR"/root-cert.pem) "$DIR/$tmp/workload-$name-cert.pem" + +# clean temporary files +if [ -f "$DIR"/.srl ]; then + rm "$DIR"/.srl +fi +if [ -f "$DIR"/ca-cert.srl ]; then + rm "$DIR"/ca-cert.srl +fi +rm "$DIR"/workload.cfg "$DIR"/workload.csr diff --git a/pkg/servicemesh/federation/example/config-poc/cacerts/root-cert.pem b/pkg/servicemesh/federation/example/config-poc/cacerts/root-cert.pem new file mode 100644 index 00000000000..64c3fd50cb2 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/cacerts/root-cert.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIID7TCCAtWgAwIBAgIJAOIRDhOcxsx6MA0GCSqGSIb3DQEBCwUAMIGLMQswCQYD +VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJU3Vubnl2YWxl +MQ4wDAYDVQQKDAVJc3RpbzENMAsGA1UECwwEVGVzdDEQMA4GA1UEAwwHUm9vdCBD +QTEiMCAGCSqGSIb3DQEJARYTdGVzdHJvb3RjYUBpc3Rpby5pbzAgFw0xODAxMjQx +OTE1NTFaGA8yMTE3MTIzMTE5MTU1MVowgYsxCzAJBgNVBAYTAlVTMRMwEQYDVQQI +DApDYWxpZm9ybmlhMRIwEAYDVQQHDAlTdW5ueXZhbGUxDjAMBgNVBAoMBUlzdGlv +MQ0wCwYDVQQLDARUZXN0MRAwDgYDVQQDDAdSb290IENBMSIwIAYJKoZIhvcNAQkB +FhN0ZXN0cm9vdGNhQGlzdGlvLmlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEA38uEfAatzQYqbaLou1nxJ348VyNzumYMmDDt5pbLYRrCo2pS3ki1ZVDN +8yxIENJFkpKw9UctTGdbNGuGCiSDP7uqF6BiVn+XKAU/3pnPFBbTd0S33NqbDEQu +IYraHSl/tSk5rARbC1DrQRdZ6nYD2KrapC4g0XbjY6Pu5l4y7KnFwSunnp9uqpZw +uERv/BgumJ5QlSeSeCmhnDhLxooG8w5tC2yVr1yDpsOHGimP/mc8Cds4V0zfIhQv +YzfIHphhE9DKjmnjBYLOdj4aycv44jHnOGc+wvA1Jqsl60t3wgms+zJTiWwABLdw +zgMAa7yxLyoV0+PiVQud6k+8ZoIFcwIDAQABo1AwTjAdBgNVHQ4EFgQUOUYGtUyh +euxO4lGe4Op1y8NVoagwHwYDVR0jBBgwFoAUOUYGtUyheuxO4lGe4Op1y8NVoagw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEANXLyfAs7J9rmBamGJvPZ +ltx390WxzzLFQsBRAaH6rgeipBq3dR9qEjAwb6BTF+ROmtQzX+fjstCRrJxCto9W +tC8KvXTdRfIjfCCZjhtIOBKqRxE4KJV/RBfv9xD5lyjtCPCQl3Ia6MSf42N+abAK +WCdU6KCojA8WB9YhSCzza3aQbPTzd26OC/JblJpVgtus5f8ILzCsz+pbMimgTkhy +AuhYRppJaQ24APijsEC9+GIaVKPg5IwWroiPoj+QXNpshuvqVQQXvGaRiq4zoSnx +xAJz+w8tjrDWcf826VN14IL+/Cmqlg/rIfB5CHdwVIfWwpuGB66q/UiPegZMNs8a +3g== +-----END CERTIFICATE----- diff --git a/pkg/servicemesh/federation/example/config-poc/cacerts/workload-bar-cert.pem b/pkg/servicemesh/federation/example/config-poc/cacerts/workload-bar-cert.pem new file mode 100644 index 00000000000..c614ffc3854 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/cacerts/workload-bar-cert.pem @@ -0,0 +1,43 @@ +-----BEGIN CERTIFICATE----- +MIIDXTCCAkWgAwIBAgIUBn+v5JAoezzNx9s3Euvzlny0LWcwDQYJKoZIhvcNAQEL +BQAwWTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcT +CVN1bm55dmFsZTEOMAwGA1UEChMFSXN0aW8xETAPBgNVBAMTCElzdGlvIENBMB4X +DTIwMDgxNDIyMTA1M1oXDTMwMDgxMjIyMTA1M1owADCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAMD18u/U1ouLwc2VblyFQCDN7XdGODoLV2eYA3NQrzMv +0873zS5wbvte2eRc+MX9jnwg8rW+Won7KUaEzD62a9QZv5ilO1137YUBZrTgQIkO +bhOnmpJRmR3Cxck8ZTEBMFsM+xyGAGc8ptdGJjEuxifFJHT3IB0ibXsnYuHnzpj1 +totq3sIPTRSkjsSOnKpyaOfBFiAyDQ0Rnm4+O32cJ654l0Co6iRABTnO9vIq1Tjn +fQm6+F99w3Wvv9Ik8HxB4HBLZ3+qgXQIJOD+d5+z88OnsiEMYKO4XHy2D/OAh9ND +7i9lzr+wXLYb5H1+TcEJuHFTHQcsm5YCl/zFt4YHgX0CAwEAAaN2MHQwDgYDVR0P +AQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMB +Af8EAjAAMDUGA1UdEQEB/wQrMCmGJ3NwaWZmZTovL3RydXN0LWRvbWFpbi1iYXIv +bnMvYmFyL3NhL2JhcjANBgkqhkiG9w0BAQsFAAOCAQEAGAWE6bLO4L8fDFg2hVCJ +G+8uTVVeO2H8wFiDOqB0xq9OCrzSp39cZsBZLj9KFBWx/V0PEAlcmGlgHozdGkVG +Z1/B+ukeRgALYBmHgOegoC2zHOz5qacqiRnV8Kijxa6nFyU0qbJCFVWs76DSZZDm +872SMmoURs2VrAQTWInbtWxR4tAyEdmecYOdHEIXQDc13LQSwu7TINLs7JnjKlv7 +xIv6TsOyAyx305DSK0htxYfgrvo4cc33JmDOtL81bHfyUfx2B8HKeDYTaDh+V01G +OesJNzqECzW6IMMFJey0f/4W7hbldpZmgXs8qa/g1CR8pCRs2eTWKTS336glXLCG +MA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDnzCCAoegAwIBAgIJAON1ifrBZ2/BMA0GCSqGSIb3DQEBCwUAMIGLMQswCQYD +VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJU3Vubnl2YWxl +MQ4wDAYDVQQKDAVJc3RpbzENMAsGA1UECwwEVGVzdDEQMA4GA1UEAwwHUm9vdCBD +QTEiMCAGCSqGSIb3DQEJARYTdGVzdHJvb3RjYUBpc3Rpby5pbzAgFw0xODAxMjQx +OTE1NTFaGA8yMTE3MTIzMTE5MTU1MVowWTELMAkGA1UEBhMCVVMxEzARBgNVBAgT +CkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTEOMAwGA1UEChMFSXN0aW8x +ETAPBgNVBAMTCElzdGlvIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAyzCxr/xu0zy5rVBiso9ffgl00bRKvB/HF4AX9/ytmZ6Hqsy13XIQk8/u/By9 +iCvVwXIMvyT0CbiJq/aPEj5mJUy0lzbrUs13oneXqrPXf7ir3HzdRw+SBhXlsh9z +APZJXcF93DJU3GabPKwBvGJ0IVMJPIFCuDIPwW4kFAI7R/8A5LSdPrFx6EyMXl7K +M8jekC0y9DnTj83/fY72WcWX7YTpgZeBHAeeQOPTZ2KYbFal2gLsar69PgFS0Tom +ESO9M14Yit7mzB1WDK2z9g3r+zLxENdJ5JG/ZskKe+TO4Diqi5OJt/h8yspS1ck8 +LJtCole9919umByg5oruflqIlQIDAQABozUwMzALBgNVHQ8EBAMCAgQwDAYDVR0T +BAUwAwEB/zAWBgNVHREEDzANggtjYS5pc3Rpby5pbzANBgkqhkiG9w0BAQsFAAOC +AQEAltHEhhyAsve4K4bLgBXtHwWzo6SpFzdAfXpLShpOJNtQNERb3qg6iUGQdY+w +A2BpmSkKr3Rw/6ClP5+cCG7fGocPaZh+c+4Nxm9suMuZBZCtNOeYOMIfvCPcCS+8 +PQ/0hC4/0J3WJKzGBssaaMufJxzgFPPtDJ998kY8rlROghdSaVt423/jXIAYnP3Y +05n8TGERBj7TLdtIVbtUIx3JHAo3PWJywA6mEDovFMJhJERp9sDHIr1BbhXK1TFN +Z6HNH6gInkSSMtvC4Ptejb749PTaePRPF7ID//eq/3AH8UK50F3TQcLjEqWUsJUn +aFKltOc+RAjzDklcUPeG4Y6eMA== +-----END CERTIFICATE----- diff --git a/pkg/servicemesh/federation/example/config-poc/cacerts/workload-bar-key.pem b/pkg/servicemesh/federation/example/config-poc/cacerts/workload-bar-key.pem new file mode 100644 index 00000000000..bc11603b998 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/cacerts/workload-bar-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAwPXy79TWi4vBzZVuXIVAIM3td0Y4OgtXZ5gDc1CvMy/TzvfN +LnBu+17Z5Fz4xf2OfCDytb5aifspRoTMPrZr1Bm/mKU7XXfthQFmtOBAiQ5uE6ea +klGZHcLFyTxlMQEwWwz7HIYAZzym10YmMS7GJ8UkdPcgHSJteydi4efOmPW2i2re +wg9NFKSOxI6cqnJo58EWIDINDRGebj47fZwnrniXQKjqJEAFOc728irVOOd9Cbr4 +X33Dda+/0iTwfEHgcEtnf6qBdAgk4P53n7Pzw6eyIQxgo7hcfLYP84CH00PuL2XO +v7BcthvkfX5NwQm4cVMdByyblgKX/MW3hgeBfQIDAQABAoIBAQCKn6bZ2YQQWGTw +tsvEOA5sAsT4jT/To1Y1nCXOcEaNdWyrIacMF8YDXI8Y2hn200PLtTfojUoqGn/6 +o2jAHPm2NJFKrlnJumCuzuTkSL7UN8Oo5x3KxEhF8yl4eqUP4ZTFtLuqMDKV+CK8 +QS8q4jmFVMHuLaOqipMwiIknVgs8IvmQSZf3LBPOLRX9vcTtT0YnOAhFQjb3048s +Da+pDSsKesVkcsTx9aw4pUHWcLFuDHxZ1f0hAXcOfkzjzuBkQ0uoUxSIE+kcA2i0 +9vZB7fSqL/5zKrKooDSjW189WHd8wMEtmGZW6VDeH0fMuC+KWEVZnyjMrrlCMesJ +MismTSABAoGBAPD2XAf01iMy4Y84XtI4vku0uO+pseyhZ2nyqLJW2q3M0bXKFMiD +jiE7GlxBjynZFfU5R/H7QJ3rDwH4PpKyd13mgnlUImyLTUVaSbC3Bu0rJ+NFLtsQ +7OCxi4F3pOvOAWUL5WJc0gyqmSBywoGFuCT1x0wch2si1/XGUH973EwBAoGBAM0A +te01yywQ+X17fApIh/R+LLPkORecpDJgC3vTcMvuvC9Rq1HEC4S4b7X0SfrUzvCw +BO+J3KUMBJXHC2S4VsWBn/jHA8vJ1RD11gDVUV776WLxhXiBekwneFyFlNUukkTa +2bcnM3vtXZBl8z8Fhddfo5i9MR0Wh6jXF3HpemV9AoGAW1k6CHYkHBH0+sOnBtEm +KzMnDQxq/EcwGjU5COruWgcU1XL3sBBXeHecha8A5B99OIrvoGfc1kE/XkLLDfgE +Up/JhM+FgVrJ/2m8F/c68/xxUbJvkfL3qjMErR87cX2Wf8Ujv8dqhgzCok9/N3UH +G1PlqxABsnbyIiV9bOb63AECgYEAqbsd5YF1b026k3dK8uSsk/RnpKWf03ngxMia +mXIt4NsPugnfU3qCoudlrnvNSL0rfUHvRDibk5dIsI21VDX/udUiEwMLlI3OOBWi +ktwLXB4sVLxtaqGhFS5UzB3ZZUwC1LlyKt9tE/0qS2Ttqc8zymcn900lPdUqitNT +WQAbU60CgYBsR9gyXA4SXFjKmk5WKFhHlvTf87UfaOrPeeDE7zeEo2iVgjq9gSHw +7zBaiVvrwcSn3COszrPgtOUM+Vl/T7Z2QmPTteP2R8mKxOJk4BWQ5q/bhoc3sEH7 +EjR9twDPRg3V9xEKtcTiJhzm4TitKGYBH8FQ22B4X6mouVE8KfXkyA== +-----END RSA PRIVATE KEY----- diff --git a/pkg/servicemesh/federation/example/config-poc/cacerts/workload-foo-cert.pem b/pkg/servicemesh/federation/example/config-poc/cacerts/workload-foo-cert.pem new file mode 100644 index 00000000000..e3697421be5 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/cacerts/workload-foo-cert.pem @@ -0,0 +1,43 @@ +-----BEGIN CERTIFICATE----- +MIIDXTCCAkWgAwIBAgIUKR+dap3TpKhxmpwtNLchLa7E4JEwDQYJKoZIhvcNAQEL +BQAwWTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcT +CVN1bm55dmFsZTEOMAwGA1UEChMFSXN0aW8xETAPBgNVBAMTCElzdGlvIENBMB4X +DTIwMDgxNDIyMTA0OVoXDTMwMDgxMjIyMTA0OVowADCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAM3y5xVP1qYDsy4DSEG7eXhQEGL/XUbXOR1kTEXTAhAk +/Wo0YclowxRQuIyeXpLM+nRN2z0xDttkMRpI0m6Qb1vK43XtPkBieVm/tBSUyis+ +iBV6KBOhw7ionoAlyq6tOkwL2V3siMK5LvkpeeC7lJPJamaRN19LJcnWS214bcur +lq6g6+owQGb4BS4STqfiRkIciw7MHTN5vWQcNmWNT3ME19KNQGKLXPkJGJoNlq4P +98pIuO58k0mow8xESpmrJ1zOtMtUUDicXV67m8BV2xkn7YLDehfAyKsqMJjsdWB3 +LUlk/kFia9n/AwFz+3mMSPWe4OnRQGdtwUMuanknfSUCAwEAAaN2MHQwDgYDVR0P +AQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMB +Af8EAjAAMDUGA1UdEQEB/wQrMCmGJ3NwaWZmZTovL3RydXN0LWRvbWFpbi1mb28v +bnMvZm9vL3NhL2ZvbzANBgkqhkiG9w0BAQsFAAOCAQEAO3Rcr/CEnEieuKujrQ/j +ZrM5cjQckt/+NcpkXsTQaqpkARmUL23D/g3Cg3P9rfJVIfSIfN2509meX+ouDzIm +JWoFW3XVFLiev18aBBO6rmLaMMMKiVOZYAYzeM8Zt/3qH8mLxNq2CQYUL8EtAd7V +P1FVx6vauFqlyqPn2BWZO3CgdGyPwPRQkBUTrItcUI8OTgAFYd/Q5vQuLt82QIAl +givsPvGaKEWV02tpf8PfAZDgXrFkJLeFhFd0pgf7RSIdvShNdPyyz4r9/2CqEVmc +BRDyTw09OLceF0Mhi4HqcnzgVeLWvWT+yUo3FYf6kzeavK93CEdSU8c9OvQbyi9D +cQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDnzCCAoegAwIBAgIJAON1ifrBZ2/BMA0GCSqGSIb3DQEBCwUAMIGLMQswCQYD +VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJU3Vubnl2YWxl +MQ4wDAYDVQQKDAVJc3RpbzENMAsGA1UECwwEVGVzdDEQMA4GA1UEAwwHUm9vdCBD +QTEiMCAGCSqGSIb3DQEJARYTdGVzdHJvb3RjYUBpc3Rpby5pbzAgFw0xODAxMjQx +OTE1NTFaGA8yMTE3MTIzMTE5MTU1MVowWTELMAkGA1UEBhMCVVMxEzARBgNVBAgT +CkNhbGlmb3JuaWExEjAQBgNVBAcTCVN1bm55dmFsZTEOMAwGA1UEChMFSXN0aW8x +ETAPBgNVBAMTCElzdGlvIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAyzCxr/xu0zy5rVBiso9ffgl00bRKvB/HF4AX9/ytmZ6Hqsy13XIQk8/u/By9 +iCvVwXIMvyT0CbiJq/aPEj5mJUy0lzbrUs13oneXqrPXf7ir3HzdRw+SBhXlsh9z +APZJXcF93DJU3GabPKwBvGJ0IVMJPIFCuDIPwW4kFAI7R/8A5LSdPrFx6EyMXl7K +M8jekC0y9DnTj83/fY72WcWX7YTpgZeBHAeeQOPTZ2KYbFal2gLsar69PgFS0Tom +ESO9M14Yit7mzB1WDK2z9g3r+zLxENdJ5JG/ZskKe+TO4Diqi5OJt/h8yspS1ck8 +LJtCole9919umByg5oruflqIlQIDAQABozUwMzALBgNVHQ8EBAMCAgQwDAYDVR0T +BAUwAwEB/zAWBgNVHREEDzANggtjYS5pc3Rpby5pbzANBgkqhkiG9w0BAQsFAAOC +AQEAltHEhhyAsve4K4bLgBXtHwWzo6SpFzdAfXpLShpOJNtQNERb3qg6iUGQdY+w +A2BpmSkKr3Rw/6ClP5+cCG7fGocPaZh+c+4Nxm9suMuZBZCtNOeYOMIfvCPcCS+8 +PQ/0hC4/0J3WJKzGBssaaMufJxzgFPPtDJ998kY8rlROghdSaVt423/jXIAYnP3Y +05n8TGERBj7TLdtIVbtUIx3JHAo3PWJywA6mEDovFMJhJERp9sDHIr1BbhXK1TFN +Z6HNH6gInkSSMtvC4Ptejb749PTaePRPF7ID//eq/3AH8UK50F3TQcLjEqWUsJUn +aFKltOc+RAjzDklcUPeG4Y6eMA== +-----END CERTIFICATE----- diff --git a/pkg/servicemesh/federation/example/config-poc/cacerts/workload-foo-key.pem b/pkg/servicemesh/federation/example/config-poc/cacerts/workload-foo-key.pem new file mode 100644 index 00000000000..bfad4d4cde4 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/cacerts/workload-foo-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAzfLnFU/WpgOzLgNIQbt5eFAQYv9dRtc5HWRMRdMCECT9ajRh +yWjDFFC4jJ5eksz6dE3bPTEO22QxGkjSbpBvW8rjde0+QGJ5Wb+0FJTKKz6IFXoo +E6HDuKiegCXKrq06TAvZXeyIwrku+Sl54LuUk8lqZpE3X0slydZLbXhty6uWrqDr +6jBAZvgFLhJOp+JGQhyLDswdM3m9ZBw2ZY1PcwTX0o1AYotc+QkYmg2Wrg/3yki4 +7nyTSajDzERKmasnXM60y1RQOJxdXrubwFXbGSftgsN6F8DIqyowmOx1YHctSWT+ +QWJr2f8DAXP7eYxI9Z7g6dFAZ23BQy5qeSd9JQIDAQABAoIBAQDLs7PpGnze284A +dvKjQYFWBSsQIDDsfrhZX/kpHxptSYj14TXPdzVtBKJlQ8ebP++B1fhBwCJH0gPX +UawB/A6JJlZxL+Vg3YXVxY2ixcBpoYIMbDTzpg7muLF9YuPkfiapTRcElY53u57A +h8urAx5kRtZc+MliEfwgdTtJ3dILnbXxGanKfi+nz9P5YuLkKzqIolbqu9ZxlJFD +/V4DKITA0IootE0OhCKP0GfeA6L9z3tH2OuEn/LXl2S8FbbFCeY4ji8FQBr2icSB +pXdee0gYIrvrU8G0eoE0ZV9bAGXkRhA3057HF9RqlAqhRc012s4ojbl/q4uINdWp +R+UiUecJAoGBAP4Pzo+NwS054kOgSYu+NMSi63j2OJD9aeHYJT6QwVYZurTMChxx +x283Da4qsCBGI37YjU5Ygd6DYc0T57GXfeka8tZQb5+v/ZvV1oIY+pVN5cp0xben +Ttm0qskF2H57TmPcH5atWkW7b5CjrSo7DYFtd6jKzzoAJ9uPH4DCM5ufAoGBAM+F +IRkSmzAPpiyPA1P7OlWy0vQLsNrFwZ59HOmovpQTgDLVW5Xbq+etEiAXmSvuxBU0 +OKiHMgGK2Pmg/vsM3mUVskrx+bDk+6GGM52feqa8N1rtxDTjamI5EHx29896jX/U +HGSW+8YYVZ/jbSSneY71AO1E2INsNEi1Ei5qWTC7AoGABOdnNEwnK2lPncCNSt48 +BIOkiewuwVWy4oIaje+bW78ZZH3/v/bOQ65LXE5EogrYio1BhP6eWx4sGBpHQZ1L +9+DmSQ66aNmryoNBJbe3toQPaG4Clv3qvrcHCORM/nwA0lqgXXcxI+FvUNpn8EW9 +h/8F7UMk5tiz7EAB+qlE978CgYAJBj8UOgzpoCSX13hLlKdKxsYJuuBsAyGSZNp3 +BtGS2u4+R6z97Vmib5JUNvKASJfaXDUCjy6LhqA86tVr0XlyZ+ki/TbgjHSs54sj +FaZdzd2SZLidnC4qK1UeNIY+TZQNtQmvDinQyYofs+IxL99HajwqFU5dGL2FU+qA +fjt2tQKBgQDrnpSRmAhhGcazmNVnzF8PVJGPwY4clGKB2jo6ru57tL0QRc/N+5pJ +8boLB7CqRpC0mHpijJLKkLoJ0oVoC9jsn3e8tfVuVqbO3AfwdB+nkABQVHRxRRGt +AlUeHXbjlY7OpemfK3smhLGBoOZKJVL7cKwyJc5MTPjcUgMwlwbW5w== +-----END RSA PRIVATE KEY----- diff --git a/pkg/servicemesh/federation/example/config-poc/cleanup.sh b/pkg/servicemesh/federation/example/config-poc/cleanup.sh new file mode 100755 index 00000000000..abb1c6c14e7 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/cleanup.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Copyright Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# shellcheck disable=SC1091 +source common.sh + +oc1 delete -n mesh1-system servicemeshpeer/mesh2 +oc2 delete -n mesh2-system servicemeshpeer/mesh1 + +oc1 delete project mesh1-system +oc2 delete project mesh2-system +# oc1 delete project mesh1-exports +# oc2 delete project mesh2-imports +oc1 delete project mesh1-bookinfo +oc2 delete project mesh2-bookinfo diff --git a/pkg/servicemesh/federation/example/config-poc/common.sh b/pkg/servicemesh/federation/example/config-poc/common.sh new file mode 100644 index 00000000000..df77127aa6c --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/common.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# Copyright Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +if [ ! -f "${MESH1_KUBECONFIG}" ] || [ ! -f "${MESH2_KUBECONFIG}" ]; then + echo "Environment variables MESH1_KUBECONFIG and/or MESH2_KUBECONFIG aren't set." + echo "Please point each to the kubeconfig file of the cluster you want to deploy" + echo "the federated service meshes to. The first cluster exports services;" + echo "the second imports them." + echo + echo "NOTE: You can use a single cluster by pointing both environment variables" + echo "to the same file. The meshes and apps are always deployed in different" + echo "namespaces (mesh1-system, mesh1-bookinfo, mesh2-system, mesh2-bookinfo)," + echo "so there are no conflicts." + exit 1 +fi + +oc1() { + if [ -f "${MESH1_KUBECONFIG}" ]; then + oc --kubeconfig="${MESH1_KUBECONFIG}" "$@" + else + oc "$@" + fi +} + +oc2() { + if [ -f "${MESH2_KUBECONFIG}" ]; then + oc --kubeconfig="${MESH2_KUBECONFIG}" "$@" + else + oc "$@" + fi +} + +log() { + echo + echo "##### $*" +} + +log "Using the following kubeconfig files: +mesh1: ${MESH1_KUBECONFIG} +mesh2: ${MESH2_KUBECONFIG}" + diff --git a/pkg/servicemesh/federation/example/config-poc/examples/authorizationpolicy-direct-to-direct.yaml b/pkg/servicemesh/federation/example/config-poc/examples/authorizationpolicy-direct-to-direct.yaml new file mode 100644 index 00000000000..8f3da945ca8 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/examples/authorizationpolicy-direct-to-direct.yaml @@ -0,0 +1,52 @@ +# AuthorizationPolicy resources that apply when ingress gateway is using +# AUTO_PASSTHROUGH. In these cases, the gateway does not authenticate, so +# the policy cannot match against principals. Note, if proxying on the import +# side, the egress gateway's principal should be used instead of the workload's. + +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: mongodb-authz + namespace: mesh1-bookinfo +spec: + action: ALLOW + selector: + matchLabels: + app: mongodb + rules: + - from: + - source: + principals: + - cluster.local/ns/mesh2-bookinfo/sa/bookinfo-ratings-v2 + to: + - operation: + ports: + - '27017' + when: + - key: connection.sni + values: + - '*.mongodb.mesh1-exports.svc.cluster.local' + +--- + +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: ratings-authz + namespace: mesh1-bookinfo +spec: + action: ALLOW + selector: + matchLabels: + app: ratings + rules: + - from: + - source: + principals: + - cluster.local/ns/mesh2-bookinfo/sa/bookinfo-reviews-v2 + to: + - operation: + hosts: + - '*.ratings.mesh1-bookinfo.svc.local' + ports: + - '9080' diff --git a/pkg/servicemesh/federation/example/config-poc/examples/authorizationpolicy-direct-to-proxied.yaml b/pkg/servicemesh/federation/example/config-poc/examples/authorizationpolicy-direct-to-proxied.yaml new file mode 100644 index 00000000000..58f5c367b78 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/examples/authorizationpolicy-direct-to-proxied.yaml @@ -0,0 +1,38 @@ +# These work when using aliased services. In these cases, the gateway +# performs authentication, so principals can be checked. Note, if using +# passthrough on the import side, the principals should match the client +# workloads, e.g. cluster.local/ns/mesh2-bookinfo/sa/bookinfo-ratings-v2 for +# mongodb-aliased. + +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy +metadata: + name: aliased-authz + namespace: mesh1-exports +spec: + action: ALLOW + rules: + - from: + - source: + principals: + - cluster.local/ns/mesh2-bookinfo/sa/bookinfo-ratings-v2 + to: + - operation: + ports: + - "27017" + when: + - key: connection.sni + values: + - "*.mongodb.bookinfo.svc.mesh2.local" + - from: + - source: + principals: + - cluster.local/ns/mesh2-bookinfo/sa/bookinfo-reviews-v2 + to: + - operation: + ports: + - "9080" + when: + - key: connection.sni + values: + - "*.ratings.bookinfo.svc.mesh2.local" diff --git a/pkg/servicemesh/federation/example/config-poc/examples/mongodb-remote-virtualservice.yaml b/pkg/servicemesh/federation/example/config-poc/examples/mongodb-remote-virtualservice.yaml new file mode 100644 index 00000000000..1917fc73e03 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/examples/mongodb-remote-virtualservice.yaml @@ -0,0 +1,15 @@ +# VirtualService resource that redirects the local service to the remote +# services. This only works with passthrough. + +kind: VirtualService +apiVersion: networking.istio.io/v1alpha3 +metadata: + name: mongodb-remote + namespace: mesh2-bookinfo +spec: + hosts: + - mongodb.mesh2-bookinfo.svc.cluster.local + tcp: + - route: + - destination: + host: mongodb.mesh2-bookinfo.svc.mesh1-imports.local diff --git a/pkg/servicemesh/federation/example/config-poc/examples/ratings-split-virtualservice.yaml b/pkg/servicemesh/federation/example/config-poc/examples/ratings-split-virtualservice.yaml new file mode 100644 index 00000000000..5543eda0656 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/examples/ratings-split-virtualservice.yaml @@ -0,0 +1,19 @@ +# VirtualService resource that redirects the local service to the remote +# services. This only works with passthrough. + +kind: VirtualService +apiVersion: networking.istio.io/v1alpha3 +metadata: + name: ratings-split + namespace: mesh2-bookinfo +spec: + hosts: + - ratings.mesh2-bookinfo.svc.cluster.local + http: + - route: + - destination: + host: ratings.mesh2-bookinfo.svc.mesh1-imports.local + weight: 50 + - destination: + host: ratings.mesh2-bookinfo.svc.cluster.local + weight: 50 diff --git a/pkg/servicemesh/federation/example/config-poc/export/configmap.yaml b/pkg/servicemesh/federation/example/config-poc/export/configmap.yaml new file mode 100644 index 00000000000..416bbb25518 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/export/configmap.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: mesh2-ca-root-cert + namespace: mesh1-system +data: + root-cert.pem: |- + {{MESH2_CERT}} diff --git a/pkg/servicemesh/federation/example/config-poc/export/exportedserviceset.yaml b/pkg/servicemesh/federation/example/config-poc/export/exportedserviceset.yaml new file mode 100644 index 00000000000..93371ae94a5 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/export/exportedserviceset.yaml @@ -0,0 +1,21 @@ +apiVersion: federation.maistra.io/v1 +kind: ExportedServiceSet +metadata: + name: mesh2 + namespace: mesh1-system +spec: + exportRules: + - type: NameSelector + nameSelector: + namespace: mesh1-bookinfo + name: ratings + alias: + namespace: bookinfo + name: ratings + - type: NameSelector + nameSelector: + namespace: mesh1-bookinfo + name: mongodb + alias: + namespace: bookinfo + name: mongodb diff --git a/pkg/servicemesh/federation/example/config-poc/export/servicemeshpeer.yaml b/pkg/servicemesh/federation/example/config-poc/export/servicemeshpeer.yaml new file mode 100644 index 00000000000..7677c720b63 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/export/servicemeshpeer.yaml @@ -0,0 +1,23 @@ +apiVersion: federation.maistra.io/v1 +kind: ServiceMeshPeer +metadata: + name: mesh2 + namespace: mesh1-system +spec: + remote: + addresses: + - {{MESH2_ADDRESS}} + discoveryPort: {{MESH2_DISCOVERY_PORT}} + servicePort: {{MESH2_SERVICE_PORT}} + gateways: + ingress: + name: mesh2-ingress + egress: + name: mesh2-egress + security: + trustDomain: mesh2.local + clientID: mesh2.local/ns/mesh2-system/sa/mesh1-egress-service-account + # same as default, if certificateChain is omitted + certificateChain: + kind: ConfigMap + name: mesh2-ca-root-cert diff --git a/pkg/servicemesh/federation/example/config-poc/export/smcp.yaml b/pkg/servicemesh/federation/example/config-poc/export/smcp.yaml new file mode 100644 index 00000000000..a56d6699334 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/export/smcp.yaml @@ -0,0 +1,94 @@ +apiVersion: maistra.io/v2 +kind: ServiceMeshControlPlane +metadata: + name: fed-export + namespace: mesh1-system +spec: + version: v2.2 + runtime: + defaults: + container: + # for testing, to ensure we're always using the latest dev image + imagePullPolicy: Always + addons: + grafana: + enabled: true + kiali: + enabled: true + prometheus: + enabled: true + tracing: + type: Jaeger + sampling: 10000 + proxy: + accessLogging: + file: + name: /dev/stdout + gateways: + additionalEgress: + # egress gateway definition for sending requests from mesh2 + mesh2-egress: + enabled: true + requestedNetworkView: + # we want to view services on mesh2's network + - network-mesh2 + routerMode: sni-dnat + service: + metadata: + labels: + # to prevent mesh2-egress's service from including default egress pods + federation.maistra.io/egress-for: mesh2 + ports: + # required for sending service requests to mesh2 + - port: 15443 + name: tls + # required for sending discovery requests to mesh2 + - port: 8188 + name: http-discovery + runtime: + deployment: + autoScaling: + enabled: false + container: + # constrain resources for use in smaller environments + resources: + requests: + cpu: 10m + memory: 128Mi + limits: {} + additionalIngress: + # ingress gateway definition for handing requests from mesh2 + mesh2-ingress: + enabled: true + routerMode: sni-dnat + service: + type: LoadBalancer + metadata: + labels: + # to prevent mesh2-ingress's service from including default ingress pods + federation.maistra.io/ingress-for: mesh2 + annotations: + # use the network load balancer on AWS + service.beta.kubernetes.io/aws-load-balancer-type: nlb + ports: + # required for handling service requests from mesh2 + - port: 15443 + name: tls + # required for handing discovery requests from mesh2 + - port: 8188 + name: https-discovery + runtime: + deployment: + autoScaling: + enabled: false + container: + # constrain resources for use in smaller environments + resources: + requests: + cpu: 10m + memory: 128Mi + limits: {} + security: + trust: + # unique trust domain for this mesh, mesh1 + domain: mesh1.local diff --git a/pkg/servicemesh/federation/example/config-poc/export/smmr.yaml b/pkg/servicemesh/federation/example/config-poc/export/smmr.yaml new file mode 100644 index 00000000000..b665e255c5e --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/export/smmr.yaml @@ -0,0 +1,8 @@ +apiVersion: maistra.io/v1 +kind: ServiceMeshMemberRoll +metadata: + name: default + namespace: mesh1-system +spec: + members: + - mesh1-bookinfo diff --git a/pkg/servicemesh/federation/example/config-poc/import/configmap.yaml b/pkg/servicemesh/federation/example/config-poc/import/configmap.yaml new file mode 100644 index 00000000000..fec454406cb --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/import/configmap.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: mesh1-ca-root-cert + namespace: mesh2-system +data: + root-cert.pem: |- + {{MESH1_CERT}} diff --git a/pkg/servicemesh/federation/example/config-poc/import/importedserviceset.yaml b/pkg/servicemesh/federation/example/config-poc/import/importedserviceset.yaml new file mode 100644 index 00000000000..2ce6e317c54 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/import/importedserviceset.yaml @@ -0,0 +1,16 @@ +apiVersion: federation.maistra.io/v1 +kind: ImportedServiceSet +metadata: + name: mesh1 + namespace: mesh2-system +spec: + importRules: + - type: NameSelector + # Set to true to aggregate remote endpoint with local services. + # When true, services will be imported as .mesh2-bookinfo.svc.cluster.local + importAsLocal: false + nameSelector: + namespace: bookinfo + alias: + # services will be imported as .mesh2-bookinfo.svc.mesh1-imports.local + namespace: mesh2-bookinfo diff --git a/pkg/servicemesh/federation/example/config-poc/import/mongodb-service.yaml b/pkg/servicemesh/federation/example/config-poc/import/mongodb-service.yaml new file mode 100644 index 00000000000..c513f767860 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/import/mongodb-service.yaml @@ -0,0 +1,12 @@ +# This is required, as apparently a VirtualService matching +# mongodb.mesh2-bookinfo.svc.cluster.local does not create DNS entry for routing +kind: Service +apiVersion: v1 +metadata: + name: mongodb + namespace: mesh2-bookinfo +spec: + type: ClusterIP + ports: + - port: 27017 + name: mongo diff --git a/pkg/servicemesh/federation/example/config-poc/import/servicemeshpeer.yaml b/pkg/servicemesh/federation/example/config-poc/import/servicemeshpeer.yaml new file mode 100644 index 00000000000..70904aa4016 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/import/servicemeshpeer.yaml @@ -0,0 +1,23 @@ +apiVersion: federation.maistra.io/v1 +kind: ServiceMeshPeer +metadata: + name: mesh1 + namespace: mesh2-system +spec: + remote: + addresses: + - {{MESH1_ADDRESS}} + discoveryPort: {{MESH1_DISCOVERY_PORT}} + servicePort: {{MESH1_SERVICE_PORT}} + gateways: + ingress: + name: mesh1-ingress + egress: + name: mesh1-egress + security: + trustDomain: mesh1.local + clientID: mesh1.local/ns/mesh1-system/sa/mesh2-egress-service-account + # same as default, if certificateChain is omitted + certificateChain: + kind: ConfigMap + name: mesh1-ca-root-cert diff --git a/pkg/servicemesh/federation/example/config-poc/import/smcp.yaml b/pkg/servicemesh/federation/example/config-poc/import/smcp.yaml new file mode 100644 index 00000000000..25bc7646381 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/import/smcp.yaml @@ -0,0 +1,94 @@ +apiVersion: maistra.io/v2 +kind: ServiceMeshControlPlane +metadata: + name: fed-import + namespace: mesh2-system +spec: + version: v2.2 + runtime: + defaults: + container: + # for testing, to ensure we're always using the latest dev image + imagePullPolicy: Always + addons: + grafana: + enabled: true + kiali: + enabled: true + prometheus: + enabled: true + tracing: + type: Jaeger + sampling: 10000 + proxy: + accessLogging: + file: + name: /dev/stdout + gateways: + additionalEgress: + # egress gateway definition for sending requests from mesh1 + mesh1-egress: + enabled: true + requestedNetworkView: + # we want to view services on mesh1's network + - network-mesh1 + routerMode: sni-dnat + service: + metadata: + labels: + # to prevent mesh1-egress's service from including default egress pods + federation.maistra.io/egress-for: mesh1 + ports: + # required for sending service requests to mesh1 + - port: 15443 + name: tls + # required for sending discovery requests to mesh1 + - port: 8188 + name: http-discovery + runtime: + deployment: + autoScaling: + enabled: false + container: + # constrain resources for use in smaller environments + resources: + requests: + cpu: 10m + memory: 128Mi + limits: {} + additionalIngress: + # ingress gateway definition for handing requests from mesh1 + mesh1-ingress: + enabled: true + routerMode: sni-dnat + service: + type: LoadBalancer + metadata: + labels: + # to prevent mesh1-ingress's service from including default ingress pods + federation.maistra.io/ingress-for: mesh1 + annotations: + # use the network load balancer on AWS + service.beta.kubernetes.io/aws-load-balancer-type: nlb + ports: + # required for handling service requests from mesh1 + - port: 15443 + name: tls + # required for handing discovery requests from mesh1 + - port: 8188 + name: https-discovery + runtime: + deployment: + autoScaling: + enabled: false + container: + # constrain resources for use in smaller environments + resources: + requests: + cpu: 10m + memory: 128Mi + limits: {} + security: + trust: + # unique trust domain for this mesh, mesh2 + domain: mesh2.local diff --git a/pkg/servicemesh/federation/example/config-poc/import/smmr.yaml b/pkg/servicemesh/federation/example/config-poc/import/smmr.yaml new file mode 100644 index 00000000000..7de7a450300 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/import/smmr.yaml @@ -0,0 +1,8 @@ +apiVersion: maistra.io/v1 +kind: ServiceMeshMemberRoll +metadata: + name: default + namespace: mesh2-system +spec: + members: + - mesh2-bookinfo diff --git a/pkg/servicemesh/federation/example/config-poc/install.sh b/pkg/servicemesh/federation/example/config-poc/install.sh new file mode 100755 index 00000000000..4a64e94c6a6 --- /dev/null +++ b/pkg/servicemesh/federation/example/config-poc/install.sh @@ -0,0 +1,154 @@ +#!/bin/bash + +# Copyright Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +# shellcheck disable=SC1091 +source common.sh + +log "Creating projects for mesh1" +oc1 new-project mesh1-system || true +oc1 new-project mesh1-bookinfo || true + +log "Installing control plane for mesh1" +oc1 apply -f export/smcp.yaml +oc1 apply -f export/smmr.yaml + +log "Creating projects for mesh2" +oc2 new-project mesh2-system || true +oc2 new-project mesh2-bookinfo || true + +log "Installing control plane for mesh2" +oc2 apply -f import/smcp.yaml +oc2 apply -f import/smmr.yaml + +log "Waiting for mesh1 installation to complete" +oc1 wait --for condition=Ready -n mesh1-system smmr/default --timeout 300s + +log "Waiting for mesh2 installation to complete" +oc2 wait --for condition=Ready -n mesh2-system smmr/default --timeout 300s + +log "Retrieving root certificates" +MESH1_CERT=$(oc1 get configmap -n mesh1-system istio-ca-root-cert -o jsonpath='{.data.root-cert\.pem}' | sed ':a;N;$!ba;s/\n/\\\n /g') +MESH2_CERT=$(oc2 get configmap -n mesh2-system istio-ca-root-cert -o jsonpath='{.data.root-cert\.pem}' | sed ':a;N;$!ba;s/\n/\\\n /g') + +MESH1_DISCOVERY_PORT="${MESH1_DISCOVERY_PORT:-8188}" +MESH1_SERVICE_PORT="${MESH1_SERVICE_PORT:-15443}" +MESH2_DISCOVERY_PORT="${MESH2_DISCOVERY_PORT:-8188}" +MESH2_SERVICE_PORT="${MESH2_SERVICE_PORT:-15443}" + +log "Retrieving ingress addresses" +if [ "${MESH1_KUBECONFIG}" == "${MESH2_KUBECONFIG}" ]; then + echo "Single cluster detected; using cluster-local service for ingress" + MESH1_ADDRESS=mesh2-ingress.mesh1-system.svc.cluster.local + MESH2_ADDRESS=mesh1-ingress.mesh2-system.svc.cluster.local +else + echo "Two clusters detected; using load-balancer service for ingress" + + while [ -z "$MESH1_ADDRESS" ] + do + MESH1_ADDRESS=$(oc1 -n mesh1-system get svc mesh2-ingress -o jsonpath="{.status.loadBalancer.ingress[].ip}") + if [ -z "$MESH1_ADDRESS" ]; then + MESH1_ADDRESS=$(oc1 -n mesh1-system get svc mesh2-ingress -o jsonpath="{.status.loadBalancer.ingress[].hostname}") + if [ -z "$MESH1_ADDRESS" ]; then + echo "Waiting for load balancer IP/hostname of Service mesh1-system/mesh2-ingress..." + sleep 30 + fi + fi + done + + while [ -z "$MESH2_ADDRESS" ] + do + MESH2_ADDRESS=$(oc2 -n mesh2-system get svc mesh1-ingress -o jsonpath="{.status.loadBalancer.ingress[].ip}") + if [ -z "$MESH2_ADDRESS" ]; then + MESH2_ADDRESS=$(oc2 -n mesh2-system get svc mesh1-ingress -o jsonpath="{.status.loadBalancer.ingress[].hostname}") + if [ -z "$MESH2_ADDRESS" ]; then + echo "Waiting for load balancer IP/hostname of Service mesh2-system/mesh1-ingress..." + sleep 30 + fi + fi + done +fi + +echo +echo MESH1_ADDRESS="${MESH1_ADDRESS}" +echo MESH1_DISCOVERY_PORT="${MESH1_DISCOVERY_PORT}" +echo MESH1_SERVICE_PORT="${MESH1_SERVICE_PORT}" +echo +echo MESH2_ADDRESS="${MESH2_ADDRESS}" +echo MESH2_DISCOVERY_PORT="${MESH2_DISCOVERY_PORT}" +echo MESH2_SERVICE_PORT="${MESH2_SERVICE_PORT}" + +log "Enabling federation for mesh1" +sed "s:{{MESH2_CERT}}:$MESH2_CERT:g" export/configmap.yaml | oc1 apply -f - +sed -e "s:{{MESH2_ADDRESS}}:$MESH2_ADDRESS:g" -e "s:{{MESH2_DISCOVERY_PORT}}:$MESH2_DISCOVERY_PORT:g" -e "s:{{MESH2_SERVICE_PORT}}:$MESH2_SERVICE_PORT:g" export/servicemeshpeer.yaml | oc1 apply -f - +oc1 apply -f export/exportedserviceset.yaml + +log "Enabling federation for mesh2" +sed "s:{{MESH1_CERT}}:$MESH1_CERT:g" import/configmap.yaml | oc2 apply -f - +sed -e "s:{{MESH1_ADDRESS}}:$MESH1_ADDRESS:g" -e "s:{{MESH1_DISCOVERY_PORT}}:$MESH1_DISCOVERY_PORT:g" -e "s:{{MESH1_SERVICE_PORT}}:$MESH1_SERVICE_PORT:g" import/servicemeshpeer.yaml | oc2 apply -f - +oc2 apply -f import/importedserviceset.yaml + +log "Installing bookinfo in mesh1" +oc1 -n mesh1-bookinfo apply -f ../../../../../samples/bookinfo/platform/kube/bookinfo.yaml +oc1 -n mesh1-bookinfo apply -f ../../../../../samples/bookinfo/platform/kube/bookinfo-ratings-v2.yaml +oc1 -n mesh1-bookinfo apply -f ../../../../../samples/bookinfo/platform/kube/bookinfo-db.yaml +oc1 -n mesh1-bookinfo apply -f ../../../../../samples/bookinfo/networking/destination-rule-all.yaml + +log "Installing bookinfo in mesh2" +oc2 -n mesh2-bookinfo apply -f ../../../../../samples/bookinfo/platform/kube/bookinfo.yaml +oc2 -n mesh2-bookinfo apply -f ../../../../../samples/bookinfo/platform/kube/bookinfo-ratings-v2.yaml +oc2 -n mesh2-bookinfo apply -f ../../../../../samples/bookinfo/networking/bookinfo-gateway.yaml +oc2 -n mesh2-bookinfo apply -f ../../../../../samples/bookinfo/networking/destination-rule-all.yaml +oc2 -n mesh2-bookinfo apply -f ../../../../../samples/bookinfo/networking/virtual-service-reviews-v3.yaml + +log "Installing mongodb k8s Service for mesh2" +oc2 apply -f import/mongodb-service.yaml + +log "Installing VirtualServices for mesh2" +oc2 apply -f examples/mongodb-remote-virtualservice.yaml +oc2 apply -f examples/ratings-split-virtualservice.yaml + +log "INSTALLATION COMPLETE + +Two service mesh control planes and two bookinfo applications are now installed. +The first cluster (mesh1) contains the namespace mesh1-system and mesh1-bookinfo. +The second cluster (mesh2) contains mesh2-system and mesh2-bookinfo. +Mesh1 exports services, mesh2 imports them. + +The meshes are configured to split ratings traffic in mesh2-bookinfo between +mesh1 and mesh2. The ratings service in mesh2 is configured to use the +mongodb service in mesh1. + +Run the following command in the mesh1 cluster to check the connection status: + + oc -n mesh1-system get servicemeshpeer mesh2 -o json | jq .status + +Run the following command to check the connection status in mesh2: + + oc -n mesh2-system get servicemeshpeer mesh1 -o json | jq .status + +Check if services from mesh1 are imported into mesh2: + + oc -n mesh2-system get importedservicesets mesh1 -o json | jq .status + +To see federation in action, use the bookinfo app in mesh2. For example: + + 1. Run this command in the mesh1 cluster: oc logs -n mesh1-bookinfo svc/ratings -f + 2. Run this command in the mesh2 cluster: oc logs -n mesh2-bookinfo svc/ratings -f + 3. Open http://$(oc2 -n mesh2-system get route istio-ingressgateway -o json | jq -r .spec.host)/productpage + 4. Refresh the page several times and observe requests hitting either the mesh1 or the mesh2 cluster. +" diff --git a/pkg/servicemesh/federation/exports/controller.go b/pkg/servicemesh/federation/exports/controller.go new file mode 100644 index 00000000000..4541bcb9dd5 --- /dev/null +++ b/pkg/servicemesh/federation/exports/controller.go @@ -0,0 +1,112 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package exports + +import ( + "fmt" + "time" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/federation/v1" + + kubecontroller "istio.io/istio/pkg/kube/controller" + "istio.io/istio/pkg/servicemesh/federation/common" +) + +const controllerName = "federation-exports-controller" + +type ServiceExportManager interface { + UpdateExportsForMesh(exports *v1.ExportedServiceSet) error + DeleteExportsForMesh(name string) +} + +type Options struct { + ResourceManager common.ResourceManager + ResyncPeriod time.Duration + ServiceExportManager ServiceExportManager +} + +type Controller struct { + *kubecontroller.Controller + rm common.ResourceManager + exportManager ServiceExportManager +} + +// NewController creates a new ServiceExports controller +func NewController(opt Options) (*Controller, error) { + if err := opt.validate(); err != nil { + return nil, fmt.Errorf("invalid Options specified for federation export controller: %s", err) + } + controller := &Controller{ + rm: opt.ResourceManager, + exportManager: opt.ServiceExportManager, + } + internalController := kubecontroller.NewController(kubecontroller.Options{ + Informer: opt.ResourceManager.ExportsInformer().Informer(), + Logger: common.Logger.WithLabels("component", controllerName), + ResyncPeriod: opt.ResyncPeriod, + Reconciler: controller.reconcile, + }) + controller.Controller = internalController + + return controller, nil +} + +func (c *Controller) RunInformer(stopChan <-chan struct{}) { + // no-op, informer is started by the shared factory in Federation.Start() +} + +func (c *Controller) reconcile(resourceName string) error { + c.Logger.Debugf("Reconciling ServiceExports %s", resourceName) + defer func() { + c.Logger.Debugf("Completed reconciliation of ServiceExports %s", resourceName) + }() + + namespace, name, err := cache.SplitMetaNamespaceKey(resourceName) + if err != nil { + c.Logger.Errorf("error splitting resource name: %s", resourceName) + } + instance, err := c.rm.ExportsInformer().Lister().ExportedServiceSets(namespace).Get(name) + if err != nil { + if apierrors.IsNotFound(err) || apierrors.IsGone(err) { + // Request object not found, could have been deleted after reconcile request. + // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. + // Return and don't requeue + c.exportManager.DeleteExportsForMesh(name) + c.Logger.Info("ServiceExports deleted") + err = nil + } + return err + } + + return c.exportManager.UpdateExportsForMesh(instance) +} + +func (opt Options) validate() error { + var allErrors []error + if opt.ResourceManager == nil { + allErrors = append(allErrors, fmt.Errorf("the ResourceManager field must not be nil")) + } + if opt.ServiceExportManager == nil { + allErrors = append(allErrors, fmt.Errorf("the ServiceExportManager field must not be nil")) + } + if opt.ResyncPeriod == 0 { + opt.ResyncPeriod = common.DefaultResyncPeriod + common.Logger.WithLabels("component", controllerName).Infof("ResyncPeriod not specified, defaulting to %s", opt.ResyncPeriod) + } + return errors.NewAggregate(allErrors) +} diff --git a/pkg/servicemesh/federation/federation.go b/pkg/servicemesh/federation/federation.go new file mode 100644 index 00000000000..7a312b105c4 --- /dev/null +++ b/pkg/servicemesh/federation/federation.go @@ -0,0 +1,209 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package federation + +import ( + "crypto/tls" + "fmt" + "time" + + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/errors" + maistraclient "maistra.io/api/client/versioned" + + "istio.io/istio/pilot/pkg/config/memory" + "istio.io/istio/pilot/pkg/leaderelection" + "istio.io/istio/pilot/pkg/model" + "istio.io/istio/pilot/pkg/serviceregistry/aggregate" + "istio.io/istio/pkg/config/schema/collection" + "istio.io/istio/pkg/kube" + "istio.io/istio/pkg/servicemesh/federation/common" + "istio.io/istio/pkg/servicemesh/federation/discovery" + "istio.io/istio/pkg/servicemesh/federation/exports" + "istio.io/istio/pkg/servicemesh/federation/imports" + "istio.io/istio/pkg/servicemesh/federation/server" + "istio.io/istio/pkg/servicemesh/federation/status" + "istio.io/pkg/log" +) + +func init() { + schemasBuilder := collection.NewSchemasBuilder() + discovery.Schemas.ForEach(func(s collection.Schema) (done bool) { + // only error is already exists, which we don't care about + _ = schemasBuilder.Add(s) + return false + }) + server.Schemas.ForEach(func(s collection.Schema) (done bool) { + // only error is already exists, which we don't care about + _ = schemasBuilder.Add(s) + return false + }) + schemas = schemasBuilder.Build() +} + +var schemas collection.Schemas + +type Options struct { + KubeClient kube.Client + FederationNamespace string + ResyncPeriod time.Duration + BindAddress string + Env *model.Environment + XDSUpdater model.XDSUpdater + ServiceController *aggregate.Controller + LocalNetwork string + LocalClusterID string + IstiodNamespace string + IstiodPodName string + TLSConfig *tls.Config +} + +type Federation struct { + configStore model.ConfigStoreController + server *server.Server + exportController *exports.Controller + importController *imports.Controller + discoveryController *discovery.Controller + leaderElection *leaderelection.LeaderElection +} + +func New(opt Options) (*Federation, error) { + if err := opt.validate(); err != nil { + return nil, err + } + cs, err := maistraclient.NewForConfig(opt.KubeClient.RESTConfig()) + if err != nil { + return nil, fmt.Errorf("error creating ClientSet for ServiceMesh: %v", err) + } + return internalNew(opt, cs) +} + +func internalNew(opt Options, cs maistraclient.Interface) (*Federation, error) { + resourceManager, err := common.NewResourceManager(common.ControllerOptions{ + KubeClient: opt.KubeClient, + MaistraCS: cs, + ResyncPeriod: opt.ResyncPeriod, + Namespace: opt.FederationNamespace, + }, opt.KubeClient.GetMemberRoll()) + if err != nil { + return nil, err + } + leaderElection := leaderelection.NewLeaderElection(opt.IstiodNamespace, opt.IstiodPodName, "servicemesh-federation", "test", opt.KubeClient) + name := types.NamespacedName{Name: opt.IstiodPodName, Namespace: opt.IstiodNamespace} + statusManager := status.NewManager(name, resourceManager, leaderElection) + configStore := newConfigStore() + server, err := server.NewServer(server.Options{ + BindAddress: opt.BindAddress, + Env: opt.Env, + Network: opt.LocalNetwork, + ConfigStore: configStore, + TLSConfig: opt.TLSConfig, + }) + if err != nil { + return nil, err + } + exportController, err := exports.NewController(exports.Options{ + ResourceManager: resourceManager, + ResyncPeriod: opt.ResyncPeriod, + ServiceExportManager: server, + }) + if err != nil { + return nil, err + } + importController, err := imports.NewController(imports.Options{ + ResourceManager: resourceManager, + ResyncPeriod: opt.ResyncPeriod, + ServiceController: opt.ServiceController, + }) + if err != nil { + return nil, err + } + discoveryController, err := discovery.NewController(discovery.Options{ + ResourceManager: resourceManager, + LocalClusterID: opt.LocalClusterID, + LocalNetwork: opt.LocalNetwork, + ServiceController: opt.ServiceController, + XDSUpdater: opt.XDSUpdater, + Env: opt.Env, + ConfigStore: configStore, + FederationManager: server, + StatusManager: statusManager, + }) + if err != nil { + return nil, err + } + + federation := &Federation{ + configStore: configStore, + server: server, + exportController: exportController, + importController: importController, + discoveryController: discoveryController, + leaderElection: leaderElection, + } + return federation, nil +} + +func newConfigStore() model.ConfigStoreController { + return memory.NewController(memory.Make(schemas)) +} + +func (f *Federation) ConfigStore() model.ConfigStoreController { + return f.configStore +} + +func (f *Federation) RegisterServiceHandlers(serviceController *aggregate.Controller) { + serviceController.AppendServiceHandler(f.server.UpdateService) +} + +func (f *Federation) StartControllers(stopCh <-chan struct{}) { + go f.leaderElection.Run(stopCh) + go f.exportController.Start(stopCh) + go f.importController.Start(stopCh) + f.discoveryController.Start(stopCh) +} + +func (f *Federation) HasSynced() bool { + return f.importController.HasSynced() && f.exportController.HasSynced() && f.discoveryController.HasSynced() +} + +func (f *Federation) StartServer(stopCh <-chan struct{}) { + f.server.Run(stopCh) +} + +func (f *Federation) GetTrustBundles() map[string]string { + return f.discoveryController.GetTrustBundles() +} + +func (opt Options) validate() error { + var allErrors []error + if opt.KubeClient == nil { + allErrors = append(allErrors, fmt.Errorf("the KubeClient field must not be nil")) + } + if opt.XDSUpdater == nil { + allErrors = append(allErrors, fmt.Errorf("the XDSUpdater field must not be nil")) + } + if opt.Env == nil { + allErrors = append(allErrors, fmt.Errorf("the Env field must not be nil")) + } + if opt.ResyncPeriod == 0 { + opt.ResyncPeriod = common.DefaultResyncPeriod + log.Warnf("ResyncPeriod not specified, defaulting to %s", opt.ResyncPeriod) + } + if opt.ServiceController == nil { + allErrors = append(allErrors, fmt.Errorf("the ServiceController field must not be nil")) + } + return errors.NewAggregate(allErrors) +} diff --git a/pkg/servicemesh/federation/federation_test.go b/pkg/servicemesh/federation/federation_test.go new file mode 100644 index 00000000000..9915e52be1d --- /dev/null +++ b/pkg/servicemesh/federation/federation_test.go @@ -0,0 +1,75 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package federation + +import ( + "testing" + + "istio.io/istio/pilot/pkg/model" + "istio.io/istio/pilot/pkg/networking/core/v1alpha3" + "istio.io/istio/pilot/pkg/serviceregistry/aggregate" + "istio.io/istio/pkg/kube" +) + +func TestInvalidOptions(t *testing.T) { + testCases := []struct { + name string + opt Options + }{ + { + name: "client", + opt: Options{ + KubeClient: nil, + ServiceController: &aggregate.Controller{}, + XDSUpdater: &v1alpha3.FakeXdsUpdater{}, + Env: &model.Environment{}, + }, + }, + { + name: "service-controller", + opt: Options{ + KubeClient: kube.NewFakeClient(), + ServiceController: nil, + XDSUpdater: &v1alpha3.FakeXdsUpdater{}, + Env: &model.Environment{}, + }, + }, + { + name: "xds-updater", + opt: Options{ + KubeClient: kube.NewFakeClient(), + ServiceController: &aggregate.Controller{}, + XDSUpdater: nil, + Env: &model.Environment{}, + }, + }, + { + name: "env", + opt: Options{ + KubeClient: kube.NewFakeClient(), + ServiceController: &aggregate.Controller{}, + XDSUpdater: &v1alpha3.FakeXdsUpdater{}, + Env: nil, + }, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if err := tc.opt.validate(); err == nil { + t.Errorf("expected error") + } + }) + } +} diff --git a/pkg/servicemesh/federation/imports/controller.go b/pkg/servicemesh/federation/imports/controller.go new file mode 100644 index 00000000000..345861f23fd --- /dev/null +++ b/pkg/servicemesh/federation/imports/controller.go @@ -0,0 +1,134 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package imports + +import ( + "fmt" + "time" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/federation/v1" + + "istio.io/istio/pilot/pkg/serviceregistry/aggregate" + "istio.io/istio/pilot/pkg/serviceregistry/federation" + kubecontroller "istio.io/istio/pkg/kube/controller" + "istio.io/istio/pkg/servicemesh/federation/common" +) + +const controllerName = "federation-imports-controller" + +type Options struct { + ResourceManager common.ResourceManager + ResyncPeriod time.Duration + ServiceController *aggregate.Controller +} + +type Controller struct { + *kubecontroller.Controller + rm common.ResourceManager + serviceController *aggregate.Controller +} + +// NewController creates a new ServiceImports controller +func NewController(opt Options) (*Controller, error) { + if err := opt.validate(); err != nil { + return nil, fmt.Errorf("invalid Options specified for federation import controller: %s", err) + } + + logger := common.Logger.WithLabels("component", controllerName) + + controller := &Controller{ + rm: opt.ResourceManager, + serviceController: opt.ServiceController, + } + internalController := kubecontroller.NewController(kubecontroller.Options{ + Informer: controller.rm.ImportsInformer().Informer(), + Logger: logger, + ResyncPeriod: opt.ResyncPeriod, + Reconciler: controller.reconcile, + }) + controller.Controller = internalController + + return controller, nil +} + +func (c *Controller) RunInformer(stopChan <-chan struct{}) { + // no-op, informer is started by the shared factory in Federation.Start() +} + +func (c *Controller) reconcile(resourceName string) error { + c.Logger.Debugf("Reconciling ServiceImports %s", resourceName) + defer func() { + c.Logger.Debugf("Completed reconciliation of ServiceImports %s", resourceName) + }() + + namespace, name, err := cache.SplitMetaNamespaceKey(resourceName) + if err != nil { + c.Logger.Errorf("error splitting resource name: %s", resourceName) + } + instance, err := c.rm.ImportsInformer().Lister().ImportedServiceSets(namespace).Get(name) + if err != nil { + if apierrors.IsNotFound(err) || apierrors.IsGone(err) { + // Request object not found, could have been deleted after reconcile request. + // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. + // Return and don't requeue + c.deleteImportsForMesh(namespace, name) + c.Logger.Info("ServiceImports deleted") + err = nil + } + return err + } + + c.updateImportsForMesh(instance) + return nil +} + +func (c *Controller) deleteImportsForMesh(namespace, name string) { + c.updateImportsForMesh(&v1.ImportedServiceSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + }) +} + +func (c *Controller) updateImportsForMesh(instance *v1.ImportedServiceSet) { + for _, registry := range c.serviceController.GetRegistries() { + if registry.Cluster().String() == instance.Name { + if federationRegistry, ok := registry.(*federation.Controller); ok { + federationRegistry.UpdateImportConfig(instance) + break + } + } + } +} + +func (opt Options) validate() error { + var allErrors []error + if opt.ResourceManager == nil { + allErrors = append(allErrors, fmt.Errorf("the ResourceManager field must not be nil")) + } + if opt.ServiceController == nil { + allErrors = append(allErrors, fmt.Errorf("the ServiceController field must not be nil")) + } + if opt.ResyncPeriod == 0 { + opt.ResyncPeriod = common.DefaultResyncPeriod + common.Logger.WithLabels("component", controllerName).Infof("ResyncPeriod not specified, defaulting to %s", opt.ResyncPeriod) + } + return errors.NewAggregate(allErrors) +} diff --git a/pkg/servicemesh/federation/model/model.go b/pkg/servicemesh/federation/model/model.go new file mode 100644 index 00000000000..bfe05aa499c --- /dev/null +++ b/pkg/servicemesh/federation/model/model.go @@ -0,0 +1,79 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package model + +import hashstructure "github.com/mitchellh/hashstructure/v2" + +type ServiceKey struct { + Name string `json:"name,omitempty"` + Namespace string `json:"namespace,omitempty"` + Hostname string `json:"hostname,omitempty"` +} + +type ServiceListMessage struct { + Checksum uint64 `json:"checksum" hash:"ignore"` + NetworkGatewayEndpoints []*ServiceEndpoint `json:"networkGatewayEndpoints,omitempty" hash:"set"` + Services []*ServiceMessage `json:"services,omitempty" hash:"set"` +} + +type ServiceMessage struct { + //nolint:revive + ServiceKey `json:",inline"` + ServicePorts []*ServicePort `json:"servicePorts,omitempty"` + ServiceAccounts []string `json:"serviceAccounts,omitempty"` +} + +type ServicePort struct { + Name string `json:"name,omitempty"` + Port int `json:"port,omitempty"` + Protocol string `json:"protocol,omitempty"` +} + +type ServiceEndpoint struct { + Port int `json:"port,omitempty"` + Hostname string `json:"hostname,omitempty"` +} + +type WatchEvent struct { + Action string `json:"action,omitempty"` + Service *ServiceMessage `json:"service,omitempty"` + Checksum uint64 `json:"checksum"` +} + +var ( + ActionAdd = "add" + ActionUpdate = "update" + ActionDelete = "delete" +) + +func (s *ServiceListMessage) GenerateChecksum() uint64 { + checksum, err := hashstructure.Hash(s, hashstructure.FormatV2, &hashstructure.HashOptions{SlicesAsSets: true}) + if err != nil { + return 0 + } + return checksum +} + +func (s *ServiceMessage) GenerateChecksum() uint64 { + checksum, err := hashstructure.Hash(s, hashstructure.FormatV2, &hashstructure.HashOptions{SlicesAsSets: true}) + if err != nil { + return 0 + } + return checksum +} + +type TrustBundleProvider interface { + GetTrustBundles() map[string]string +} diff --git a/pkg/servicemesh/federation/server/routing.go b/pkg/servicemesh/federation/server/routing.go new file mode 100644 index 00000000000..94d7636cc56 --- /dev/null +++ b/pkg/servicemesh/federation/server/routing.go @@ -0,0 +1,281 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "fmt" + "strconv" + "time" + + "github.com/pkg/errors" + + rawnetworking "istio.io/api/networking/v1alpha3" + rawsecurity "istio.io/api/security/v1beta1" + rawtype "istio.io/api/type/v1beta1" + "istio.io/istio/pilot/pkg/config/kube/ior" + "istio.io/istio/pkg/config" + "istio.io/istio/pkg/config/schema/collection" + "istio.io/istio/pkg/config/schema/collections" + "istio.io/istio/pkg/servicemesh/federation/common" + federationmodel "istio.io/istio/pkg/servicemesh/federation/model" +) + +func init() { + schemasBuilder := collection.NewSchemasBuilder() + schemasBuilder.MustAdd(collections.IstioNetworkingV1Alpha3Virtualservices) + schemasBuilder.MustAdd(collections.IstioNetworkingV1Alpha3Gateways) + schemasBuilder.MustAdd(collections.IstioSecurityV1Beta1Authorizationpolicies) + Schemas = schemasBuilder.Build() +} + +var ( + Schemas collection.Schemas + // ensure our config gets ignored if the user wants to change routing for + // exported services + armageddonTime = time.Unix(1<<62-1, 0) +) + +func createResourceName(mesh string, source federationmodel.ServiceKey) string { + return fmt.Sprintf("federation-exports-%s-%s-%s", mesh, source.Name, source.Namespace) +} + +func (s *meshServer) deleteExportResources(source federationmodel.ServiceKey, target *federationmodel.ServiceMessage) error { + resourceName := createResourceName(s.mesh.Name, source) + // Delete() is always successful + _ = s.configStore.Delete(collections.IstioNetworkingV1Alpha3Gateways.Resource().GroupVersionKind(), resourceName, s.mesh.Namespace, nil) + _ = s.configStore.Delete(collections.IstioNetworkingV1Alpha3Virtualservices.Resource().GroupVersionKind(), resourceName, s.mesh.Namespace, nil) + return s.removeServiceFromAuthorizationPolicy(target) +} + +func (s *meshServer) removeServiceFromAuthorizationPolicy(target *federationmodel.ServiceMessage) error { + // AuthorizationPolicy used to restrict inbound requests to known clients accessing exported services. + // We use a DENY policy to block any traffic coming in that's not from a known client or destined for an exported service + name := fmt.Sprintf("federation-exports-%s", s.mesh.Name) + rawAP := s.configStore.Get(collections.IstioSecurityV1Beta1Authorizationpolicies.Resource().GroupVersionKind(), name, s.mesh.Namespace) + if rawAP == nil { + // nothing to remove + s.logger.Warnf("could not find AuthorizationPolicy %s/%s associated with federation export", s.mesh.Namespace, name) + return nil + } + apSpec := rawAP.Spec.(*rawsecurity.AuthorizationPolicy) + if len(apSpec.Rules) != 1 || len(apSpec.Rules[0].To) != 1 { + return fmt.Errorf("invalid AuthorizationPolicy for service export") + } + for index, host := range apSpec.Rules[0].To[0].Operation.NotHosts { + if host == target.Hostname { + apSpec.Rules[0].To[0].Operation.NotHosts = append(apSpec.Rules[0].To[0].Operation.NotHosts[:index], + apSpec.Rules[0].To[0].Operation.NotHosts[index+1:]...) + if _, err := s.configStore.Update(*rawAP); err != nil { + return err + } + return nil + } + } + s.logger.Warnf("AuthorizationPolicy %s/%s did not have rule for exported service %s", s.mesh.Namespace, name, target.Hostname) + return nil +} + +func (s *meshServer) createExportResources(source federationmodel.ServiceKey, target *federationmodel.ServiceMessage) error { + if err := s.createOrUpdateAuthorizationPolicy(target); err != nil { + return errors.Wrapf(err, "error updating AuthorinzationPolicy resource") + } + gateway := s.gatewayForExport(source, target) + if rawGateway := s.configStore.Get( + collections.IstioNetworkingV1Alpha3Gateways.Resource().GroupVersionKind(), gateway.Name, s.mesh.Namespace); rawGateway == nil { + if _, err := s.configStore.Create(*gateway); err != nil { + return errors.Wrapf(err, "error creating Gateway resource") + } + } else { + // overwrite whatever's there + s.logger.Warnf("Gateway resource %s already exists for exported service (%s => %s). It will be overwritten.", + gateway.Name, source.Hostname, target.Hostname) + if _, err := s.configStore.Update(*gateway); err != nil { + return errors.Wrapf(err, "error updating Gateway resource") + } + } + vs := s.virtualServiceForExport(source, target) + if rawVS := s.configStore.Get(collections.IstioNetworkingV1Alpha3Virtualservices.Resource().GroupVersionKind(), vs.Name, s.mesh.Namespace); rawVS == nil { + if _, err := s.configStore.Create(*vs); err != nil { + return errors.Wrapf(err, "error creating VirtualService resource") + } + } else { + // overwrite whatever's there + s.logger.Warnf("VirtualService resource %s already exists for exported service (%s => %s). It will be overwritten.", + vs.Name, source.Hostname, target.Hostname) + if _, err := s.configStore.Update(*vs); err != nil { + return errors.Wrapf(err, "error updating VirtualService resource") + } + } + return nil +} + +func (s *meshServer) createOrUpdateAuthorizationPolicy(target *federationmodel.ServiceMessage) error { + // AuthorizationPolicy used to restrict inbound requests to known clients accessing exported services. + // We use a DENY policy to block any traffic coming in that's not from a known client or destined for an exported service + name := fmt.Sprintf("federation-exports-%s", s.mesh.Name) + rawAP := s.configStore.Get(collections.IstioSecurityV1Beta1Authorizationpolicies.Resource().GroupVersionKind(), name, s.mesh.Namespace) + if rawAP == nil { + if s.mesh.Spec.Security.ClientID == "" { + s.logger.Errorf("no ClientID specified for MeshFederation %s/%s: AuthorizationPolicy for exported services will not be created", + s.mesh.Namespace, s.mesh.Name) + return nil + } + ap := &config.Config{ + Meta: config.Meta{ + GroupVersionKind: collections.IstioSecurityV1Beta1Authorizationpolicies.Resource().GroupVersionKind(), + Name: name, + Namespace: s.mesh.Namespace, + }, + Spec: &rawsecurity.AuthorizationPolicy{ + Selector: &rawtype.WorkloadSelector{ + MatchLabels: map[string]string{ + "service.istio.io/canonical-name": s.mesh.Spec.Gateways.Ingress.Name, + }, + }, + Action: rawsecurity.AuthorizationPolicy_DENY, + Rules: []*rawsecurity.Rule{ + { + From: []*rawsecurity.Rule_From{ + { + Source: &rawsecurity.Source{ + NotPrincipals: []string{ + s.mesh.Spec.Security.ClientID, + }, + }, + }, + }, + To: []*rawsecurity.Rule_To{ + { + Operation: &rawsecurity.Operation{ + NotHosts: []string{ + target.Hostname, + }, + Ports: []string{ + strconv.FormatInt(common.DefaultFederationPort, 10), + }, + }, + }, + }, + }, + }, + }, + } + if _, err := s.configStore.Create(*ap); err != nil { + return err + } + return nil + } + apSpec := rawAP.Spec.(*rawsecurity.AuthorizationPolicy) + if len(apSpec.Rules) != 1 || len(apSpec.Rules[0].To) != 1 { + return fmt.Errorf("invalid AuthorizationPolicy for service export") + } + for _, host := range apSpec.Rules[0].To[0].Operation.NotHosts { + if host == target.Hostname { + // no update required + return nil + } + } + // add the host to the list of available targets + apSpec.Rules[0].To[0].Operation.NotHosts = append(apSpec.Rules[0].To[0].Operation.NotHosts, target.Hostname) + if _, err := s.configStore.Update(*rawAP); err != nil { + return err + } + return nil +} + +func (s *meshServer) gatewayForExport(source federationmodel.ServiceKey, target *federationmodel.ServiceMessage) *config.Config { + resourceName := createResourceName(s.mesh.Name, source) + mode := rawnetworking.ServerTLSSettings_ISTIO_MUTUAL + if s.mesh.Spec.Security.AllowDirectInbound { + // XXX: this will not work, as the exported services will have a different domain suffix + // for example, svc.mesh2.local as opposed to svc.cluster.local + mode = rawnetworking.ServerTLSSettings_AUTO_PASSTHROUGH + } + gateway := &config.Config{ + Meta: config.Meta{ + GroupVersionKind: collections.IstioNetworkingV1Alpha3Gateways.Resource().GroupVersionKind(), + Name: resourceName, + Namespace: s.mesh.Namespace, + Annotations: map[string]string{ior.ShouldManageRouteAnnotation: "false"}, + }, + Spec: &rawnetworking.Gateway{ + Selector: map[string]string{ + "service.istio.io/canonical-name": s.mesh.Spec.Gateways.Ingress.Name, + }, + Servers: []*rawnetworking.Server{ + { + Name: resourceName, + Hosts: []string{ + target.Hostname, + fmt.Sprintf("*.%s", target.Hostname), + }, + Port: &rawnetworking.Port{ + Name: "tls-federation", + Number: uint32(common.DefaultFederationPort), + Protocol: "TLS", + }, + Tls: &rawnetworking.ServerTLSSettings{ + Mode: mode, + }, + }, + }, + }, + } + return gateway +} + +func (s *meshServer) virtualServiceForExport(source federationmodel.ServiceKey, target *federationmodel.ServiceMessage) *config.Config { + // VirtualService used to route inbound requests to the service. + name := createResourceName(s.mesh.Name, source) + ingressGatewayName := fmt.Sprintf("%s/%s", s.mesh.Namespace, name) + vs := &config.Config{ + Meta: config.Meta{ + GroupVersionKind: collections.IstioNetworkingV1Alpha3Virtualservices.Resource().GroupVersionKind(), + Name: name, + Namespace: s.mesh.Namespace, + CreationTimestamp: armageddonTime, + }, + Spec: &rawnetworking.VirtualService{ + Hosts: []string{ + target.Hostname, + }, + Gateways: []string{ + ingressGatewayName, + }, + ExportTo: []string{ + ".", + }, + Tcp: []*rawnetworking.TCPRoute{ + { + Match: []*rawnetworking.L4MatchAttributes{ + { + Gateways: []string{ + ingressGatewayName, + }, + }, + }, + Route: []*rawnetworking.RouteDestination{ + { + Destination: &rawnetworking.Destination{ + Host: source.Hostname, + }, + }, + }, + }, + }, + }, + } + return vs +} diff --git a/pkg/servicemesh/federation/server/server.go b/pkg/servicemesh/federation/server/server.go new file mode 100644 index 00000000000..3a478b940dc --- /dev/null +++ b/pkg/servicemesh/federation/server/server.go @@ -0,0 +1,723 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "context" + "crypto/tls" + "encoding/json" + "fmt" + "net" + "net/http" + "sort" + "strings" + "sync" + "time" + + "github.com/gorilla/mux" + hashstructure "github.com/mitchellh/hashstructure/v2" + "k8s.io/apimachinery/pkg/util/errors" + v1 "maistra.io/api/federation/v1" + + "istio.io/istio/pilot/pkg/model" + "istio.io/istio/pkg/config/host" + "istio.io/istio/pkg/config/visibility" + "istio.io/istio/pkg/servicemesh/federation/common" + federationmodel "istio.io/istio/pkg/servicemesh/federation/model" + "istio.io/istio/pkg/servicemesh/federation/status" + "istio.io/pkg/log" +) + +const ( + meshURLParameter = "mesh" +) + +type Options struct { + BindAddress string + Env *model.Environment + Network string + ConfigStore model.ConfigStoreController + TLSConfig *tls.Config +} + +type FederationManager interface { + AddPeer(mesh *v1.ServiceMeshPeer, exports *v1.ExportedServiceSet, statusHandler status.Handler) error + DeletePeer(name string) + UpdateExportsForMesh(exports *v1.ExportedServiceSet) error + DeleteExportsForMesh(name string) +} + +type Server struct { + sync.RWMutex + + logger *log.Scope + + env *model.Environment + listener net.Listener + httpServer *http.Server + + configStore model.ConfigStoreController + + meshes *sync.Map + + // XXX: we need to decide if we really want to allow this or not. + // Gateway configuration is managed explicitly through the MeshFederation + // resource and using other gateway addresses over discovery would force + // us to know what the workload identifiers were so we could manage the + // routing config for each mesh. This may or may not be possible. + network string + + currentGatewayEndpoints []*federationmodel.ServiceEndpoint +} + +var _ FederationManager = (*Server)(nil) + +func NewServer(opt Options) (*Server, error) { + if err := opt.validate(); err != nil { + return nil, err + } + listener, err := net.Listen("tcp", opt.BindAddress) + if err != nil { + return nil, err + } + fed := &Server{ + logger: common.Logger.WithLabels("component", "federation-server"), + env: opt.Env, + httpServer: &http.Server{ + ReadTimeout: 10 * time.Second, + MaxHeaderBytes: 1 << 20, + TLSConfig: opt.TLSConfig, + }, + configStore: opt.ConfigStore, + meshes: &sync.Map{}, + network: opt.Network, + listener: listener, + } + mux := mux.NewRouter() + mux.HandleFunc("/v1/services/{mesh}", fed.handleServiceList) + mux.HandleFunc("/v1/watch/{mesh}", fed.handleWatch) + fed.httpServer.Handler = mux + return fed, nil +} + +func (s *Server) Addr() string { + return s.listener.Addr().String() +} + +func exportDomainSuffix(mesh string) string { + return fmt.Sprintf("svc.%s-exports.local", mesh) +} + +func (s *Server) ingressServiceName(mesh *v1.ServiceMeshPeer) string { + return fmt.Sprintf("%s.%s.svc.%s", mesh.Spec.Gateways.Ingress.Name, mesh.Namespace, s.env.DomainSuffix) +} + +func (s *Server) AddPeer(mesh *v1.ServiceMeshPeer, exports *v1.ExportedServiceSet, statusHandler status.Handler) error { + exportConfig := common.NewServiceExporter(exports, nil, exportDomainSuffix(mesh.Name)) + + untypedMeshServer, ok := s.meshes.Load(mesh.Name) + if untypedMeshServer != nil && ok { + return fmt.Errorf("exporter already exists for federation %s", mesh.Name) + } + meshServer := &meshServer{ + GatewayEndpointsProvider: s, + logger: s.logger.WithLabels("mesh", mesh.Name), + env: s.env, + mesh: mesh, + exportConfig: exportConfig, + statusHandler: statusHandler, + configStore: s.configStore, + ingressService: s.ingressServiceName(mesh), + currentServices: make(map[federationmodel.ServiceKey]*federationmodel.ServiceMessage), + } + if _, loaded := s.meshes.LoadOrStore(mesh.Name, meshServer); !loaded { + meshServer.resync() + } + return nil +} + +func (s *Server) DeletePeer(name string) { + ms, ok := s.meshes.Load(name) + s.meshes.Delete(name) + if ms == nil || !ok { + return + } + ms.(*meshServer).stop() +} + +func (s *Server) UpdateExportsForMesh(exports *v1.ExportedServiceSet) error { + untypedMeshServer, ok := s.meshes.Load(exports.Name) + if untypedMeshServer == nil || !ok { + // not really an error; ExportedServiceSet might just be created earlier than ServiceMeshPeer + return nil + } + untypedMeshServer.(*meshServer).updateExportConfig(common.NewServiceExporter(exports, nil, exportDomainSuffix(exports.Name))) + return nil +} + +func (s *Server) DeleteExportsForMesh(name string) { + untypedMeshServer, ok := s.meshes.Load(name) + if untypedMeshServer == nil || !ok { + return + } + // set an empty set of export rules + untypedMeshServer.(*meshServer).updateExportConfig(&common.ServiceExporter{}) +} + +func (s *Server) getMeshServerForRequest(request *http.Request) (*meshServer, error) { + vars := mux.Vars(request) + if vars == nil { + return nil, fmt.Errorf("no mesh specified") + } + meshName := vars[meshURLParameter] + untypedMesh, ok := s.meshes.Load(meshName) + if !ok || untypedMesh == nil { + return nil, fmt.Errorf("unknown mesh specified: %s", meshName) + } + + return untypedMesh.(*meshServer), nil +} + +func (s *Server) handleServiceList(response http.ResponseWriter, request *http.Request) { + mesh, err := s.getMeshServerForRequest(request) + if err != nil { + s.logger.Errorf("error handling /services/ request: %s", err) + response.WriteHeader(400) + return + } + ret := mesh.getServiceListMessage() + + respBytes, err := json.Marshal(ret) + if err != nil { + s.logger.Errorf("failed to marshal to json: %s", err) + response.WriteHeader(500) + return + } + _, err = response.Write(respBytes) + if err != nil { + s.logger.Errorf("failed to send response: %s", err) + response.WriteHeader(500) + return + } + connection := getClientConnectionKey(request) + mesh.statusHandler.FullSyncSent(connection) +} + +func (s *Server) handleWatch(response http.ResponseWriter, request *http.Request) { + mesh, err := s.getMeshServerForRequest(request) + if err != nil { + s.logger.Errorf("error handling /watch request: %s", err) + response.WriteHeader(400) + return + } + mesh.handleWatch(response, request) +} + +func (s *Server) Run(stopCh <-chan struct{}) { + s.logger.Infof("starting federation service discovery at %s", s.Addr()) + go func() { + _ = s.httpServer.ServeTLS(s.listener, "", "") + }() + <-stopCh + _ = s.httpServer.Shutdown(context.TODO()) +} + +func (s *Server) GetGatewayEndpoints() []*federationmodel.ServiceEndpoint { + s.Lock() + defer s.Unlock() + return append([]*federationmodel.ServiceEndpoint(nil), s.currentGatewayEndpoints...) +} + +func (s *Server) resyncNetworkGateways() (bool, error) { + s.Lock() + defer s.Unlock() + + gatewayEndpoints := []*federationmodel.ServiceEndpoint{} + for _, gateway := range s.env.NetworkGateways() { + gatewayEndpoints = append(gatewayEndpoints, &federationmodel.ServiceEndpoint{ + Port: int(gateway.Port), + Hostname: gateway.Addr, + }) + } + + newGatewayChecksum, err := hashstructure.Hash(gatewayEndpoints, hashstructure.FormatV2, &hashstructure.HashOptions{SlicesAsSets: true}) + if err != nil { + return false, err + } + + oldGatewayChecksum, err := hashstructure.Hash(s.currentGatewayEndpoints, hashstructure.FormatV2, &hashstructure.HashOptions{SlicesAsSets: true}) + if err != nil { + return false, err + } + if oldGatewayChecksum != newGatewayChecksum { + s.currentGatewayEndpoints = gatewayEndpoints + return true, nil + } + return false, nil +} + +func (s *Server) UpdateService(svc *model.Service, event model.Event) { + // this might be a NetworkGateway + if svc != nil { + networkGatewaysChanged, _ := s.resyncNetworkGateways() + if networkGatewaysChanged { + s.meshes.Range(func(_, value interface{}) bool { + value.(*meshServer).resync() + return true + }) + s.meshes.Range(func(_, value interface{}) bool { + value.(*meshServer).pushWatchEvent(&federationmodel.WatchEvent{ + Action: federationmodel.ActionUpdate, + Service: nil, + }) + return true + }) + } + } + s.meshes.Range(func(_, value interface{}) bool { + value.(*meshServer).serviceUpdated(svc, event) + return true + }) +} + +// resync ensures the export lists are current. used for testing +func (s *Server) resync() { + _, _ = s.resyncNetworkGateways() + s.meshes.Range(func(_, value interface{}) bool { + value.(*meshServer).resync() + return true + }) +} + +type GatewayEndpointsProvider interface { + GetGatewayEndpoints() []*federationmodel.ServiceEndpoint +} + +func serviceKeyForService(svc *model.Service) federationmodel.ServiceKey { + return federationmodel.ServiceKey{ + Name: svc.Attributes.Name, + Namespace: svc.Attributes.Namespace, + Hostname: string(svc.Hostname), + } +} + +type meshServer struct { + GatewayEndpointsProvider + sync.RWMutex + + logger *log.Scope + + env *model.Environment + + mesh *v1.ServiceMeshPeer + exportConfig *common.ServiceExporter + + statusHandler status.Handler + configStore model.ConfigStoreController + + ingressService string + gatewaySAs []string + currentServices map[federationmodel.ServiceKey]*federationmodel.ServiceMessage + + watchMut sync.RWMutex + currentWatches []chan *federationmodel.WatchEvent +} + +func (s *meshServer) updateExportConfig(exportConfig *common.ServiceExporter) { + s.Lock() + s.exportConfig = exportConfig + s.Unlock() + s.resync() +} + +func (s *meshServer) getServiceHostName(exportedName *v1.ServiceName) string { + return fmt.Sprintf("%s.%s.svc.%s-exports.local", exportedName.Name, exportedName.Namespace, s.mesh.Name) +} + +func (s *meshServer) getServiceMessage(svc *model.Service, exportedName *federationmodel.ServiceKey) *federationmodel.ServiceMessage { + if svc == nil || exportedName == nil { + return nil + } + ret := &federationmodel.ServiceMessage{ + ServiceKey: *exportedName, + ServicePorts: make([]*federationmodel.ServicePort, 0), + } + addServiceSAs := s.mesh.Spec.Security.AllowDirectInbound + if addServiceSAs { + ret.ServiceAccounts = append([]string(nil), svc.ServiceAccounts...) + } else { + ret.ServiceAccounts = append([]string(nil), s.gatewaySAs...) + } + for _, port := range svc.Ports { + ret.ServicePorts = append(ret.ServicePorts, &federationmodel.ServicePort{ + Name: port.Name, + Port: port.Port, + Protocol: string(port.Protocol), + }) + if addServiceSAs { + for _, si := range s.env.InstancesByPort(svc, port.Port, nil) { + ret.ServiceAccounts = append(ret.ServiceAccounts, si.Endpoint.ServiceAccount) + } + } + } + return ret +} + +// s has to be Lock()ed +func (s *meshServer) getServiceListMessage() *federationmodel.ServiceListMessage { + ret := &federationmodel.ServiceListMessage{ + NetworkGatewayEndpoints: s.GetGatewayEndpoints(), + } + ret.Services = []*federationmodel.ServiceMessage{} + for _, svcMessage := range s.currentServices { + ret.Services = append(ret.Services, svcMessage) + } + sort.Slice(ret.Services, func(i, j int) bool { return strings.Compare(ret.Services[i].Hostname, ret.Services[j].Hostname) < 0 }) + ret.Checksum = ret.GenerateChecksum() + return ret +} + +func (s *meshServer) handleServiceList(response http.ResponseWriter) { + ret := func() *federationmodel.ServiceListMessage { + s.RLock() + defer s.RUnlock() + return s.getServiceListMessage() + }() + + respBytes, err := json.Marshal(ret) + if err != nil { + s.logger.Errorf("failed to marshal to json: %s", err) + response.WriteHeader(500) + return + } + _, err = response.Write(respBytes) + if err != nil { + s.logger.Errorf("failed to send response: %s", err) + response.WriteHeader(500) + return + } +} + +func getClientConnectionKey(request *http.Request) string { + forwardedIPs := strings.Split(request.Header.Get("X-Forwarded-For"), ",") + if len(forwardedIPs) > 0 { + return strings.TrimSpace(forwardedIPs[0]) + } + return request.RemoteAddr +} + +func (s *meshServer) handleWatch(response http.ResponseWriter, request *http.Request) { + watch := make(chan *federationmodel.WatchEvent, 10) + s.watchMut.Lock() + s.currentWatches = append(s.currentWatches, watch) + s.watchMut.Unlock() + connection := getClientConnectionKey(request) + s.statusHandler.RemoteWatchAccepted(connection) + defer func() { + s.statusHandler.RemoteWatchTerminated(connection) + s.watchMut.Lock() + for i, w := range s.currentWatches { + if w == watch { + s.currentWatches[i] = s.currentWatches[len(s.currentWatches)-1] + s.currentWatches = s.currentWatches[:len(s.currentWatches)-1] + break + } + } + s.watchMut.Unlock() + }() + response.Header().Set("Content-Type", "application/json") + response.Header().Set("Transfer-Encoding", "chunked") + response.WriteHeader(200) + flusher, ok := response.(http.Flusher) + if !ok { + panic("expected http.ResponseWriter to be an http.Flusher") + } + flusher.Flush() + for { + var event *federationmodel.WatchEvent + select { + case event = <-watch: + if event == nil { + s.logger.Debugf("watch handler: watch closed") + return + } + case <-request.Context().Done(): + s.logger.Debugf("watch handler: request context closed") + return + } + respBytes, err := json.Marshal(event) + if err != nil { + s.logger.Errorf("error marshaling watch event: %s", err) + return + } + _, err = response.Write(respBytes) + if err != nil { + s.logger.Errorf("failed to write http response: %s", err) + return + } + _, err = response.Write([]byte("\r\n")) + if err != nil { + s.logger.Errorf("failed to write http response: %s", err) + return + } + flusher.Flush() + s.statusHandler.WatchEventSent(connection) + } +} + +// checkServiceExportTo checks the service's `exportTo` field and returns +// whether this service is reachable from the SMP object. +func (s *meshServer) checkServiceExportTo(svc *model.Service) bool { + if len(svc.Attributes.ExportTo) == 0 { + return true + } + if value, exists := svc.Attributes.ExportTo[visibility.Public]; exists && value { + return true + } + if value, exists := svc.Attributes.ExportTo[visibility.Private]; exists && value && s.mesh.Namespace == svc.Attributes.Namespace { + return true + } + if value, exists := svc.Attributes.ExportTo[visibility.Instance(s.mesh.Namespace)]; exists && value { + return true + } + + return false +} + +func (s *meshServer) resync() { + s.Lock() + defer s.Unlock() + services := s.env.Services() + s.updateGatewayServiceAccounts() + for _, svc := range services { + if svc.Attributes.Name == "" || svc.Attributes.Namespace == "" { + s.logger.Debugf("skipping service with no Namespace/Name: %s", svc.Hostname) + continue + } else if svc.External() { + s.logger.Debugf("skipping external service: %s", svc.Hostname) + continue + } + svcKey := serviceKeyForService(svc) + svcMessage := s.getServiceMessage(svc, s.exportConfig.NameForService(svc)) + if svcMessage == nil { + if existingSvc, found := s.currentServices[svcKey]; found { + s.logger.Debugf("export for service %+v as %+v deleted", svcKey, existingSvc.ServiceKey) + s.deleteService(svcKey, existingSvc) + continue + } + s.logger.Debugf("skipping export of service %+v, as it does not match any export filter", serviceKeyForService(svc)) + continue + } + + if !s.checkServiceExportTo(svc) { + s.logger.Debugf("skipping export of service %s/%s as its `exportTo` field prevents reachability from the gateway", + svc.Attributes.Namespace, svc.Attributes.Name) + continue + } + + if existingSvc, found := s.currentServices[svcKey]; found { + if existingSvc.GenerateChecksum() == svcMessage.GenerateChecksum() { + continue + } + if existingSvc.Name != svcMessage.Name || existingSvc.Namespace != svcMessage.Namespace { + s.logger.Debugf("export for service %+v has changed from %+v to %+v", svcKey, existingSvc.ServiceKey, svcMessage.ServiceKey) + s.deleteService(svcKey, existingSvc) + s.addService(svcKey, svcMessage) + } else { + s.logger.Debugf("service %+v still exported as %+v", svcKey, svcMessage.ServiceKey) + s.updateService(svcKey, svcMessage) + } + } else if svcMessage != nil { + s.logger.Debugf("exporting service %+v as %+v", svcKey, svcMessage.ServiceKey) + s.addService(svcKey, svcMessage) + } + } + if err := s.statusHandler.Flush(); err != nil { + s.logger.Errorf("error updating federation export status for mesh %s: %s", s.mesh.Name, err) + } +} + +// s must be lock()ed +func (s *meshServer) updateGatewayServiceAccounts() bool { + oldSAs := s.gatewaySAs + if s.mesh.Spec.Security.AllowDirectInbound { + // access is direct to the service, so we'll be using the service's SAs + s.gatewaySAs = nil + return len(oldSAs) > 0 + } + gatewayService := s.env.GetService(host.Name(s.ingressService)) + if gatewayService == nil { + s.logger.Errorf("unexpected error retrieving ServiceAccount details for MeshFederation %s: "+ + "could not locate ingress gateway service %s", s.mesh.Name, s.ingressService) + // XXX: keep using the old SAs? + return false + } + s.gatewaySAs = append([]string(nil), gatewayService.ServiceAccounts...) + for _, si := range s.env.InstancesByPort(gatewayService, common.DefaultFederationPort, nil) { + s.gatewaySAs = append(s.gatewaySAs, si.Endpoint.ServiceAccount) + } + sort.Slice(s.gatewaySAs, func(i, j int) bool { return strings.Compare(s.gatewaySAs[i], s.gatewaySAs[j]) < 0 }) + if len(oldSAs) != len(s.gatewaySAs) { + s.logger.Debugf("gateway ServiceAccounts configured as: %s", s.gatewaySAs) + return true + } + for index, sa := range oldSAs { + if s.gatewaySAs[index] != sa { + s.logger.Debugf("gateway ServiceAccounts configured as: %s", s.gatewaySAs) + return true + } + } + return false +} + +func (s *meshServer) serviceUpdated(svc *model.Service, event model.Event) { + if svc == nil { + return + } + if svc.Hostname == host.Name(s.ingressService) { + if s.updateGatewayServiceAccounts() { + s.resync() + } + // we don't ever want to export our ingress service + return + } + s.Lock() + defer s.Unlock() + var svcMessage *federationmodel.ServiceMessage + switch event { + case model.EventAdd: + svcMessage = s.getServiceMessage(svc, s.exportConfig.NameForService(svc)) + if svcMessage != nil { + s.logger.Debugf("exporting service %+v as %+v", serviceKeyForService(svc), svcMessage.ServiceKey) + s.addService(serviceKeyForService(svc), svcMessage) + } else if s.logger.DebugEnabled() { + s.logger.Debugf("skipping export of service %+v, as it does not match any export filter", serviceKeyForService(svc)) + } + case model.EventUpdate: + svcMessage = s.getServiceMessage(svc, s.exportConfig.NameForService(svc)) + svcKey := serviceKeyForService(svc) + if svcMessage != nil { + if existingSvc, found := s.currentServices[svcKey]; found { + if existingSvc.Name != svcMessage.Name || existingSvc.Namespace != svcMessage.Namespace { + s.logger.Debugf("export for service %+v has changed from %+v to %+v", svcKey, existingSvc.ServiceKey, svcMessage.ServiceKey) + s.deleteService(svcKey, existingSvc) + s.addService(svcKey, svcMessage) + } else { + s.logger.Debugf("service %+v still exported as %+v", svcKey, svcMessage.ServiceKey) + s.updateService(svcKey, svcMessage) + } + } else { + s.logger.Debugf("exporting service %+v as %+v", serviceKeyForService(svc), svcMessage.ServiceKey) + s.addService(svcKey, svcMessage) + } + } else if existingSvc, found := s.currentServices[svcKey]; found { + s.logger.Debugf("unexporting service %+v (was exported as %+v)", serviceKeyForService(svc), existingSvc.ServiceKey) + s.deleteService(svcKey, existingSvc) + } else if s.logger.DebugEnabled() { + s.logger.Debugf("skipping export of service %+v, as it does not match any export filter", serviceKeyForService(svc), svcMessage.ServiceKey) + } + case model.EventDelete: + svcKey := serviceKeyForService(svc) + if existingSvc, found := s.currentServices[svcKey]; found { + s.logger.Debugf("unexporting service %+v (was exported as %+v)", serviceKeyForService(svc), existingSvc.ServiceKey) + s.deleteService(svcKey, existingSvc) + } + } +} + +// s has to be Lock()ed +func (s *meshServer) addService(svc federationmodel.ServiceKey, msg *federationmodel.ServiceMessage) { + if err := s.createExportResources(svc, msg); err != nil { + s.logger.Errorf("error creating resources for exported service %s => %s: %s", svc.Hostname, msg.Hostname, err) + return + } + s.currentServices[svc] = msg + e := &federationmodel.WatchEvent{ + Action: federationmodel.ActionAdd, + Service: msg, + } + s.statusHandler.ExportAdded(svc, msg.Hostname) + s.pushWatchEvent(e) +} + +// s has to be Lock()ed +func (s *meshServer) updateService(svc federationmodel.ServiceKey, msg *federationmodel.ServiceMessage) { + // resources used to configure export are all based on names, so we don't need to update them + s.currentServices[svc] = msg + e := &federationmodel.WatchEvent{ + Action: federationmodel.ActionUpdate, + Service: msg, + } + s.statusHandler.ExportUpdated(svc, msg.Hostname) + s.pushWatchEvent(e) +} + +// s has to be Lock()ed +func (s *meshServer) deleteService(svc federationmodel.ServiceKey, msg *federationmodel.ServiceMessage) { + if err := s.deleteExportResources(svc, msg); err != nil { + s.logger.Errorf("couldn't remove resources associated with exported service %s => %s: %s", svc.Hostname, msg.Hostname, err) + // let the deletion go through, so the other mesh won't try to call us + } + delete(s.currentServices, svc) + e := &federationmodel.WatchEvent{ + Action: federationmodel.ActionDelete, + Service: msg, + } + s.statusHandler.ExportRemoved(svc) + s.pushWatchEvent(e) +} + +// s has to be Lock()ed +func (s *meshServer) pushWatchEvent(e *federationmodel.WatchEvent) { + list := s.getServiceListMessage() + e.Checksum = list.Checksum + s.watchMut.RLock() + defer s.watchMut.RUnlock() + for _, w := range s.currentWatches { + w <- e + } +} + +func (s *meshServer) stop() { + s.Lock() + defer s.Unlock() + s.watchMut.Lock() + defer s.watchMut.Unlock() + + // copy map as deleteService() removes entries + currentServices := make(map[federationmodel.ServiceKey]*federationmodel.ServiceMessage) + for source, svc := range s.currentServices { + currentServices[source] = svc + } + // send a delete event for all the services + for source, svc := range currentServices { + s.deleteService(source, svc) + } + + for _, watch := range s.currentWatches { + close(watch) + } +} + +func (opt Options) validate() error { + var allErrors []error + if opt.Env == nil { + allErrors = append(allErrors, fmt.Errorf("the Env field must not be nil")) + } + if opt.ConfigStore == nil { + allErrors = append(allErrors, fmt.Errorf("the ConfigStore field must not be nil")) + } + return errors.NewAggregate(allErrors) +} diff --git a/pkg/servicemesh/federation/server/server_test.go b/pkg/servicemesh/federation/server/server_test.go new file mode 100644 index 00000000000..82308016090 --- /dev/null +++ b/pkg/servicemesh/federation/server/server_test.go @@ -0,0 +1,1033 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "crypto/tls" + "encoding/json" + "io" + "io/ioutil" + "net/http" + "path/filepath" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "maistra.io/api/federation/v1" + + configmemory "istio.io/istio/pilot/pkg/config/memory" + "istio.io/istio/pilot/pkg/model" + serviceregistrymemory "istio.io/istio/pilot/pkg/serviceregistry/memory" + "istio.io/istio/pkg/cluster" + "istio.io/istio/pkg/config/protocol" + "istio.io/istio/pkg/config/visibility" + "istio.io/istio/pkg/servicemesh/federation/common" + federationmodel "istio.io/istio/pkg/servicemesh/federation/model" + istioenv "istio.io/istio/pkg/test/env" +) + +var ( + ignoreChecksum = cmp.FilterPath(func(p cmp.Path) bool { return p.String() == "Checksum" }, cmp.Ignore()) + httpsClient = http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + }, + Timeout: time.Second, + } +) + +func TestServiceList(t *testing.T) { + federation := &v1.ServiceMeshPeer{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-remote", + Namespace: "istio-system-test", + }, + Spec: v1.ServiceMeshPeerSpec{ + Security: v1.ServiceMeshPeerSecurity{ + ClientID: "federation-egress.other-mesh.svc.cluster.local", + }, + }, + } + exportAllServices := &v1.ExportedServiceSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-remote", + Namespace: "istio-system-test", + }, + Spec: v1.ExportedServiceSetSpec{ + ExportRules: []v1.ExportedServiceRule{ + { + Type: v1.NameSelectorType, + NameSelector: &v1.ServiceNameMapping{}, + }, + }, + }, + } + testCases := []struct { + name string + remoteName string + defaultExports *v1.ExportedServiceSet + serviceExports *v1.ExportedServiceSet + services []*model.Service + serviceEvents []struct { + event model.Event + svc *model.Service + } + gateways []model.NetworkGateway + expectedMessage federationmodel.ServiceListMessage + }{ + { + name: "empty serviceList", + remoteName: "test-remote", + serviceExports: exportAllServices, + services: []*model.Service{}, + expectedMessage: federationmodel.ServiceListMessage{}, + }, + { + name: "exported service, no gateway", + remoteName: "test-remote", + serviceExports: &v1.ExportedServiceSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-remote", + Namespace: "istio-system-test", + }, + Spec: v1.ExportedServiceSetSpec{ + ExportRules: []v1.ExportedServiceRule{ + { + Type: v1.NameSelectorType, + NameSelector: &v1.ServiceNameMapping{ + ServiceName: v1.ServiceName{ + Namespace: "bookinfo", + Name: "productpage", + }, + Alias: &v1.ServiceName{ + Namespace: "federation", + Name: "service", + }, + }, + }, + }, + }, + }, + services: []*model.Service{ + { + Hostname: "productpage.bookinfo.svc.cluster.local", + Attributes: model.ServiceAttributes{ + Name: "productpage", + Namespace: "bookinfo", + }, + Ports: model.PortList{ + &model.Port{ + Name: "https", + Protocol: protocol.HTTPS, + Port: 443, + }, + }, + }, + }, + expectedMessage: federationmodel.ServiceListMessage{ + Services: []*federationmodel.ServiceMessage{ + { + ServiceKey: federationmodel.ServiceKey{ + Name: "service", + Namespace: "federation", + Hostname: "service.federation.svc.test-remote-exports.local", + }, + ServicePorts: []*federationmodel.ServicePort{ + { + Name: "https", + Port: 443, + Protocol: "HTTPS", + }, + }, + }, + }, + }, + }, + { + name: "service, no exports, no gateway", + remoteName: "test-remote", + serviceExports: nil, + services: []*model.Service{ + { + Hostname: "productpage.bookinfo.svc.cluster.local", + Attributes: model.ServiceAttributes{ + Name: "productpage", + Namespace: "bookinfo", + }, + Ports: model.PortList{ + &model.Port{ + Name: "https", + Protocol: protocol.HTTPS, + Port: 443, + }, + }, + }, + }, + expectedMessage: federationmodel.ServiceListMessage{}, + }, + { + name: "exported service + gateway", + remoteName: "test-remote", + serviceExports: &v1.ExportedServiceSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-remote", + Namespace: "istio-system-test", + }, + Spec: v1.ExportedServiceSetSpec{ + ExportRules: []v1.ExportedServiceRule{ + { + Type: v1.NameSelectorType, + NameSelector: &v1.ServiceNameMapping{ + ServiceName: v1.ServiceName{ + Namespace: "bookinfo", + Name: "productpage", + }, + Alias: &v1.ServiceName{ + Namespace: "federation", + Name: "service", + }, + }, + }, + }, + }, + }, + services: []*model.Service{ + { + Hostname: "productpage.bookinfo.svc.cluster.local", + Attributes: model.ServiceAttributes{ + Name: "productpage", + Namespace: "bookinfo", + }, + Ports: model.PortList{ + &model.Port{ + Name: "https", + Protocol: protocol.HTTPS, + Port: 443, + }, + }, + }, + { + Hostname: "ratings.bookinfo.svc.cluster.local", + Attributes: model.ServiceAttributes{ + Name: "ratings", + Namespace: "bookinfo", + }, + Ports: model.PortList{ + &model.Port{ + Name: "https", + Protocol: protocol.HTTPS, + Port: 443, + }, + }, + }, + }, + gateways: []model.NetworkGateway{ + { + Addr: "127.0.0.1", + Port: 8080, + }, + }, + expectedMessage: federationmodel.ServiceListMessage{ + NetworkGatewayEndpoints: []*federationmodel.ServiceEndpoint{ + { + Port: 8080, + Hostname: "127.0.0.1", + }, + }, + Services: []*federationmodel.ServiceMessage{ + { + ServiceKey: federationmodel.ServiceKey{ + Name: "service", + Namespace: "federation", + Hostname: "service.federation.svc.test-remote-exports.local", + }, + ServicePorts: []*federationmodel.ServicePort{ + { + Name: "https", + Port: 443, + Protocol: "HTTPS", + }, + }, + }, + }, + }, + }, + { + name: "exported service + gateway, updated", + remoteName: "test-remote", + serviceExports: exportAllServices, + services: []*model.Service{ + { + Hostname: "productpage.bookinfo.svc.cluster.local", + Attributes: model.ServiceAttributes{ + Name: "productpage", + Namespace: "bookinfo", + }, + Ports: model.PortList{ + &model.Port{ + Name: "https", + Protocol: protocol.HTTPS, + Port: 443, + }, + }, + }, + { + Hostname: "ratings.bookinfo.svc.cluster.local", + Attributes: model.ServiceAttributes{ + Name: "ratings", + Namespace: "bookinfo", + }, + Ports: model.PortList{ + &model.Port{ + Name: "https", + Protocol: protocol.HTTPS, + Port: 443, + }, + }, + }, + }, + gateways: []model.NetworkGateway{ + { + Addr: "127.0.0.1", + Port: 8080, + }, + }, + serviceEvents: []struct { + event model.Event + svc *model.Service + }{ + { + event: model.EventUpdate, + svc: &model.Service{ + Hostname: "productpage.bookinfo.svc.cluster.local", + Attributes: model.ServiceAttributes{ + Name: "productpage", + Namespace: "bookinfo", + }, + Ports: model.PortList{ + &model.Port{ + Name: "https", + Protocol: protocol.HTTPS, + Port: 8443, + }, + }, + }, + }, + }, + expectedMessage: federationmodel.ServiceListMessage{ + NetworkGatewayEndpoints: []*federationmodel.ServiceEndpoint{ + { + Port: 8080, + Hostname: "127.0.0.1", + }, + }, + Services: []*federationmodel.ServiceMessage{ + { + ServiceKey: federationmodel.ServiceKey{ + Name: "productpage", + Namespace: "bookinfo", + Hostname: "productpage.bookinfo.svc.test-remote-exports.local", + }, + ServicePorts: []*federationmodel.ServicePort{ + { + Name: "https", + Port: 8443, + Protocol: "HTTPS", + }, + }, + }, + { + ServiceKey: federationmodel.ServiceKey{ + Name: "ratings", + Namespace: "bookinfo", + Hostname: "ratings.bookinfo.svc.test-remote-exports.local", + }, + ServicePorts: []*federationmodel.ServicePort{ + { + Name: "https", + Port: 443, + Protocol: "HTTPS", + }, + }, + }, + }, + }, + }, + { + name: "exportTo - service invisible", + remoteName: "test-remote", + serviceExports: &v1.ExportedServiceSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-remote", + Namespace: "istio-system-test", + }, + Spec: v1.ExportedServiceSetSpec{ + ExportRules: []v1.ExportedServiceRule{ + { + Type: v1.NameSelectorType, + NameSelector: &v1.ServiceNameMapping{ + ServiceName: v1.ServiceName{ + Namespace: "bookinfo", + Name: "productpage", + }, + }, + }, + }, + }, + }, + services: []*model.Service{ + { + Hostname: "productpage.bookinfo.svc.cluster.local", + Attributes: model.ServiceAttributes{ + Name: "productpage", + Namespace: "bookinfo", + ExportTo: map[visibility.Instance]bool{ + visibility.None: true, + }, + }, + }, + }, + expectedMessage: federationmodel.ServiceListMessage{}, + }, + { + name: "exportTo - service private", + remoteName: "test-remote", + serviceExports: &v1.ExportedServiceSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-remote", + Namespace: "istio-system-test", + }, + Spec: v1.ExportedServiceSetSpec{ + ExportRules: []v1.ExportedServiceRule{ + { + Type: v1.NameSelectorType, + NameSelector: &v1.ServiceNameMapping{ + ServiceName: v1.ServiceName{ + Namespace: "bookinfo", + Name: "productpage", + }, + }, + }, + }, + }, + }, + services: []*model.Service{ + { + Hostname: "productpage.bookinfo.svc.cluster.local", + Attributes: model.ServiceAttributes{ + Name: "productpage", + Namespace: "bookinfo", + ExportTo: map[visibility.Instance]bool{ + visibility.Private: true, + }, + }, + }, + }, + expectedMessage: federationmodel.ServiceListMessage{}, + }, + { + name: "exportTo - service private to the same namespace", + remoteName: "test-remote", + serviceExports: &v1.ExportedServiceSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-remote", + Namespace: "istio-system-test", + }, + Spec: v1.ExportedServiceSetSpec{ + ExportRules: []v1.ExportedServiceRule{ + { + Type: v1.NameSelectorType, + NameSelector: &v1.ServiceNameMapping{ + ServiceName: v1.ServiceName{ + Namespace: "istio-system-test", + Name: "productpage", + }, + }, + }, + }, + }, + }, + services: []*model.Service{ + { + Hostname: "productpage.bookinfo.svc.cluster.local", + Attributes: model.ServiceAttributes{ + Name: "productpage", + Namespace: "istio-system-test", + ExportTo: map[visibility.Instance]bool{ + visibility.Private: true, + }, + }, + }, + }, + expectedMessage: federationmodel.ServiceListMessage{ + Services: []*federationmodel.ServiceMessage{ + { + ServiceKey: federationmodel.ServiceKey{ + Name: "productpage", + Namespace: "istio-system-test", + Hostname: "productpage.istio-system-test.svc.test-remote-exports.local", + }, + }, + }, + }, + }, + { + name: "exportTo - foreign namespace", + remoteName: "test-remote", + serviceExports: &v1.ExportedServiceSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-remote", + Namespace: "istio-system-test", + }, + Spec: v1.ExportedServiceSetSpec{ + ExportRules: []v1.ExportedServiceRule{ + { + Type: v1.NameSelectorType, + NameSelector: &v1.ServiceNameMapping{ + ServiceName: v1.ServiceName{ + Namespace: "bookinfo", + Name: "productpage", + }, + }, + }, + }, + }, + }, + services: []*model.Service{ + { + Hostname: "productpage.bookinfo.svc.cluster.local", + Attributes: model.ServiceAttributes{ + Name: "productpage", + Namespace: "bookinfo", + ExportTo: map[visibility.Instance]bool{ + visibility.Instance("foreign-namespace"): true, + }, + }, + }, + }, + expectedMessage: federationmodel.ServiceListMessage{}, + }, + { + name: "exportTo - same namespace as control plane", + remoteName: "test-remote", + serviceExports: &v1.ExportedServiceSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-remote", + Namespace: "istio-system-test", + }, + Spec: v1.ExportedServiceSetSpec{ + ExportRules: []v1.ExportedServiceRule{ + { + Type: v1.NameSelectorType, + NameSelector: &v1.ServiceNameMapping{ + ServiceName: v1.ServiceName{ + Namespace: "bookinfo", + Name: "productpage", + }, + }, + }, + }, + }, + }, + services: []*model.Service{ + { + Hostname: "productpage.bookinfo.svc.cluster.local", + Attributes: model.ServiceAttributes{ + Name: "productpage", + Namespace: "bookinfo", + ExportTo: map[visibility.Instance]bool{ + visibility.Instance("istio-system-test"): true, + }, + }, + }, + }, + expectedMessage: federationmodel.ServiceListMessage{ + Services: []*federationmodel.ServiceMessage{ + { + ServiceKey: federationmodel.ServiceKey{ + Name: "productpage", + Namespace: "bookinfo", + Hostname: "productpage.bookinfo.svc.test-remote-exports.local", + }, + }, + }, + }, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + serviceDiscovery := serviceregistrymemory.NewServiceDiscovery(tc.services...) + serviceDiscovery.AddGateways(tc.gateways...) + env := &model.Environment{ + ServiceDiscovery: serviceDiscovery, + } + s := createServer(env) + stopCh := make(chan struct{}) + go s.Run(stopCh) + defer close(stopCh) + s.resyncNetworkGateways() + s.AddPeer(federation, tc.serviceExports, &common.FakeStatusHandler{}) + for _, e := range tc.serviceEvents { + s.UpdateService(e.svc, e.event) + } + serviceList := getServiceList(t, s.Addr(), tc.remoteName) + tc.expectedMessage.Checksum = tc.expectedMessage.GenerateChecksum() + if tc.expectedMessage.Checksum != serviceList.GenerateChecksum() { + t.Errorf("checksums don't match") + } + if diff := cmp.Diff(serviceList, tc.expectedMessage); diff != "" { + t.Fatalf("comparison failed, -got +want:\n%s", diff) + } + }) + } +} + +func createServer(env *model.Environment) *Server { + cert, _ := tls.LoadX509KeyPair( + filepath.Join(istioenv.IstioSrc, "./tests/testdata/certs/pilot/cert-chain.pem"), + filepath.Join(istioenv.IstioSrc, "./tests/testdata/certs/pilot/key.pem")) + + s, _ := NewServer(Options{ + BindAddress: "127.0.0.1:0", + Env: env, + Network: "network1", + ConfigStore: configmemory.NewController(configmemory.Make(Schemas)), + TLSConfig: &tls.Config{ + Certificates: []tls.Certificate{ + cert, + }, + }, + }) + return s +} + +func getServiceList(t *testing.T, addr, remoteName string) federationmodel.ServiceListMessage { + resp, err := httpsClient.Get("https://" + addr + "/v1/services/" + remoteName) + if err != nil { + t.Fatal(err) + } + if resp.StatusCode != http.StatusOK { + t.Fatalf("Status code is not OK: %v (%s)", resp.StatusCode, resp.Status) + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + serviceList := federationmodel.ServiceListMessage{} + err = json.Unmarshal(body, &serviceList) + if err != nil { + t.Fatal(err) + } + return serviceList +} + +func TestWatch(t *testing.T) { + federation := &v1.ServiceMeshPeer{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-remote", + Namespace: "istio-system-test", + }, + Spec: v1.ServiceMeshPeerSpec{ + Security: v1.ServiceMeshPeerSecurity{ + ClientID: "federation-egress.other-mesh.svc.cluster.local", + }, + }, + } + exportProductPage := &v1.ExportedServiceSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-remote", + Namespace: "istio-system-test", + }, + Spec: v1.ExportedServiceSetSpec{ + ExportRules: []v1.ExportedServiceRule{ + { + Type: v1.NameSelectorType, + NameSelector: &v1.ServiceNameMapping{ + ServiceName: v1.ServiceName{ + Namespace: "bookinfo", + Name: "productpage", + }, + Alias: &v1.ServiceName{ + Namespace: "federation", + Name: "service", + }, + }, + }, + }, + }, + } + testCases := []struct { + name string + remoteName string + defaultExports *v1.ExportedServiceSet + serviceExports *v1.ExportedServiceSet + updatedExports *v1.ExportedServiceSet + services []*model.Service + serviceEvents []struct { + event model.Event + svc *model.Service + } + gateways []model.NetworkGateway + gatewayEvents []struct { + newGateways []model.NetworkGateway + } + expectedWatchEvents []*federationmodel.WatchEvent + }{ + { + name: "no gateways, service added + removed", + remoteName: "test-remote", + serviceExports: exportProductPage, + services: []*model.Service{}, + serviceEvents: []struct { + event model.Event + svc *model.Service + }{ + { + event: model.EventAdd, + svc: &model.Service{ + Hostname: "productpage.bookinfo.svc.cluster.local", + Attributes: model.ServiceAttributes{ + Name: "productpage", + Namespace: "bookinfo", + }, + Ports: model.PortList{ + &model.Port{ + Name: "https", + Protocol: protocol.HTTPS, + Port: 443, + }, + }, + }, + }, + { + event: model.EventDelete, + svc: &model.Service{ + Hostname: "productpage.bookinfo.svc.cluster.local", + Attributes: model.ServiceAttributes{ + Name: "productpage", + Namespace: "bookinfo", + }, + }, + }, + }, + expectedWatchEvents: []*federationmodel.WatchEvent{ + { + Action: federationmodel.ActionAdd, + Service: &federationmodel.ServiceMessage{ + ServiceKey: federationmodel.ServiceKey{ + Name: "service", + Namespace: "federation", + Hostname: "service.federation.svc.test-remote-exports.local", + }, + ServicePorts: []*federationmodel.ServicePort{ + { + Name: "https", + Port: 443, + Protocol: "HTTPS", + }, + }, + }, + }, + { + Action: federationmodel.ActionDelete, + Service: &federationmodel.ServiceMessage{ + ServiceKey: federationmodel.ServiceKey{ + Name: "service", + Namespace: "federation", + Hostname: "service.federation.svc.test-remote-exports.local", + }, + ServicePorts: []*federationmodel.ServicePort{ + { + Name: "https", + Port: 443, + Protocol: "HTTPS", + }, + }, + }, + }, + }, + }, + { + name: "no gateways, service exported name changes, filtered service", + remoteName: "test-remote", + serviceExports: exportProductPage, + updatedExports: &v1.ExportedServiceSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-remote", + Namespace: "istio-system-test", + }, + Spec: v1.ExportedServiceSetSpec{ + ExportRules: []v1.ExportedServiceRule{ + { + Type: v1.NameSelectorType, + NameSelector: &v1.ServiceNameMapping{ + ServiceName: v1.ServiceName{ + Namespace: "bookinfo", + Name: "productpage", + }, + Alias: &v1.ServiceName{ + Namespace: "cluster", + Name: "service", + }, + }, + }, + }, + }, + }, + services: []*model.Service{ + { + Hostname: "productpage.bookinfo.svc.cluster.local", + Attributes: model.ServiceAttributes{ + Name: "productpage", + Namespace: "bookinfo", + }, + Ports: model.PortList{ + &model.Port{ + Name: "https", + Protocol: protocol.HTTPS, + Port: 443, + }, + }, + }, + { + Hostname: "ratings.bookinfo.svc.cluster.local", + Attributes: model.ServiceAttributes{ + Name: "productpage", + Namespace: "ratings", + }, + Ports: model.PortList{ + &model.Port{ + Name: "https", + Protocol: protocol.HTTPS, + Port: 443, + }, + }, + }, + }, + serviceEvents: nil, + expectedWatchEvents: []*federationmodel.WatchEvent{ + { + Action: federationmodel.ActionDelete, + Service: &federationmodel.ServiceMessage{ + ServiceKey: federationmodel.ServiceKey{ + Name: "service", + Namespace: "federation", + Hostname: "service.federation.svc.test-remote-exports.local", + }, + ServicePorts: []*federationmodel.ServicePort{ + { + Name: "https", + Port: 443, + Protocol: "HTTPS", + }, + }, + }, + }, + { + Action: federationmodel.ActionAdd, + Service: &federationmodel.ServiceMessage{ + ServiceKey: federationmodel.ServiceKey{ + Name: "service", + Namespace: "cluster", + Hostname: "service.cluster.svc.test-remote-exports.local", + }, + ServicePorts: []*federationmodel.ServicePort{ + { + Name: "https", + Port: 443, + Protocol: "HTTPS", + }, + }, + }, + }, + }, + }, + { + name: "single gateway, public IP changed", + remoteName: "test-remote", + serviceExports: exportProductPage, + services: []*model.Service{ + { + Hostname: "productpage.bookinfo.svc.cluster.local", + Attributes: model.ServiceAttributes{ + Name: "productpage", + Namespace: "bookinfo", + }, + Ports: model.PortList{ + &model.Port{ + Name: "https", + Protocol: protocol.HTTPS, + Port: 443, + }, + }, + }, + }, + gateways: []model.NetworkGateway{ + { + Addr: "127.0.0.1", + Port: 443, + }, + }, + gatewayEvents: []struct{ newGateways []model.NetworkGateway }{ + { + newGateways: []model.NetworkGateway{ + { + Addr: "127.0.0.2", + Port: 443, + }, + }, + }, + }, + expectedWatchEvents: []*federationmodel.WatchEvent{ + { + Action: federationmodel.ActionUpdate, + Service: nil, + }, + }, + }, + { + name: "service export removed", + remoteName: "test-remote", + serviceExports: exportProductPage, + updatedExports: &v1.ExportedServiceSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-remote", + }, + }, + services: []*model.Service{ + { + Hostname: "productpage.bookinfo.svc.cluster.local", + Attributes: model.ServiceAttributes{ + Name: "productpage", + Namespace: "bookinfo", + }, + Ports: model.PortList{ + &model.Port{ + Name: "https", + Protocol: protocol.HTTPS, + Port: 443, + }, + }, + }, + }, + serviceEvents: nil, + expectedWatchEvents: []*federationmodel.WatchEvent{ + { + Action: federationmodel.ActionDelete, + Service: &federationmodel.ServiceMessage{ + ServiceKey: federationmodel.ServiceKey{ + Name: "service", + Namespace: "federation", + Hostname: "service.federation.svc.test-remote-exports.local", + }, + ServicePorts: []*federationmodel.ServicePort{ + { + Name: "https", + Port: 443, + Protocol: "HTTPS", + }, + }, + }, + }, + }, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + serviceDiscovery := serviceregistrymemory.NewServiceDiscovery(tc.services...) + serviceDiscovery.AddGateways(tc.gateways...) + env := &model.Environment{ + ServiceDiscovery: serviceDiscovery, + } + s := createServer(env) + stopCh := make(chan struct{}) + go s.Run(stopCh) + defer close(stopCh) + s.resyncNetworkGateways() + s.AddPeer(federation, tc.serviceExports, &common.FakeStatusHandler{}) + req, err := http.NewRequest("GET", "https://"+s.Addr()+"/v1/watch/"+tc.remoteName, nil) + if err != nil { + t.Fatal(err) + } + resp, err := httpsClient.Do(req) + if err != nil { + t.Fatal(err) + } + if resp.StatusCode != http.StatusOK { + t.Fatalf("Status code is not OK: %v (%s)", resp.StatusCode, resp.Status) + } + for _, e := range tc.serviceEvents { + s.UpdateService(e.svc, e.event) + } + if tc.updatedExports != nil { + s.UpdateExportsForMesh(tc.updatedExports) + } + for _, e := range tc.gatewayEvents { + serviceDiscovery.AddGateways(e.newGateways...) + // trigger a gateway resync + s.UpdateService(&model.Service{ + Attributes: model.ServiceAttributes{ + ClusterExternalAddresses: model.AddressMap{ + Addresses: map[cluster.ID][]string{ + cluster.ID("network1"): {"a"}, + }, + }, + }, + }, model.EventUpdate) + } + svcList := federationmodel.ServiceListMessage{} + dec := json.NewDecoder(resp.Body) + for i := 0; i < len(tc.expectedWatchEvents); i++ { + var e federationmodel.WatchEvent + err := dec.Decode(&e) + if err != nil { + if err == io.EOF { + break + } + t.Fatal(err) + } + if diff := cmp.Diff(&e, tc.expectedWatchEvents[i], ignoreChecksum); diff != "" { + t.Fatalf("comparison failed, -got +want:\n%s", diff) + } + + if e.Service == nil { + svcList = getServiceList(t, s.Addr(), tc.remoteName) + } else if e.Action == federationmodel.ActionAdd { + svcList.Services = append(svcList.Services, e.Service) + } else if e.Action == federationmodel.ActionUpdate { + for i, svc := range svcList.Services { + if svc.Name == e.Service.Name { + svcList.Services[i] = e.Service + break + } + } + } else if e.Action == federationmodel.ActionDelete { + for i, svc := range svcList.Services { + if svc.Name == e.Service.Name { + svcList.Services = append(svcList.Services[:i], svcList.Services[i+1:]...) + break + } + } + } + if e.Checksum != svcList.GenerateChecksum() { + t.Fatalf("checksum mismatch, expected %d but got %d", svcList.GenerateChecksum(), e.Checksum) + } + } + }) + } +} diff --git a/pkg/servicemesh/federation/status/handler.go b/pkg/servicemesh/federation/status/handler.go new file mode 100644 index 00000000000..d4e00942bea --- /dev/null +++ b/pkg/servicemesh/federation/status/handler.go @@ -0,0 +1,629 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package status + +import ( + "context" + "encoding/json" + "reflect" + "sort" + "strings" + "sync" + "time" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/strategicpatch" + "k8s.io/client-go/util/retry" + v1 "maistra.io/api/federation/v1" + + "istio.io/istio/pkg/servicemesh/federation/model" + "istio.io/pkg/log" +) + +const ( + // used to prune old remote connection statuses from the status, e.g. if a + // pod was deleted, etc. + staleRemoteStatusDuration = 5 * time.Minute +) + +func newHandler(manager *manager, mesh types.NamespacedName) *handler { + return &handler{ + manager: manager, + mesh: mesh, + logger: manager.logger.WithLabels("peer", mesh.String()), + discovery: map[string]*v1.DiscoveryRemoteStatus{}, + exports: map[v1.ServiceKey]v1.PeerServiceMapping{}, + exportsStatus: []v1.PeerServiceMapping{}, + imports: map[string]v1.PeerServiceMapping{}, + importsStatus: []v1.PeerServiceMapping{}, + discoveryDirty: true, + watchDirty: true, + exportsDirty: true, + importsDirty: true, + } +} + +type handler struct { + mu sync.Mutex + manager *manager + mesh types.NamespacedName + logger *log.Scope + + discovery map[string]*v1.DiscoveryRemoteStatus + exports map[v1.ServiceKey]v1.PeerServiceMapping + imports map[string]v1.PeerServiceMapping + + discoveryDirty bool + exportsDirty bool + importsDirty bool + watchDirty bool + + discoveryStatus v1.PeerDiscoveryStatus + exportsStatus []v1.PeerServiceMapping + importsStatus []v1.PeerServiceMapping +} + +var _ Handler = (*handler)(nil) + +// Outbound connections +func (h *handler) WatchInitiated() { + h.logger.Debugf("%s.WatchInitiated()", h.mesh) + + h.mu.Lock() + defer h.mu.Unlock() + + h.discoveryStatus.Watch.Connected = false + h.discoveryStatus.Watch.LastConnected = metav1.Now() + + h.watchDirty = true + + // we don't flush on initiation, as we expect either a Watching() or + // WatchTerminated() immediately following this +} + +func (h *handler) Watching() { + h.logger.Debugf("%s.Watching()", h.mesh) + + func() { + h.mu.Lock() + defer h.mu.Unlock() + + h.discoveryStatus.Watch.Connected = true + + h.watchDirty = true + }() + + if err := h.Flush(); err != nil { + h.logger.Errorf("error updating status for ServiceMeshPeer %s: %s", h.mesh, err) + } +} + +func (h *handler) WatchEventReceived() { + h.logger.Debugf("%s.WatchEventReceived()", h.mesh) + + h.mu.Lock() + defer h.mu.Unlock() + + h.discoveryStatus.Watch.LastEvent = metav1.Now() + + h.watchDirty = true +} + +func (h *handler) FullSyncComplete() { + h.logger.Debugf("%s.FullSyncComplete()", h.mesh) + + func() { + h.mu.Lock() + defer h.mu.Unlock() + + h.discoveryStatus.Watch.LastFullSync = metav1.Now() + + h.watchDirty = true + }() + + if err := h.Flush(); err != nil { + h.logger.Errorf("error updating status for ServiceMeshPeer %s: %s", h.mesh, err) + } +} + +func (h *handler) WatchTerminated(status string) { + h.logger.Debugf("%s.WatchTerminated(%s)", h.mesh, status) + + func() { + h.mu.Lock() + defer h.mu.Unlock() + + if h.discoveryStatus.Watch.Connected { + // only update the disconnect time if we successfully connected + h.discoveryStatus.Watch.LastDisconnect = metav1.Now() + } + h.discoveryStatus.Watch.Connected = false + h.discoveryStatus.Watch.LastDisconnectStatus = status + + h.watchDirty = true + }() + + if err := h.Flush(); err != nil { + h.logger.Errorf("error updating status for ServiceMeshPeer %s: %s", h.mesh, err) + } +} + +// Inbound connections +func (h *handler) RemoteWatchAccepted(source string) { + h.logger.Debugf("%s.RemoteWatchAccepted(%s)", h.mesh, source) + + func() { + h.mu.Lock() + defer h.mu.Unlock() + + remoteStatus, ok := h.discovery[source] + if ok { + h.logger.Debugf("RemoteWatchAccepted called when watch status already exists: %s", source) + } else { + remoteStatus = &v1.DiscoveryRemoteStatus{ + Source: source, + } + h.discovery[source] = remoteStatus + } + remoteStatus.Connected = true + remoteStatus.LastConnected = metav1.Now() + + h.discoveryDirty = true + }() + + if err := h.Flush(); err != nil { + h.logger.Errorf("error updating status for ServiceMeshPeer %s: %s", h.mesh, err) + } +} + +func (h *handler) WatchEventSent(source string) { + h.logger.Debugf("%s.WatchEventSent(%s)", h.mesh, source) + + h.mu.Lock() + defer h.mu.Unlock() + + if remoteStatus, ok := h.discovery[source]; !ok { + h.logger.Debugf("WatchEventSent called when no status exists: %s", source) + } else { + remoteStatus.LastEvent = metav1.Now() + h.discoveryDirty = true + } +} + +func (h *handler) FullSyncSent(source string) { + h.logger.Debugf("%s.FullSyncSent(%s)", h.mesh, source) + + func() { + h.mu.Lock() + defer h.mu.Unlock() + + if remoteStatus, ok := h.discovery[source]; !ok { + h.logger.Debugf("skipping FullSyncSent event: no status for source %s", source) + } else { + remoteStatus.LastFullSync = metav1.Now() + h.discoveryDirty = true + } + }() + + if err := h.Flush(); err != nil { + h.logger.Errorf("error updating status for ServiceMeshPeer %s: %s", h.mesh, err) + } +} + +func (h *handler) RemoteWatchTerminated(source string) { + h.logger.Debugf("%s.RemoteWatchTerminated(%s)", h.mesh, source) + + func() { + h.mu.Lock() + defer h.mu.Unlock() + + remoteStatus, ok := h.discovery[source] + if !ok { + h.logger.Debugf("RemoteWatchTerminated called when no status exists: %s", source) + return + } + + remoteStatus.Connected = false + remoteStatus.LastDisconnect = metav1.Now() + + h.discoveryDirty = true + }() + + if err := h.Flush(); err != nil { + h.logger.Errorf("error updating status for ServiceMeshPeer %s: %s", h.mesh, err) + } +} + +func statusServiceKeyFor(service model.ServiceKey) v1.ServiceKey { + return v1.ServiceKey{ + Name: service.Name, + Namespace: service.Namespace, + Hostname: service.Hostname, + } +} + +func statusMappingFor(service model.ServiceKey, exportedName string) v1.PeerServiceMapping { + return v1.PeerServiceMapping{ + LocalService: statusServiceKeyFor(service), + ExportedName: exportedName, + } +} + +// Exports +func (h *handler) ExportAdded(service model.ServiceKey, exportedName string) { + h.logger.Debugf("%s.ExportAdded(%+v, %s)", h.mesh, service, exportedName) + + h.mu.Lock() + defer h.mu.Unlock() + + mapping := statusMappingFor(service, exportedName) + if existing, ok := h.exports[mapping.LocalService]; ok { + h.logger.Debugf("ExportAdded called when export mapping already exists: existing=%+v, new=%+v", existing, mapping) + if reflect.DeepEqual(existing, mapping) { + return + } + } + h.exports[mapping.LocalService] = mapping + h.exportsDirty = true +} + +func (h *handler) ExportUpdated(service model.ServiceKey, exportedName string) { + h.logger.Debugf("%s.ExportUpdated(%+v, %s)", h.mesh, service, exportedName) + + h.mu.Lock() + defer h.mu.Unlock() + + mapping := statusMappingFor(service, exportedName) + if existing, ok := h.exports[mapping.LocalService]; !ok { + h.logger.Debugf("ExportUpdated called when export mapping does not exist: %+v", mapping.LocalService) + } else if reflect.DeepEqual(existing, mapping) { + return + } + h.exports[mapping.LocalService] = mapping + h.exportsDirty = true +} + +func (h *handler) ExportRemoved(service model.ServiceKey) { + h.logger.Debugf("%s.ExportRemoved(%+v)", h.mesh, service) + + h.mu.Lock() + defer h.mu.Unlock() + + h.logger.Debugf("h.exports: %+v", h.exports) + key := statusServiceKeyFor(service) + if _, ok := h.exports[key]; !ok { + h.logger.Debugf("ExportRemoved called when export mapping does not exist: %+v", key) + return + } + delete(h.exports, key) + h.logger.Debugf("h.exports: %+v", h.exports) + h.exportsDirty = true +} + +// Imports +func (h *handler) ImportAdded(service model.ServiceKey, exportedName string) { + h.logger.Debugf("%s.ImportAdded(%+v, %s)", h.mesh, service, exportedName) + + h.mu.Lock() + defer h.mu.Unlock() + + mapping := statusMappingFor(service, exportedName) + if existing, ok := h.imports[mapping.ExportedName]; ok { + h.logger.Debugf("ImportAdded called when import mapping already exists: existing=%+v, new=%+v", existing, mapping) + if reflect.DeepEqual(existing, mapping) { + return + } + } + h.imports[mapping.ExportedName] = mapping + h.importsDirty = true +} + +func (h *handler) ImportUpdated(service model.ServiceKey, exportedName string) { + h.logger.Debugf("%s.ImportUpdated(%+v, %s)", h.mesh, service, exportedName) + + h.mu.Lock() + defer h.mu.Unlock() + + mapping := statusMappingFor(service, exportedName) + if existing, ok := h.imports[mapping.ExportedName]; !ok { + h.logger.Debugf("ImportUpdated called when import mapping does not exist: %s", mapping.ExportedName) + } else if reflect.DeepEqual(existing, mapping) { + return + } + h.imports[mapping.ExportedName] = mapping + h.importsDirty = true +} + +func (h *handler) ImportRemoved(exportedName string) { + h.logger.Debugf("%s.ImportRemoved(%s)", h.mesh, exportedName) + + h.mu.Lock() + defer h.mu.Unlock() + + h.logger.Debugf("h.imports: %v", h.imports) + if _, ok := h.imports[exportedName]; !ok { + h.logger.Debugf("ImportRemoved called when import mapping does not exist: %s", exportedName) + return + } + delete(h.imports, exportedName) + h.logger.Debugf("h.imports: %v", h.imports) + h.importsDirty = true +} + +func (h *handler) shouldPush() (bool, bool) { + // only push exports/imports if we're the leader + isLeader := h.manager.IsLeader() + return h.watchDirty || h.discoveryDirty || (isLeader && (h.exportsDirty || h.importsDirty)), isLeader +} + +func (h *handler) pruneOldRemotes() { + var connections []string + for connection, status := range h.discovery { + if status.Connected || metav1.Now().Sub(status.LastDisconnect.Time) < staleRemoteStatusDuration { + continue + } + h.logger.Debugf("removing stale remote watch status for connection from %s", connection) + connections = append(connections, connection) + } + h.discoveryDirty = h.discoveryDirty || len(connections) > 0 + for _, connection := range connections { + delete(h.discovery, connection) + } +} + +// Write status +func (h *handler) Flush() error { + h.mu.Lock() + defer h.mu.Unlock() + h.pruneOldRemotes() + push, isLeader := h.shouldPush() + + if !push { + h.logger.Debugf("no status changes to push") + return nil + } + + // see if we need to update the export status + if h.exportsDirty { + var exports []v1.PeerServiceMapping + for _, mapping := range h.exports { + exports = append(exports, mapping) + } + sort.Slice(exports, func(i, j int) bool { + diff := strings.Compare(exports[i].LocalService.Namespace, exports[j].LocalService.Namespace) + if diff == 0 { + diff = strings.Compare(exports[i].LocalService.Name, exports[j].LocalService.Name) + if diff == 0 { + // we really shouldn't ever get here, as there should never be an overlap of namespace/name + diff = strings.Compare(exports[i].ExportedName, exports[j].ExportedName) + } + } + return diff < 0 + }) + h.exportsStatus = exports + h.exportsDirty = false + } + + // see if we need to update the import status + if h.importsDirty { + var imports []v1.PeerServiceMapping + for _, mapping := range h.imports { + imports = append(imports, mapping) + } + sort.Slice(imports, func(i, j int) bool { return strings.Compare(imports[i].ExportedName, imports[j].ExportedName) < 0 }) + h.importsStatus = imports + h.importsDirty = false + } + + // see if we need to update the discovery status + if h.discoveryDirty { + var remoteStatuses []v1.DiscoveryRemoteStatus + for _, status := range h.discovery { + remoteStatuses = append(remoteStatuses, *status) + } + sort.Slice(remoteStatuses, + func(i, j int) bool { + return strings.Compare(remoteStatuses[i].Source, remoteStatuses[j].Source) < 0 + }) + h.discoveryStatus.Remotes = remoteStatuses + h.discoveryDirty = false + } + + peer, err := h.manager.rm.PeerInformer().Lister().ServiceMeshPeers(h.mesh.Namespace).Get(h.mesh.Name) + if err != nil { + if apierrors.IsGone(err) || apierrors.IsNotFound(err) { + h.logger.Debugf("could not locate ServiceMeshPeer %s for status update", h.mesh) + return nil + } + return err + } + + newStatus := v1.ServiceMeshPeerStatus{} + newStatus.DiscoveryStatus = peer.Status.DeepCopy().DiscoveryStatus + if h.discoveryStatus.Watch.Connected { + newStatus.DiscoveryStatus.Active = h.putDiscoveryStatus(newStatus.DiscoveryStatus.Active, h.discoveryStatus) + newStatus.DiscoveryStatus.Inactive = h.removeDiscoveryStatus(newStatus.DiscoveryStatus.Inactive) + } else { + newStatus.DiscoveryStatus.Inactive = h.putDiscoveryStatus(newStatus.DiscoveryStatus.Inactive, h.discoveryStatus) + newStatus.DiscoveryStatus.Active = h.removeDiscoveryStatus(newStatus.DiscoveryStatus.Active) + } + + var allErrors []error + if isLeader { + // clean up deleted pods + newStatus.DiscoveryStatus.Inactive = h.removeDeadPods(newStatus.DiscoveryStatus.Inactive) + newStatus.DiscoveryStatus.Active = h.removeDeadPods(newStatus.DiscoveryStatus.Active) + if err := h.patchExports(); err != nil && !(apierrors.IsGone(err) || apierrors.IsNotFound(err)) { + allErrors = append(allErrors, err) + } + if err := h.patchImports(); err != nil && !(apierrors.IsGone(err) || apierrors.IsNotFound(err)) { + allErrors = append(allErrors, err) + } + } + + if reflect.DeepEqual(peer.Status, newStatus) { // TODO: peer.Status may be stale, causing us to skip the update when we shouldn't + h.logger.Debugf("no status updates for ServiceMeshPeer %s", h.mesh) + return nil + } + + updatedPeer := peer.DeepCopy() + updatedPeer.Status = newStatus + + if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + _, err = h.manager.rm.MaistraClientSet().FederationV1().ServiceMeshPeers(h.mesh.Namespace).UpdateStatus(context.TODO(), updatedPeer, metav1.UpdateOptions{}) + return err + }); err != nil { + if err != nil && !(apierrors.IsGone(err) || apierrors.IsNotFound(err)) { + return utilerrors.NewAggregate(append(allErrors, err)) + } + } + h.watchDirty = false + return utilerrors.NewAggregate(allErrors) +} + +func (h *handler) patchExports() error { + exportSet, err := h.manager.rm.ExportsInformer().Lister().ExportedServiceSets(h.mesh.Namespace).Get(h.mesh.Name) + if err != nil { + if (apierrors.IsGone(err) || apierrors.IsNotFound(err)) && len(h.exports) == 0 { + h.logger.Debugf("could not locate ExportedServiceSet %s for status update", h.mesh) + return nil + } + return err + } + + exportedServices := h.exportsStatus + if exportedServices == nil { + exportedServices = []v1.PeerServiceMapping{} + } + newStatus := v1.ExportedServiceSetStatus{ExportedServices: exportedServices} + + h.logger.Debugf("exportSet.Status=%+v", exportSet.Status) + h.logger.Debugf("newStatus=%+v", newStatus) + if reflect.DeepEqual(exportSet.Status, newStatus) { // TODO: exportSet.Status may be stale, causing us to skip the update when we shouldn't + h.logger.Debugf("no status updates for ExportedServiceSet %s", h.mesh) + return nil + } + + updatedExportSet := exportSet.DeepCopy() + updatedExportSet.Status = newStatus + + if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + _, err = h.manager.rm.MaistraClientSet().FederationV1().ExportedServiceSets(h.mesh.Namespace). + UpdateStatus(context.TODO(), updatedExportSet, metav1.UpdateOptions{}) + return err + }); err != nil { + if !(apierrors.IsGone(err) || apierrors.IsNotFound(err)) { + return err + } + } + return nil +} + +func (h *handler) patchImports() error { + importSet, err := h.manager.rm.ImportsInformer().Lister().ImportedServiceSets(h.mesh.Namespace).Get(h.mesh.Name) + if err != nil { + if (apierrors.IsGone(err) || apierrors.IsNotFound(err)) && len(h.exports) == 0 { + h.logger.Debugf("could not locate ImportedServiceSet %s for status update", h.mesh) + return nil + } + return err + } + + importedServices := h.importsStatus + if importedServices == nil { + importedServices = []v1.PeerServiceMapping{} + } + newStatus := v1.ImportedServiceSetStatus{ImportedServices: importedServices} + + h.logger.Debugf("importSet.Status=%+v", importSet.Status) + h.logger.Debugf("newStatus=%+v", newStatus) + if reflect.DeepEqual(importSet.Status, newStatus) { // TODO: importSet.Status may be stale, causing us to skip the update when we shouldn't + h.logger.Debugf("no status updates for ImportedServiceSet %s", h.mesh) + return nil + } + + updatedImportSet := importSet.DeepCopy() + updatedImportSet.Status = newStatus + + if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + _, err = h.manager.rm.MaistraClientSet().FederationV1().ImportedServiceSets(h.mesh.Namespace). + UpdateStatus(context.TODO(), updatedImportSet, metav1.UpdateOptions{}) + return err + }); err != nil { + if !(apierrors.IsGone(err) || apierrors.IsNotFound(err)) { + return err + } + } + return nil +} + +func (h *handler) createPatch(newObj, oldObj interface{}, metadata strategicpatch.LookupPatchMeta) ([]byte, error) { + newBytes, err := json.Marshal(newObj) + if err != nil { + return nil, err + } + oldBytes, err := json.Marshal(oldObj) + if err != nil { + return nil, err + } + + h.logger.Debugf("old bytes: %s", string(oldBytes)) + h.logger.Debugf("new bytes: %s", string(newBytes)) + + patch, err := strategicpatch.CreateTwoWayMergePatchUsingLookupPatchMeta(oldBytes, newBytes, metadata) + if err != nil { + return nil, err + } + return patch, nil +} + +func (h *handler) putDiscoveryStatus(statuses []v1.PodPeerDiscoveryStatus, newStatus v1.PeerDiscoveryStatus) []v1.PodPeerDiscoveryStatus { + count := len(statuses) + index := sort.Search(count, func(i int) bool { return statuses[i].Pod == h.manager.name.Name }) + if index < count { + status := statuses[index] + status.PeerDiscoveryStatus = newStatus + statuses[index] = status + return statuses + } + statuses = append(statuses, v1.PodPeerDiscoveryStatus{Pod: h.manager.name.Name, PeerDiscoveryStatus: newStatus}) + sort.Slice(statuses, func(i, j int) bool { return strings.Compare(statuses[i].Pod, statuses[j].Pod) < 0 }) + return statuses +} + +func (h *handler) removeDiscoveryStatus(statuses []v1.PodPeerDiscoveryStatus) []v1.PodPeerDiscoveryStatus { + count := len(statuses) + index := sort.Search(count, func(i int) bool { return statuses[i].Pod == h.manager.name.Name }) + if index < count { + return append(statuses[:index], statuses[index+1:]...) + } + return statuses +} + +func (h *handler) removeDeadPods(statuses []v1.PodPeerDiscoveryStatus) []v1.PodPeerDiscoveryStatus { + var filteredStatuses []v1.PodPeerDiscoveryStatus + for index, status := range statuses { + // XXX: this shouldn't be necessary, but patching isn't working correctly + if index == 0 || statuses[index].Pod != statuses[index-1].Pod { + if _, err := h.manager.rm.KubeClient().KubeInformer().Core().V1().Pods().Lister().Pods(h.manager.name.Namespace).Get(status.Pod); err == nil { + filteredStatuses = append(filteredStatuses, status) + } + } + } + return filteredStatuses +} diff --git a/pkg/servicemesh/federation/status/manager.go b/pkg/servicemesh/federation/status/manager.go new file mode 100644 index 00000000000..a30d0d6fb15 --- /dev/null +++ b/pkg/servicemesh/federation/status/manager.go @@ -0,0 +1,162 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package status + +import ( + "sync" + + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/errors" + + "istio.io/istio/pilot/pkg/leaderelection" + "istio.io/istio/pkg/servicemesh/federation/common" + "istio.io/istio/pkg/servicemesh/federation/model" + "istio.io/pkg/log" +) + +type Manager interface { + PeerAdded(mesh types.NamespacedName) Handler + PeerDeleted(mesh types.NamespacedName) + HandlerFor(mesh types.NamespacedName) Handler + IsLeader() bool + PushStatus() error +} + +type Handler interface { + // Outbound connections + WatchInitiated() + Watching() + WatchEventReceived() + FullSyncComplete() + WatchTerminated(status string) + + // Inbound connections + RemoteWatchAccepted(source string) + WatchEventSent(source string) + FullSyncSent(source string) + RemoteWatchTerminated(source string) + + // Exports + ExportAdded(service model.ServiceKey, exportedName string) + ExportUpdated(service model.ServiceKey, exportedName string) + ExportRemoved(service model.ServiceKey) + + // Imports + ImportAdded(service model.ServiceKey, exportedName string) + ImportUpdated(service model.ServiceKey, exportedName string) + ImportRemoved(exportedName string) + + // Write status + Flush() error +} + +func NewManager(name types.NamespacedName, rm common.ResourceManager, leaderElection *leaderelection.LeaderElection) Manager { + manager := &manager{ + rm: rm, + logger: common.Logger.WithLabels("component", "federation-status"), + name: name, + leaderElection: leaderElection, + handlers: map[types.NamespacedName]*handler{}, + } + leaderElection.AddRunFunction(manager.BecomeLeader) + return manager +} + +type manager struct { + mu sync.Mutex + rm common.ResourceManager + logger *log.Scope + + name types.NamespacedName + + handlers map[types.NamespacedName]*handler + + leaderElection *leaderelection.LeaderElection + isLeader bool +} + +var _ Manager = (*manager)(nil) + +func (m *manager) BecomeLeader(stop <-chan struct{}) { + func() { + m.mu.Lock() + defer m.mu.Unlock() + m.isLeader = true + }() + _ = m.PushStatus() + <-stop + m.mu.Lock() + defer m.mu.Unlock() + m.isLeader = false +} + +func (m *manager) IsLeader() bool { + m.mu.Lock() + defer m.mu.Unlock() + return m.isLeader +} + +func (m *manager) PeerAdded(mesh types.NamespacedName) Handler { + m.mu.Lock() + defer m.mu.Unlock() + + if handler, exists := m.handlers[mesh]; exists { + m.logger.Debugf("already have a handler for mesh %s", mesh) + return handler + } + handler := newHandler(m, mesh) + m.handlers[mesh] = handler + return handler +} + +func (m *manager) PeerDeleted(mesh types.NamespacedName) { + func() { + m.mu.Lock() + defer m.mu.Unlock() + + if _, exists := m.handlers[mesh]; !exists { + m.logger.Debugf("deleting unknown handler for mesh %s", mesh) + } + delete(m.handlers, mesh) + }() +} + +func (m *manager) HandlerFor(mesh types.NamespacedName) Handler { + handler, exists := m.handlers[mesh] + if !exists { + m.logger.Debugf("handler for mesh %s does not exist", mesh.String()) + return nil + } + return handler +} + +func (m *manager) PushStatus() error { + handlers := func() []*handler { + m.mu.Lock() + defer m.mu.Unlock() + var handlers []*handler + for _, handler := range m.handlers { + handlers = append(handlers, handler) + } + return handlers + }() + var allErrors []error + for _, handler := range handlers { + if err := handler.Flush(); err != nil { + allErrors = append(allErrors, err) + } + } + return errors.NewAggregate(allErrors) +} diff --git a/pkg/servicemesh/federation/status/manager_test.go b/pkg/servicemesh/federation/status/manager_test.go new file mode 100644 index 00000000000..8b8d5924788 --- /dev/null +++ b/pkg/servicemesh/federation/status/manager_test.go @@ -0,0 +1,868 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package status + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/cache" + maistraclient "maistra.io/api/client/versioned" + "maistra.io/api/client/versioned/fake" + v1 "maistra.io/api/federation/v1" + + "istio.io/istio/pilot/pkg/leaderelection" + "istio.io/istio/pkg/kube" + "istio.io/istio/pkg/servicemesh/federation/common" + "istio.io/istio/pkg/servicemesh/federation/model" + "istio.io/istio/pkg/test/util/retry" + "istio.io/pkg/log" +) + +var ignoreTimestamps = cmp.FilterPath(func(p cmp.Path) bool { + switch p.Last().String() { + case ".LastConnected", ".LastDisconnect", ".LastEvent", ".LastFullSync": + return true + } + return false +}, cmp.Ignore()) + +func TestStatusManager(t *testing.T) { + const ( + namespace = "test-namespace" + name = "test" + ) + type federationStatus struct { + peer v1.ServiceMeshPeerStatus + exports v1.ExportedServiceSetStatus + imports v1.ImportedServiceSetStatus + } + istiodName := metav1.ObjectMeta{Name: "istiod-test", Namespace: namespace, UID: "12345"} + meshName := metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + } + testCases := []struct { + name string + mesh types.NamespacedName + events []func(h Handler) + status []federationStatus + assertions []func(t *testing.T, status *v1.ServiceMeshPeerStatus) error + }{ + { + name: "initial-status", + mesh: types.NamespacedName{Namespace: namespace, Name: name}, + }, + { + name: "watch-init-connect-error", + mesh: types.NamespacedName{Namespace: namespace, Name: name}, + events: []func(h Handler){ + func(h Handler) { + h.WatchInitiated() + h.Flush() + }, + func(h Handler) { + h.WatchTerminated("503") + }, + }, + assertions: []func(t *testing.T, status *v1.ServiceMeshPeerStatus) error{ + nil, + func(t *testing.T, status *v1.ServiceMeshPeerStatus) error { + if status.DiscoveryStatus.Inactive[0].Watch.LastConnected.IsZero() { + return fmt.Errorf("expected LastConnected to be updated") + } + return nil + }, + }, + status: []federationStatus{ + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + PeerDiscoveryStatus: v1.PeerDiscoveryStatus{ + Watch: v1.DiscoveryWatchStatus{ + DiscoveryConnectionStatus: v1.DiscoveryConnectionStatus{ + Connected: false, + }, + }, + }, + }, + }, + }, + }, + }, + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + PeerDiscoveryStatus: v1.PeerDiscoveryStatus{ + Watch: v1.DiscoveryWatchStatus{ + DiscoveryConnectionStatus: v1.DiscoveryConnectionStatus{ + Connected: false, + LastDisconnectStatus: "503", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "watch-init-connect-success", + mesh: types.NamespacedName{Namespace: namespace, Name: name}, + events: []func(h Handler){ + func(h Handler) { + h.WatchInitiated() + h.Flush() + }, + func(h Handler) { + h.Watching() + }, + func(h Handler) { + h.WatchTerminated("200") + }, + }, + assertions: []func(t *testing.T, status *v1.ServiceMeshPeerStatus) error{ + nil, + func(t *testing.T, status *v1.ServiceMeshPeerStatus) error { + if status.DiscoveryStatus.Active[0].Watch.LastConnected.IsZero() { + return fmt.Errorf("expected LastConnected to be updated") + } + return nil + }, + func(t *testing.T, status *v1.ServiceMeshPeerStatus) error { + if status.DiscoveryStatus.Inactive[0].Watch.LastDisconnect.IsZero() { + return fmt.Errorf("expected LastDisconnect to be updated") + } + return nil + }, + }, + status: []federationStatus{ + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + PeerDiscoveryStatus: v1.PeerDiscoveryStatus{ + Watch: v1.DiscoveryWatchStatus{ + DiscoveryConnectionStatus: v1.DiscoveryConnectionStatus{ + Connected: false, + }, + }, + }, + }, + }, + }, + }, + }, + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Active: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + PeerDiscoveryStatus: v1.PeerDiscoveryStatus{ + Watch: v1.DiscoveryWatchStatus{ + DiscoveryConnectionStatus: v1.DiscoveryConnectionStatus{ + Connected: true, + }, + }, + }, + }, + }, + }, + }, + }, + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + PeerDiscoveryStatus: v1.PeerDiscoveryStatus{ + Watch: v1.DiscoveryWatchStatus{ + DiscoveryConnectionStatus: v1.DiscoveryConnectionStatus{ + Connected: false, + LastDisconnectStatus: "200", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "watch-remote", + mesh: types.NamespacedName{Namespace: namespace, Name: name}, + events: []func(h Handler){ + func(h Handler) { + h.RemoteWatchAccepted("10.10.10.10") + }, + func(h Handler) { + h.WatchEventSent("10.10.10.10") + }, + func(h Handler) { + h.FullSyncSent("10.10.10.10") + }, + func(h Handler) { + h.RemoteWatchTerminated("10.10.10.10") + }, + }, + assertions: []func(t *testing.T, status *v1.ServiceMeshPeerStatus) error{ + func(t *testing.T, status *v1.ServiceMeshPeerStatus) error { + if status.DiscoveryStatus.Inactive[0].Remotes[0].LastConnected.IsZero() { + return fmt.Errorf("expected LastConnected to be updated") + } + return nil + }, + nil, + func(t *testing.T, status *v1.ServiceMeshPeerStatus) error { + // full sync causes a push, so we can also verify that an event was seen + if status.DiscoveryStatus.Inactive[0].Remotes[0].LastEvent.IsZero() { + return fmt.Errorf("expected LastEvent to be updated") + } + if status.DiscoveryStatus.Inactive[0].Remotes[0].LastFullSync.IsZero() { + return fmt.Errorf("expected LastFullSync to be updated") + } + return nil + }, + func(t *testing.T, status *v1.ServiceMeshPeerStatus) error { + if status.DiscoveryStatus.Inactive[0].Remotes[0].LastDisconnect.IsZero() { + return fmt.Errorf("expected LastDisconnect to be updated") + } + return nil + }, + }, + status: []federationStatus{ + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + PeerDiscoveryStatus: v1.PeerDiscoveryStatus{ + Remotes: []v1.DiscoveryRemoteStatus{ + { + Source: "10.10.10.10", + DiscoveryConnectionStatus: v1.DiscoveryConnectionStatus{ + Connected: true, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + PeerDiscoveryStatus: v1.PeerDiscoveryStatus{ + Remotes: []v1.DiscoveryRemoteStatus{ + { + Source: "10.10.10.10", + DiscoveryConnectionStatus: v1.DiscoveryConnectionStatus{ + Connected: true, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + PeerDiscoveryStatus: v1.PeerDiscoveryStatus{ + Remotes: []v1.DiscoveryRemoteStatus{ + { + Source: "10.10.10.10", + DiscoveryConnectionStatus: v1.DiscoveryConnectionStatus{ + Connected: true, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + PeerDiscoveryStatus: v1.PeerDiscoveryStatus{ + Remotes: []v1.DiscoveryRemoteStatus{ + { + Source: "10.10.10.10", + DiscoveryConnectionStatus: v1.DiscoveryConnectionStatus{ + Connected: false, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "watch-export-added-updated-deleted", + mesh: types.NamespacedName{Namespace: namespace, Name: name}, + events: []func(h Handler){ + func(h Handler) { + h.ExportAdded( + model.ServiceKey{ + Name: "real-service", + Namespace: "real-namespace", + Hostname: "real-service.real-namespace.svc.cluster.local", + }, + "exported-service.exported-namespace.svc.mesh.local") + h.Flush() + }, + func(h Handler) { + h.ExportUpdated( + model.ServiceKey{ + Name: "real-service", + Namespace: "real-namespace", + Hostname: "real-service.real-namespace.svc.cluster.local", + }, + "updated-exported-service.exported-namespace.svc.mesh.local") + h.Flush() + }, + func(h Handler) { + h.ExportRemoved( + model.ServiceKey{ + Name: "real-service", + Namespace: "real-namespace", + Hostname: "real-service.real-namespace.svc.cluster.local", + }) + h.Flush() + }, + }, + assertions: []func(t *testing.T, status *v1.ServiceMeshPeerStatus) error{ + nil, nil, nil, + }, + status: []federationStatus{ + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + }, + }, + }, + }, + exports: v1.ExportedServiceSetStatus{ + ExportedServices: []v1.PeerServiceMapping{ + { + LocalService: v1.ServiceKey{ + Name: "real-service", + Namespace: "real-namespace", + Hostname: "real-service.real-namespace.svc.cluster.local", + }, + ExportedName: "exported-service.exported-namespace.svc.mesh.local", + }, + }, + }, + }, + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + }, + }, + }, + }, + exports: v1.ExportedServiceSetStatus{ + ExportedServices: []v1.PeerServiceMapping{ + { + LocalService: v1.ServiceKey{ + Name: "real-service", + Namespace: "real-namespace", + Hostname: "real-service.real-namespace.svc.cluster.local", + }, + ExportedName: "updated-exported-service.exported-namespace.svc.mesh.local", + }, + }, + }, + }, + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + }, + }, + }, + }, + }, + }, + }, + { + name: "watch-export-added-updated-deleted-no-flush", + mesh: types.NamespacedName{Namespace: namespace, Name: name}, + events: []func(h Handler){ + func(h Handler) { + h.ExportAdded( + model.ServiceKey{ + Name: "real-service", + Namespace: "real-namespace", + Hostname: "real-service.real-namespace.svc.cluster.local", + }, + "exported-service.exported-namespace.svc.mesh.local") + }, + func(h Handler) { + h.ExportUpdated( + model.ServiceKey{ + Name: "real-service", + Namespace: "real-namespace", + Hostname: "real-service.real-namespace.svc.cluster.local", + }, + "updated-exported-service.exported-namespace.svc.mesh.local") + }, + func(h Handler) { + h.ExportRemoved( + model.ServiceKey{ + Name: "real-service", + Namespace: "real-namespace", + Hostname: "real-service.real-namespace.svc.cluster.local", + }) + }, + func(h Handler) { + h.Flush() + }, + }, + assertions: []func(t *testing.T, status *v1.ServiceMeshPeerStatus) error{ + nil, nil, nil, nil, + }, + status: []federationStatus{ + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + }, + }, + }, + }, + }, + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + }, + }, + }, + }, + }, + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + }, + }, + }, + }, + }, + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + }, + }, + }, + }, + }, + }, + }, + { + name: "watch-import-added-updated-deleted", + mesh: types.NamespacedName{Namespace: namespace, Name: name}, + events: []func(h Handler){ + func(h Handler) { + h.WatchEventReceived() + h.ImportAdded( + model.ServiceKey{ + Name: "local-service", + Namespace: "local-namespace", + Hostname: "local-service.local-namespace.svc.test-mesh.local", + }, + "exported-service.exported-namespace.svc.mesh.local") + h.Flush() + }, + func(h Handler) { + h.WatchEventReceived() + h.ImportUpdated( + model.ServiceKey{}, + "exported-service.exported-namespace.svc.mesh.local") + h.Flush() + }, + func(h Handler) { + h.WatchEventReceived() + h.ImportRemoved("exported-service.exported-namespace.svc.mesh.local") + h.Flush() + }, + }, + assertions: []func(t *testing.T, status *v1.ServiceMeshPeerStatus) error{ + func(t *testing.T, status *v1.ServiceMeshPeerStatus) error { + if len(status.DiscoveryStatus.Inactive) == 0 || + (len(status.DiscoveryStatus.Inactive) > 0 && status.DiscoveryStatus.Inactive[0].Watch.LastEvent.IsZero()) { + return fmt.Errorf("expected LastEvent to be updated") + } + return nil + }, + nil, nil, + }, + status: []federationStatus{ + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + }, + }, + }, + }, + imports: v1.ImportedServiceSetStatus{ + ImportedServices: []v1.PeerServiceMapping{ + { + LocalService: v1.ServiceKey{ + Name: "local-service", + Namespace: "local-namespace", + Hostname: "local-service.local-namespace.svc.test-mesh.local", + }, + ExportedName: "exported-service.exported-namespace.svc.mesh.local", + }, + }, + }, + }, + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + }, + }, + }, + }, + imports: v1.ImportedServiceSetStatus{ + ImportedServices: []v1.PeerServiceMapping{ + { + LocalService: v1.ServiceKey{}, + ExportedName: "exported-service.exported-namespace.svc.mesh.local", + }, + }, + }, + }, + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + }, + }, + }, + }, + }, + }, + }, + { + name: "watch-import-added-updated-deleted-no-flush", + mesh: types.NamespacedName{Namespace: namespace, Name: name}, + events: []func(h Handler){ + func(h Handler) { + h.WatchEventReceived() + h.ImportAdded( + model.ServiceKey{ + Name: "local-service", + Namespace: "local-namespace", + Hostname: "local-service.local-namespace.svc.test-mesh.local", + }, + "exported-service.exported-namespace.svc.mesh.local") + }, + func(h Handler) { + h.WatchEventReceived() + h.ImportUpdated( + model.ServiceKey{}, + "exported-service.exported-namespace.svc.mesh.local") + }, + func(h Handler) { + h.WatchEventReceived() + h.ImportRemoved("exported-service.exported-namespace.svc.mesh.local") + }, + func(h Handler) { + h.FullSyncComplete() + }, + }, + assertions: []func(t *testing.T, status *v1.ServiceMeshPeerStatus) error{ + func(t *testing.T, status *v1.ServiceMeshPeerStatus) error { + if !status.DiscoveryStatus.Inactive[0].Watch.LastEvent.IsZero() { + return fmt.Errorf("did not expect LastEvent to be updated") + } + if !status.DiscoveryStatus.Inactive[0].Watch.LastFullSync.IsZero() { + return fmt.Errorf("did not expect LastFullSync to be updated") + } + return nil + }, + nil, nil, + func(t *testing.T, status *v1.ServiceMeshPeerStatus) error { + // this should have been updated in one of the previous events + if status.DiscoveryStatus.Inactive[0].Watch.LastEvent.IsZero() { + return fmt.Errorf("expected LastEvent to be updated") + } + if status.DiscoveryStatus.Inactive[0].Watch.LastFullSync.IsZero() { + return fmt.Errorf("expected LastFullSync to be updated") + } + return nil + }, + }, + status: []federationStatus{ + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + }, + }, + }, + }, + }, + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + }, + }, + }, + }, + }, + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + }, + }, + }, + }, + }, + { + peer: v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + }, + }, + }, + }, + }, + }, + }, + } + logOpts := log.DefaultOptions() + logOpts.SetOutputLevel("federation", log.DebugLevel) + logOpts.JSONEncoding = false + log.Configure(logOpts) + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // verify test is setup correctly + if len(tc.status) != len(tc.events) || len(tc.assertions) != len(tc.events) { + t.Fatalf("number of status elements and asserts must equal the number of events") + } + kubeClient := kube.NewFakeClient(&corev1.Pod{ + ObjectMeta: istiodName, + }) + stop := make(chan struct{}) + defer func() { close(stop) }() + go kubeClient.KubeInformer().Core().V1().Pods().Informer().Run(stop) + for !kubeClient.KubeInformer().Core().V1().Pods().Informer().HasSynced() { + } + cs := fake.NewSimpleClientset( + &v1.ExportedServiceSet{ObjectMeta: metav1.ObjectMeta{Name: tc.mesh.Name, Namespace: tc.mesh.Namespace}}, + &v1.ImportedServiceSet{ObjectMeta: metav1.ObjectMeta{Name: tc.mesh.Name, Namespace: tc.mesh.Namespace}}) + rm, err := common.NewResourceManager(common.ControllerOptions{ + KubeClient: kubeClient, + MaistraCS: cs, + ResyncPeriod: 1 * time.Millisecond, + }, nil) + if err != nil { + t.Fatalf("error creating ResourceManager: %s", err) + } + stopChan := make(chan struct{}) + defer close(stopChan) + go rm.Start(stopChan) + cs.FederationV1().ServiceMeshPeers(namespace).Create(context.TODO(), &v1.ServiceMeshPeer{ + ObjectMeta: meshName, + }, metav1.CreateOptions{}) + leaderStarted := make(chan struct{}) + le := leaderelection.NewLeaderElection(istiodName.Namespace, istiodName.Name, "test", "test", kubeClient) + manager := NewManager(types.NamespacedName{Name: istiodName.Name, Namespace: istiodName.Namespace}, rm, le) + le.AddRunFunction(func(stop <-chan struct{}) { + cache.WaitForCacheSync(stopChan, manager.IsLeader) + close(leaderStarted) + }) + go le.Run(stopChan) + select { + case <-leaderStarted: + case <-time.After(30 * time.Second): + close(stopChan) + t.Fatalf("timed out waiting for leader election") + } + for !rm.ExportsInformer().Informer().HasSynced() || + !rm.ImportsInformer().Informer().HasSynced() || + !rm.PeerInformer().Informer().HasSynced() { + } + manager.PeerAdded(tc.mesh) + if err := manager.PushStatus(); err != nil { + t.Fatalf("error updating initial status: %s", err) + } + verifyPeerStatus(t, cs, tc.mesh, &v1.ServiceMeshPeerStatus{ + DiscoveryStatus: v1.ServiceMeshPeerDiscoveryStatus{ + Inactive: []v1.PodPeerDiscoveryStatus{ + { + Pod: istiodName.Name, + }, + }, + }, + }, nil) + + handler := manager.HandlerFor(types.NamespacedName{Namespace: tc.mesh.Namespace, Name: tc.mesh.Name}) + if handler == nil { + t.Fatalf("nil handler for %s/%s", tc.mesh.Namespace, tc.mesh.Name) + } + for index, f := range tc.events { + t.Logf("processing event %d", index) + f(handler) + verifyPeerStatus(t, cs, tc.mesh, &tc.status[index].peer, tc.assertions[index]) + verifyExportStatus(t, cs, tc.mesh, &tc.status[index].exports) + verifyImportStatus(t, cs, tc.mesh, &tc.status[index].imports) + } + }) + } +} + +func verifyPeerStatus(t *testing.T, cs maistraclient.Interface, name types.NamespacedName, expected *v1.ServiceMeshPeerStatus, + assert func(*testing.T, *v1.ServiceMeshPeerStatus) error, +) { + t.Helper() + tryMultipleTimes(t, func() error { + actual, err := cs.FederationV1().ServiceMeshPeers(name.Namespace).Get(context.TODO(), name.Name, metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("unexpected error retrieving ServiceMeshPeer %s/%s: %s", name.Namespace, name.Name, err) + } + if diff := cmp.Diff(&actual.Status, expected, ignoreTimestamps); diff != "" { + return fmt.Errorf("comparison failed, -got +want:\n%s", diff) + } + if assert != nil { + return assert(t, &actual.Status) + } + return nil + }) +} + +func verifyExportStatus(t *testing.T, cs maistraclient.Interface, name types.NamespacedName, + expected *v1.ExportedServiceSetStatus, +) { + t.Helper() + tryMultipleTimes(t, func() error { + actual, err := cs.FederationV1().ExportedServiceSets(name.Namespace).Get(context.TODO(), name.Name, metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("unexpected error retrieving ExportedServiceSet %s/%s: %s", name.Namespace, name.Name, err) + } + if expected.ExportedServices == nil { + expected.ExportedServices = []v1.PeerServiceMapping{} + } + if diff := cmp.Diff(&actual.Status, expected, ignoreTimestamps); diff != "" { + return fmt.Errorf("comparison failed, -got +want:\n%s", diff) + } + return nil + }) +} + +func verifyImportStatus(t *testing.T, cs maistraclient.Interface, name types.NamespacedName, + expected *v1.ImportedServiceSetStatus, +) { + t.Helper() + tryMultipleTimes(t, func() error { + actual, err := cs.FederationV1().ImportedServiceSets(name.Namespace).Get(context.TODO(), name.Name, metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("unexpected error retrieving ImportedServiceSet %s/%s: %s", name.Namespace, name.Name, err) + } + if expected.ImportedServices == nil { + expected.ImportedServices = []v1.PeerServiceMapping{} + } + if diff := cmp.Diff(&actual.Status, expected, ignoreTimestamps); diff != "" { + return fmt.Errorf("comparison failed, -got +want:\n%s", diff) + } + return nil + }) +} + +func tryMultipleTimes(t *testing.T, fn func() error) { + if err := retry.UntilSuccess(fn, retry.Timeout(10*time.Second), retry.Delay(10*time.Millisecond)); err != nil { + t.Error(err.Error()) + } +} diff --git a/pkg/servicemesh/maistra.mk b/pkg/servicemesh/maistra.mk deleted file mode 100644 index 2caa81bf8fb..00000000000 --- a/pkg/servicemesh/maistra.mk +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2019 Istio Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -client_gen = client-gen -lister_gen = lister-gen -informer_gen = informer-gen - -kube_base_output_package = istio.io/istio/pkg/servicemesh -kube_api_base_package = $(kube_base_output_package)/apis -kube_api_packages = $(kube_api_base_package)/servicemesh/v1 -kube_clientset_package = $(kube_base_output_package)/clientset - -# file header text -kube_go_header_text = pkg/servicemesh/header.go.txt -# clientset name used by kubernetes client-gen -kube_clientset_name = versioned -# base output package used by kubernetes client-gen -kube_clientset_package = $(kube_base_output_package)/client/clientset -# base output package used by kubernetes lister-gen -kube_listers_package = $(kube_base_output_package)/client/listers -# base output package used by kubernetes informer-gen -kube_informers_package = $(kube_base_output_package)/client/informers - -ifeq ($(IN_BUILD_CONTAINER),1) - # k8s code generators rely on GOPATH, using $GOPATH/src as the base package - # directory. Using --output-base . does not work, as that ends up generating - # code into ./, e.g. ./istio.io/client-go/pkg/apis/... To work - # around this, we'll just let k8s generate the code where it wants and copy - # back to where it should have been generated. - move_generated=cp -r $(GOPATH)/src/$(kube_base_output_package)/ ./pkg && rm -rf $(GOPATH)/src/$(kube_base_output_package)/ -else - # nothing special for local builds - move_generated= -endif - -.PHONY: maistra-gen-k8s-client -maistra-gen-k8s-client: - @$(client_gen) --clientset-name $(kube_clientset_name) --input-base "" --input $(kube_api_packages) --output-package $(kube_clientset_package) -h $(kube_go_header_text) - @$(lister_gen) --input-dirs $(kube_api_packages) --output-package $(kube_listers_package) -h $(kube_go_header_text) - @$(informer_gen) --input-dirs $(kube_api_packages) --versioned-clientset-package $(kube_clientset_package)/$(kube_clientset_name) --listers-package $(kube_listers_package) --output-package $(kube_informers_package) -h $(kube_go_header_text) - @$(move_generated) - -.PHONY: vendor -vendor: - @echo "updating vendor" - @go mod vendor - @echo "done updating vendor" - -.PHONY: gen -maistra-gen: maistra-gen-k8s-client vendor diff --git a/pkg/servicemesh/model/extension.go b/pkg/servicemesh/model/extension.go new file mode 100644 index 00000000000..cfb4501d4e6 --- /dev/null +++ b/pkg/servicemesh/model/extension.go @@ -0,0 +1,46 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package model + +import ( + v1 "maistra.io/api/core/v1" + + "istio.io/istio/pkg/config/labels" +) + +// ExtensionWrapper is a wrapper around extensions +type ExtensionWrapper struct { + Name string + WorkloadSelector labels.Instance + Config *v1.ServiceMeshExtensionConfig + Image string + FilterURL string + SHA256 string + Phase v1.FilterPhase + Priority int +} + +func ToWrapper(extension *v1.ServiceMeshExtension) *ExtensionWrapper { + return &ExtensionWrapper{ + Name: extension.Name, + WorkloadSelector: extension.Spec.WorkloadSelector.Labels, + Config: extension.Spec.Config.DeepCopy(), + Image: extension.Spec.Image, + FilterURL: extension.Status.Deployment.URL, + SHA256: extension.Status.Deployment.SHA256, + Phase: extension.Status.Phase, + Priority: extension.Status.Priority, + } +} diff --git a/pkg/test/framework/components/istio/config.go b/pkg/test/framework/components/istio/config.go index d45069cf24d..4a02cbba771 100644 --- a/pkg/test/framework/components/istio/config.go +++ b/pkg/test/framework/components/istio/config.go @@ -87,6 +87,8 @@ var ( DumpKubernetesManifests: false, IstiodlessRemotes: false, EnableCNI: false, + ConfigureMultiCluster: true, + ConfigureRemoteCluster: true, } ) @@ -153,6 +155,12 @@ type Config struct { // EnableCNI indicates the test should have CNI enabled. EnableCNI bool + + ConfigureMultiCluster bool + + ConfigureRemoteCluster bool + + DifferentTrustDomains bool } func (c *Config) OverridesYAML(s *resource.Settings) string { @@ -306,6 +314,8 @@ func (c *Config) String() string { result += fmt.Sprintf("IstiodlessRemotes: %v\n", c.IstiodlessRemotes) result += fmt.Sprintf("OperatorOptions: %v\n", c.OperatorOptions) result += fmt.Sprintf("EnableCNI: %v\n", c.EnableCNI) + result += fmt.Sprintf("ConfigureMultiCluster: %v\n", c.ConfigureMultiCluster) + result += fmt.Sprintf("DifferentTrustDomains: %v\n", c.DifferentTrustDomains) return result } diff --git a/pkg/test/framework/components/istio/operator.go b/pkg/test/framework/components/istio/operator.go index 12ec051044d..a582e7f182e 100644 --- a/pkg/test/framework/components/istio/operator.go +++ b/pkg/test/framework/components/istio/operator.go @@ -323,18 +323,20 @@ func deploy(ctx resource.Context, env *kube.Environment, cfg Config) (Instance, } // For multicluster, create and push the CA certs to all clusters to establish a shared root of trust. - if env.IsMulticluster() { + if env.IsMulticluster() && cfg.ConfigureMultiCluster { if err := deployCACerts(workDir, env, cfg); err != nil { return nil, err } } - // First install remote-config clusters. - // We do this first because the external istiod needs to read the config cluster at startup. s := ctx.Settings() - for _, c := range ctx.Clusters().Kube().Configs().Remotes() { - if err = installConfigCluster(s, i, cfg, c, istioctlConfigFiles.configIopFile); err != nil { - return i, err + if cfg.ConfigureRemoteCluster { + // First install remote-config clusters. + // We do this first because the external istiod needs to read the config cluster at startup. + for _, c := range ctx.Clusters().Kube().Configs().Remotes() { + if err = installConfigCluster(s, i, cfg, c, istioctlConfigFiles.configIopFile); err != nil { + return i, err + } } } @@ -355,7 +357,7 @@ func deploy(ctx resource.Context, env *kube.Environment, cfg Config) (Instance, // This needs to be done before installing remote clusters to accommodate non-istiodless remote cluster // that use the default profile, which installs gateways right away and will fail if the control plane // isn't responding. - if ctx.Clusters().IsMulticluster() { + if ctx.Clusters().IsMulticluster() && cfg.ConfigureMultiCluster { if err := i.configureDirectAPIServerAccess(ctx, cfg); err != nil { return nil, err } @@ -395,7 +397,7 @@ func deploy(ctx resource.Context, env *kube.Environment, cfg Config) (Instance, } // remote clusters only need east-west gateway for multi-network purposes - if ctx.Environment().IsMultinetwork() { + if ctx.Environment().IsMultinetwork() && cfg.DeployEastWestGW { spec := istioctlConfigFiles.remoteOperatorSpec if c.IsConfig() { spec = istioctlConfigFiles.configOperatorSpec @@ -620,7 +622,7 @@ func installRemoteCommon(s *resource.Settings, i *operatorComponent, cfg Config, } // Configure the cluster and network arguments to pass through the injector webhook. - if i.isExternalControlPlane() { + if i.isExternalControlPlane() || !cfg.DeployEastWestGW { installArgs.Set = append(installArgs.Set, fmt.Sprintf("values.istiodRemote.injectionPath=/inject/net/%s/cluster/%s", c.NetworkName(), c.Name())) } else { @@ -720,6 +722,11 @@ func (i *operatorComponent) generateCommonInstallArgs(s *resource.Settings, cfg "components.cni.enabled=true") } + if cfg.DifferentTrustDomains { + delete(cfg.Values, "meshConfig.trustDomain") + installArgs.Set = append(installArgs.Set, fmt.Sprintf("values.meshConfig.trustDomain=%s.local", c.Name())) + } + // Include all user-specified values. for k, v := range cfg.Values { installArgs.Set = append(installArgs.Set, fmt.Sprintf("values.%s=%s", k, v)) diff --git a/pkg/test/framework/label/labels.go b/pkg/test/framework/label/labels.go index ca72bd8dbc8..1725965d4cc 100644 --- a/pkg/test/framework/label/labels.go +++ b/pkg/test/framework/label/labels.go @@ -24,12 +24,17 @@ const ( // IPv4 indicates a test is only compatible with IPv4 clusters. // Any usage of this should have an associated GitHub issue to make it compatible with IPv6 IPv4 Instance = "ipv4" + + // TODO: Make sure that we need this label + // Multicluster indicates that the test requires a multicluster configuration. + Multicluster Instance = "multicluster" ) var all = NewSet( Postsubmit, CustomSetup, - IPv4) + IPv4, + Multicluster) // Find the label with the given name func Find(name string) (Instance, bool) { diff --git a/pkg/util/gogo/conversion.go b/pkg/util/gogo/conversion.go new file mode 100644 index 00000000000..fa3862cc9ac --- /dev/null +++ b/pkg/util/gogo/conversion.go @@ -0,0 +1,71 @@ +// Copyright Istio Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gogo + +import ( + "fmt" + + "github.com/gogo/protobuf/proto" + "github.com/gogo/protobuf/types" + any "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/durationpb" + wrappers "google.golang.org/protobuf/types/known/wrapperspb" + + iproto "istio.io/istio/pkg/proto" + "istio.io/pkg/log" +) + +// MessageToAnyWithError converts from proto message to proto Any +func MessageToAnyWithError(msg proto.Message) (*any.Any, error) { + b := proto.NewBuffer(nil) + err := b.Marshal(msg) + if err != nil { + return nil, err + } + return &any.Any{ + TypeUrl: "type.googleapis.com/" + proto.MessageName(msg), + Value: b.Bytes(), + }, nil +} + +// MessageToAny converts from proto message to proto Any +func MessageToAny(msg proto.Message) *any.Any { + out, err := MessageToAnyWithError(msg) + if err != nil { + log.Error(fmt.Sprintf("error marshaling Any %s: %v", msg.String(), err)) + return nil + } + return out +} + +func BoolToProtoBool(gogo *types.BoolValue) *wrappers.BoolValue { + if gogo == nil { + return nil + } + if gogo.Value { + return iproto.BoolTrue + } + return iproto.BoolFalse +} + +func DurationToProtoDuration(gogo *types.Duration) *durationpb.Duration { + if gogo == nil { + return nil + } + return &durationpb.Duration{ + Seconds: gogo.Seconds, + Nanos: gogo.Nanos, + } +} diff --git a/pkg/util/gogo/conversion_test.go b/pkg/util/gogo/conversion_test.go new file mode 100644 index 00000000000..957b287f1a0 --- /dev/null +++ b/pkg/util/gogo/conversion_test.go @@ -0,0 +1,95 @@ +// Copyright Istio Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gogo + +import ( + "reflect" + "testing" + + "github.com/gogo/protobuf/types" + "google.golang.org/protobuf/types/known/durationpb" + wrappers "google.golang.org/protobuf/types/known/wrapperspb" + + "istio.io/istio/pkg/proto" +) + +func TestBoolToProtoBool(t *testing.T) { + tests := []struct { + desc string + gogo *types.BoolValue + expectedValue *wrappers.BoolValue + }{ + { + desc: "BoolToProtoBool with nil gogo", + gogo: nil, + expectedValue: nil, + }, + { + desc: "BoolToProtoBool with true gogo.Value", + gogo: &types.BoolValue{ + Value: true, + }, + expectedValue: proto.BoolTrue, + }, + { + desc: "BoolToProtoBool with false gogo.Value", + gogo: &types.BoolValue{ + Value: false, + }, + expectedValue: proto.BoolFalse, + }, + } + + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + if got := BoolToProtoBool(tt.gogo); got != tt.expectedValue { + t.Errorf("%s: got: %v, expected: %v", tt.desc, got, tt.expectedValue) + } + }) + } +} + +func TestDurationToProtoDuration(t *testing.T) { + tests := []struct { + desc string + gogo *types.Duration + expectedValue *durationpb.Duration + }{ + { + desc: "DurationToProtoDuration with nil gogo", + gogo: nil, + expectedValue: nil, + }, + { + desc: "DurationToProtoDuration with valid Seconds and Nanos", + gogo: &types.Duration{ + Seconds: 1000000, + Nanos: 100000, + }, + expectedValue: &durationpb.Duration{ + Seconds: 1000000, + Nanos: 100000, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + if got := DurationToProtoDuration(tt.gogo); !reflect.DeepEqual(got, tt.expectedValue) { + t.Errorf("%s: got: %v, expected: %v", tt.desc, got, tt.expectedValue) + } + }) + } +} diff --git a/security/pkg/nodeagent/cache/secretcache.go b/security/pkg/nodeagent/cache/secretcache.go index 4ace00c6f23..239e6d1871b 100644 --- a/security/pkg/nodeagent/cache/secretcache.go +++ b/security/pkg/nodeagent/cache/secretcache.go @@ -126,6 +126,10 @@ type secretCache struct { mu sync.RWMutex workload *security.SecretItem certRoot []byte + + // Read/Write to trustBundleMap and trustBundleExpireTime should use getRootCertByTrustDomain() and setRootCertByTrustDomain(). + trustBundleMap map[string][]byte + trustBundleExpireTime time.Time } // GetRoot returns cached root cert and cert expiration time. This method is thread safe. @@ -226,6 +230,7 @@ func (sc *SecretManagerClient) getCachedSecret(resourceName string) (secret *sec ResourceName: resourceName, RootCert: rootCertBundle, } + sc.addTrustBundles(ns) cacheLog.WithLabels("ttl", time.Until(c.ExpireTime)).Info("returned workload trust anchor from cache") } else { @@ -244,6 +249,30 @@ func (sc *SecretManagerClient) getCachedSecret(resourceName string) (secret *sec return nil } +func (sc *SecretManagerClient) GetTrustBundles() (trustBundles map[string][]byte, earliestExpiry time.Time) { + sc.cache.mu.RLock() + trustBundles = sc.cache.trustBundleMap + earliestExpiry = sc.cache.trustBundleExpireTime + if trustBundles != nil && sc.cache.certRoot != nil { + trustBundles[sc.configOptions.TrustDomain] = sc.cache.certRoot + } + sc.cache.mu.RUnlock() + return trustBundles, earliestExpiry +} + +func (sc *SecretManagerClient) SetTrustBundles(trustBundles map[string][]byte, earliestExpiry time.Time) { + sc.cache.mu.Lock() + trustBundlesUpdated := !compareTrustBundles(sc.cache.trustBundleMap, trustBundles) + if trustBundlesUpdated { + sc.cache.trustBundleMap = trustBundles + sc.cache.trustBundleExpireTime = earliestExpiry + } + sc.cache.mu.Unlock() + if trustBundlesUpdated { + sc.OnSecretUpdate(security.RootCertReqResourceName) + } +} + // GenerateSecret passes the cached secret to SDS.StreamSecrets and SDS.FetchSecret. func (sc *SecretManagerClient) GenerateSecret(resourceName string) (secret *security.SecretItem, err error) { cacheLog.Debugf("generate secret %q", resourceName) @@ -307,6 +336,7 @@ func (sc *SecretManagerClient) GenerateSecret(resourceName string) (secret *secu if resourceName == security.RootCertReqResourceName { ns.RootCert = sc.mergeTrustAnchorBytes(ns.RootCert) + sc.addTrustBundles(ns) } else { // If periodic cert refresh resulted in discovery of a new root, trigger a ROOTCA request to refresh trust anchor oldRoot := sc.cache.GetRoot() @@ -499,6 +529,7 @@ func (sc *SecretManagerClient) generateFileSecret(resourceName string) (bool, *s if sitem, err = sc.generateRootCertFromExistingFile(cf.CaCertificatePath, resourceName, true); err == nil { // If retrieving workload trustBundle, then merge other configured trustAnchors in ProxyConfig sitem.RootCert = sc.mergeTrustAnchorBytes(sitem.RootCert) + sc.addTrustBundles(sitem) sc.addFileWatcher(cf.CaCertificatePath, resourceName) } // Default workload certificate. @@ -772,3 +803,25 @@ func (sc *SecretManagerClient) mergeConfigTrustBundle(rootCerts []string) []byte } return anchorBytes } + +func (sc *SecretManagerClient) addTrustBundles(secretItem *security.SecretItem) { + trustBundles, trustBundleExpiry := sc.GetTrustBundles() + secretItem.TrustBundles = trustBundles + if trustBundles != nil && trustBundleExpiry.Before(secretItem.ExpireTime) { + secretItem.ExpireTime = trustBundleExpiry + } +} + +// returns true if trust bundles are the same +func compareTrustBundles(a map[string][]byte, b map[string][]byte) bool { + if len(a) != len(b) { + return false + } + for k, v := range a { + //nolint:gocritic + if string(b[k]) != string(v) { + return false + } + } + return true +} diff --git a/security/pkg/nodeagent/sds/sdsservice.go b/security/pkg/nodeagent/sds/sdsservice.go index 3a6ab330671..d3ce60a9b4f 100644 --- a/security/pkg/nodeagent/sds/sdsservice.go +++ b/security/pkg/nodeagent/sds/sdsservice.go @@ -214,64 +214,90 @@ func toEnvoySecret(s *security.SecretItem, caRootPath string, pkpConf *mesh.Priv secret := &tls.Secret{ Name: s.ResourceName, } - cfg := security.SdsCertificateConfig{} - ok := false - if s.ResourceName == security.FileRootSystemCACert { - cfg, ok = security.SdsCertificateConfigFromResourceNameForOSCACert(caRootPath) - } else { - cfg, ok = security.SdsCertificateConfigFromResourceName(s.ResourceName) - } - if s.ResourceName == security.RootCertReqResourceName || (ok && cfg.IsRootCertificate()) { + + if s.TrustBundles != nil { + spiffeValidatorConfig := &tls.SPIFFECertValidatorConfig{} + for trustDomain, rootCert := range s.TrustBundles { + spiffeValidatorConfig.TrustDomains = append( + spiffeValidatorConfig.TrustDomains, + &tls.SPIFFECertValidatorConfig_TrustDomain{ + Name: trustDomain, + TrustBundle: &core.DataSource{ + Specifier: &core.DataSource_InlineBytes{ + InlineBytes: rootCert, + }, + }, + }, + ) + } secret.Type = &tls.Secret_ValidationContext{ ValidationContext: &tls.CertificateValidationContext{ - TrustedCa: &core.DataSource{ - Specifier: &core.DataSource_InlineBytes{ - InlineBytes: s.RootCert, - }, + CustomValidatorConfig: &core.TypedExtensionConfig{ + Name: "envoy.tls.cert_validator.spiffe", + TypedConfig: util.MessageToAny(spiffeValidatorConfig), }, }, } } else { - switch pkpConf.GetProvider().(type) { - case *mesh.PrivateKeyProvider_Cryptomb: - crypto := pkpConf.GetCryptomb() - msg := util.MessageToAny(&cryptomb.CryptoMbPrivateKeyMethodConfig{ - PollDelay: durationpb.New(time.Duration(crypto.GetPollDelay().Nanos)), - PrivateKey: &core.DataSource{ - Specifier: &core.DataSource_InlineBytes{ - InlineBytes: s.PrivateKey, - }, - }, - }) - secret.Type = &tls.Secret_TlsCertificate{ - TlsCertificate: &tls.TlsCertificate{ - CertificateChain: &core.DataSource{ + cfg := security.SdsCertificateConfig{} + ok := false + if s.ResourceName == security.FileRootSystemCACert { + cfg, ok = security.SdsCertificateConfigFromResourceNameForOSCACert(caRootPath) + } else { + cfg, ok = security.SdsCertificateConfigFromResourceName(s.ResourceName) + } + if s.ResourceName == security.RootCertReqResourceName || (ok && cfg.IsRootCertificate()) { + secret.Type = &tls.Secret_ValidationContext{ + ValidationContext: &tls.CertificateValidationContext{ + TrustedCa: &core.DataSource{ Specifier: &core.DataSource_InlineBytes{ - InlineBytes: s.CertificateChain, - }, - }, - PrivateKeyProvider: &tls.PrivateKeyProvider{ - ProviderName: "cryptomb", - ConfigType: &tls.PrivateKeyProvider_TypedConfig{ - TypedConfig: msg, + InlineBytes: s.RootCert, }, }, }, } - default: - secret.Type = &tls.Secret_TlsCertificate{ - TlsCertificate: &tls.TlsCertificate{ - CertificateChain: &core.DataSource{ - Specifier: &core.DataSource_InlineBytes{ - InlineBytes: s.CertificateChain, - }, - }, + } else { + switch pkpConf.GetProvider().(type) { + case *mesh.PrivateKeyProvider_Cryptomb: + crypto := pkpConf.GetCryptomb() + msg := util.MessageToAny(&cryptomb.CryptoMbPrivateKeyMethodConfig{ + PollDelay: durationpb.New(time.Duration(crypto.GetPollDelay().Nanos)), PrivateKey: &core.DataSource{ Specifier: &core.DataSource_InlineBytes{ InlineBytes: s.PrivateKey, }, }, - }, + }) + secret.Type = &tls.Secret_TlsCertificate{ + TlsCertificate: &tls.TlsCertificate{ + CertificateChain: &core.DataSource{ + Specifier: &core.DataSource_InlineBytes{ + InlineBytes: s.CertificateChain, + }, + }, + PrivateKeyProvider: &tls.PrivateKeyProvider{ + ProviderName: "cryptomb", + ConfigType: &tls.PrivateKeyProvider_TypedConfig{ + TypedConfig: msg, + }, + }, + }, + } + default: + secret.Type = &tls.Secret_TlsCertificate{ + TlsCertificate: &tls.TlsCertificate{ + CertificateChain: &core.DataSource{ + Specifier: &core.DataSource_InlineBytes{ + InlineBytes: s.CertificateChain, + }, + }, + PrivateKey: &core.DataSource{ + Specifier: &core.DataSource_InlineBytes{ + InlineBytes: s.PrivateKey, + }, + }, + }, + } } } } diff --git a/tests/integration/iop-integration-test-defaults.yaml b/tests/integration/iop-integration-test-defaults.yaml index 7badcc5a00a..cb931f108d5 100644 --- a/tests/integration/iop-integration-test-defaults.yaml +++ b/tests/integration/iop-integration-test-defaults.yaml @@ -4,6 +4,13 @@ kind: IstioOperator metadata: name: install spec: + # TODO: make sure that this meshConfig is necessary + meshConfig: + accessLogFile: "/dev/stdout" + defaultConfig: + proxyMetadata: + ISTIO_META_DNS_CAPTURE: "true" + ISTIO_META_DNS_AUTO_ALLOCATE: "true" components: ingressGateways: - name: istio-ingressgateway diff --git a/tests/integration/servicemesh/federation/federation.go b/tests/integration/servicemesh/federation/federation.go new file mode 100644 index 00000000000..30a61af1c3e --- /dev/null +++ b/tests/integration/servicemesh/federation/federation.go @@ -0,0 +1,272 @@ +//go:build integ +// +build integ + +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package servicemesh + +import ( + "context" + "fmt" + "math/rand" + "time" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "istio.io/istio/pkg/test/env" + "istio.io/istio/pkg/test/framework" + "istio.io/istio/pkg/test/framework/components/cluster" + "istio.io/istio/pkg/test/framework/components/istio" + "istio.io/istio/pkg/test/framework/resource" + kubetest "istio.io/istio/pkg/test/kube" + "istio.io/istio/pkg/test/util/retry" +) + +var ( + bookinfoManifests = []string{ + env.IstioSrc + "/samples/bookinfo/platform/kube/bookinfo.yaml", + env.IstioSrc + "/samples/bookinfo/networking/bookinfo-gateway.yaml", + } + sleepManifest = env.IstioSrc + "/samples/sleep/sleep.yaml" + rnd = rand.New(rand.NewSource(time.Now().UnixNano())) +) + +func InstallBookinfo(ctx framework.TestContext, c cluster.Cluster, namespace string) { + if err := c.ApplyYAMLFiles(namespace, bookinfoManifests...); err != nil { + ctx.Fatal(err) + } + if err := retry.UntilSuccess(func() error { + if _, err := kubetest.CheckPodsAreReady(kubetest.NewPodFetch(c, namespace, "app=ratings")); err != nil { + return fmt.Errorf("ratings pod is not ready: %v", err) + } + return nil + }, retry.Timeout(300*time.Second), retry.Delay(time.Second)); err != nil { + ctx.Fatal(err) + } +} + +func InstallSleep(ctx framework.TestContext, c cluster.Cluster, namespace string) { + if err := c.ApplyYAMLFiles(namespace, sleepManifest); err != nil { + ctx.Fatal(err) + } + if err := retry.UntilSuccess(func() error { + if _, err := kubetest.CheckPodsAreReady(kubetest.NewPodFetch(c, namespace, "app=sleep")); err != nil { + return fmt.Errorf("sleep pod is not ready: %v", err) + } + return nil + }, retry.Timeout(300*time.Second), retry.Delay(time.Second)); err != nil { + ctx.Fatal(err) + } +} + +// TODO for some reason namespace.NewOrFail() doesn't work so I'm doing this manually +func CreateNamespace(ctx framework.TestContext, cluster cluster.Cluster, prefix string) string { + ns, err := cluster.Kube().CoreV1().Namespaces().Create(context.TODO(), &v1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-%d", prefix, rnd.Intn(99999)), + Labels: map[string]string{ + "istio-injection": "enabled", + }, + }, + }, metav1.CreateOptions{}) + if err != nil { + ctx.Fatal(err) + } + name := ns.Name + ctx.Cleanup(func() { + cluster.Kube().CoreV1().Namespaces().Delete(context.TODO(), name, metav1.DeleteOptions{}) + }) + return name +} + +func setupConfig(_ resource.Context, cfg *istio.Config) { + if cfg == nil { + return + } + cfg.DeployEastWestGW = false + cfg.ConfigureMultiCluster = false + cfg.ConfigureRemoteCluster = false + cfg.DifferentTrustDomains = true + cfg.ControlPlaneValues = ` +components: + ingressGateways: + - name: federation-ingress + namespace: istio-system + enabled: true + label: + unique: ingress + k8s: + env: + - name: ISTIO_META_ROUTER_MODE + value: sni-dnat + service: + ports: + # required for handling service requests from mesh2 + - port: 15443 + name: tls + # required for handing discovery requests from mesh2 + - port: 8188 + name: https-discovery + egressGateways: + - name: federation-egress + namespace: istio-system + enabled: true + label: + unique: egress + k8s: + env: + - name: ISTIO_META_ROUTER_MODE + value: sni-dnat + service: + ports: + # required for handling service requests from mesh2 + - port: 15443 + name: tls + # required for handing discovery requests from mesh2 + - port: 8188 + name: https-discovery +values: + pilot: + env: + PILOT_USE_ENDPOINT_SLICE: "false" +` +} + +// CreateServiceMeshPeersOrFail wires all primary clusters together in a federation. +func CreateServiceMeshPeersOrFail(ctx framework.TestContext) { + ctx.Log("Creating ServiceMeshPeer resources") + remoteIPs := map[string]string{} + remoteCerts := map[string]*v1.ConfigMap{} + for _, cluster := range ctx.Clusters().Primaries() { + svc, err := cluster.Kube().CoreV1().Services("istio-system").Get(context.TODO(), "federation-ingress", metav1.GetOptions{}) + if err != nil { + ctx.Fatalf("failed to get service federation-ingress: %s", err) + } + if len(svc.Status.LoadBalancer.Ingress) < 1 { + ctx.Fatalf("federation-ingress svc has no public IP") + } + remoteIPs[cluster.Name()] = svc.Status.LoadBalancer.Ingress[0].IP + ctx.Logf("Cluster '%s': detected %s as public IP\n", cluster.Name(), remoteIPs[cluster.Name()]) + configMap, err := cluster.Kube().CoreV1().ConfigMaps("istio-system").Get(context.TODO(), "istio-ca-root-cert", metav1.GetOptions{}) + if err != nil { + ctx.Fatalf("failed to get config map istio-ca-root-cert: %s", err) + } + remoteCerts[cluster.Name()] = configMap.DeepCopy() + } + for _, cluster := range ctx.Clusters().Primaries() { + for remoteCluster, remoteIP := range remoteIPs { + // skip local cluster + if remoteCluster == cluster.Name() { + continue + } + configMap := remoteCerts[remoteCluster] + configMap.ObjectMeta = metav1.ObjectMeta{ + Name: remoteCluster + "-ca-cert", + } + if _, err := cluster.Kube().CoreV1().ConfigMaps("istio-system").Create(context.TODO(), configMap, metav1.CreateOptions{}); err != nil { + ctx.Fatalf("failed to create config map %s: %s", configMap.ObjectMeta.Name, err) + } + ctx.ConfigKube(cluster).YAML("istio-system", fmt.Sprintf(` +apiVersion: federation.maistra.io/v1 +kind: ServiceMeshPeer +metadata: + name: %s +spec: + remote: + addresses: + - %s + gateways: + ingress: + name: federation-ingress + egress: + name: federation-egress + security: + trustDomain: %s + clientID: %s + certificateChain: + kind: ConfigMap + name: %s +`, remoteCluster, remoteIP, remoteCluster+".local", remoteCluster+".local/ns/istio-system/sa/federation-egress-service-account", remoteCluster+"-ca-cert")). + ApplyOrFail(ctx) + } + } +} + +func SetupExportsAndImportsOrFail(ctx framework.TestContext, exportFrom string) { + primary := ctx.Clusters().GetByName("primary") + ctx.ConfigKube(primary).YAML("istio-system", fmt.Sprintf(` +apiVersion: federation.maistra.io/v1 +kind: ExportedServiceSet +metadata: + name: cross-network-primary + namespace: istio-system +spec: + exportRules: + - type: NameSelector + nameSelector: + namespace: %s + name: ratings + alias: + namespace: bookinfo + name: ratings + `, exportFrom)).ApplyOrFail(ctx) + + secondary := ctx.Clusters().GetByName("cross-network-primary") + ctx.ConfigKube(secondary).YAML("istio-system", ` +apiVersion: federation.maistra.io/v1 +kind: ImportedServiceSet +metadata: + name: primary + namespace: istio-system +spec: + importRules: + - type: NameSelector + importAsLocal: false + nameSelector: + namespace: bookinfo +`).ApplyOrFail(ctx) +} + +func checkConnectivity(ctx framework.TestContext, source cluster.Cluster, namespace string) { + var podName string + err := retry.UntilSuccess(func() error { + podList, err := source.PodsForSelector(context.TODO(), namespace, "app=sleep") + if err != nil { + return err + } + if len(podList.Items) < 1 { + return fmt.Errorf("no sleep pod found in namespace %s", namespace) + } + podName = podList.Items[0].Name + return nil + }, retry.Timeout(300*time.Second), retry.Delay(time.Second)) + if err != nil { + ctx.Fatal(err) + } + cmd := "curl http://ratings.bookinfo.svc.primary-imports.local:9080/ratings/123" + err = retry.UntilSuccess(func() error { + stdout, _, err := source.PodExec(podName, namespace, "sleep", cmd) + if err != nil { + return err + } else if stdout != `{"id":123,"ratings":{"Reviewer1":5,"Reviewer2":4}}` { + return fmt.Errorf("podexec output does not look right: %s", stdout) + } + return nil + }, retry.Timeout(300*time.Second), retry.Delay(time.Second)) + if err != nil { + ctx.Fatal(err) + } +} diff --git a/tests/integration/servicemesh/federation/federation_test.go b/tests/integration/servicemesh/federation/federation_test.go new file mode 100644 index 00000000000..0c7f457aaea --- /dev/null +++ b/tests/integration/servicemesh/federation/federation_test.go @@ -0,0 +1,59 @@ +//go:build integ +// +build integ + +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package servicemesh + +import ( + "testing" + + "istio.io/istio/pkg/test/framework" + "istio.io/istio/pkg/test/framework/components/istio" + "istio.io/istio/pkg/test/framework/label" + "istio.io/istio/tests/integration/servicemesh/maistra" +) + +var i istio.Instance + +// GetIstioInstance gets Istio instance. +func GetIstioInstance() *istio.Instance { + return &i +} + +func TestMain(m *testing.M) { + framework. + NewSuite(m). + RequireMinClusters(2). + Setup(maistra.ApplyServiceMeshCRDs). + Setup(istio.Setup(GetIstioInstance(), setupConfig)). + Run() +} + +func TestFederation(t *testing.T) { + framework.NewTest(t). + Label(label.Multicluster). + Run(func(ctx framework.TestContext) { + CreateServiceMeshPeersOrFail(ctx) + primary := ctx.Clusters().GetByName("primary") + secondary := ctx.Clusters().GetByName("cross-network-primary") + primaryNamespace := CreateNamespace(ctx, primary, "bookinfo") + secondaryNamespace := CreateNamespace(ctx, secondary, "bookinfo") + SetupExportsAndImportsOrFail(ctx, primaryNamespace) + InstallBookinfo(ctx, primary, primaryNamespace) + InstallSleep(ctx, secondary, secondaryNamespace) + checkConnectivity(ctx, secondary, secondaryNamespace) + }) +} diff --git a/tests/integration/servicemesh/maistra/maistra.go b/tests/integration/servicemesh/maistra/maistra.go index 03d181deb0e..eb64730715b 100644 --- a/tests/integration/servicemesh/maistra/maistra.go +++ b/tests/integration/servicemesh/maistra/maistra.go @@ -34,12 +34,12 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes" + maistrav1 "maistra.io/api/client/versioned/typed/core/v1" // import maistra CRD manifests _ "maistra.io/api/manifests" "sigs.k8s.io/yaml" - maistrav1 "istio.io/istio/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1" "istio.io/istio/pkg/test/env" "istio.io/istio/pkg/test/framework" "istio.io/istio/pkg/test/framework/components/cluster" diff --git a/vendor/github.com/cenkalti/backoff/.gitignore b/vendor/github.com/cenkalti/backoff/.gitignore new file mode 100644 index 00000000000..00268614f04 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/.gitignore @@ -0,0 +1,22 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/vendor/github.com/cenkalti/backoff/.travis.yml b/vendor/github.com/cenkalti/backoff/.travis.yml new file mode 100644 index 00000000000..47a6a46ec2a --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/.travis.yml @@ -0,0 +1,10 @@ +language: go +go: + - 1.7 + - 1.x + - tip +before_install: + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover +script: + - $HOME/gopath/bin/goveralls -service=travis-ci diff --git a/vendor/github.com/cenkalti/backoff/LICENSE b/vendor/github.com/cenkalti/backoff/LICENSE new file mode 100644 index 00000000000..89b81799655 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Cenk Altı + +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/vendor/github.com/cenkalti/backoff/README.md b/vendor/github.com/cenkalti/backoff/README.md new file mode 100644 index 00000000000..55ebc98fc25 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/README.md @@ -0,0 +1,30 @@ +# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveralls image]][coveralls] + +This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client]. + +[Exponential backoff][exponential backoff wiki] +is an algorithm that uses feedback to multiplicatively decrease the rate of some process, +in order to gradually find an acceptable rate. +The retries exponentially increase and stop increasing when a certain threshold is met. + +## Usage + +See https://godoc.org/github.com/cenkalti/backoff#pkg-examples + +## Contributing + +* I would like to keep this library as small as possible. +* Please don't send a PR without opening an issue and discussing it first. +* If proposed change is not a common use case, I will probably not accept it. + +[godoc]: https://godoc.org/github.com/cenkalti/backoff +[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png +[travis]: https://travis-ci.org/cenkalti/backoff +[travis image]: https://travis-ci.org/cenkalti/backoff.png?branch=master +[coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master +[coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master + +[google-http-java-client]: https://github.com/google/google-http-java-client/blob/da1aa993e90285ec18579f1553339b00e19b3ab5/google-http-client/src/main/java/com/google/api/client/util/ExponentialBackOff.java +[exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff + +[advanced example]: https://godoc.org/github.com/cenkalti/backoff#example_ diff --git a/vendor/github.com/cenkalti/backoff/backoff.go b/vendor/github.com/cenkalti/backoff/backoff.go new file mode 100644 index 00000000000..3676ee405d8 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/backoff.go @@ -0,0 +1,66 @@ +// Package backoff implements backoff algorithms for retrying operations. +// +// Use Retry function for retrying operations that may fail. +// If Retry does not meet your needs, +// copy/paste the function into your project and modify as you wish. +// +// There is also Ticker type similar to time.Ticker. +// You can use it if you need to work with channels. +// +// See Examples section below for usage examples. +package backoff + +import "time" + +// BackOff is a backoff policy for retrying an operation. +type BackOff interface { + // NextBackOff returns the duration to wait before retrying the operation, + // or backoff. Stop to indicate that no more retries should be made. + // + // Example usage: + // + // duration := backoff.NextBackOff(); + // if (duration == backoff.Stop) { + // // Do not retry operation. + // } else { + // // Sleep for duration and retry operation. + // } + // + NextBackOff() time.Duration + + // Reset to initial state. + Reset() +} + +// Stop indicates that no more retries should be made for use in NextBackOff(). +const Stop time.Duration = -1 + +// ZeroBackOff is a fixed backoff policy whose backoff time is always zero, +// meaning that the operation is retried immediately without waiting, indefinitely. +type ZeroBackOff struct{} + +func (b *ZeroBackOff) Reset() {} + +func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 } + +// StopBackOff is a fixed backoff policy that always returns backoff.Stop for +// NextBackOff(), meaning that the operation should never be retried. +type StopBackOff struct{} + +func (b *StopBackOff) Reset() {} + +func (b *StopBackOff) NextBackOff() time.Duration { return Stop } + +// ConstantBackOff is a backoff policy that always returns the same backoff delay. +// This is in contrast to an exponential backoff policy, +// which returns a delay that grows longer as you call NextBackOff() over and over again. +type ConstantBackOff struct { + Interval time.Duration +} + +func (b *ConstantBackOff) Reset() {} +func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Interval } + +func NewConstantBackOff(d time.Duration) *ConstantBackOff { + return &ConstantBackOff{Interval: d} +} diff --git a/vendor/github.com/cenkalti/backoff/context.go b/vendor/github.com/cenkalti/backoff/context.go new file mode 100644 index 00000000000..7706faa2b60 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/context.go @@ -0,0 +1,63 @@ +package backoff + +import ( + "context" + "time" +) + +// BackOffContext is a backoff policy that stops retrying after the context +// is canceled. +type BackOffContext interface { + BackOff + Context() context.Context +} + +type backOffContext struct { + BackOff + ctx context.Context +} + +// WithContext returns a BackOffContext with context ctx +// +// ctx must not be nil +func WithContext(b BackOff, ctx context.Context) BackOffContext { + if ctx == nil { + panic("nil context") + } + + if b, ok := b.(*backOffContext); ok { + return &backOffContext{ + BackOff: b.BackOff, + ctx: ctx, + } + } + + return &backOffContext{ + BackOff: b, + ctx: ctx, + } +} + +func ensureContext(b BackOff) BackOffContext { + if cb, ok := b.(BackOffContext); ok { + return cb + } + return WithContext(b, context.Background()) +} + +func (b *backOffContext) Context() context.Context { + return b.ctx +} + +func (b *backOffContext) NextBackOff() time.Duration { + select { + case <-b.ctx.Done(): + return Stop + default: + } + next := b.BackOff.NextBackOff() + if deadline, ok := b.ctx.Deadline(); ok && deadline.Sub(time.Now()) < next { + return Stop + } + return next +} diff --git a/vendor/github.com/cenkalti/backoff/exponential.go b/vendor/github.com/cenkalti/backoff/exponential.go new file mode 100644 index 00000000000..a031a659799 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/exponential.go @@ -0,0 +1,153 @@ +package backoff + +import ( + "math/rand" + "time" +) + +/* +ExponentialBackOff is a backoff implementation that increases the backoff +period for each retry attempt using a randomization function that grows exponentially. + +NextBackOff() is calculated using the following formula: + + randomized interval = + RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor]) + +In other words NextBackOff() will range between the randomization factor +percentage below and above the retry interval. + +For example, given the following parameters: + + RetryInterval = 2 + RandomizationFactor = 0.5 + Multiplier = 2 + +the actual backoff period used in the next retry attempt will range between 1 and 3 seconds, +multiplied by the exponential, that is, between 2 and 6 seconds. + +Note: MaxInterval caps the RetryInterval and not the randomized interval. + +If the time elapsed since an ExponentialBackOff instance is created goes past the +MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop. + +The elapsed time can be reset by calling Reset(). + +Example: Given the following default arguments, for 10 tries the sequence will be, +and assuming we go over the MaxElapsedTime on the 10th try: + + Request # RetryInterval (seconds) Randomized Interval (seconds) + + 1 0.5 [0.25, 0.75] + 2 0.75 [0.375, 1.125] + 3 1.125 [0.562, 1.687] + 4 1.687 [0.8435, 2.53] + 5 2.53 [1.265, 3.795] + 6 3.795 [1.897, 5.692] + 7 5.692 [2.846, 8.538] + 8 8.538 [4.269, 12.807] + 9 12.807 [6.403, 19.210] + 10 19.210 backoff.Stop + +Note: Implementation is not thread-safe. +*/ +type ExponentialBackOff struct { + InitialInterval time.Duration + RandomizationFactor float64 + Multiplier float64 + MaxInterval time.Duration + // After MaxElapsedTime the ExponentialBackOff stops. + // It never stops if MaxElapsedTime == 0. + MaxElapsedTime time.Duration + Clock Clock + + currentInterval time.Duration + startTime time.Time +} + +// Clock is an interface that returns current time for BackOff. +type Clock interface { + Now() time.Time +} + +// Default values for ExponentialBackOff. +const ( + DefaultInitialInterval = 500 * time.Millisecond + DefaultRandomizationFactor = 0.5 + DefaultMultiplier = 1.5 + DefaultMaxInterval = 60 * time.Second + DefaultMaxElapsedTime = 15 * time.Minute +) + +// NewExponentialBackOff creates an instance of ExponentialBackOff using default values. +func NewExponentialBackOff() *ExponentialBackOff { + b := &ExponentialBackOff{ + InitialInterval: DefaultInitialInterval, + RandomizationFactor: DefaultRandomizationFactor, + Multiplier: DefaultMultiplier, + MaxInterval: DefaultMaxInterval, + MaxElapsedTime: DefaultMaxElapsedTime, + Clock: SystemClock, + } + b.Reset() + return b +} + +type systemClock struct{} + +func (t systemClock) Now() time.Time { + return time.Now() +} + +// SystemClock implements Clock interface that uses time.Now(). +var SystemClock = systemClock{} + +// Reset the interval back to the initial retry interval and restarts the timer. +func (b *ExponentialBackOff) Reset() { + b.currentInterval = b.InitialInterval + b.startTime = b.Clock.Now() +} + +// NextBackOff calculates the next backoff interval using the formula: +// Randomized interval = RetryInterval +/- (RandomizationFactor * RetryInterval) +func (b *ExponentialBackOff) NextBackOff() time.Duration { + // Make sure we have not gone over the maximum elapsed time. + if b.MaxElapsedTime != 0 && b.GetElapsedTime() > b.MaxElapsedTime { + return Stop + } + defer b.incrementCurrentInterval() + return getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval) +} + +// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance +// is created and is reset when Reset() is called. +// +// The elapsed time is computed using time.Now().UnixNano(). It is +// safe to call even while the backoff policy is used by a running +// ticker. +func (b *ExponentialBackOff) GetElapsedTime() time.Duration { + return b.Clock.Now().Sub(b.startTime) +} + +// Increments the current interval by multiplying it with the multiplier. +func (b *ExponentialBackOff) incrementCurrentInterval() { + // Check for overflow, if overflow is detected set the current interval to the max interval. + if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier { + b.currentInterval = b.MaxInterval + } else { + b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier) + } +} + +// Returns a random value from the following interval: +// [randomizationFactor * currentInterval, randomizationFactor * currentInterval]. +func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration { + var delta = randomizationFactor * float64(currentInterval) + var minInterval = float64(currentInterval) - delta + var maxInterval = float64(currentInterval) + delta + + // Get a random value from the range [minInterval, maxInterval]. + // The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then + // we want a 33% chance for selecting either 1, 2 or 3. + return time.Duration(minInterval + (random * (maxInterval - minInterval + 1))) +} diff --git a/vendor/github.com/cenkalti/backoff/retry.go b/vendor/github.com/cenkalti/backoff/retry.go new file mode 100644 index 00000000000..e936a506f84 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/retry.go @@ -0,0 +1,82 @@ +package backoff + +import "time" + +// An Operation is executing by Retry() or RetryNotify(). +// The operation will be retried using a backoff policy if it returns an error. +type Operation func() error + +// Notify is a notify-on-error function. It receives an operation error and +// backoff delay if the operation failed (with an error). +// +// NOTE that if the backoff policy stated to stop retrying, +// the notify function isn't called. +type Notify func(error, time.Duration) + +// Retry the operation o until it does not return error or BackOff stops. +// o is guaranteed to be run at least once. +// +// If o returns a *PermanentError, the operation is not retried, and the +// wrapped error is returned. +// +// Retry sleeps the goroutine for the duration returned by BackOff after a +// failed operation returns. +func Retry(o Operation, b BackOff) error { return RetryNotify(o, b, nil) } + +// RetryNotify calls notify function with the error and wait duration +// for each failed attempt before sleep. +func RetryNotify(operation Operation, b BackOff, notify Notify) error { + var err error + var next time.Duration + var t *time.Timer + + cb := ensureContext(b) + + b.Reset() + for { + if err = operation(); err == nil { + return nil + } + + if permanent, ok := err.(*PermanentError); ok { + return permanent.Err + } + + if next = cb.NextBackOff(); next == Stop { + return err + } + + if notify != nil { + notify(err, next) + } + + if t == nil { + t = time.NewTimer(next) + defer t.Stop() + } else { + t.Reset(next) + } + + select { + case <-cb.Context().Done(): + return err + case <-t.C: + } + } +} + +// PermanentError signals that the operation should not be retried. +type PermanentError struct { + Err error +} + +func (e *PermanentError) Error() string { + return e.Err.Error() +} + +// Permanent wraps the given err in a *PermanentError. +func Permanent(err error) *PermanentError { + return &PermanentError{ + Err: err, + } +} diff --git a/vendor/github.com/cenkalti/backoff/ticker.go b/vendor/github.com/cenkalti/backoff/ticker.go new file mode 100644 index 00000000000..e41084b0eff --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/ticker.go @@ -0,0 +1,82 @@ +package backoff + +import ( + "sync" + "time" +) + +// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff. +// +// Ticks will continue to arrive when the previous operation is still running, +// so operations that take a while to fail could run in quick succession. +type Ticker struct { + C <-chan time.Time + c chan time.Time + b BackOffContext + stop chan struct{} + stopOnce sync.Once +} + +// NewTicker returns a new Ticker containing a channel that will send +// the time at times specified by the BackOff argument. Ticker is +// guaranteed to tick at least once. The channel is closed when Stop +// method is called or BackOff stops. It is not safe to manipulate the +// provided backoff policy (notably calling NextBackOff or Reset) +// while the ticker is running. +func NewTicker(b BackOff) *Ticker { + c := make(chan time.Time) + t := &Ticker{ + C: c, + c: c, + b: ensureContext(b), + stop: make(chan struct{}), + } + t.b.Reset() + go t.run() + return t +} + +// Stop turns off a ticker. After Stop, no more ticks will be sent. +func (t *Ticker) Stop() { + t.stopOnce.Do(func() { close(t.stop) }) +} + +func (t *Ticker) run() { + c := t.c + defer close(c) + + // Ticker is guaranteed to tick at least once. + afterC := t.send(time.Now()) + + for { + if afterC == nil { + return + } + + select { + case tick := <-afterC: + afterC = t.send(tick) + case <-t.stop: + t.c = nil // Prevent future ticks from being sent to the channel. + return + case <-t.b.Context().Done(): + return + } + } +} + +func (t *Ticker) send(tick time.Time) <-chan time.Time { + select { + case t.c <- tick: + case <-t.stop: + return nil + } + + next := t.b.NextBackOff() + if next == Stop { + t.Stop() + return nil + } + + return time.After(next) +} diff --git a/vendor/github.com/cenkalti/backoff/tries.go b/vendor/github.com/cenkalti/backoff/tries.go new file mode 100644 index 00000000000..cfeefd9b764 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/tries.go @@ -0,0 +1,35 @@ +package backoff + +import "time" + +/* +WithMaxRetries creates a wrapper around another BackOff, which will +return Stop if NextBackOff() has been called too many times since +the last time Reset() was called + +Note: Implementation is not thread-safe. +*/ +func WithMaxRetries(b BackOff, max uint64) BackOff { + return &backOffTries{delegate: b, maxTries: max} +} + +type backOffTries struct { + delegate BackOff + maxTries uint64 + numTries uint64 +} + +func (b *backOffTries) NextBackOff() time.Duration { + if b.maxTries > 0 { + if b.maxTries <= b.numTries { + return Stop + } + b.numTries++ + } + return b.delegate.NextBackOff() +} + +func (b *backOffTries) Reset() { + b.numTries = 0 + b.delegate.Reset() +} diff --git a/vendor/github.com/mitchellh/hashstructure/v2/LICENSE b/vendor/github.com/mitchellh/hashstructure/v2/LICENSE new file mode 100644 index 00000000000..a3866a291fd --- /dev/null +++ b/vendor/github.com/mitchellh/hashstructure/v2/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Mitchell Hashimoto + +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/vendor/github.com/mitchellh/hashstructure/v2/README.md b/vendor/github.com/mitchellh/hashstructure/v2/README.md new file mode 100644 index 00000000000..21f36be193e --- /dev/null +++ b/vendor/github.com/mitchellh/hashstructure/v2/README.md @@ -0,0 +1,76 @@ +# hashstructure [![GoDoc](https://godoc.org/github.com/mitchellh/hashstructure?status.svg)](https://godoc.org/github.com/mitchellh/hashstructure) + +hashstructure is a Go library for creating a unique hash value +for arbitrary values in Go. + +This can be used to key values in a hash (for use in a map, set, etc.) +that are complex. The most common use case is comparing two values without +sending data across the network, caching values locally (de-dup), and so on. + +## Features + + * Hash any arbitrary Go value, including complex types. + + * Tag a struct field to ignore it and not affect the hash value. + + * Tag a slice type struct field to treat it as a set where ordering + doesn't affect the hash code but the field itself is still taken into + account to create the hash value. + + * Optionally, specify a custom hash function to optimize for speed, collision + avoidance for your data set, etc. + + * Optionally, hash the output of `.String()` on structs that implement fmt.Stringer, + allowing effective hashing of time.Time + + * Optionally, override the hashing process by implementing `Hashable`. + +## Installation + +Standard `go get`: + +``` +$ go get github.com/mitchellh/hashstructure/v2 +``` + +**Note on v2:** It is highly recommended you use the "v2" release since this +fixes some significant hash collisions issues from v1. In practice, we used +v1 for many years in real projects at HashiCorp and never had issues, but it +is highly dependent on the shape of the data you're hashing and how you use +those hashes. + +When using v2+, you can still generate weaker v1 hashes by using the +`FormatV1` format when calling `Hash`. + +## Usage & Example + +For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/hashstructure). + +A quick code example is shown below: + +```go +type ComplexStruct struct { + Name string + Age uint + Metadata map[string]interface{} +} + +v := ComplexStruct{ + Name: "mitchellh", + Age: 64, + Metadata: map[string]interface{}{ + "car": true, + "location": "California", + "siblings": []string{"Bob", "John"}, + }, +} + +hash, err := hashstructure.Hash(v, hashstructure.FormatV2, nil) +if err != nil { + panic(err) +} + +fmt.Printf("%d", hash) +// Output: +// 2307517237273902113 +``` diff --git a/vendor/github.com/mitchellh/hashstructure/v2/errors.go b/vendor/github.com/mitchellh/hashstructure/v2/errors.go new file mode 100644 index 00000000000..44b8951478e --- /dev/null +++ b/vendor/github.com/mitchellh/hashstructure/v2/errors.go @@ -0,0 +1,22 @@ +package hashstructure + +import ( + "fmt" +) + +// ErrNotStringer is returned when there's an error with hash:"string" +type ErrNotStringer struct { + Field string +} + +// Error implements error for ErrNotStringer +func (ens *ErrNotStringer) Error() string { + return fmt.Sprintf("hashstructure: %s has hash:\"string\" set, but does not implement fmt.Stringer", ens.Field) +} + +// ErrFormat is returned when an invalid format is given to the Hash function. +type ErrFormat struct{} + +func (*ErrFormat) Error() string { + return "format must be one of the defined Format values in the hashstructure library" +} diff --git a/vendor/github.com/mitchellh/hashstructure/v2/hashstructure.go b/vendor/github.com/mitchellh/hashstructure/v2/hashstructure.go new file mode 100644 index 00000000000..3dc0eb74e07 --- /dev/null +++ b/vendor/github.com/mitchellh/hashstructure/v2/hashstructure.go @@ -0,0 +1,482 @@ +package hashstructure + +import ( + "encoding/binary" + "fmt" + "hash" + "hash/fnv" + "reflect" + "time" +) + +// HashOptions are options that are available for hashing. +type HashOptions struct { + // Hasher is the hash function to use. If this isn't set, it will + // default to FNV. + Hasher hash.Hash64 + + // TagName is the struct tag to look at when hashing the structure. + // By default this is "hash". + TagName string + + // ZeroNil is flag determining if nil pointer should be treated equal + // to a zero value of pointed type. By default this is false. + ZeroNil bool + + // IgnoreZeroValue is determining if zero value fields should be + // ignored for hash calculation. + IgnoreZeroValue bool + + // SlicesAsSets assumes that a `set` tag is always present for slices. + // Default is false (in which case the tag is used instead) + SlicesAsSets bool + + // UseStringer will attempt to use fmt.Stringer always. If the struct + // doesn't implement fmt.Stringer, it'll fall back to trying usual tricks. + // If this is true, and the "string" tag is also set, the tag takes + // precedence (meaning that if the type doesn't implement fmt.Stringer, we + // panic) + UseStringer bool +} + +// Format specifies the hashing process used. Different formats typically +// generate different hashes for the same value and have different properties. +type Format uint + +const ( + // To disallow the zero value + formatInvalid Format = iota + + // FormatV1 is the format used in v1.x of this library. This has the + // downsides noted in issue #18 but allows simultaneous v1/v2 usage. + FormatV1 + + // FormatV2 is the current recommended format and fixes the issues + // noted in FormatV1. + FormatV2 + + formatMax // so we can easily find the end +) + +// Hash returns the hash value of an arbitrary value. +// +// If opts is nil, then default options will be used. See HashOptions +// for the default values. The same *HashOptions value cannot be used +// concurrently. None of the values within a *HashOptions struct are +// safe to read/write while hashing is being done. +// +// The "format" is required and must be one of the format values defined +// by this library. You should probably just use "FormatV2". This allows +// generated hashes uses alternate logic to maintain compatibility with +// older versions. +// +// Notes on the value: +// +// * Unexported fields on structs are ignored and do not affect the +// hash value. +// +// * Adding an exported field to a struct with the zero value will change +// the hash value. +// +// For structs, the hashing can be controlled using tags. For example: +// +// struct { +// Name string +// UUID string `hash:"ignore"` +// } +// +// The available tag values are: +// +// * "ignore" or "-" - The field will be ignored and not affect the hash code. +// +// * "set" - The field will be treated as a set, where ordering doesn't +// affect the hash code. This only works for slices. +// +// * "string" - The field will be hashed as a string, only works when the +// field implements fmt.Stringer +// +func Hash(v interface{}, format Format, opts *HashOptions) (uint64, error) { + // Validate our format + if format <= formatInvalid || format >= formatMax { + return 0, &ErrFormat{} + } + + // Create default options + if opts == nil { + opts = &HashOptions{} + } + if opts.Hasher == nil { + opts.Hasher = fnv.New64() + } + if opts.TagName == "" { + opts.TagName = "hash" + } + + // Reset the hash + opts.Hasher.Reset() + + // Create our walker and walk the structure + w := &walker{ + format: format, + h: opts.Hasher, + tag: opts.TagName, + zeronil: opts.ZeroNil, + ignorezerovalue: opts.IgnoreZeroValue, + sets: opts.SlicesAsSets, + stringer: opts.UseStringer, + } + return w.visit(reflect.ValueOf(v), nil) +} + +type walker struct { + format Format + h hash.Hash64 + tag string + zeronil bool + ignorezerovalue bool + sets bool + stringer bool +} + +type visitOpts struct { + // Flags are a bitmask of flags to affect behavior of this visit + Flags visitFlag + + // Information about the struct containing this field + Struct interface{} + StructField string +} + +var timeType = reflect.TypeOf(time.Time{}) + +func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) { + t := reflect.TypeOf(0) + + // Loop since these can be wrapped in multiple layers of pointers + // and interfaces. + for { + // If we have an interface, dereference it. We have to do this up + // here because it might be a nil in there and the check below must + // catch that. + if v.Kind() == reflect.Interface { + v = v.Elem() + continue + } + + if v.Kind() == reflect.Ptr { + if w.zeronil { + t = v.Type().Elem() + } + v = reflect.Indirect(v) + continue + } + + break + } + + // If it is nil, treat it like a zero. + if !v.IsValid() { + v = reflect.Zero(t) + } + + // Binary writing can use raw ints, we have to convert to + // a sized-int, we'll choose the largest... + switch v.Kind() { + case reflect.Int: + v = reflect.ValueOf(int64(v.Int())) + case reflect.Uint: + v = reflect.ValueOf(uint64(v.Uint())) + case reflect.Bool: + var tmp int8 + if v.Bool() { + tmp = 1 + } + v = reflect.ValueOf(tmp) + } + + k := v.Kind() + + // We can shortcut numeric values by directly binary writing them + if k >= reflect.Int && k <= reflect.Complex64 { + // A direct hash calculation + w.h.Reset() + err := binary.Write(w.h, binary.LittleEndian, v.Interface()) + return w.h.Sum64(), err + } + + switch v.Type() { + case timeType: + w.h.Reset() + b, err := v.Interface().(time.Time).MarshalBinary() + if err != nil { + return 0, err + } + + err = binary.Write(w.h, binary.LittleEndian, b) + return w.h.Sum64(), err + } + + switch k { + case reflect.Array: + var h uint64 + l := v.Len() + for i := 0; i < l; i++ { + current, err := w.visit(v.Index(i), nil) + if err != nil { + return 0, err + } + + h = hashUpdateOrdered(w.h, h, current) + } + + return h, nil + + case reflect.Map: + var includeMap IncludableMap + if opts != nil && opts.Struct != nil { + if v, ok := opts.Struct.(IncludableMap); ok { + includeMap = v + } + } + + // Build the hash for the map. We do this by XOR-ing all the key + // and value hashes. This makes it deterministic despite ordering. + var h uint64 + for _, k := range v.MapKeys() { + v := v.MapIndex(k) + if includeMap != nil { + incl, err := includeMap.HashIncludeMap( + opts.StructField, k.Interface(), v.Interface()) + if err != nil { + return 0, err + } + if !incl { + continue + } + } + + kh, err := w.visit(k, nil) + if err != nil { + return 0, err + } + vh, err := w.visit(v, nil) + if err != nil { + return 0, err + } + + fieldHash := hashUpdateOrdered(w.h, kh, vh) + h = hashUpdateUnordered(h, fieldHash) + } + + if w.format != FormatV1 { + // Important: read the docs for hashFinishUnordered + h = hashFinishUnordered(w.h, h) + } + + return h, nil + + case reflect.Struct: + parent := v.Interface() + var include Includable + if impl, ok := parent.(Includable); ok { + include = impl + } + + if impl, ok := parent.(Hashable); ok { + return impl.Hash() + } + + // If we can address this value, check if the pointer value + // implements our interfaces and use that if so. + if v.CanAddr() { + vptr := v.Addr() + parentptr := vptr.Interface() + if impl, ok := parentptr.(Includable); ok { + include = impl + } + + if impl, ok := parentptr.(Hashable); ok { + return impl.Hash() + } + } + + t := v.Type() + h, err := w.visit(reflect.ValueOf(t.Name()), nil) + if err != nil { + return 0, err + } + + l := v.NumField() + for i := 0; i < l; i++ { + if innerV := v.Field(i); v.CanSet() || t.Field(i).Name != "_" { + var f visitFlag + fieldType := t.Field(i) + if fieldType.PkgPath != "" { + // Unexported + continue + } + + tag := fieldType.Tag.Get(w.tag) + if tag == "ignore" || tag == "-" { + // Ignore this field + continue + } + + if w.ignorezerovalue { + if innerV.IsZero() { + continue + } + } + + // if string is set, use the string value + if tag == "string" || w.stringer { + if impl, ok := innerV.Interface().(fmt.Stringer); ok { + innerV = reflect.ValueOf(impl.String()) + } else if tag == "string" { + // We only show this error if the tag explicitly + // requests a stringer. + return 0, &ErrNotStringer{ + Field: v.Type().Field(i).Name, + } + } + } + + // Check if we implement includable and check it + if include != nil { + incl, err := include.HashInclude(fieldType.Name, innerV) + if err != nil { + return 0, err + } + if !incl { + continue + } + } + + switch tag { + case "set": + f |= visitFlagSet + } + + kh, err := w.visit(reflect.ValueOf(fieldType.Name), nil) + if err != nil { + return 0, err + } + + vh, err := w.visit(innerV, &visitOpts{ + Flags: f, + Struct: parent, + StructField: fieldType.Name, + }) + if err != nil { + return 0, err + } + + fieldHash := hashUpdateOrdered(w.h, kh, vh) + h = hashUpdateUnordered(h, fieldHash) + } + + if w.format != FormatV1 { + // Important: read the docs for hashFinishUnordered + h = hashFinishUnordered(w.h, h) + } + } + + return h, nil + + case reflect.Slice: + // We have two behaviors here. If it isn't a set, then we just + // visit all the elements. If it is a set, then we do a deterministic + // hash code. + var h uint64 + var set bool + if opts != nil { + set = (opts.Flags & visitFlagSet) != 0 + } + l := v.Len() + for i := 0; i < l; i++ { + current, err := w.visit(v.Index(i), nil) + if err != nil { + return 0, err + } + + if set || w.sets { + h = hashUpdateUnordered(h, current) + } else { + h = hashUpdateOrdered(w.h, h, current) + } + } + + if set && w.format != FormatV1 { + // Important: read the docs for hashFinishUnordered + h = hashFinishUnordered(w.h, h) + } + + return h, nil + + case reflect.String: + // Directly hash + w.h.Reset() + _, err := w.h.Write([]byte(v.String())) + return w.h.Sum64(), err + + default: + return 0, fmt.Errorf("unknown kind to hash: %s", k) + } + +} + +func hashUpdateOrdered(h hash.Hash64, a, b uint64) uint64 { + // For ordered updates, use a real hash function + h.Reset() + + // We just panic if the binary writes fail because we are writing + // an int64 which should never be fail-able. + e1 := binary.Write(h, binary.LittleEndian, a) + e2 := binary.Write(h, binary.LittleEndian, b) + if e1 != nil { + panic(e1) + } + if e2 != nil { + panic(e2) + } + + return h.Sum64() +} + +func hashUpdateUnordered(a, b uint64) uint64 { + return a ^ b +} + +// After mixing a group of unique hashes with hashUpdateUnordered, it's always +// necessary to call hashFinishUnordered. Why? Because hashUpdateUnordered +// is a simple XOR, and calling hashUpdateUnordered on hashes produced by +// hashUpdateUnordered can effectively cancel out a previous change to the hash +// result if the same hash value appears later on. For example, consider: +// +// hashUpdateUnordered(hashUpdateUnordered("A", "B"), hashUpdateUnordered("A", "C")) = +// H("A") ^ H("B")) ^ (H("A") ^ H("C")) = +// (H("A") ^ H("A")) ^ (H("B") ^ H(C)) = +// H(B) ^ H(C) = +// hashUpdateUnordered(hashUpdateUnordered("Z", "B"), hashUpdateUnordered("Z", "C")) +// +// hashFinishUnordered "hardens" the result, so that encountering partially +// overlapping input data later on in a different context won't cancel out. +func hashFinishUnordered(h hash.Hash64, a uint64) uint64 { + h.Reset() + + // We just panic if the writes fail + e1 := binary.Write(h, binary.LittleEndian, a) + if e1 != nil { + panic(e1) + } + + return h.Sum64() +} + +// visitFlag is used as a bitmask for affecting visit behavior +type visitFlag uint + +const ( + visitFlagInvalid visitFlag = iota + visitFlagSet = iota << 1 +) diff --git a/vendor/github.com/mitchellh/hashstructure/v2/include.go b/vendor/github.com/mitchellh/hashstructure/v2/include.go new file mode 100644 index 00000000000..702d35415d4 --- /dev/null +++ b/vendor/github.com/mitchellh/hashstructure/v2/include.go @@ -0,0 +1,22 @@ +package hashstructure + +// Includable is an interface that can optionally be implemented by +// a struct. It will be called for each field in the struct to check whether +// it should be included in the hash. +type Includable interface { + HashInclude(field string, v interface{}) (bool, error) +} + +// IncludableMap is an interface that can optionally be implemented by +// a struct. It will be called when a map-type field is found to ask the +// struct if the map item should be included in the hash. +type IncludableMap interface { + HashIncludeMap(field string, k, v interface{}) (bool, error) +} + +// Hashable is an interface that can optionally be implemented by a struct +// to override the hash value. This value will override the hash value for +// the entire struct. Entries in the struct will not be hashed. +type Hashable interface { + Hash() (uint64, error) +} diff --git a/vendor/gopkg.in/yaml.v3/decode.go b/vendor/gopkg.in/yaml.v3/decode.go index df36e3a30f5..0173b6982e8 100644 --- a/vendor/gopkg.in/yaml.v3/decode.go +++ b/vendor/gopkg.in/yaml.v3/decode.go @@ -100,7 +100,10 @@ func (p *parser) peek() yaml_event_type_t { if p.event.typ != yaml_NO_EVENT { return p.event.typ } - if !yaml_parser_parse(&p.parser, &p.event) { + // It's curious choice from the underlying API to generally return a + // positive result on success, but on this case return true in an error + // scenario. This was the source of bugs in the past (issue #666). + if !yaml_parser_parse(&p.parser, &p.event) || p.parser.error != yaml_NO_ERROR { p.fail() } return p.event.typ @@ -320,6 +323,8 @@ type decoder struct { decodeCount int aliasCount int aliasDepth int + + mergedFields map[interface{}]bool } var ( @@ -808,6 +813,11 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) { } } + mergedFields := d.mergedFields + d.mergedFields = nil + + var mergeNode *Node + mapIsNew := false if out.IsNil() { out.Set(reflect.MakeMap(outt)) @@ -815,11 +825,18 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) { } for i := 0; i < l; i += 2 { if isMerge(n.Content[i]) { - d.merge(n.Content[i+1], out) + mergeNode = n.Content[i+1] continue } k := reflect.New(kt).Elem() if d.unmarshal(n.Content[i], k) { + if mergedFields != nil { + ki := k.Interface() + if mergedFields[ki] { + continue + } + mergedFields[ki] = true + } kkind := k.Kind() if kkind == reflect.Interface { kkind = k.Elem().Kind() @@ -833,6 +850,12 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) { } } } + + d.mergedFields = mergedFields + if mergeNode != nil { + d.merge(n, mergeNode, out) + } + d.stringMapType = stringMapType d.generalMapType = generalMapType return true @@ -844,7 +867,8 @@ func isStringMap(n *Node) bool { } l := len(n.Content) for i := 0; i < l; i += 2 { - if n.Content[i].ShortTag() != strTag { + shortTag := n.Content[i].ShortTag() + if shortTag != strTag && shortTag != mergeTag { return false } } @@ -861,7 +885,6 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) { var elemType reflect.Type if sinfo.InlineMap != -1 { inlineMap = out.Field(sinfo.InlineMap) - inlineMap.Set(reflect.New(inlineMap.Type()).Elem()) elemType = inlineMap.Type().Elem() } @@ -870,6 +893,9 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) { d.prepare(n, field) } + mergedFields := d.mergedFields + d.mergedFields = nil + var mergeNode *Node var doneFields []bool if d.uniqueKeys { doneFields = make([]bool, len(sinfo.FieldsList)) @@ -879,13 +905,20 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) { for i := 0; i < l; i += 2 { ni := n.Content[i] if isMerge(ni) { - d.merge(n.Content[i+1], out) + mergeNode = n.Content[i+1] continue } if !d.unmarshal(ni, name) { continue } - if info, ok := sinfo.FieldsMap[name.String()]; ok { + sname := name.String() + if mergedFields != nil { + if mergedFields[sname] { + continue + } + mergedFields[sname] = true + } + if info, ok := sinfo.FieldsMap[sname]; ok { if d.uniqueKeys { if doneFields[info.Id] { d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type())) @@ -911,6 +944,11 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) { d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type())) } } + + d.mergedFields = mergedFields + if mergeNode != nil { + d.merge(n, mergeNode, out) + } return true } @@ -918,19 +956,29 @@ func failWantMap() { failf("map merge requires map or sequence of maps as the value") } -func (d *decoder) merge(n *Node, out reflect.Value) { - switch n.Kind { +func (d *decoder) merge(parent *Node, merge *Node, out reflect.Value) { + mergedFields := d.mergedFields + if mergedFields == nil { + d.mergedFields = make(map[interface{}]bool) + for i := 0; i < len(parent.Content); i += 2 { + k := reflect.New(ifaceType).Elem() + if d.unmarshal(parent.Content[i], k) { + d.mergedFields[k.Interface()] = true + } + } + } + + switch merge.Kind { case MappingNode: - d.unmarshal(n, out) + d.unmarshal(merge, out) case AliasNode: - if n.Alias != nil && n.Alias.Kind != MappingNode { + if merge.Alias != nil && merge.Alias.Kind != MappingNode { failWantMap() } - d.unmarshal(n, out) + d.unmarshal(merge, out) case SequenceNode: - // Step backwards as earlier nodes take precedence. - for i := len(n.Content) - 1; i >= 0; i-- { - ni := n.Content[i] + for i := 0; i < len(merge.Content); i++ { + ni := merge.Content[i] if ni.Kind == AliasNode { if ni.Alias != nil && ni.Alias.Kind != MappingNode { failWantMap() @@ -943,6 +991,8 @@ func (d *decoder) merge(n *Node, out reflect.Value) { default: failWantMap() } + + d.mergedFields = mergedFields } func isMerge(n *Node) bool { diff --git a/vendor/maistra.io/api/client/informers/externalversions/core/interface.go b/vendor/maistra.io/api/client/informers/externalversions/core/interface.go new file mode 100644 index 00000000000..fe85c4ad7f8 --- /dev/null +++ b/vendor/maistra.io/api/client/informers/externalversions/core/interface.go @@ -0,0 +1,60 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package core + +import ( + v1 "maistra.io/api/client/informers/externalversions/core/v1" + v1alpha1 "maistra.io/api/client/informers/externalversions/core/v1alpha1" + v2 "maistra.io/api/client/informers/externalversions/core/v2" + internalinterfaces "maistra.io/api/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1 provides access to shared informers for resources in V1. + V1() v1.Interface + // V1alpha1 provides access to shared informers for resources in V1alpha1. + V1alpha1() v1alpha1.Interface + // V2 provides access to shared informers for resources in V2. + V2() v2.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1 returns a new v1.Interface. +func (g *group) V1() v1.Interface { + return v1.New(g.factory, g.namespace, g.tweakListOptions) +} + +// V1alpha1 returns a new v1alpha1.Interface. +func (g *group) V1alpha1() v1alpha1.Interface { + return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) +} + +// V2 returns a new v2.Interface. +func (g *group) V2() v2.Interface { + return v2.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/vendor/maistra.io/api/client/informers/externalversions/core/v1/interface.go b/vendor/maistra.io/api/client/informers/externalversions/core/v1/interface.go new file mode 100644 index 00000000000..bd0fd137a60 --- /dev/null +++ b/vendor/maistra.io/api/client/informers/externalversions/core/v1/interface.go @@ -0,0 +1,64 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + internalinterfaces "maistra.io/api/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // ServiceMeshControlPlanes returns a ServiceMeshControlPlaneInformer. + ServiceMeshControlPlanes() ServiceMeshControlPlaneInformer + // ServiceMeshExtensions returns a ServiceMeshExtensionInformer. + ServiceMeshExtensions() ServiceMeshExtensionInformer + // ServiceMeshMembers returns a ServiceMeshMemberInformer. + ServiceMeshMembers() ServiceMeshMemberInformer + // ServiceMeshMemberRolls returns a ServiceMeshMemberRollInformer. + ServiceMeshMemberRolls() ServiceMeshMemberRollInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// ServiceMeshControlPlanes returns a ServiceMeshControlPlaneInformer. +func (v *version) ServiceMeshControlPlanes() ServiceMeshControlPlaneInformer { + return &serviceMeshControlPlaneInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// ServiceMeshExtensions returns a ServiceMeshExtensionInformer. +func (v *version) ServiceMeshExtensions() ServiceMeshExtensionInformer { + return &serviceMeshExtensionInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// ServiceMeshMembers returns a ServiceMeshMemberInformer. +func (v *version) ServiceMeshMembers() ServiceMeshMemberInformer { + return &serviceMeshMemberInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// ServiceMeshMemberRolls returns a ServiceMeshMemberRollInformer. +func (v *version) ServiceMeshMemberRolls() ServiceMeshMemberRollInformer { + return &serviceMeshMemberRollInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/vendor/maistra.io/api/client/informers/externalversions/core/v1/servicemeshcontrolplane.go b/vendor/maistra.io/api/client/informers/externalversions/core/v1/servicemeshcontrolplane.go new file mode 100644 index 00000000000..f6636227e80 --- /dev/null +++ b/vendor/maistra.io/api/client/informers/externalversions/core/v1/servicemeshcontrolplane.go @@ -0,0 +1,88 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + internalinterfaces "maistra.io/api/client/informers/externalversions/internalinterfaces" + v1 "maistra.io/api/client/listers/core/v1" + versioned "maistra.io/api/client/versioned" + corev1 "maistra.io/api/core/v1" +) + +// ServiceMeshControlPlaneInformer provides access to a shared informer and lister for +// ServiceMeshControlPlanes. +type ServiceMeshControlPlaneInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.ServiceMeshControlPlaneLister +} + +type serviceMeshControlPlaneInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewServiceMeshControlPlaneInformer constructs a new informer for ServiceMeshControlPlane type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewServiceMeshControlPlaneInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredServiceMeshControlPlaneInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredServiceMeshControlPlaneInformer constructs a new informer for ServiceMeshControlPlane type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredServiceMeshControlPlaneInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV1().ServiceMeshControlPlanes(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV1().ServiceMeshControlPlanes(namespace).Watch(context.TODO(), options) + }, + }, + &corev1.ServiceMeshControlPlane{}, + resyncPeriod, + indexers, + ) +} + +func (f *serviceMeshControlPlaneInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredServiceMeshControlPlaneInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *serviceMeshControlPlaneInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&corev1.ServiceMeshControlPlane{}, f.defaultInformer) +} + +func (f *serviceMeshControlPlaneInformer) Lister() v1.ServiceMeshControlPlaneLister { + return v1.NewServiceMeshControlPlaneLister(f.Informer().GetIndexer()) +} diff --git a/vendor/maistra.io/api/client/informers/externalversions/core/v1/servicemeshextension.go b/vendor/maistra.io/api/client/informers/externalversions/core/v1/servicemeshextension.go new file mode 100644 index 00000000000..5d1dba5949c --- /dev/null +++ b/vendor/maistra.io/api/client/informers/externalversions/core/v1/servicemeshextension.go @@ -0,0 +1,88 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + internalinterfaces "maistra.io/api/client/informers/externalversions/internalinterfaces" + v1 "maistra.io/api/client/listers/core/v1" + versioned "maistra.io/api/client/versioned" + corev1 "maistra.io/api/core/v1" +) + +// ServiceMeshExtensionInformer provides access to a shared informer and lister for +// ServiceMeshExtensions. +type ServiceMeshExtensionInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.ServiceMeshExtensionLister +} + +type serviceMeshExtensionInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewServiceMeshExtensionInformer constructs a new informer for ServiceMeshExtension type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewServiceMeshExtensionInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredServiceMeshExtensionInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredServiceMeshExtensionInformer constructs a new informer for ServiceMeshExtension type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredServiceMeshExtensionInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV1().ServiceMeshExtensions(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV1().ServiceMeshExtensions(namespace).Watch(context.TODO(), options) + }, + }, + &corev1.ServiceMeshExtension{}, + resyncPeriod, + indexers, + ) +} + +func (f *serviceMeshExtensionInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredServiceMeshExtensionInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *serviceMeshExtensionInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&corev1.ServiceMeshExtension{}, f.defaultInformer) +} + +func (f *serviceMeshExtensionInformer) Lister() v1.ServiceMeshExtensionLister { + return v1.NewServiceMeshExtensionLister(f.Informer().GetIndexer()) +} diff --git a/vendor/maistra.io/api/client/informers/externalversions/core/v1/servicemeshmember.go b/vendor/maistra.io/api/client/informers/externalversions/core/v1/servicemeshmember.go new file mode 100644 index 00000000000..35490ad2e34 --- /dev/null +++ b/vendor/maistra.io/api/client/informers/externalversions/core/v1/servicemeshmember.go @@ -0,0 +1,88 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + internalinterfaces "maistra.io/api/client/informers/externalversions/internalinterfaces" + v1 "maistra.io/api/client/listers/core/v1" + versioned "maistra.io/api/client/versioned" + corev1 "maistra.io/api/core/v1" +) + +// ServiceMeshMemberInformer provides access to a shared informer and lister for +// ServiceMeshMembers. +type ServiceMeshMemberInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.ServiceMeshMemberLister +} + +type serviceMeshMemberInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewServiceMeshMemberInformer constructs a new informer for ServiceMeshMember type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewServiceMeshMemberInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredServiceMeshMemberInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredServiceMeshMemberInformer constructs a new informer for ServiceMeshMember type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredServiceMeshMemberInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV1().ServiceMeshMembers(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV1().ServiceMeshMembers(namespace).Watch(context.TODO(), options) + }, + }, + &corev1.ServiceMeshMember{}, + resyncPeriod, + indexers, + ) +} + +func (f *serviceMeshMemberInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredServiceMeshMemberInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *serviceMeshMemberInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&corev1.ServiceMeshMember{}, f.defaultInformer) +} + +func (f *serviceMeshMemberInformer) Lister() v1.ServiceMeshMemberLister { + return v1.NewServiceMeshMemberLister(f.Informer().GetIndexer()) +} diff --git a/pkg/servicemesh/client/informers/externalversions/servicemesh/v1/servicemeshmemberroll.go b/vendor/maistra.io/api/client/informers/externalversions/core/v1/servicemeshmemberroll.go similarity index 83% rename from pkg/servicemesh/client/informers/externalversions/servicemesh/v1/servicemeshmemberroll.go rename to vendor/maistra.io/api/client/informers/externalversions/core/v1/servicemeshmemberroll.go index 009b137cba0..9a962edec95 100644 --- a/pkg/servicemesh/client/informers/externalversions/servicemesh/v1/servicemeshmemberroll.go +++ b/vendor/maistra.io/api/client/informers/externalversions/core/v1/servicemeshmemberroll.go @@ -20,14 +20,14 @@ import ( "context" time "time" - servicemeshv1 "istio.io/istio/pkg/servicemesh/apis/servicemesh/v1" - versioned "istio.io/istio/pkg/servicemesh/client/clientset/versioned" - internalinterfaces "istio.io/istio/pkg/servicemesh/client/informers/externalversions/internalinterfaces" - v1 "istio.io/istio/pkg/servicemesh/client/listers/servicemesh/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" watch "k8s.io/apimachinery/pkg/watch" cache "k8s.io/client-go/tools/cache" + internalinterfaces "maistra.io/api/client/informers/externalversions/internalinterfaces" + v1 "maistra.io/api/client/listers/core/v1" + versioned "maistra.io/api/client/versioned" + corev1 "maistra.io/api/core/v1" ) // ServiceMeshMemberRollInformer provides access to a shared informer and lister for @@ -60,16 +60,16 @@ func NewFilteredServiceMeshMemberRollInformer(client versioned.Interface, namesp if tweakListOptions != nil { tweakListOptions(&options) } - return client.MaistraV1().ServiceMeshMemberRolls(namespace).List(context.TODO(), options) + return client.CoreV1().ServiceMeshMemberRolls(namespace).List(context.TODO(), options) }, WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { if tweakListOptions != nil { tweakListOptions(&options) } - return client.MaistraV1().ServiceMeshMemberRolls(namespace).Watch(context.TODO(), options) + return client.CoreV1().ServiceMeshMemberRolls(namespace).Watch(context.TODO(), options) }, }, - &servicemeshv1.ServiceMeshMemberRoll{}, + &corev1.ServiceMeshMemberRoll{}, resyncPeriod, indexers, ) @@ -80,7 +80,7 @@ func (f *serviceMeshMemberRollInformer) defaultInformer(client versioned.Interfa } func (f *serviceMeshMemberRollInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&servicemeshv1.ServiceMeshMemberRoll{}, f.defaultInformer) + return f.factory.InformerFor(&corev1.ServiceMeshMemberRoll{}, f.defaultInformer) } func (f *serviceMeshMemberRollInformer) Lister() v1.ServiceMeshMemberRollLister { diff --git a/pkg/servicemesh/client/informers/externalversions/servicemesh/v1/interface.go b/vendor/maistra.io/api/client/informers/externalversions/core/v1alpha1/interface.go similarity index 70% rename from pkg/servicemesh/client/informers/externalversions/servicemesh/v1/interface.go rename to vendor/maistra.io/api/client/informers/externalversions/core/v1alpha1/interface.go index 662ff340e29..343c28098e9 100644 --- a/pkg/servicemesh/client/informers/externalversions/servicemesh/v1/interface.go +++ b/vendor/maistra.io/api/client/informers/externalversions/core/v1alpha1/interface.go @@ -14,16 +14,16 @@ // Code generated by informer-gen. DO NOT EDIT. -package v1 +package v1alpha1 import ( - internalinterfaces "istio.io/istio/pkg/servicemesh/client/informers/externalversions/internalinterfaces" + internalinterfaces "maistra.io/api/client/informers/externalversions/internalinterfaces" ) // Interface provides access to all the informers in this group version. type Interface interface { - // ServiceMeshMemberRolls returns a ServiceMeshMemberRollInformer. - ServiceMeshMemberRolls() ServiceMeshMemberRollInformer + // ServiceMeshExtensions returns a ServiceMeshExtensionInformer. + ServiceMeshExtensions() ServiceMeshExtensionInformer } type version struct { @@ -37,7 +37,7 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } -// ServiceMeshMemberRolls returns a ServiceMeshMemberRollInformer. -func (v *version) ServiceMeshMemberRolls() ServiceMeshMemberRollInformer { - return &serviceMeshMemberRollInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +// ServiceMeshExtensions returns a ServiceMeshExtensionInformer. +func (v *version) ServiceMeshExtensions() ServiceMeshExtensionInformer { + return &serviceMeshExtensionInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } diff --git a/vendor/maistra.io/api/client/informers/externalversions/core/v1alpha1/servicemeshextension.go b/vendor/maistra.io/api/client/informers/externalversions/core/v1alpha1/servicemeshextension.go new file mode 100644 index 00000000000..0d7be1d3dbc --- /dev/null +++ b/vendor/maistra.io/api/client/informers/externalversions/core/v1alpha1/servicemeshextension.go @@ -0,0 +1,88 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + internalinterfaces "maistra.io/api/client/informers/externalversions/internalinterfaces" + v1alpha1 "maistra.io/api/client/listers/core/v1alpha1" + versioned "maistra.io/api/client/versioned" + corev1alpha1 "maistra.io/api/core/v1alpha1" +) + +// ServiceMeshExtensionInformer provides access to a shared informer and lister for +// ServiceMeshExtensions. +type ServiceMeshExtensionInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.ServiceMeshExtensionLister +} + +type serviceMeshExtensionInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewServiceMeshExtensionInformer constructs a new informer for ServiceMeshExtension type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewServiceMeshExtensionInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredServiceMeshExtensionInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredServiceMeshExtensionInformer constructs a new informer for ServiceMeshExtension type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredServiceMeshExtensionInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV1alpha1().ServiceMeshExtensions(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV1alpha1().ServiceMeshExtensions(namespace).Watch(context.TODO(), options) + }, + }, + &corev1alpha1.ServiceMeshExtension{}, + resyncPeriod, + indexers, + ) +} + +func (f *serviceMeshExtensionInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredServiceMeshExtensionInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *serviceMeshExtensionInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&corev1alpha1.ServiceMeshExtension{}, f.defaultInformer) +} + +func (f *serviceMeshExtensionInformer) Lister() v1alpha1.ServiceMeshExtensionLister { + return v1alpha1.NewServiceMeshExtensionLister(f.Informer().GetIndexer()) +} diff --git a/vendor/maistra.io/api/client/informers/externalversions/core/v2/interface.go b/vendor/maistra.io/api/client/informers/externalversions/core/v2/interface.go new file mode 100644 index 00000000000..0759b73b7d8 --- /dev/null +++ b/vendor/maistra.io/api/client/informers/externalversions/core/v2/interface.go @@ -0,0 +1,43 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v2 + +import ( + internalinterfaces "maistra.io/api/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // ServiceMeshControlPlanes returns a ServiceMeshControlPlaneInformer. + ServiceMeshControlPlanes() ServiceMeshControlPlaneInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// ServiceMeshControlPlanes returns a ServiceMeshControlPlaneInformer. +func (v *version) ServiceMeshControlPlanes() ServiceMeshControlPlaneInformer { + return &serviceMeshControlPlaneInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/vendor/maistra.io/api/client/informers/externalversions/core/v2/servicemeshcontrolplane.go b/vendor/maistra.io/api/client/informers/externalversions/core/v2/servicemeshcontrolplane.go new file mode 100644 index 00000000000..1ca20e511f3 --- /dev/null +++ b/vendor/maistra.io/api/client/informers/externalversions/core/v2/servicemeshcontrolplane.go @@ -0,0 +1,88 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v2 + +import ( + "context" + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + internalinterfaces "maistra.io/api/client/informers/externalversions/internalinterfaces" + v2 "maistra.io/api/client/listers/core/v2" + versioned "maistra.io/api/client/versioned" + corev2 "maistra.io/api/core/v2" +) + +// ServiceMeshControlPlaneInformer provides access to a shared informer and lister for +// ServiceMeshControlPlanes. +type ServiceMeshControlPlaneInformer interface { + Informer() cache.SharedIndexInformer + Lister() v2.ServiceMeshControlPlaneLister +} + +type serviceMeshControlPlaneInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewServiceMeshControlPlaneInformer constructs a new informer for ServiceMeshControlPlane type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewServiceMeshControlPlaneInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredServiceMeshControlPlaneInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredServiceMeshControlPlaneInformer constructs a new informer for ServiceMeshControlPlane type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredServiceMeshControlPlaneInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV2().ServiceMeshControlPlanes(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV2().ServiceMeshControlPlanes(namespace).Watch(context.TODO(), options) + }, + }, + &corev2.ServiceMeshControlPlane{}, + resyncPeriod, + indexers, + ) +} + +func (f *serviceMeshControlPlaneInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredServiceMeshControlPlaneInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *serviceMeshControlPlaneInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&corev2.ServiceMeshControlPlane{}, f.defaultInformer) +} + +func (f *serviceMeshControlPlaneInformer) Lister() v2.ServiceMeshControlPlaneLister { + return v2.NewServiceMeshControlPlaneLister(f.Informer().GetIndexer()) +} diff --git a/pkg/servicemesh/client/informers/externalversions/factory.go b/vendor/maistra.io/api/client/informers/externalversions/factory.go similarity index 91% rename from pkg/servicemesh/client/informers/externalversions/factory.go rename to vendor/maistra.io/api/client/informers/externalversions/factory.go index b92bedcd2e4..9350c35563b 100644 --- a/pkg/servicemesh/client/informers/externalversions/factory.go +++ b/vendor/maistra.io/api/client/informers/externalversions/factory.go @@ -21,13 +21,14 @@ import ( sync "sync" time "time" - versioned "istio.io/istio/pkg/servicemesh/client/clientset/versioned" - internalinterfaces "istio.io/istio/pkg/servicemesh/client/informers/externalversions/internalinterfaces" - servicemesh "istio.io/istio/pkg/servicemesh/client/informers/externalversions/servicemesh" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" + core "maistra.io/api/client/informers/externalversions/core" + federation "maistra.io/api/client/informers/externalversions/federation" + internalinterfaces "maistra.io/api/client/informers/externalversions/internalinterfaces" + versioned "maistra.io/api/client/versioned" ) // SharedInformerOption defines the functional option type for SharedInformerFactory. @@ -170,9 +171,14 @@ type SharedInformerFactory interface { ForResource(resource schema.GroupVersionResource) (GenericInformer, error) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool - Maistra() servicemesh.Interface + Core() core.Interface + Federation() federation.Interface } -func (f *sharedInformerFactory) Maistra() servicemesh.Interface { - return servicemesh.New(f, f.namespace, f.tweakListOptions) +func (f *sharedInformerFactory) Core() core.Interface { + return core.New(f, f.namespace, f.tweakListOptions) +} + +func (f *sharedInformerFactory) Federation() federation.Interface { + return federation.New(f, f.namespace, f.tweakListOptions) } diff --git a/pkg/servicemesh/client/informers/externalversions/servicemesh/interface.go b/vendor/maistra.io/api/client/informers/externalversions/federation/interface.go similarity index 86% rename from pkg/servicemesh/client/informers/externalversions/servicemesh/interface.go rename to vendor/maistra.io/api/client/informers/externalversions/federation/interface.go index 228660bdfe7..12efb7bccbd 100644 --- a/pkg/servicemesh/client/informers/externalversions/servicemesh/interface.go +++ b/vendor/maistra.io/api/client/informers/externalversions/federation/interface.go @@ -14,11 +14,11 @@ // Code generated by informer-gen. DO NOT EDIT. -package servicemesh +package federation import ( - internalinterfaces "istio.io/istio/pkg/servicemesh/client/informers/externalversions/internalinterfaces" - v1 "istio.io/istio/pkg/servicemesh/client/informers/externalversions/servicemesh/v1" + v1 "maistra.io/api/client/informers/externalversions/federation/v1" + internalinterfaces "maistra.io/api/client/informers/externalversions/internalinterfaces" ) // Interface provides access to each of this group's versions. diff --git a/vendor/maistra.io/api/client/informers/externalversions/federation/v1/exportedserviceset.go b/vendor/maistra.io/api/client/informers/externalversions/federation/v1/exportedserviceset.go new file mode 100644 index 00000000000..97fb3b42787 --- /dev/null +++ b/vendor/maistra.io/api/client/informers/externalversions/federation/v1/exportedserviceset.go @@ -0,0 +1,88 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + internalinterfaces "maistra.io/api/client/informers/externalversions/internalinterfaces" + v1 "maistra.io/api/client/listers/federation/v1" + versioned "maistra.io/api/client/versioned" + federationv1 "maistra.io/api/federation/v1" +) + +// ExportedServiceSetInformer provides access to a shared informer and lister for +// ExportedServiceSets. +type ExportedServiceSetInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.ExportedServiceSetLister +} + +type exportedServiceSetInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewExportedServiceSetInformer constructs a new informer for ExportedServiceSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewExportedServiceSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredExportedServiceSetInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredExportedServiceSetInformer constructs a new informer for ExportedServiceSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredExportedServiceSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.FederationV1().ExportedServiceSets(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.FederationV1().ExportedServiceSets(namespace).Watch(context.TODO(), options) + }, + }, + &federationv1.ExportedServiceSet{}, + resyncPeriod, + indexers, + ) +} + +func (f *exportedServiceSetInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredExportedServiceSetInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *exportedServiceSetInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&federationv1.ExportedServiceSet{}, f.defaultInformer) +} + +func (f *exportedServiceSetInformer) Lister() v1.ExportedServiceSetLister { + return v1.NewExportedServiceSetLister(f.Informer().GetIndexer()) +} diff --git a/vendor/maistra.io/api/client/informers/externalversions/federation/v1/importedserviceset.go b/vendor/maistra.io/api/client/informers/externalversions/federation/v1/importedserviceset.go new file mode 100644 index 00000000000..62bd57d1d9a --- /dev/null +++ b/vendor/maistra.io/api/client/informers/externalversions/federation/v1/importedserviceset.go @@ -0,0 +1,88 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + internalinterfaces "maistra.io/api/client/informers/externalversions/internalinterfaces" + v1 "maistra.io/api/client/listers/federation/v1" + versioned "maistra.io/api/client/versioned" + federationv1 "maistra.io/api/federation/v1" +) + +// ImportedServiceSetInformer provides access to a shared informer and lister for +// ImportedServiceSets. +type ImportedServiceSetInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.ImportedServiceSetLister +} + +type importedServiceSetInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewImportedServiceSetInformer constructs a new informer for ImportedServiceSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewImportedServiceSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredImportedServiceSetInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredImportedServiceSetInformer constructs a new informer for ImportedServiceSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredImportedServiceSetInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.FederationV1().ImportedServiceSets(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.FederationV1().ImportedServiceSets(namespace).Watch(context.TODO(), options) + }, + }, + &federationv1.ImportedServiceSet{}, + resyncPeriod, + indexers, + ) +} + +func (f *importedServiceSetInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredImportedServiceSetInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *importedServiceSetInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&federationv1.ImportedServiceSet{}, f.defaultInformer) +} + +func (f *importedServiceSetInformer) Lister() v1.ImportedServiceSetLister { + return v1.NewImportedServiceSetLister(f.Informer().GetIndexer()) +} diff --git a/vendor/maistra.io/api/client/informers/externalversions/federation/v1/interface.go b/vendor/maistra.io/api/client/informers/externalversions/federation/v1/interface.go new file mode 100644 index 00000000000..2a085c90751 --- /dev/null +++ b/vendor/maistra.io/api/client/informers/externalversions/federation/v1/interface.go @@ -0,0 +1,57 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + internalinterfaces "maistra.io/api/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // ExportedServiceSets returns a ExportedServiceSetInformer. + ExportedServiceSets() ExportedServiceSetInformer + // ImportedServiceSets returns a ImportedServiceSetInformer. + ImportedServiceSets() ImportedServiceSetInformer + // ServiceMeshPeers returns a ServiceMeshPeerInformer. + ServiceMeshPeers() ServiceMeshPeerInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// ExportedServiceSets returns a ExportedServiceSetInformer. +func (v *version) ExportedServiceSets() ExportedServiceSetInformer { + return &exportedServiceSetInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// ImportedServiceSets returns a ImportedServiceSetInformer. +func (v *version) ImportedServiceSets() ImportedServiceSetInformer { + return &importedServiceSetInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// ServiceMeshPeers returns a ServiceMeshPeerInformer. +func (v *version) ServiceMeshPeers() ServiceMeshPeerInformer { + return &serviceMeshPeerInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/vendor/maistra.io/api/client/informers/externalversions/federation/v1/servicemeshpeer.go b/vendor/maistra.io/api/client/informers/externalversions/federation/v1/servicemeshpeer.go new file mode 100644 index 00000000000..164c32dfd77 --- /dev/null +++ b/vendor/maistra.io/api/client/informers/externalversions/federation/v1/servicemeshpeer.go @@ -0,0 +1,88 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + internalinterfaces "maistra.io/api/client/informers/externalversions/internalinterfaces" + v1 "maistra.io/api/client/listers/federation/v1" + versioned "maistra.io/api/client/versioned" + federationv1 "maistra.io/api/federation/v1" +) + +// ServiceMeshPeerInformer provides access to a shared informer and lister for +// ServiceMeshPeers. +type ServiceMeshPeerInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.ServiceMeshPeerLister +} + +type serviceMeshPeerInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewServiceMeshPeerInformer constructs a new informer for ServiceMeshPeer type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewServiceMeshPeerInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredServiceMeshPeerInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredServiceMeshPeerInformer constructs a new informer for ServiceMeshPeer type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredServiceMeshPeerInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.FederationV1().ServiceMeshPeers(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.FederationV1().ServiceMeshPeers(namespace).Watch(context.TODO(), options) + }, + }, + &federationv1.ServiceMeshPeer{}, + resyncPeriod, + indexers, + ) +} + +func (f *serviceMeshPeerInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredServiceMeshPeerInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *serviceMeshPeerInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&federationv1.ServiceMeshPeer{}, f.defaultInformer) +} + +func (f *serviceMeshPeerInformer) Lister() v1.ServiceMeshPeerLister { + return v1.NewServiceMeshPeerLister(f.Informer().GetIndexer()) +} diff --git a/vendor/maistra.io/api/client/informers/externalversions/generic.go b/vendor/maistra.io/api/client/informers/externalversions/generic.go new file mode 100644 index 00000000000..4ec4ac5cf7b --- /dev/null +++ b/vendor/maistra.io/api/client/informers/externalversions/generic.go @@ -0,0 +1,85 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package externalversions + +import ( + "fmt" + + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/core/v1" + v1alpha1 "maistra.io/api/core/v1alpha1" + v2 "maistra.io/api/core/v2" + federationv1 "maistra.io/api/federation/v1" +) + +// GenericInformer is type of SharedIndexInformer which will locate and delegate to other +// sharedInformers based on type +type GenericInformer interface { + Informer() cache.SharedIndexInformer + Lister() cache.GenericLister +} + +type genericInformer struct { + informer cache.SharedIndexInformer + resource schema.GroupResource +} + +// Informer returns the SharedIndexInformer. +func (f *genericInformer) Informer() cache.SharedIndexInformer { + return f.informer +} + +// Lister returns the GenericLister. +func (f *genericInformer) Lister() cache.GenericLister { + return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) +} + +// ForResource gives generic access to a shared informer of the matching type +// TODO extend this to unknown resources with a client pool +func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { + switch resource { + // Group=core, Version=v1 + case v1.SchemeGroupVersion.WithResource("servicemeshcontrolplanes"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Core().V1().ServiceMeshControlPlanes().Informer()}, nil + case v1.SchemeGroupVersion.WithResource("servicemeshextensions"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Core().V1().ServiceMeshExtensions().Informer()}, nil + case v1.SchemeGroupVersion.WithResource("servicemeshmembers"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Core().V1().ServiceMeshMembers().Informer()}, nil + case v1.SchemeGroupVersion.WithResource("servicemeshmemberrolls"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Core().V1().ServiceMeshMemberRolls().Informer()}, nil + + // Group=core, Version=v1alpha1 + case v1alpha1.SchemeGroupVersion.WithResource("servicemeshextensions"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Core().V1alpha1().ServiceMeshExtensions().Informer()}, nil + + // Group=core, Version=v2 + case v2.SchemeGroupVersion.WithResource("servicemeshcontrolplanes"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Core().V2().ServiceMeshControlPlanes().Informer()}, nil + + // Group=federation.maistra.io, Version=v1 + case federationv1.SchemeGroupVersion.WithResource("exportedservicesets"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Federation().V1().ExportedServiceSets().Informer()}, nil + case federationv1.SchemeGroupVersion.WithResource("importedservicesets"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Federation().V1().ImportedServiceSets().Informer()}, nil + case federationv1.SchemeGroupVersion.WithResource("servicemeshpeers"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Federation().V1().ServiceMeshPeers().Informer()}, nil + + } + + return nil, fmt.Errorf("no informer found for %v", resource) +} diff --git a/pkg/servicemesh/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/vendor/maistra.io/api/client/informers/externalversions/internalinterfaces/factory_interfaces.go similarity index 95% rename from pkg/servicemesh/client/informers/externalversions/internalinterfaces/factory_interfaces.go rename to vendor/maistra.io/api/client/informers/externalversions/internalinterfaces/factory_interfaces.go index e478fa30958..71582358601 100644 --- a/pkg/servicemesh/client/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/vendor/maistra.io/api/client/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -19,10 +19,10 @@ package internalinterfaces import ( time "time" - versioned "istio.io/istio/pkg/servicemesh/client/clientset/versioned" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" cache "k8s.io/client-go/tools/cache" + versioned "maistra.io/api/client/versioned" ) // NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. diff --git a/vendor/maistra.io/api/client/listers/core/v1/expansion_generated.go b/vendor/maistra.io/api/client/listers/core/v1/expansion_generated.go new file mode 100644 index 00000000000..c8f10de46eb --- /dev/null +++ b/vendor/maistra.io/api/client/listers/core/v1/expansion_generated.go @@ -0,0 +1,49 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +// ServiceMeshControlPlaneListerExpansion allows custom methods to be added to +// ServiceMeshControlPlaneLister. +type ServiceMeshControlPlaneListerExpansion interface{} + +// ServiceMeshControlPlaneNamespaceListerExpansion allows custom methods to be added to +// ServiceMeshControlPlaneNamespaceLister. +type ServiceMeshControlPlaneNamespaceListerExpansion interface{} + +// ServiceMeshExtensionListerExpansion allows custom methods to be added to +// ServiceMeshExtensionLister. +type ServiceMeshExtensionListerExpansion interface{} + +// ServiceMeshExtensionNamespaceListerExpansion allows custom methods to be added to +// ServiceMeshExtensionNamespaceLister. +type ServiceMeshExtensionNamespaceListerExpansion interface{} + +// ServiceMeshMemberListerExpansion allows custom methods to be added to +// ServiceMeshMemberLister. +type ServiceMeshMemberListerExpansion interface{} + +// ServiceMeshMemberNamespaceListerExpansion allows custom methods to be added to +// ServiceMeshMemberNamespaceLister. +type ServiceMeshMemberNamespaceListerExpansion interface{} + +// ServiceMeshMemberRollListerExpansion allows custom methods to be added to +// ServiceMeshMemberRollLister. +type ServiceMeshMemberRollListerExpansion interface{} + +// ServiceMeshMemberRollNamespaceListerExpansion allows custom methods to be added to +// ServiceMeshMemberRollNamespaceLister. +type ServiceMeshMemberRollNamespaceListerExpansion interface{} diff --git a/vendor/maistra.io/api/client/listers/core/v1/servicemeshcontrolplane.go b/vendor/maistra.io/api/client/listers/core/v1/servicemeshcontrolplane.go new file mode 100644 index 00000000000..4eb3214520f --- /dev/null +++ b/vendor/maistra.io/api/client/listers/core/v1/servicemeshcontrolplane.go @@ -0,0 +1,97 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/core/v1" +) + +// ServiceMeshControlPlaneLister helps list ServiceMeshControlPlanes. +// All objects returned here must be treated as read-only. +type ServiceMeshControlPlaneLister interface { + // List lists all ServiceMeshControlPlanes in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.ServiceMeshControlPlane, err error) + // ServiceMeshControlPlanes returns an object that can list and get ServiceMeshControlPlanes. + ServiceMeshControlPlanes(namespace string) ServiceMeshControlPlaneNamespaceLister + ServiceMeshControlPlaneListerExpansion +} + +// serviceMeshControlPlaneLister implements the ServiceMeshControlPlaneLister interface. +type serviceMeshControlPlaneLister struct { + indexer cache.Indexer +} + +// NewServiceMeshControlPlaneLister returns a new ServiceMeshControlPlaneLister. +func NewServiceMeshControlPlaneLister(indexer cache.Indexer) ServiceMeshControlPlaneLister { + return &serviceMeshControlPlaneLister{indexer: indexer} +} + +// List lists all ServiceMeshControlPlanes in the indexer. +func (s *serviceMeshControlPlaneLister) List(selector labels.Selector) (ret []*v1.ServiceMeshControlPlane, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.ServiceMeshControlPlane)) + }) + return ret, err +} + +// ServiceMeshControlPlanes returns an object that can list and get ServiceMeshControlPlanes. +func (s *serviceMeshControlPlaneLister) ServiceMeshControlPlanes(namespace string) ServiceMeshControlPlaneNamespaceLister { + return serviceMeshControlPlaneNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ServiceMeshControlPlaneNamespaceLister helps list and get ServiceMeshControlPlanes. +// All objects returned here must be treated as read-only. +type ServiceMeshControlPlaneNamespaceLister interface { + // List lists all ServiceMeshControlPlanes in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.ServiceMeshControlPlane, err error) + // Get retrieves the ServiceMeshControlPlane from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1.ServiceMeshControlPlane, error) + ServiceMeshControlPlaneNamespaceListerExpansion +} + +// serviceMeshControlPlaneNamespaceLister implements the ServiceMeshControlPlaneNamespaceLister +// interface. +type serviceMeshControlPlaneNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ServiceMeshControlPlanes in the indexer for a given namespace. +func (s serviceMeshControlPlaneNamespaceLister) List(selector labels.Selector) (ret []*v1.ServiceMeshControlPlane, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1.ServiceMeshControlPlane)) + }) + return ret, err +} + +// Get retrieves the ServiceMeshControlPlane from the indexer for a given namespace and name. +func (s serviceMeshControlPlaneNamespaceLister) Get(name string) (*v1.ServiceMeshControlPlane, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("servicemeshcontrolplane"), name) + } + return obj.(*v1.ServiceMeshControlPlane), nil +} diff --git a/vendor/maistra.io/api/client/listers/core/v1/servicemeshextension.go b/vendor/maistra.io/api/client/listers/core/v1/servicemeshextension.go new file mode 100644 index 00000000000..b6694ce83ec --- /dev/null +++ b/vendor/maistra.io/api/client/listers/core/v1/servicemeshextension.go @@ -0,0 +1,97 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/core/v1" +) + +// ServiceMeshExtensionLister helps list ServiceMeshExtensions. +// All objects returned here must be treated as read-only. +type ServiceMeshExtensionLister interface { + // List lists all ServiceMeshExtensions in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.ServiceMeshExtension, err error) + // ServiceMeshExtensions returns an object that can list and get ServiceMeshExtensions. + ServiceMeshExtensions(namespace string) ServiceMeshExtensionNamespaceLister + ServiceMeshExtensionListerExpansion +} + +// serviceMeshExtensionLister implements the ServiceMeshExtensionLister interface. +type serviceMeshExtensionLister struct { + indexer cache.Indexer +} + +// NewServiceMeshExtensionLister returns a new ServiceMeshExtensionLister. +func NewServiceMeshExtensionLister(indexer cache.Indexer) ServiceMeshExtensionLister { + return &serviceMeshExtensionLister{indexer: indexer} +} + +// List lists all ServiceMeshExtensions in the indexer. +func (s *serviceMeshExtensionLister) List(selector labels.Selector) (ret []*v1.ServiceMeshExtension, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.ServiceMeshExtension)) + }) + return ret, err +} + +// ServiceMeshExtensions returns an object that can list and get ServiceMeshExtensions. +func (s *serviceMeshExtensionLister) ServiceMeshExtensions(namespace string) ServiceMeshExtensionNamespaceLister { + return serviceMeshExtensionNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ServiceMeshExtensionNamespaceLister helps list and get ServiceMeshExtensions. +// All objects returned here must be treated as read-only. +type ServiceMeshExtensionNamespaceLister interface { + // List lists all ServiceMeshExtensions in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.ServiceMeshExtension, err error) + // Get retrieves the ServiceMeshExtension from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1.ServiceMeshExtension, error) + ServiceMeshExtensionNamespaceListerExpansion +} + +// serviceMeshExtensionNamespaceLister implements the ServiceMeshExtensionNamespaceLister +// interface. +type serviceMeshExtensionNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ServiceMeshExtensions in the indexer for a given namespace. +func (s serviceMeshExtensionNamespaceLister) List(selector labels.Selector) (ret []*v1.ServiceMeshExtension, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1.ServiceMeshExtension)) + }) + return ret, err +} + +// Get retrieves the ServiceMeshExtension from the indexer for a given namespace and name. +func (s serviceMeshExtensionNamespaceLister) Get(name string) (*v1.ServiceMeshExtension, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("servicemeshextension"), name) + } + return obj.(*v1.ServiceMeshExtension), nil +} diff --git a/vendor/maistra.io/api/client/listers/core/v1/servicemeshmember.go b/vendor/maistra.io/api/client/listers/core/v1/servicemeshmember.go new file mode 100644 index 00000000000..d0c2c4367ce --- /dev/null +++ b/vendor/maistra.io/api/client/listers/core/v1/servicemeshmember.go @@ -0,0 +1,97 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/core/v1" +) + +// ServiceMeshMemberLister helps list ServiceMeshMembers. +// All objects returned here must be treated as read-only. +type ServiceMeshMemberLister interface { + // List lists all ServiceMeshMembers in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.ServiceMeshMember, err error) + // ServiceMeshMembers returns an object that can list and get ServiceMeshMembers. + ServiceMeshMembers(namespace string) ServiceMeshMemberNamespaceLister + ServiceMeshMemberListerExpansion +} + +// serviceMeshMemberLister implements the ServiceMeshMemberLister interface. +type serviceMeshMemberLister struct { + indexer cache.Indexer +} + +// NewServiceMeshMemberLister returns a new ServiceMeshMemberLister. +func NewServiceMeshMemberLister(indexer cache.Indexer) ServiceMeshMemberLister { + return &serviceMeshMemberLister{indexer: indexer} +} + +// List lists all ServiceMeshMembers in the indexer. +func (s *serviceMeshMemberLister) List(selector labels.Selector) (ret []*v1.ServiceMeshMember, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.ServiceMeshMember)) + }) + return ret, err +} + +// ServiceMeshMembers returns an object that can list and get ServiceMeshMembers. +func (s *serviceMeshMemberLister) ServiceMeshMembers(namespace string) ServiceMeshMemberNamespaceLister { + return serviceMeshMemberNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ServiceMeshMemberNamespaceLister helps list and get ServiceMeshMembers. +// All objects returned here must be treated as read-only. +type ServiceMeshMemberNamespaceLister interface { + // List lists all ServiceMeshMembers in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.ServiceMeshMember, err error) + // Get retrieves the ServiceMeshMember from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1.ServiceMeshMember, error) + ServiceMeshMemberNamespaceListerExpansion +} + +// serviceMeshMemberNamespaceLister implements the ServiceMeshMemberNamespaceLister +// interface. +type serviceMeshMemberNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ServiceMeshMembers in the indexer for a given namespace. +func (s serviceMeshMemberNamespaceLister) List(selector labels.Selector) (ret []*v1.ServiceMeshMember, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1.ServiceMeshMember)) + }) + return ret, err +} + +// Get retrieves the ServiceMeshMember from the indexer for a given namespace and name. +func (s serviceMeshMemberNamespaceLister) Get(name string) (*v1.ServiceMeshMember, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("servicemeshmember"), name) + } + return obj.(*v1.ServiceMeshMember), nil +} diff --git a/pkg/servicemesh/client/listers/servicemesh/v1/servicemeshmemberroll.go b/vendor/maistra.io/api/client/listers/core/v1/servicemeshmemberroll.go similarity index 98% rename from pkg/servicemesh/client/listers/servicemesh/v1/servicemeshmemberroll.go rename to vendor/maistra.io/api/client/listers/core/v1/servicemeshmemberroll.go index edfffa7aee5..560e36df8e7 100644 --- a/pkg/servicemesh/client/listers/servicemesh/v1/servicemeshmemberroll.go +++ b/vendor/maistra.io/api/client/listers/core/v1/servicemeshmemberroll.go @@ -17,10 +17,10 @@ package v1 import ( - v1 "istio.io/istio/pkg/servicemesh/apis/servicemesh/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/core/v1" ) // ServiceMeshMemberRollLister helps list ServiceMeshMemberRolls. diff --git a/pkg/servicemesh/client/listers/servicemesh/v1/expansion_generated.go b/vendor/maistra.io/api/client/listers/core/v1alpha1/expansion_generated.go similarity index 63% rename from pkg/servicemesh/client/listers/servicemesh/v1/expansion_generated.go rename to vendor/maistra.io/api/client/listers/core/v1alpha1/expansion_generated.go index ada26b7c7c2..a92f0a1fee0 100644 --- a/pkg/servicemesh/client/listers/servicemesh/v1/expansion_generated.go +++ b/vendor/maistra.io/api/client/listers/core/v1alpha1/expansion_generated.go @@ -14,12 +14,12 @@ // Code generated by lister-gen. DO NOT EDIT. -package v1 +package v1alpha1 -// ServiceMeshMemberRollListerExpansion allows custom methods to be added to -// ServiceMeshMemberRollLister. -type ServiceMeshMemberRollListerExpansion interface{} +// ServiceMeshExtensionListerExpansion allows custom methods to be added to +// ServiceMeshExtensionLister. +type ServiceMeshExtensionListerExpansion interface{} -// ServiceMeshMemberRollNamespaceListerExpansion allows custom methods to be added to -// ServiceMeshMemberRollNamespaceLister. -type ServiceMeshMemberRollNamespaceListerExpansion interface{} +// ServiceMeshExtensionNamespaceListerExpansion allows custom methods to be added to +// ServiceMeshExtensionNamespaceLister. +type ServiceMeshExtensionNamespaceListerExpansion interface{} diff --git a/vendor/maistra.io/api/client/listers/core/v1alpha1/servicemeshextension.go b/vendor/maistra.io/api/client/listers/core/v1alpha1/servicemeshextension.go new file mode 100644 index 00000000000..6c641fc2c4d --- /dev/null +++ b/vendor/maistra.io/api/client/listers/core/v1alpha1/servicemeshextension.go @@ -0,0 +1,97 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1alpha1 "maistra.io/api/core/v1alpha1" +) + +// ServiceMeshExtensionLister helps list ServiceMeshExtensions. +// All objects returned here must be treated as read-only. +type ServiceMeshExtensionLister interface { + // List lists all ServiceMeshExtensions in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ServiceMeshExtension, err error) + // ServiceMeshExtensions returns an object that can list and get ServiceMeshExtensions. + ServiceMeshExtensions(namespace string) ServiceMeshExtensionNamespaceLister + ServiceMeshExtensionListerExpansion +} + +// serviceMeshExtensionLister implements the ServiceMeshExtensionLister interface. +type serviceMeshExtensionLister struct { + indexer cache.Indexer +} + +// NewServiceMeshExtensionLister returns a new ServiceMeshExtensionLister. +func NewServiceMeshExtensionLister(indexer cache.Indexer) ServiceMeshExtensionLister { + return &serviceMeshExtensionLister{indexer: indexer} +} + +// List lists all ServiceMeshExtensions in the indexer. +func (s *serviceMeshExtensionLister) List(selector labels.Selector) (ret []*v1alpha1.ServiceMeshExtension, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ServiceMeshExtension)) + }) + return ret, err +} + +// ServiceMeshExtensions returns an object that can list and get ServiceMeshExtensions. +func (s *serviceMeshExtensionLister) ServiceMeshExtensions(namespace string) ServiceMeshExtensionNamespaceLister { + return serviceMeshExtensionNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ServiceMeshExtensionNamespaceLister helps list and get ServiceMeshExtensions. +// All objects returned here must be treated as read-only. +type ServiceMeshExtensionNamespaceLister interface { + // List lists all ServiceMeshExtensions in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.ServiceMeshExtension, err error) + // Get retrieves the ServiceMeshExtension from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.ServiceMeshExtension, error) + ServiceMeshExtensionNamespaceListerExpansion +} + +// serviceMeshExtensionNamespaceLister implements the ServiceMeshExtensionNamespaceLister +// interface. +type serviceMeshExtensionNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ServiceMeshExtensions in the indexer for a given namespace. +func (s serviceMeshExtensionNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ServiceMeshExtension, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.ServiceMeshExtension)) + }) + return ret, err +} + +// Get retrieves the ServiceMeshExtension from the indexer for a given namespace and name. +func (s serviceMeshExtensionNamespaceLister) Get(name string) (*v1alpha1.ServiceMeshExtension, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("servicemeshextension"), name) + } + return obj.(*v1alpha1.ServiceMeshExtension), nil +} diff --git a/vendor/maistra.io/api/client/listers/core/v2/expansion_generated.go b/vendor/maistra.io/api/client/listers/core/v2/expansion_generated.go new file mode 100644 index 00000000000..bae6f4ccdcd --- /dev/null +++ b/vendor/maistra.io/api/client/listers/core/v2/expansion_generated.go @@ -0,0 +1,25 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v2 + +// ServiceMeshControlPlaneListerExpansion allows custom methods to be added to +// ServiceMeshControlPlaneLister. +type ServiceMeshControlPlaneListerExpansion interface{} + +// ServiceMeshControlPlaneNamespaceListerExpansion allows custom methods to be added to +// ServiceMeshControlPlaneNamespaceLister. +type ServiceMeshControlPlaneNamespaceListerExpansion interface{} diff --git a/vendor/maistra.io/api/client/listers/core/v2/servicemeshcontrolplane.go b/vendor/maistra.io/api/client/listers/core/v2/servicemeshcontrolplane.go new file mode 100644 index 00000000000..5df4105a8b0 --- /dev/null +++ b/vendor/maistra.io/api/client/listers/core/v2/servicemeshcontrolplane.go @@ -0,0 +1,97 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v2 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v2 "maistra.io/api/core/v2" +) + +// ServiceMeshControlPlaneLister helps list ServiceMeshControlPlanes. +// All objects returned here must be treated as read-only. +type ServiceMeshControlPlaneLister interface { + // List lists all ServiceMeshControlPlanes in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v2.ServiceMeshControlPlane, err error) + // ServiceMeshControlPlanes returns an object that can list and get ServiceMeshControlPlanes. + ServiceMeshControlPlanes(namespace string) ServiceMeshControlPlaneNamespaceLister + ServiceMeshControlPlaneListerExpansion +} + +// serviceMeshControlPlaneLister implements the ServiceMeshControlPlaneLister interface. +type serviceMeshControlPlaneLister struct { + indexer cache.Indexer +} + +// NewServiceMeshControlPlaneLister returns a new ServiceMeshControlPlaneLister. +func NewServiceMeshControlPlaneLister(indexer cache.Indexer) ServiceMeshControlPlaneLister { + return &serviceMeshControlPlaneLister{indexer: indexer} +} + +// List lists all ServiceMeshControlPlanes in the indexer. +func (s *serviceMeshControlPlaneLister) List(selector labels.Selector) (ret []*v2.ServiceMeshControlPlane, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v2.ServiceMeshControlPlane)) + }) + return ret, err +} + +// ServiceMeshControlPlanes returns an object that can list and get ServiceMeshControlPlanes. +func (s *serviceMeshControlPlaneLister) ServiceMeshControlPlanes(namespace string) ServiceMeshControlPlaneNamespaceLister { + return serviceMeshControlPlaneNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ServiceMeshControlPlaneNamespaceLister helps list and get ServiceMeshControlPlanes. +// All objects returned here must be treated as read-only. +type ServiceMeshControlPlaneNamespaceLister interface { + // List lists all ServiceMeshControlPlanes in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v2.ServiceMeshControlPlane, err error) + // Get retrieves the ServiceMeshControlPlane from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v2.ServiceMeshControlPlane, error) + ServiceMeshControlPlaneNamespaceListerExpansion +} + +// serviceMeshControlPlaneNamespaceLister implements the ServiceMeshControlPlaneNamespaceLister +// interface. +type serviceMeshControlPlaneNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ServiceMeshControlPlanes in the indexer for a given namespace. +func (s serviceMeshControlPlaneNamespaceLister) List(selector labels.Selector) (ret []*v2.ServiceMeshControlPlane, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v2.ServiceMeshControlPlane)) + }) + return ret, err +} + +// Get retrieves the ServiceMeshControlPlane from the indexer for a given namespace and name. +func (s serviceMeshControlPlaneNamespaceLister) Get(name string) (*v2.ServiceMeshControlPlane, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v2.Resource("servicemeshcontrolplane"), name) + } + return obj.(*v2.ServiceMeshControlPlane), nil +} diff --git a/vendor/maistra.io/api/client/listers/federation/v1/expansion_generated.go b/vendor/maistra.io/api/client/listers/federation/v1/expansion_generated.go new file mode 100644 index 00000000000..67d6acf2ed0 --- /dev/null +++ b/vendor/maistra.io/api/client/listers/federation/v1/expansion_generated.go @@ -0,0 +1,41 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +// ExportedServiceSetListerExpansion allows custom methods to be added to +// ExportedServiceSetLister. +type ExportedServiceSetListerExpansion interface{} + +// ExportedServiceSetNamespaceListerExpansion allows custom methods to be added to +// ExportedServiceSetNamespaceLister. +type ExportedServiceSetNamespaceListerExpansion interface{} + +// ImportedServiceSetListerExpansion allows custom methods to be added to +// ImportedServiceSetLister. +type ImportedServiceSetListerExpansion interface{} + +// ImportedServiceSetNamespaceListerExpansion allows custom methods to be added to +// ImportedServiceSetNamespaceLister. +type ImportedServiceSetNamespaceListerExpansion interface{} + +// ServiceMeshPeerListerExpansion allows custom methods to be added to +// ServiceMeshPeerLister. +type ServiceMeshPeerListerExpansion interface{} + +// ServiceMeshPeerNamespaceListerExpansion allows custom methods to be added to +// ServiceMeshPeerNamespaceLister. +type ServiceMeshPeerNamespaceListerExpansion interface{} diff --git a/vendor/maistra.io/api/client/listers/federation/v1/exportedserviceset.go b/vendor/maistra.io/api/client/listers/federation/v1/exportedserviceset.go new file mode 100644 index 00000000000..71c4571ddf3 --- /dev/null +++ b/vendor/maistra.io/api/client/listers/federation/v1/exportedserviceset.go @@ -0,0 +1,97 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/federation/v1" +) + +// ExportedServiceSetLister helps list ExportedServiceSets. +// All objects returned here must be treated as read-only. +type ExportedServiceSetLister interface { + // List lists all ExportedServiceSets in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.ExportedServiceSet, err error) + // ExportedServiceSets returns an object that can list and get ExportedServiceSets. + ExportedServiceSets(namespace string) ExportedServiceSetNamespaceLister + ExportedServiceSetListerExpansion +} + +// exportedServiceSetLister implements the ExportedServiceSetLister interface. +type exportedServiceSetLister struct { + indexer cache.Indexer +} + +// NewExportedServiceSetLister returns a new ExportedServiceSetLister. +func NewExportedServiceSetLister(indexer cache.Indexer) ExportedServiceSetLister { + return &exportedServiceSetLister{indexer: indexer} +} + +// List lists all ExportedServiceSets in the indexer. +func (s *exportedServiceSetLister) List(selector labels.Selector) (ret []*v1.ExportedServiceSet, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.ExportedServiceSet)) + }) + return ret, err +} + +// ExportedServiceSets returns an object that can list and get ExportedServiceSets. +func (s *exportedServiceSetLister) ExportedServiceSets(namespace string) ExportedServiceSetNamespaceLister { + return exportedServiceSetNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ExportedServiceSetNamespaceLister helps list and get ExportedServiceSets. +// All objects returned here must be treated as read-only. +type ExportedServiceSetNamespaceLister interface { + // List lists all ExportedServiceSets in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.ExportedServiceSet, err error) + // Get retrieves the ExportedServiceSet from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1.ExportedServiceSet, error) + ExportedServiceSetNamespaceListerExpansion +} + +// exportedServiceSetNamespaceLister implements the ExportedServiceSetNamespaceLister +// interface. +type exportedServiceSetNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ExportedServiceSets in the indexer for a given namespace. +func (s exportedServiceSetNamespaceLister) List(selector labels.Selector) (ret []*v1.ExportedServiceSet, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1.ExportedServiceSet)) + }) + return ret, err +} + +// Get retrieves the ExportedServiceSet from the indexer for a given namespace and name. +func (s exportedServiceSetNamespaceLister) Get(name string) (*v1.ExportedServiceSet, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("exportedserviceset"), name) + } + return obj.(*v1.ExportedServiceSet), nil +} diff --git a/vendor/maistra.io/api/client/listers/federation/v1/importedserviceset.go b/vendor/maistra.io/api/client/listers/federation/v1/importedserviceset.go new file mode 100644 index 00000000000..0987837308c --- /dev/null +++ b/vendor/maistra.io/api/client/listers/federation/v1/importedserviceset.go @@ -0,0 +1,97 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/federation/v1" +) + +// ImportedServiceSetLister helps list ImportedServiceSets. +// All objects returned here must be treated as read-only. +type ImportedServiceSetLister interface { + // List lists all ImportedServiceSets in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.ImportedServiceSet, err error) + // ImportedServiceSets returns an object that can list and get ImportedServiceSets. + ImportedServiceSets(namespace string) ImportedServiceSetNamespaceLister + ImportedServiceSetListerExpansion +} + +// importedServiceSetLister implements the ImportedServiceSetLister interface. +type importedServiceSetLister struct { + indexer cache.Indexer +} + +// NewImportedServiceSetLister returns a new ImportedServiceSetLister. +func NewImportedServiceSetLister(indexer cache.Indexer) ImportedServiceSetLister { + return &importedServiceSetLister{indexer: indexer} +} + +// List lists all ImportedServiceSets in the indexer. +func (s *importedServiceSetLister) List(selector labels.Selector) (ret []*v1.ImportedServiceSet, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.ImportedServiceSet)) + }) + return ret, err +} + +// ImportedServiceSets returns an object that can list and get ImportedServiceSets. +func (s *importedServiceSetLister) ImportedServiceSets(namespace string) ImportedServiceSetNamespaceLister { + return importedServiceSetNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ImportedServiceSetNamespaceLister helps list and get ImportedServiceSets. +// All objects returned here must be treated as read-only. +type ImportedServiceSetNamespaceLister interface { + // List lists all ImportedServiceSets in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.ImportedServiceSet, err error) + // Get retrieves the ImportedServiceSet from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1.ImportedServiceSet, error) + ImportedServiceSetNamespaceListerExpansion +} + +// importedServiceSetNamespaceLister implements the ImportedServiceSetNamespaceLister +// interface. +type importedServiceSetNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ImportedServiceSets in the indexer for a given namespace. +func (s importedServiceSetNamespaceLister) List(selector labels.Selector) (ret []*v1.ImportedServiceSet, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1.ImportedServiceSet)) + }) + return ret, err +} + +// Get retrieves the ImportedServiceSet from the indexer for a given namespace and name. +func (s importedServiceSetNamespaceLister) Get(name string) (*v1.ImportedServiceSet, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("importedserviceset"), name) + } + return obj.(*v1.ImportedServiceSet), nil +} diff --git a/vendor/maistra.io/api/client/listers/federation/v1/servicemeshpeer.go b/vendor/maistra.io/api/client/listers/federation/v1/servicemeshpeer.go new file mode 100644 index 00000000000..61f4d502e6d --- /dev/null +++ b/vendor/maistra.io/api/client/listers/federation/v1/servicemeshpeer.go @@ -0,0 +1,97 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/federation/v1" +) + +// ServiceMeshPeerLister helps list ServiceMeshPeers. +// All objects returned here must be treated as read-only. +type ServiceMeshPeerLister interface { + // List lists all ServiceMeshPeers in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.ServiceMeshPeer, err error) + // ServiceMeshPeers returns an object that can list and get ServiceMeshPeers. + ServiceMeshPeers(namespace string) ServiceMeshPeerNamespaceLister + ServiceMeshPeerListerExpansion +} + +// serviceMeshPeerLister implements the ServiceMeshPeerLister interface. +type serviceMeshPeerLister struct { + indexer cache.Indexer +} + +// NewServiceMeshPeerLister returns a new ServiceMeshPeerLister. +func NewServiceMeshPeerLister(indexer cache.Indexer) ServiceMeshPeerLister { + return &serviceMeshPeerLister{indexer: indexer} +} + +// List lists all ServiceMeshPeers in the indexer. +func (s *serviceMeshPeerLister) List(selector labels.Selector) (ret []*v1.ServiceMeshPeer, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.ServiceMeshPeer)) + }) + return ret, err +} + +// ServiceMeshPeers returns an object that can list and get ServiceMeshPeers. +func (s *serviceMeshPeerLister) ServiceMeshPeers(namespace string) ServiceMeshPeerNamespaceLister { + return serviceMeshPeerNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// ServiceMeshPeerNamespaceLister helps list and get ServiceMeshPeers. +// All objects returned here must be treated as read-only. +type ServiceMeshPeerNamespaceLister interface { + // List lists all ServiceMeshPeers in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1.ServiceMeshPeer, err error) + // Get retrieves the ServiceMeshPeer from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1.ServiceMeshPeer, error) + ServiceMeshPeerNamespaceListerExpansion +} + +// serviceMeshPeerNamespaceLister implements the ServiceMeshPeerNamespaceLister +// interface. +type serviceMeshPeerNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all ServiceMeshPeers in the indexer for a given namespace. +func (s serviceMeshPeerNamespaceLister) List(selector labels.Selector) (ret []*v1.ServiceMeshPeer, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1.ServiceMeshPeer)) + }) + return ret, err +} + +// Get retrieves the ServiceMeshPeer from the indexer for a given namespace and name. +func (s serviceMeshPeerNamespaceLister) Get(name string) (*v1.ServiceMeshPeer, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("servicemeshpeer"), name) + } + return obj.(*v1.ServiceMeshPeer), nil +} diff --git a/pkg/servicemesh/client/clientset/versioned/clientset.go b/vendor/maistra.io/api/client/versioned/clientset.go similarity index 57% rename from pkg/servicemesh/client/clientset/versioned/clientset.go rename to vendor/maistra.io/api/client/versioned/clientset.go index c76832e8528..d5cfdaa2699 100644 --- a/pkg/servicemesh/client/clientset/versioned/clientset.go +++ b/vendor/maistra.io/api/client/versioned/clientset.go @@ -18,29 +18,52 @@ package versioned import ( "fmt" - "net/http" - maistrav1 "istio.io/istio/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" + corev1 "maistra.io/api/client/versioned/typed/core/v1" + corev1alpha1 "maistra.io/api/client/versioned/typed/core/v1alpha1" + corev2 "maistra.io/api/client/versioned/typed/core/v2" + federationv1 "maistra.io/api/client/versioned/typed/federation/v1" ) type Interface interface { Discovery() discovery.DiscoveryInterface - MaistraV1() maistrav1.MaistraV1Interface + CoreV1() corev1.CoreV1Interface + CoreV1alpha1() corev1alpha1.CoreV1alpha1Interface + CoreV2() corev2.CoreV2Interface + FederationV1() federationv1.FederationV1Interface } // Clientset contains the clients for groups. Each group has exactly one // version included in a Clientset. type Clientset struct { *discovery.DiscoveryClient - maistraV1 *maistrav1.MaistraV1Client + coreV1 *corev1.CoreV1Client + coreV1alpha1 *corev1alpha1.CoreV1alpha1Client + coreV2 *corev2.CoreV2Client + federationV1 *federationv1.FederationV1Client } -// MaistraV1 retrieves the MaistraV1Client -func (c *Clientset) MaistraV1() maistrav1.MaistraV1Interface { - return c.maistraV1 +// CoreV1 retrieves the CoreV1Client +func (c *Clientset) CoreV1() corev1.CoreV1Interface { + return c.coreV1 +} + +// CoreV1alpha1 retrieves the CoreV1alpha1Client +func (c *Clientset) CoreV1alpha1() corev1alpha1.CoreV1alpha1Interface { + return c.coreV1alpha1 +} + +// CoreV2 retrieves the CoreV2Client +func (c *Clientset) CoreV2() corev2.CoreV2Interface { + return c.coreV2 +} + +// FederationV1 retrieves the FederationV1Client +func (c *Clientset) FederationV1() federationv1.FederationV1Interface { + return c.federationV1 } // Discovery retrieves the DiscoveryClient @@ -54,41 +77,34 @@ func (c *Clientset) Discovery() discovery.DiscoveryInterface { // NewForConfig creates a new Clientset for the given config. // If config's RateLimiter is not set and QPS and Burst are acceptable, // NewForConfig will generate a rate-limiter in configShallowCopy. -// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), -// where httpClient was generated with rest.HTTPClientFor(c). func NewForConfig(c *rest.Config) (*Clientset, error) { configShallowCopy := *c - - // share the transport between all clients - httpClient, err := rest.HTTPClientFor(&configShallowCopy) - if err != nil { - return nil, err - } - - return NewForConfigAndClient(&configShallowCopy, httpClient) -} - -// NewForConfigAndClient creates a new Clientset for the given config and http client. -// Note the http client provided takes precedence over the configured transport values. -// If config's RateLimiter is not set and QPS and Burst are acceptable, -// NewForConfigAndClient will generate a rate-limiter in configShallowCopy. -func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) { - configShallowCopy := *c if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { if configShallowCopy.Burst <= 0 { return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0") } configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) } - var cs Clientset var err error - cs.maistraV1, err = maistrav1.NewForConfigAndClient(&configShallowCopy, httpClient) + cs.coreV1, err = corev1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.coreV1alpha1, err = corev1alpha1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.coreV2, err = corev2.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + cs.federationV1, err = federationv1.NewForConfig(&configShallowCopy) if err != nil { return nil, err } - cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient) + cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) if err != nil { return nil, err } @@ -98,17 +114,23 @@ func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, // NewForConfigOrDie creates a new Clientset for the given config and // panics if there is an error in the config. func NewForConfigOrDie(c *rest.Config) *Clientset { - cs, err := NewForConfig(c) - if err != nil { - panic(err) - } - return cs + var cs Clientset + cs.coreV1 = corev1.NewForConfigOrDie(c) + cs.coreV1alpha1 = corev1alpha1.NewForConfigOrDie(c) + cs.coreV2 = corev2.NewForConfigOrDie(c) + cs.federationV1 = federationv1.NewForConfigOrDie(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) + return &cs } // New creates a new Clientset for the given RESTClient. func New(c rest.Interface) *Clientset { var cs Clientset - cs.maistraV1 = maistrav1.New(c) + cs.coreV1 = corev1.New(c) + cs.coreV1alpha1 = corev1alpha1.New(c) + cs.coreV2 = corev2.New(c) + cs.federationV1 = federationv1.New(c) cs.DiscoveryClient = discovery.NewDiscoveryClient(c) return &cs diff --git a/pkg/servicemesh/client/clientset/versioned/doc.go b/vendor/maistra.io/api/client/versioned/doc.go similarity index 100% rename from pkg/servicemesh/client/clientset/versioned/doc.go rename to vendor/maistra.io/api/client/versioned/doc.go diff --git a/pkg/servicemesh/client/clientset/versioned/fake/clientset_generated.go b/vendor/maistra.io/api/client/versioned/fake/clientset_generated.go similarity index 66% rename from pkg/servicemesh/client/clientset/versioned/fake/clientset_generated.go rename to vendor/maistra.io/api/client/versioned/fake/clientset_generated.go index 75430f7d01a..87545f81a2b 100644 --- a/pkg/servicemesh/client/clientset/versioned/fake/clientset_generated.go +++ b/vendor/maistra.io/api/client/versioned/fake/clientset_generated.go @@ -17,14 +17,20 @@ package fake import ( - clientset "istio.io/istio/pkg/servicemesh/client/clientset/versioned" - maistrav1 "istio.io/istio/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1" - fakemaistrav1 "istio.io/istio/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/fake" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/discovery" fakediscovery "k8s.io/client-go/discovery/fake" "k8s.io/client-go/testing" + clientset "maistra.io/api/client/versioned" + corev1 "maistra.io/api/client/versioned/typed/core/v1" + fakecorev1 "maistra.io/api/client/versioned/typed/core/v1/fake" + corev1alpha1 "maistra.io/api/client/versioned/typed/core/v1alpha1" + fakecorev1alpha1 "maistra.io/api/client/versioned/typed/core/v1alpha1/fake" + corev2 "maistra.io/api/client/versioned/typed/core/v2" + fakecorev2 "maistra.io/api/client/versioned/typed/core/v2/fake" + federationv1 "maistra.io/api/client/versioned/typed/federation/v1" + fakefederationv1 "maistra.io/api/client/versioned/typed/federation/v1/fake" ) // NewSimpleClientset returns a clientset that will respond with the provided objects. @@ -77,7 +83,22 @@ var ( _ testing.FakeClient = &Clientset{} ) -// MaistraV1 retrieves the MaistraV1Client -func (c *Clientset) MaistraV1() maistrav1.MaistraV1Interface { - return &fakemaistrav1.FakeMaistraV1{Fake: &c.Fake} +// CoreV1 retrieves the CoreV1Client +func (c *Clientset) CoreV1() corev1.CoreV1Interface { + return &fakecorev1.FakeCoreV1{Fake: &c.Fake} +} + +// CoreV1alpha1 retrieves the CoreV1alpha1Client +func (c *Clientset) CoreV1alpha1() corev1alpha1.CoreV1alpha1Interface { + return &fakecorev1alpha1.FakeCoreV1alpha1{Fake: &c.Fake} +} + +// CoreV2 retrieves the CoreV2Client +func (c *Clientset) CoreV2() corev2.CoreV2Interface { + return &fakecorev2.FakeCoreV2{Fake: &c.Fake} +} + +// FederationV1 retrieves the FederationV1Client +func (c *Clientset) FederationV1() federationv1.FederationV1Interface { + return &fakefederationv1.FakeFederationV1{Fake: &c.Fake} } diff --git a/pkg/servicemesh/client/clientset/versioned/fake/doc.go b/vendor/maistra.io/api/client/versioned/fake/doc.go similarity index 100% rename from pkg/servicemesh/client/clientset/versioned/fake/doc.go rename to vendor/maistra.io/api/client/versioned/fake/doc.go diff --git a/pkg/servicemesh/client/clientset/versioned/fake/register.go b/vendor/maistra.io/api/client/versioned/fake/register.go similarity index 87% rename from pkg/servicemesh/client/clientset/versioned/fake/register.go rename to vendor/maistra.io/api/client/versioned/fake/register.go index 6fd08588bab..19d1191f48d 100644 --- a/pkg/servicemesh/client/clientset/versioned/fake/register.go +++ b/vendor/maistra.io/api/client/versioned/fake/register.go @@ -17,19 +17,25 @@ package fake import ( - maistrav1 "istio.io/istio/pkg/servicemesh/apis/servicemesh/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + corev1 "maistra.io/api/core/v1" + corev1alpha1 "maistra.io/api/core/v1alpha1" + corev2 "maistra.io/api/core/v2" + federationv1 "maistra.io/api/federation/v1" ) var scheme = runtime.NewScheme() var codecs = serializer.NewCodecFactory(scheme) var localSchemeBuilder = runtime.SchemeBuilder{ - maistrav1.AddToScheme, + corev1.AddToScheme, + corev1alpha1.AddToScheme, + corev2.AddToScheme, + federationv1.AddToScheme, } // AddToScheme adds all types of this clientset into the given scheme. This allows composition diff --git a/pkg/servicemesh/client/clientset/versioned/scheme/doc.go b/vendor/maistra.io/api/client/versioned/scheme/doc.go similarity index 100% rename from pkg/servicemesh/client/clientset/versioned/scheme/doc.go rename to vendor/maistra.io/api/client/versioned/scheme/doc.go diff --git a/pkg/servicemesh/client/clientset/versioned/scheme/register.go b/vendor/maistra.io/api/client/versioned/scheme/register.go similarity index 87% rename from pkg/servicemesh/client/clientset/versioned/scheme/register.go rename to vendor/maistra.io/api/client/versioned/scheme/register.go index 7b74fba4a79..11708c52b6d 100644 --- a/pkg/servicemesh/client/clientset/versioned/scheme/register.go +++ b/vendor/maistra.io/api/client/versioned/scheme/register.go @@ -17,19 +17,25 @@ package scheme import ( - maistrav1 "istio.io/istio/pkg/servicemesh/apis/servicemesh/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" serializer "k8s.io/apimachinery/pkg/runtime/serializer" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + corev1 "maistra.io/api/core/v1" + corev1alpha1 "maistra.io/api/core/v1alpha1" + corev2 "maistra.io/api/core/v2" + federationv1 "maistra.io/api/federation/v1" ) var Scheme = runtime.NewScheme() var Codecs = serializer.NewCodecFactory(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme) var localSchemeBuilder = runtime.SchemeBuilder{ - maistrav1.AddToScheme, + corev1.AddToScheme, + corev1alpha1.AddToScheme, + corev2.AddToScheme, + federationv1.AddToScheme, } // AddToScheme adds all types of this clientset into the given scheme. This allows composition diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v1/core_client.go b/vendor/maistra.io/api/client/versioned/typed/core/v1/core_client.go new file mode 100644 index 00000000000..add7128ec43 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v1/core_client.go @@ -0,0 +1,102 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + rest "k8s.io/client-go/rest" + "maistra.io/api/client/versioned/scheme" + v1 "maistra.io/api/core/v1" +) + +type CoreV1Interface interface { + RESTClient() rest.Interface + ServiceMeshControlPlanesGetter + ServiceMeshExtensionsGetter + ServiceMeshMembersGetter + ServiceMeshMemberRollsGetter +} + +// CoreV1Client is used to interact with features provided by the group. +type CoreV1Client struct { + restClient rest.Interface +} + +func (c *CoreV1Client) ServiceMeshControlPlanes(namespace string) ServiceMeshControlPlaneInterface { + return newServiceMeshControlPlanes(c, namespace) +} + +func (c *CoreV1Client) ServiceMeshExtensions(namespace string) ServiceMeshExtensionInterface { + return newServiceMeshExtensions(c, namespace) +} + +func (c *CoreV1Client) ServiceMeshMembers(namespace string) ServiceMeshMemberInterface { + return newServiceMeshMembers(c, namespace) +} + +func (c *CoreV1Client) ServiceMeshMemberRolls(namespace string) ServiceMeshMemberRollInterface { + return newServiceMeshMemberRolls(c, namespace) +} + +// NewForConfig creates a new CoreV1Client for the given config. +func NewForConfig(c *rest.Config) (*CoreV1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &CoreV1Client{client}, nil +} + +// NewForConfigOrDie creates a new CoreV1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *CoreV1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new CoreV1Client for the given RESTClient. +func New(c rest.Interface) *CoreV1Client { + return &CoreV1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *CoreV1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/doc.go b/vendor/maistra.io/api/client/versioned/typed/core/v1/doc.go similarity index 100% rename from pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/doc.go rename to vendor/maistra.io/api/client/versioned/typed/core/v1/doc.go diff --git a/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/fake/doc.go b/vendor/maistra.io/api/client/versioned/typed/core/v1/fake/doc.go similarity index 100% rename from pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/fake/doc.go rename to vendor/maistra.io/api/client/versioned/typed/core/v1/fake/doc.go diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_core_client.go b/vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_core_client.go new file mode 100644 index 00000000000..56b0cea23dd --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_core_client.go @@ -0,0 +1,50 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" + v1 "maistra.io/api/client/versioned/typed/core/v1" +) + +type FakeCoreV1 struct { + *testing.Fake +} + +func (c *FakeCoreV1) ServiceMeshControlPlanes(namespace string) v1.ServiceMeshControlPlaneInterface { + return &FakeServiceMeshControlPlanes{c, namespace} +} + +func (c *FakeCoreV1) ServiceMeshExtensions(namespace string) v1.ServiceMeshExtensionInterface { + return &FakeServiceMeshExtensions{c, namespace} +} + +func (c *FakeCoreV1) ServiceMeshMembers(namespace string) v1.ServiceMeshMemberInterface { + return &FakeServiceMeshMembers{c, namespace} +} + +func (c *FakeCoreV1) ServiceMeshMemberRolls(namespace string) v1.ServiceMeshMemberRollInterface { + return &FakeServiceMeshMemberRolls{c, namespace} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeCoreV1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_servicemeshcontrolplane.go b/vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_servicemeshcontrolplane.go new file mode 100644 index 00000000000..bf4af727fa1 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_servicemeshcontrolplane.go @@ -0,0 +1,140 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + corev1 "maistra.io/api/core/v1" +) + +// FakeServiceMeshControlPlanes implements ServiceMeshControlPlaneInterface +type FakeServiceMeshControlPlanes struct { + Fake *FakeCoreV1 + ns string +} + +var servicemeshcontrolplanesResource = schema.GroupVersionResource{Group: "maistra.io", Version: "v1", Resource: "servicemeshcontrolplanes"} + +var servicemeshcontrolplanesKind = schema.GroupVersionKind{Group: "maistra.io", Version: "v1", Kind: "ServiceMeshControlPlane"} + +// Get takes name of the serviceMeshControlPlane, and returns the corresponding serviceMeshControlPlane object, and an error if there is any. +func (c *FakeServiceMeshControlPlanes) Get(ctx context.Context, name string, options v1.GetOptions) (result *corev1.ServiceMeshControlPlane, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(servicemeshcontrolplanesResource, c.ns, name), &corev1.ServiceMeshControlPlane{}) + + if obj == nil { + return nil, err + } + return obj.(*corev1.ServiceMeshControlPlane), err +} + +// List takes label and field selectors, and returns the list of ServiceMeshControlPlanes that match those selectors. +func (c *FakeServiceMeshControlPlanes) List(ctx context.Context, opts v1.ListOptions) (result *corev1.ServiceMeshControlPlaneList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(servicemeshcontrolplanesResource, servicemeshcontrolplanesKind, c.ns, opts), &corev1.ServiceMeshControlPlaneList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &corev1.ServiceMeshControlPlaneList{ListMeta: obj.(*corev1.ServiceMeshControlPlaneList).ListMeta} + for _, item := range obj.(*corev1.ServiceMeshControlPlaneList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested serviceMeshControlPlanes. +func (c *FakeServiceMeshControlPlanes) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(servicemeshcontrolplanesResource, c.ns, opts)) + +} + +// Create takes the representation of a serviceMeshControlPlane and creates it. Returns the server's representation of the serviceMeshControlPlane, and an error, if there is any. +func (c *FakeServiceMeshControlPlanes) Create(ctx context.Context, serviceMeshControlPlane *corev1.ServiceMeshControlPlane, opts v1.CreateOptions) (result *corev1.ServiceMeshControlPlane, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(servicemeshcontrolplanesResource, c.ns, serviceMeshControlPlane), &corev1.ServiceMeshControlPlane{}) + + if obj == nil { + return nil, err + } + return obj.(*corev1.ServiceMeshControlPlane), err +} + +// Update takes the representation of a serviceMeshControlPlane and updates it. Returns the server's representation of the serviceMeshControlPlane, and an error, if there is any. +func (c *FakeServiceMeshControlPlanes) Update(ctx context.Context, serviceMeshControlPlane *corev1.ServiceMeshControlPlane, opts v1.UpdateOptions) (result *corev1.ServiceMeshControlPlane, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(servicemeshcontrolplanesResource, c.ns, serviceMeshControlPlane), &corev1.ServiceMeshControlPlane{}) + + if obj == nil { + return nil, err + } + return obj.(*corev1.ServiceMeshControlPlane), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeServiceMeshControlPlanes) UpdateStatus(ctx context.Context, serviceMeshControlPlane *corev1.ServiceMeshControlPlane, opts v1.UpdateOptions) (*corev1.ServiceMeshControlPlane, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(servicemeshcontrolplanesResource, "status", c.ns, serviceMeshControlPlane), &corev1.ServiceMeshControlPlane{}) + + if obj == nil { + return nil, err + } + return obj.(*corev1.ServiceMeshControlPlane), err +} + +// Delete takes name of the serviceMeshControlPlane and deletes it. Returns an error if one occurs. +func (c *FakeServiceMeshControlPlanes) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(servicemeshcontrolplanesResource, c.ns, name), &corev1.ServiceMeshControlPlane{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeServiceMeshControlPlanes) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(servicemeshcontrolplanesResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &corev1.ServiceMeshControlPlaneList{}) + return err +} + +// Patch applies the patch and returns the patched serviceMeshControlPlane. +func (c *FakeServiceMeshControlPlanes) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *corev1.ServiceMeshControlPlane, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(servicemeshcontrolplanesResource, c.ns, name, pt, data, subresources...), &corev1.ServiceMeshControlPlane{}) + + if obj == nil { + return nil, err + } + return obj.(*corev1.ServiceMeshControlPlane), err +} diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_servicemeshextension.go b/vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_servicemeshextension.go new file mode 100644 index 00000000000..baf2692b986 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_servicemeshextension.go @@ -0,0 +1,140 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + corev1 "maistra.io/api/core/v1" +) + +// FakeServiceMeshExtensions implements ServiceMeshExtensionInterface +type FakeServiceMeshExtensions struct { + Fake *FakeCoreV1 + ns string +} + +var servicemeshextensionsResource = schema.GroupVersionResource{Group: "maistra.io", Version: "v1", Resource: "servicemeshextensions"} + +var servicemeshextensionsKind = schema.GroupVersionKind{Group: "maistra.io", Version: "v1", Kind: "ServiceMeshExtension"} + +// Get takes name of the serviceMeshExtension, and returns the corresponding serviceMeshExtension object, and an error if there is any. +func (c *FakeServiceMeshExtensions) Get(ctx context.Context, name string, options v1.GetOptions) (result *corev1.ServiceMeshExtension, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(servicemeshextensionsResource, c.ns, name), &corev1.ServiceMeshExtension{}) + + if obj == nil { + return nil, err + } + return obj.(*corev1.ServiceMeshExtension), err +} + +// List takes label and field selectors, and returns the list of ServiceMeshExtensions that match those selectors. +func (c *FakeServiceMeshExtensions) List(ctx context.Context, opts v1.ListOptions) (result *corev1.ServiceMeshExtensionList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(servicemeshextensionsResource, servicemeshextensionsKind, c.ns, opts), &corev1.ServiceMeshExtensionList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &corev1.ServiceMeshExtensionList{ListMeta: obj.(*corev1.ServiceMeshExtensionList).ListMeta} + for _, item := range obj.(*corev1.ServiceMeshExtensionList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested serviceMeshExtensions. +func (c *FakeServiceMeshExtensions) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(servicemeshextensionsResource, c.ns, opts)) + +} + +// Create takes the representation of a serviceMeshExtension and creates it. Returns the server's representation of the serviceMeshExtension, and an error, if there is any. +func (c *FakeServiceMeshExtensions) Create(ctx context.Context, serviceMeshExtension *corev1.ServiceMeshExtension, opts v1.CreateOptions) (result *corev1.ServiceMeshExtension, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(servicemeshextensionsResource, c.ns, serviceMeshExtension), &corev1.ServiceMeshExtension{}) + + if obj == nil { + return nil, err + } + return obj.(*corev1.ServiceMeshExtension), err +} + +// Update takes the representation of a serviceMeshExtension and updates it. Returns the server's representation of the serviceMeshExtension, and an error, if there is any. +func (c *FakeServiceMeshExtensions) Update(ctx context.Context, serviceMeshExtension *corev1.ServiceMeshExtension, opts v1.UpdateOptions) (result *corev1.ServiceMeshExtension, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(servicemeshextensionsResource, c.ns, serviceMeshExtension), &corev1.ServiceMeshExtension{}) + + if obj == nil { + return nil, err + } + return obj.(*corev1.ServiceMeshExtension), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeServiceMeshExtensions) UpdateStatus(ctx context.Context, serviceMeshExtension *corev1.ServiceMeshExtension, opts v1.UpdateOptions) (*corev1.ServiceMeshExtension, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(servicemeshextensionsResource, "status", c.ns, serviceMeshExtension), &corev1.ServiceMeshExtension{}) + + if obj == nil { + return nil, err + } + return obj.(*corev1.ServiceMeshExtension), err +} + +// Delete takes name of the serviceMeshExtension and deletes it. Returns an error if one occurs. +func (c *FakeServiceMeshExtensions) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(servicemeshextensionsResource, c.ns, name), &corev1.ServiceMeshExtension{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeServiceMeshExtensions) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(servicemeshextensionsResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &corev1.ServiceMeshExtensionList{}) + return err +} + +// Patch applies the patch and returns the patched serviceMeshExtension. +func (c *FakeServiceMeshExtensions) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *corev1.ServiceMeshExtension, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(servicemeshextensionsResource, c.ns, name, pt, data, subresources...), &corev1.ServiceMeshExtension{}) + + if obj == nil { + return nil, err + } + return obj.(*corev1.ServiceMeshExtension), err +} diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_servicemeshmember.go b/vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_servicemeshmember.go new file mode 100644 index 00000000000..5e089a48056 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_servicemeshmember.go @@ -0,0 +1,140 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + corev1 "maistra.io/api/core/v1" +) + +// FakeServiceMeshMembers implements ServiceMeshMemberInterface +type FakeServiceMeshMembers struct { + Fake *FakeCoreV1 + ns string +} + +var servicemeshmembersResource = schema.GroupVersionResource{Group: "maistra.io", Version: "v1", Resource: "servicemeshmembers"} + +var servicemeshmembersKind = schema.GroupVersionKind{Group: "maistra.io", Version: "v1", Kind: "ServiceMeshMember"} + +// Get takes name of the serviceMeshMember, and returns the corresponding serviceMeshMember object, and an error if there is any. +func (c *FakeServiceMeshMembers) Get(ctx context.Context, name string, options v1.GetOptions) (result *corev1.ServiceMeshMember, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(servicemeshmembersResource, c.ns, name), &corev1.ServiceMeshMember{}) + + if obj == nil { + return nil, err + } + return obj.(*corev1.ServiceMeshMember), err +} + +// List takes label and field selectors, and returns the list of ServiceMeshMembers that match those selectors. +func (c *FakeServiceMeshMembers) List(ctx context.Context, opts v1.ListOptions) (result *corev1.ServiceMeshMemberList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(servicemeshmembersResource, servicemeshmembersKind, c.ns, opts), &corev1.ServiceMeshMemberList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &corev1.ServiceMeshMemberList{ListMeta: obj.(*corev1.ServiceMeshMemberList).ListMeta} + for _, item := range obj.(*corev1.ServiceMeshMemberList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested serviceMeshMembers. +func (c *FakeServiceMeshMembers) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(servicemeshmembersResource, c.ns, opts)) + +} + +// Create takes the representation of a serviceMeshMember and creates it. Returns the server's representation of the serviceMeshMember, and an error, if there is any. +func (c *FakeServiceMeshMembers) Create(ctx context.Context, serviceMeshMember *corev1.ServiceMeshMember, opts v1.CreateOptions) (result *corev1.ServiceMeshMember, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(servicemeshmembersResource, c.ns, serviceMeshMember), &corev1.ServiceMeshMember{}) + + if obj == nil { + return nil, err + } + return obj.(*corev1.ServiceMeshMember), err +} + +// Update takes the representation of a serviceMeshMember and updates it. Returns the server's representation of the serviceMeshMember, and an error, if there is any. +func (c *FakeServiceMeshMembers) Update(ctx context.Context, serviceMeshMember *corev1.ServiceMeshMember, opts v1.UpdateOptions) (result *corev1.ServiceMeshMember, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(servicemeshmembersResource, c.ns, serviceMeshMember), &corev1.ServiceMeshMember{}) + + if obj == nil { + return nil, err + } + return obj.(*corev1.ServiceMeshMember), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeServiceMeshMembers) UpdateStatus(ctx context.Context, serviceMeshMember *corev1.ServiceMeshMember, opts v1.UpdateOptions) (*corev1.ServiceMeshMember, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(servicemeshmembersResource, "status", c.ns, serviceMeshMember), &corev1.ServiceMeshMember{}) + + if obj == nil { + return nil, err + } + return obj.(*corev1.ServiceMeshMember), err +} + +// Delete takes name of the serviceMeshMember and deletes it. Returns an error if one occurs. +func (c *FakeServiceMeshMembers) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(servicemeshmembersResource, c.ns, name), &corev1.ServiceMeshMember{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeServiceMeshMembers) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(servicemeshmembersResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &corev1.ServiceMeshMemberList{}) + return err +} + +// Patch applies the patch and returns the patched serviceMeshMember. +func (c *FakeServiceMeshMembers) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *corev1.ServiceMeshMember, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(servicemeshmembersResource, c.ns, name, pt, data, subresources...), &corev1.ServiceMeshMember{}) + + if obj == nil { + return nil, err + } + return obj.(*corev1.ServiceMeshMember), err +} diff --git a/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/fake/fake_servicemeshmemberroll.go b/vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_servicemeshmemberroll.go similarity index 69% rename from pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/fake/fake_servicemeshmemberroll.go rename to vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_servicemeshmemberroll.go index 509254429b4..6e19889d8f5 100644 --- a/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/fake/fake_servicemeshmemberroll.go +++ b/vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_servicemeshmemberroll.go @@ -19,18 +19,18 @@ package fake import ( "context" - servicemeshv1 "istio.io/istio/pkg/servicemesh/apis/servicemesh/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" schema "k8s.io/apimachinery/pkg/runtime/schema" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" testing "k8s.io/client-go/testing" + corev1 "maistra.io/api/core/v1" ) // FakeServiceMeshMemberRolls implements ServiceMeshMemberRollInterface type FakeServiceMeshMemberRolls struct { - Fake *FakeMaistraV1 + Fake *FakeCoreV1 ns string } @@ -39,20 +39,20 @@ var servicemeshmemberrollsResource = schema.GroupVersionResource{Group: "maistra var servicemeshmemberrollsKind = schema.GroupVersionKind{Group: "maistra.io", Version: "v1", Kind: "ServiceMeshMemberRoll"} // Get takes name of the serviceMeshMemberRoll, and returns the corresponding serviceMeshMemberRoll object, and an error if there is any. -func (c *FakeServiceMeshMemberRolls) Get(ctx context.Context, name string, options v1.GetOptions) (result *servicemeshv1.ServiceMeshMemberRoll, err error) { +func (c *FakeServiceMeshMemberRolls) Get(ctx context.Context, name string, options v1.GetOptions) (result *corev1.ServiceMeshMemberRoll, err error) { obj, err := c.Fake. - Invokes(testing.NewGetAction(servicemeshmemberrollsResource, c.ns, name), &servicemeshv1.ServiceMeshMemberRoll{}) + Invokes(testing.NewGetAction(servicemeshmemberrollsResource, c.ns, name), &corev1.ServiceMeshMemberRoll{}) if obj == nil { return nil, err } - return obj.(*servicemeshv1.ServiceMeshMemberRoll), err + return obj.(*corev1.ServiceMeshMemberRoll), err } // List takes label and field selectors, and returns the list of ServiceMeshMemberRolls that match those selectors. -func (c *FakeServiceMeshMemberRolls) List(ctx context.Context, opts v1.ListOptions) (result *servicemeshv1.ServiceMeshMemberRollList, err error) { +func (c *FakeServiceMeshMemberRolls) List(ctx context.Context, opts v1.ListOptions) (result *corev1.ServiceMeshMemberRollList, err error) { obj, err := c.Fake. - Invokes(testing.NewListAction(servicemeshmemberrollsResource, servicemeshmemberrollsKind, c.ns, opts), &servicemeshv1.ServiceMeshMemberRollList{}) + Invokes(testing.NewListAction(servicemeshmemberrollsResource, servicemeshmemberrollsKind, c.ns, opts), &corev1.ServiceMeshMemberRollList{}) if obj == nil { return nil, err @@ -62,8 +62,8 @@ func (c *FakeServiceMeshMemberRolls) List(ctx context.Context, opts v1.ListOptio if label == nil { label = labels.Everything() } - list := &servicemeshv1.ServiceMeshMemberRollList{ListMeta: obj.(*servicemeshv1.ServiceMeshMemberRollList).ListMeta} - for _, item := range obj.(*servicemeshv1.ServiceMeshMemberRollList).Items { + list := &corev1.ServiceMeshMemberRollList{ListMeta: obj.(*corev1.ServiceMeshMemberRollList).ListMeta} + for _, item := range obj.(*corev1.ServiceMeshMemberRollList).Items { if label.Matches(labels.Set(item.Labels)) { list.Items = append(list.Items, item) } @@ -79,43 +79,43 @@ func (c *FakeServiceMeshMemberRolls) Watch(ctx context.Context, opts v1.ListOpti } // Create takes the representation of a serviceMeshMemberRoll and creates it. Returns the server's representation of the serviceMeshMemberRoll, and an error, if there is any. -func (c *FakeServiceMeshMemberRolls) Create(ctx context.Context, serviceMeshMemberRoll *servicemeshv1.ServiceMeshMemberRoll, opts v1.CreateOptions) (result *servicemeshv1.ServiceMeshMemberRoll, err error) { +func (c *FakeServiceMeshMemberRolls) Create(ctx context.Context, serviceMeshMemberRoll *corev1.ServiceMeshMemberRoll, opts v1.CreateOptions) (result *corev1.ServiceMeshMemberRoll, err error) { obj, err := c.Fake. - Invokes(testing.NewCreateAction(servicemeshmemberrollsResource, c.ns, serviceMeshMemberRoll), &servicemeshv1.ServiceMeshMemberRoll{}) + Invokes(testing.NewCreateAction(servicemeshmemberrollsResource, c.ns, serviceMeshMemberRoll), &corev1.ServiceMeshMemberRoll{}) if obj == nil { return nil, err } - return obj.(*servicemeshv1.ServiceMeshMemberRoll), err + return obj.(*corev1.ServiceMeshMemberRoll), err } // Update takes the representation of a serviceMeshMemberRoll and updates it. Returns the server's representation of the serviceMeshMemberRoll, and an error, if there is any. -func (c *FakeServiceMeshMemberRolls) Update(ctx context.Context, serviceMeshMemberRoll *servicemeshv1.ServiceMeshMemberRoll, opts v1.UpdateOptions) (result *servicemeshv1.ServiceMeshMemberRoll, err error) { +func (c *FakeServiceMeshMemberRolls) Update(ctx context.Context, serviceMeshMemberRoll *corev1.ServiceMeshMemberRoll, opts v1.UpdateOptions) (result *corev1.ServiceMeshMemberRoll, err error) { obj, err := c.Fake. - Invokes(testing.NewUpdateAction(servicemeshmemberrollsResource, c.ns, serviceMeshMemberRoll), &servicemeshv1.ServiceMeshMemberRoll{}) + Invokes(testing.NewUpdateAction(servicemeshmemberrollsResource, c.ns, serviceMeshMemberRoll), &corev1.ServiceMeshMemberRoll{}) if obj == nil { return nil, err } - return obj.(*servicemeshv1.ServiceMeshMemberRoll), err + return obj.(*corev1.ServiceMeshMemberRoll), err } // UpdateStatus was generated because the type contains a Status member. // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *FakeServiceMeshMemberRolls) UpdateStatus(ctx context.Context, serviceMeshMemberRoll *servicemeshv1.ServiceMeshMemberRoll, opts v1.UpdateOptions) (*servicemeshv1.ServiceMeshMemberRoll, error) { +func (c *FakeServiceMeshMemberRolls) UpdateStatus(ctx context.Context, serviceMeshMemberRoll *corev1.ServiceMeshMemberRoll, opts v1.UpdateOptions) (*corev1.ServiceMeshMemberRoll, error) { obj, err := c.Fake. - Invokes(testing.NewUpdateSubresourceAction(servicemeshmemberrollsResource, "status", c.ns, serviceMeshMemberRoll), &servicemeshv1.ServiceMeshMemberRoll{}) + Invokes(testing.NewUpdateSubresourceAction(servicemeshmemberrollsResource, "status", c.ns, serviceMeshMemberRoll), &corev1.ServiceMeshMemberRoll{}) if obj == nil { return nil, err } - return obj.(*servicemeshv1.ServiceMeshMemberRoll), err + return obj.(*corev1.ServiceMeshMemberRoll), err } // Delete takes name of the serviceMeshMemberRoll and deletes it. Returns an error if one occurs. func (c *FakeServiceMeshMemberRolls) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { _, err := c.Fake. - Invokes(testing.NewDeleteActionWithOptions(servicemeshmemberrollsResource, c.ns, name, opts), &servicemeshv1.ServiceMeshMemberRoll{}) + Invokes(testing.NewDeleteAction(servicemeshmemberrollsResource, c.ns, name), &corev1.ServiceMeshMemberRoll{}) return err } @@ -124,17 +124,17 @@ func (c *FakeServiceMeshMemberRolls) Delete(ctx context.Context, name string, op func (c *FakeServiceMeshMemberRolls) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { action := testing.NewDeleteCollectionAction(servicemeshmemberrollsResource, c.ns, listOpts) - _, err := c.Fake.Invokes(action, &servicemeshv1.ServiceMeshMemberRollList{}) + _, err := c.Fake.Invokes(action, &corev1.ServiceMeshMemberRollList{}) return err } // Patch applies the patch and returns the patched serviceMeshMemberRoll. -func (c *FakeServiceMeshMemberRolls) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *servicemeshv1.ServiceMeshMemberRoll, err error) { +func (c *FakeServiceMeshMemberRolls) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *corev1.ServiceMeshMemberRoll, err error) { obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(servicemeshmemberrollsResource, c.ns, name, pt, data, subresources...), &servicemeshv1.ServiceMeshMemberRoll{}) + Invokes(testing.NewPatchSubresourceAction(servicemeshmemberrollsResource, c.ns, name, pt, data, subresources...), &corev1.ServiceMeshMemberRoll{}) if obj == nil { return nil, err } - return obj.(*servicemeshv1.ServiceMeshMemberRoll), err + return obj.(*corev1.ServiceMeshMemberRoll), err } diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v1/generated_expansion.go b/vendor/maistra.io/api/client/versioned/typed/core/v1/generated_expansion.go new file mode 100644 index 00000000000..83886a80b43 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v1/generated_expansion.go @@ -0,0 +1,25 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +type ServiceMeshControlPlaneExpansion interface{} + +type ServiceMeshExtensionExpansion interface{} + +type ServiceMeshMemberExpansion interface{} + +type ServiceMeshMemberRollExpansion interface{} diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v1/servicemeshcontrolplane.go b/vendor/maistra.io/api/client/versioned/typed/core/v1/servicemeshcontrolplane.go new file mode 100644 index 00000000000..1be32724d25 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v1/servicemeshcontrolplane.go @@ -0,0 +1,193 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + scheme "maistra.io/api/client/versioned/scheme" + v1 "maistra.io/api/core/v1" +) + +// ServiceMeshControlPlanesGetter has a method to return a ServiceMeshControlPlaneInterface. +// A group's client should implement this interface. +type ServiceMeshControlPlanesGetter interface { + ServiceMeshControlPlanes(namespace string) ServiceMeshControlPlaneInterface +} + +// ServiceMeshControlPlaneInterface has methods to work with ServiceMeshControlPlane resources. +type ServiceMeshControlPlaneInterface interface { + Create(ctx context.Context, serviceMeshControlPlane *v1.ServiceMeshControlPlane, opts metav1.CreateOptions) (*v1.ServiceMeshControlPlane, error) + Update(ctx context.Context, serviceMeshControlPlane *v1.ServiceMeshControlPlane, opts metav1.UpdateOptions) (*v1.ServiceMeshControlPlane, error) + UpdateStatus(ctx context.Context, serviceMeshControlPlane *v1.ServiceMeshControlPlane, opts metav1.UpdateOptions) (*v1.ServiceMeshControlPlane, error) + Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error + Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.ServiceMeshControlPlane, error) + List(ctx context.Context, opts metav1.ListOptions) (*v1.ServiceMeshControlPlaneList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.ServiceMeshControlPlane, err error) + ServiceMeshControlPlaneExpansion +} + +// serviceMeshControlPlanes implements ServiceMeshControlPlaneInterface +type serviceMeshControlPlanes struct { + client rest.Interface + ns string +} + +// newServiceMeshControlPlanes returns a ServiceMeshControlPlanes +func newServiceMeshControlPlanes(c *CoreV1Client, namespace string) *serviceMeshControlPlanes { + return &serviceMeshControlPlanes{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the serviceMeshControlPlane, and returns the corresponding serviceMeshControlPlane object, and an error if there is any. +func (c *serviceMeshControlPlanes) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.ServiceMeshControlPlane, err error) { + result = &v1.ServiceMeshControlPlane{} + err = c.client.Get(). + Namespace(c.ns). + Resource("servicemeshcontrolplanes"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ServiceMeshControlPlanes that match those selectors. +func (c *serviceMeshControlPlanes) List(ctx context.Context, opts metav1.ListOptions) (result *v1.ServiceMeshControlPlaneList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.ServiceMeshControlPlaneList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("servicemeshcontrolplanes"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested serviceMeshControlPlanes. +func (c *serviceMeshControlPlanes) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("servicemeshcontrolplanes"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a serviceMeshControlPlane and creates it. Returns the server's representation of the serviceMeshControlPlane, and an error, if there is any. +func (c *serviceMeshControlPlanes) Create(ctx context.Context, serviceMeshControlPlane *v1.ServiceMeshControlPlane, opts metav1.CreateOptions) (result *v1.ServiceMeshControlPlane, err error) { + result = &v1.ServiceMeshControlPlane{} + err = c.client.Post(). + Namespace(c.ns). + Resource("servicemeshcontrolplanes"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serviceMeshControlPlane). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a serviceMeshControlPlane and updates it. Returns the server's representation of the serviceMeshControlPlane, and an error, if there is any. +func (c *serviceMeshControlPlanes) Update(ctx context.Context, serviceMeshControlPlane *v1.ServiceMeshControlPlane, opts metav1.UpdateOptions) (result *v1.ServiceMeshControlPlane, err error) { + result = &v1.ServiceMeshControlPlane{} + err = c.client.Put(). + Namespace(c.ns). + Resource("servicemeshcontrolplanes"). + Name(serviceMeshControlPlane.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serviceMeshControlPlane). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *serviceMeshControlPlanes) UpdateStatus(ctx context.Context, serviceMeshControlPlane *v1.ServiceMeshControlPlane, opts metav1.UpdateOptions) (result *v1.ServiceMeshControlPlane, err error) { + result = &v1.ServiceMeshControlPlane{} + err = c.client.Put(). + Namespace(c.ns). + Resource("servicemeshcontrolplanes"). + Name(serviceMeshControlPlane.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serviceMeshControlPlane). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the serviceMeshControlPlane and deletes it. Returns an error if one occurs. +func (c *serviceMeshControlPlanes) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("servicemeshcontrolplanes"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *serviceMeshControlPlanes) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("servicemeshcontrolplanes"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched serviceMeshControlPlane. +func (c *serviceMeshControlPlanes) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.ServiceMeshControlPlane, err error) { + result = &v1.ServiceMeshControlPlane{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("servicemeshcontrolplanes"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v1/servicemeshextension.go b/vendor/maistra.io/api/client/versioned/typed/core/v1/servicemeshextension.go new file mode 100644 index 00000000000..042dbdac802 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v1/servicemeshextension.go @@ -0,0 +1,193 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + scheme "maistra.io/api/client/versioned/scheme" + v1 "maistra.io/api/core/v1" +) + +// ServiceMeshExtensionsGetter has a method to return a ServiceMeshExtensionInterface. +// A group's client should implement this interface. +type ServiceMeshExtensionsGetter interface { + ServiceMeshExtensions(namespace string) ServiceMeshExtensionInterface +} + +// ServiceMeshExtensionInterface has methods to work with ServiceMeshExtension resources. +type ServiceMeshExtensionInterface interface { + Create(ctx context.Context, serviceMeshExtension *v1.ServiceMeshExtension, opts metav1.CreateOptions) (*v1.ServiceMeshExtension, error) + Update(ctx context.Context, serviceMeshExtension *v1.ServiceMeshExtension, opts metav1.UpdateOptions) (*v1.ServiceMeshExtension, error) + UpdateStatus(ctx context.Context, serviceMeshExtension *v1.ServiceMeshExtension, opts metav1.UpdateOptions) (*v1.ServiceMeshExtension, error) + Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error + Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.ServiceMeshExtension, error) + List(ctx context.Context, opts metav1.ListOptions) (*v1.ServiceMeshExtensionList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.ServiceMeshExtension, err error) + ServiceMeshExtensionExpansion +} + +// serviceMeshExtensions implements ServiceMeshExtensionInterface +type serviceMeshExtensions struct { + client rest.Interface + ns string +} + +// newServiceMeshExtensions returns a ServiceMeshExtensions +func newServiceMeshExtensions(c *CoreV1Client, namespace string) *serviceMeshExtensions { + return &serviceMeshExtensions{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the serviceMeshExtension, and returns the corresponding serviceMeshExtension object, and an error if there is any. +func (c *serviceMeshExtensions) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.ServiceMeshExtension, err error) { + result = &v1.ServiceMeshExtension{} + err = c.client.Get(). + Namespace(c.ns). + Resource("servicemeshextensions"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ServiceMeshExtensions that match those selectors. +func (c *serviceMeshExtensions) List(ctx context.Context, opts metav1.ListOptions) (result *v1.ServiceMeshExtensionList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.ServiceMeshExtensionList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("servicemeshextensions"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested serviceMeshExtensions. +func (c *serviceMeshExtensions) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("servicemeshextensions"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a serviceMeshExtension and creates it. Returns the server's representation of the serviceMeshExtension, and an error, if there is any. +func (c *serviceMeshExtensions) Create(ctx context.Context, serviceMeshExtension *v1.ServiceMeshExtension, opts metav1.CreateOptions) (result *v1.ServiceMeshExtension, err error) { + result = &v1.ServiceMeshExtension{} + err = c.client.Post(). + Namespace(c.ns). + Resource("servicemeshextensions"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serviceMeshExtension). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a serviceMeshExtension and updates it. Returns the server's representation of the serviceMeshExtension, and an error, if there is any. +func (c *serviceMeshExtensions) Update(ctx context.Context, serviceMeshExtension *v1.ServiceMeshExtension, opts metav1.UpdateOptions) (result *v1.ServiceMeshExtension, err error) { + result = &v1.ServiceMeshExtension{} + err = c.client.Put(). + Namespace(c.ns). + Resource("servicemeshextensions"). + Name(serviceMeshExtension.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serviceMeshExtension). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *serviceMeshExtensions) UpdateStatus(ctx context.Context, serviceMeshExtension *v1.ServiceMeshExtension, opts metav1.UpdateOptions) (result *v1.ServiceMeshExtension, err error) { + result = &v1.ServiceMeshExtension{} + err = c.client.Put(). + Namespace(c.ns). + Resource("servicemeshextensions"). + Name(serviceMeshExtension.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serviceMeshExtension). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the serviceMeshExtension and deletes it. Returns an error if one occurs. +func (c *serviceMeshExtensions) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("servicemeshextensions"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *serviceMeshExtensions) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("servicemeshextensions"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched serviceMeshExtension. +func (c *serviceMeshExtensions) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.ServiceMeshExtension, err error) { + result = &v1.ServiceMeshExtension{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("servicemeshextensions"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v1/servicemeshmember.go b/vendor/maistra.io/api/client/versioned/typed/core/v1/servicemeshmember.go new file mode 100644 index 00000000000..3921cae61dd --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v1/servicemeshmember.go @@ -0,0 +1,193 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + scheme "maistra.io/api/client/versioned/scheme" + v1 "maistra.io/api/core/v1" +) + +// ServiceMeshMembersGetter has a method to return a ServiceMeshMemberInterface. +// A group's client should implement this interface. +type ServiceMeshMembersGetter interface { + ServiceMeshMembers(namespace string) ServiceMeshMemberInterface +} + +// ServiceMeshMemberInterface has methods to work with ServiceMeshMember resources. +type ServiceMeshMemberInterface interface { + Create(ctx context.Context, serviceMeshMember *v1.ServiceMeshMember, opts metav1.CreateOptions) (*v1.ServiceMeshMember, error) + Update(ctx context.Context, serviceMeshMember *v1.ServiceMeshMember, opts metav1.UpdateOptions) (*v1.ServiceMeshMember, error) + UpdateStatus(ctx context.Context, serviceMeshMember *v1.ServiceMeshMember, opts metav1.UpdateOptions) (*v1.ServiceMeshMember, error) + Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error + Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.ServiceMeshMember, error) + List(ctx context.Context, opts metav1.ListOptions) (*v1.ServiceMeshMemberList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.ServiceMeshMember, err error) + ServiceMeshMemberExpansion +} + +// serviceMeshMembers implements ServiceMeshMemberInterface +type serviceMeshMembers struct { + client rest.Interface + ns string +} + +// newServiceMeshMembers returns a ServiceMeshMembers +func newServiceMeshMembers(c *CoreV1Client, namespace string) *serviceMeshMembers { + return &serviceMeshMembers{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the serviceMeshMember, and returns the corresponding serviceMeshMember object, and an error if there is any. +func (c *serviceMeshMembers) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.ServiceMeshMember, err error) { + result = &v1.ServiceMeshMember{} + err = c.client.Get(). + Namespace(c.ns). + Resource("servicemeshmembers"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ServiceMeshMembers that match those selectors. +func (c *serviceMeshMembers) List(ctx context.Context, opts metav1.ListOptions) (result *v1.ServiceMeshMemberList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.ServiceMeshMemberList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("servicemeshmembers"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested serviceMeshMembers. +func (c *serviceMeshMembers) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("servicemeshmembers"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a serviceMeshMember and creates it. Returns the server's representation of the serviceMeshMember, and an error, if there is any. +func (c *serviceMeshMembers) Create(ctx context.Context, serviceMeshMember *v1.ServiceMeshMember, opts metav1.CreateOptions) (result *v1.ServiceMeshMember, err error) { + result = &v1.ServiceMeshMember{} + err = c.client.Post(). + Namespace(c.ns). + Resource("servicemeshmembers"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serviceMeshMember). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a serviceMeshMember and updates it. Returns the server's representation of the serviceMeshMember, and an error, if there is any. +func (c *serviceMeshMembers) Update(ctx context.Context, serviceMeshMember *v1.ServiceMeshMember, opts metav1.UpdateOptions) (result *v1.ServiceMeshMember, err error) { + result = &v1.ServiceMeshMember{} + err = c.client.Put(). + Namespace(c.ns). + Resource("servicemeshmembers"). + Name(serviceMeshMember.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serviceMeshMember). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *serviceMeshMembers) UpdateStatus(ctx context.Context, serviceMeshMember *v1.ServiceMeshMember, opts metav1.UpdateOptions) (result *v1.ServiceMeshMember, err error) { + result = &v1.ServiceMeshMember{} + err = c.client.Put(). + Namespace(c.ns). + Resource("servicemeshmembers"). + Name(serviceMeshMember.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serviceMeshMember). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the serviceMeshMember and deletes it. Returns an error if one occurs. +func (c *serviceMeshMembers) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("servicemeshmembers"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *serviceMeshMembers) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("servicemeshmembers"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched serviceMeshMember. +func (c *serviceMeshMembers) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.ServiceMeshMember, err error) { + result = &v1.ServiceMeshMember{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("servicemeshmembers"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/servicemeshmemberroll.go b/vendor/maistra.io/api/client/versioned/typed/core/v1/servicemeshmemberroll.go similarity index 97% rename from pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/servicemeshmemberroll.go rename to vendor/maistra.io/api/client/versioned/typed/core/v1/servicemeshmemberroll.go index f114abc919a..5c3a0ba9f28 100644 --- a/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/servicemeshmemberroll.go +++ b/vendor/maistra.io/api/client/versioned/typed/core/v1/servicemeshmemberroll.go @@ -20,12 +20,12 @@ import ( "context" "time" - v1 "istio.io/istio/pkg/servicemesh/apis/servicemesh/v1" - scheme "istio.io/istio/pkg/servicemesh/client/clientset/versioned/scheme" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" rest "k8s.io/client-go/rest" + scheme "maistra.io/api/client/versioned/scheme" + v1 "maistra.io/api/core/v1" ) // ServiceMeshMemberRollsGetter has a method to return a ServiceMeshMemberRollInterface. @@ -55,7 +55,7 @@ type serviceMeshMemberRolls struct { } // newServiceMeshMemberRolls returns a ServiceMeshMemberRolls -func newServiceMeshMemberRolls(c *MaistraV1Client, namespace string) *serviceMeshMemberRolls { +func newServiceMeshMemberRolls(c *CoreV1Client, namespace string) *serviceMeshMemberRolls { return &serviceMeshMemberRolls{ client: c.RESTClient(), ns: namespace, diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/core_client.go b/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/core_client.go new file mode 100644 index 00000000000..ad0cc820173 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/core_client.go @@ -0,0 +1,87 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + rest "k8s.io/client-go/rest" + "maistra.io/api/client/versioned/scheme" + v1alpha1 "maistra.io/api/core/v1alpha1" +) + +type CoreV1alpha1Interface interface { + RESTClient() rest.Interface + ServiceMeshExtensionsGetter +} + +// CoreV1alpha1Client is used to interact with features provided by the group. +type CoreV1alpha1Client struct { + restClient rest.Interface +} + +func (c *CoreV1alpha1Client) ServiceMeshExtensions(namespace string) ServiceMeshExtensionInterface { + return newServiceMeshExtensions(c, namespace) +} + +// NewForConfig creates a new CoreV1alpha1Client for the given config. +func NewForConfig(c *rest.Config) (*CoreV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &CoreV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new CoreV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *CoreV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new CoreV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *CoreV1alpha1Client { + return &CoreV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *CoreV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/doc.go b/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/doc.go new file mode 100644 index 00000000000..0a35b213437 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/doc.go @@ -0,0 +1,18 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/fake/doc.go b/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/fake/doc.go new file mode 100644 index 00000000000..52886aa70f6 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/fake/doc.go @@ -0,0 +1,18 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/fake/fake_servicemesh_client.go b/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/fake/fake_core_client.go similarity index 73% rename from pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/fake/fake_servicemesh_client.go rename to vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/fake/fake_core_client.go index 4596552de6d..11056c2fffc 100644 --- a/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/fake/fake_servicemesh_client.go +++ b/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/fake/fake_core_client.go @@ -17,22 +17,22 @@ package fake import ( - v1 "istio.io/istio/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1" rest "k8s.io/client-go/rest" testing "k8s.io/client-go/testing" + v1alpha1 "maistra.io/api/client/versioned/typed/core/v1alpha1" ) -type FakeMaistraV1 struct { +type FakeCoreV1alpha1 struct { *testing.Fake } -func (c *FakeMaistraV1) ServiceMeshMemberRolls(namespace string) v1.ServiceMeshMemberRollInterface { - return &FakeServiceMeshMemberRolls{c, namespace} +func (c *FakeCoreV1alpha1) ServiceMeshExtensions(namespace string) v1alpha1.ServiceMeshExtensionInterface { + return &FakeServiceMeshExtensions{c, namespace} } // RESTClient returns a RESTClient that is used to communicate // with API server by this client implementation. -func (c *FakeMaistraV1) RESTClient() rest.Interface { +func (c *FakeCoreV1alpha1) RESTClient() rest.Interface { var ret *rest.RESTClient return ret } diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/fake/fake_servicemeshextension.go b/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/fake/fake_servicemeshextension.go new file mode 100644 index 00000000000..5c2e5e825c5 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/fake/fake_servicemeshextension.go @@ -0,0 +1,140 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1alpha1 "maistra.io/api/core/v1alpha1" +) + +// FakeServiceMeshExtensions implements ServiceMeshExtensionInterface +type FakeServiceMeshExtensions struct { + Fake *FakeCoreV1alpha1 + ns string +} + +var servicemeshextensionsResource = schema.GroupVersionResource{Group: "maistra.io", Version: "v1alpha1", Resource: "servicemeshextensions"} + +var servicemeshextensionsKind = schema.GroupVersionKind{Group: "maistra.io", Version: "v1alpha1", Kind: "ServiceMeshExtension"} + +// Get takes name of the serviceMeshExtension, and returns the corresponding serviceMeshExtension object, and an error if there is any. +func (c *FakeServiceMeshExtensions) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ServiceMeshExtension, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(servicemeshextensionsResource, c.ns, name), &v1alpha1.ServiceMeshExtension{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ServiceMeshExtension), err +} + +// List takes label and field selectors, and returns the list of ServiceMeshExtensions that match those selectors. +func (c *FakeServiceMeshExtensions) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ServiceMeshExtensionList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(servicemeshextensionsResource, servicemeshextensionsKind, c.ns, opts), &v1alpha1.ServiceMeshExtensionList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.ServiceMeshExtensionList{ListMeta: obj.(*v1alpha1.ServiceMeshExtensionList).ListMeta} + for _, item := range obj.(*v1alpha1.ServiceMeshExtensionList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested serviceMeshExtensions. +func (c *FakeServiceMeshExtensions) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(servicemeshextensionsResource, c.ns, opts)) + +} + +// Create takes the representation of a serviceMeshExtension and creates it. Returns the server's representation of the serviceMeshExtension, and an error, if there is any. +func (c *FakeServiceMeshExtensions) Create(ctx context.Context, serviceMeshExtension *v1alpha1.ServiceMeshExtension, opts v1.CreateOptions) (result *v1alpha1.ServiceMeshExtension, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(servicemeshextensionsResource, c.ns, serviceMeshExtension), &v1alpha1.ServiceMeshExtension{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ServiceMeshExtension), err +} + +// Update takes the representation of a serviceMeshExtension and updates it. Returns the server's representation of the serviceMeshExtension, and an error, if there is any. +func (c *FakeServiceMeshExtensions) Update(ctx context.Context, serviceMeshExtension *v1alpha1.ServiceMeshExtension, opts v1.UpdateOptions) (result *v1alpha1.ServiceMeshExtension, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(servicemeshextensionsResource, c.ns, serviceMeshExtension), &v1alpha1.ServiceMeshExtension{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ServiceMeshExtension), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeServiceMeshExtensions) UpdateStatus(ctx context.Context, serviceMeshExtension *v1alpha1.ServiceMeshExtension, opts v1.UpdateOptions) (*v1alpha1.ServiceMeshExtension, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(servicemeshextensionsResource, "status", c.ns, serviceMeshExtension), &v1alpha1.ServiceMeshExtension{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ServiceMeshExtension), err +} + +// Delete takes name of the serviceMeshExtension and deletes it. Returns an error if one occurs. +func (c *FakeServiceMeshExtensions) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(servicemeshextensionsResource, c.ns, name), &v1alpha1.ServiceMeshExtension{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeServiceMeshExtensions) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(servicemeshextensionsResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.ServiceMeshExtensionList{}) + return err +} + +// Patch applies the patch and returns the patched serviceMeshExtension. +func (c *FakeServiceMeshExtensions) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ServiceMeshExtension, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(servicemeshextensionsResource, c.ns, name, pt, data, subresources...), &v1alpha1.ServiceMeshExtension{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.ServiceMeshExtension), err +} diff --git a/pkg/servicemesh/header.go.txt b/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/generated_expansion.go similarity index 83% rename from pkg/servicemesh/header.go.txt rename to vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/generated_expansion.go index 662978327ef..0ac191c6e7d 100644 --- a/pkg/servicemesh/header.go.txt +++ b/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/generated_expansion.go @@ -12,3 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +type ServiceMeshExtensionExpansion interface{} diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/servicemeshextension.go b/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/servicemeshextension.go new file mode 100644 index 00000000000..f39cc6e67e6 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/servicemeshextension.go @@ -0,0 +1,193 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + scheme "maistra.io/api/client/versioned/scheme" + v1alpha1 "maistra.io/api/core/v1alpha1" +) + +// ServiceMeshExtensionsGetter has a method to return a ServiceMeshExtensionInterface. +// A group's client should implement this interface. +type ServiceMeshExtensionsGetter interface { + ServiceMeshExtensions(namespace string) ServiceMeshExtensionInterface +} + +// ServiceMeshExtensionInterface has methods to work with ServiceMeshExtension resources. +type ServiceMeshExtensionInterface interface { + Create(ctx context.Context, serviceMeshExtension *v1alpha1.ServiceMeshExtension, opts v1.CreateOptions) (*v1alpha1.ServiceMeshExtension, error) + Update(ctx context.Context, serviceMeshExtension *v1alpha1.ServiceMeshExtension, opts v1.UpdateOptions) (*v1alpha1.ServiceMeshExtension, error) + UpdateStatus(ctx context.Context, serviceMeshExtension *v1alpha1.ServiceMeshExtension, opts v1.UpdateOptions) (*v1alpha1.ServiceMeshExtension, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ServiceMeshExtension, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ServiceMeshExtensionList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ServiceMeshExtension, err error) + ServiceMeshExtensionExpansion +} + +// serviceMeshExtensions implements ServiceMeshExtensionInterface +type serviceMeshExtensions struct { + client rest.Interface + ns string +} + +// newServiceMeshExtensions returns a ServiceMeshExtensions +func newServiceMeshExtensions(c *CoreV1alpha1Client, namespace string) *serviceMeshExtensions { + return &serviceMeshExtensions{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the serviceMeshExtension, and returns the corresponding serviceMeshExtension object, and an error if there is any. +func (c *serviceMeshExtensions) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ServiceMeshExtension, err error) { + result = &v1alpha1.ServiceMeshExtension{} + err = c.client.Get(). + Namespace(c.ns). + Resource("servicemeshextensions"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ServiceMeshExtensions that match those selectors. +func (c *serviceMeshExtensions) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ServiceMeshExtensionList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.ServiceMeshExtensionList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("servicemeshextensions"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested serviceMeshExtensions. +func (c *serviceMeshExtensions) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("servicemeshextensions"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a serviceMeshExtension and creates it. Returns the server's representation of the serviceMeshExtension, and an error, if there is any. +func (c *serviceMeshExtensions) Create(ctx context.Context, serviceMeshExtension *v1alpha1.ServiceMeshExtension, opts v1.CreateOptions) (result *v1alpha1.ServiceMeshExtension, err error) { + result = &v1alpha1.ServiceMeshExtension{} + err = c.client.Post(). + Namespace(c.ns). + Resource("servicemeshextensions"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serviceMeshExtension). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a serviceMeshExtension and updates it. Returns the server's representation of the serviceMeshExtension, and an error, if there is any. +func (c *serviceMeshExtensions) Update(ctx context.Context, serviceMeshExtension *v1alpha1.ServiceMeshExtension, opts v1.UpdateOptions) (result *v1alpha1.ServiceMeshExtension, err error) { + result = &v1alpha1.ServiceMeshExtension{} + err = c.client.Put(). + Namespace(c.ns). + Resource("servicemeshextensions"). + Name(serviceMeshExtension.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serviceMeshExtension). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *serviceMeshExtensions) UpdateStatus(ctx context.Context, serviceMeshExtension *v1alpha1.ServiceMeshExtension, opts v1.UpdateOptions) (result *v1alpha1.ServiceMeshExtension, err error) { + result = &v1alpha1.ServiceMeshExtension{} + err = c.client.Put(). + Namespace(c.ns). + Resource("servicemeshextensions"). + Name(serviceMeshExtension.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serviceMeshExtension). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the serviceMeshExtension and deletes it. Returns an error if one occurs. +func (c *serviceMeshExtensions) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("servicemeshextensions"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *serviceMeshExtensions) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("servicemeshextensions"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched serviceMeshExtension. +func (c *serviceMeshExtensions) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ServiceMeshExtension, err error) { + result = &v1alpha1.ServiceMeshExtension{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("servicemeshextensions"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v2/core_client.go b/vendor/maistra.io/api/client/versioned/typed/core/v2/core_client.go new file mode 100644 index 00000000000..efc2e51df3a --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v2/core_client.go @@ -0,0 +1,87 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v2 + +import ( + rest "k8s.io/client-go/rest" + "maistra.io/api/client/versioned/scheme" + v2 "maistra.io/api/core/v2" +) + +type CoreV2Interface interface { + RESTClient() rest.Interface + ServiceMeshControlPlanesGetter +} + +// CoreV2Client is used to interact with features provided by the group. +type CoreV2Client struct { + restClient rest.Interface +} + +func (c *CoreV2Client) ServiceMeshControlPlanes(namespace string) ServiceMeshControlPlaneInterface { + return newServiceMeshControlPlanes(c, namespace) +} + +// NewForConfig creates a new CoreV2Client for the given config. +func NewForConfig(c *rest.Config) (*CoreV2Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &CoreV2Client{client}, nil +} + +// NewForConfigOrDie creates a new CoreV2Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *CoreV2Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new CoreV2Client for the given RESTClient. +func New(c rest.Interface) *CoreV2Client { + return &CoreV2Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v2.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *CoreV2Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v2/doc.go b/vendor/maistra.io/api/client/versioned/typed/core/v2/doc.go new file mode 100644 index 00000000000..a3b66f3ce49 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v2/doc.go @@ -0,0 +1,18 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v2 diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v2/fake/doc.go b/vendor/maistra.io/api/client/versioned/typed/core/v2/fake/doc.go new file mode 100644 index 00000000000..52886aa70f6 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v2/fake/doc.go @@ -0,0 +1,18 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v2/fake/fake_core_client.go b/vendor/maistra.io/api/client/versioned/typed/core/v2/fake/fake_core_client.go new file mode 100644 index 00000000000..331c932a56d --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v2/fake/fake_core_client.go @@ -0,0 +1,38 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" + v2 "maistra.io/api/client/versioned/typed/core/v2" +) + +type FakeCoreV2 struct { + *testing.Fake +} + +func (c *FakeCoreV2) ServiceMeshControlPlanes(namespace string) v2.ServiceMeshControlPlaneInterface { + return &FakeServiceMeshControlPlanes{c, namespace} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeCoreV2) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v2/fake/fake_servicemeshcontrolplane.go b/vendor/maistra.io/api/client/versioned/typed/core/v2/fake/fake_servicemeshcontrolplane.go new file mode 100644 index 00000000000..e1433d50ef8 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v2/fake/fake_servicemeshcontrolplane.go @@ -0,0 +1,140 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v2 "maistra.io/api/core/v2" +) + +// FakeServiceMeshControlPlanes implements ServiceMeshControlPlaneInterface +type FakeServiceMeshControlPlanes struct { + Fake *FakeCoreV2 + ns string +} + +var servicemeshcontrolplanesResource = schema.GroupVersionResource{Group: "maistra.io", Version: "v2", Resource: "servicemeshcontrolplanes"} + +var servicemeshcontrolplanesKind = schema.GroupVersionKind{Group: "maistra.io", Version: "v2", Kind: "ServiceMeshControlPlane"} + +// Get takes name of the serviceMeshControlPlane, and returns the corresponding serviceMeshControlPlane object, and an error if there is any. +func (c *FakeServiceMeshControlPlanes) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2.ServiceMeshControlPlane, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(servicemeshcontrolplanesResource, c.ns, name), &v2.ServiceMeshControlPlane{}) + + if obj == nil { + return nil, err + } + return obj.(*v2.ServiceMeshControlPlane), err +} + +// List takes label and field selectors, and returns the list of ServiceMeshControlPlanes that match those selectors. +func (c *FakeServiceMeshControlPlanes) List(ctx context.Context, opts v1.ListOptions) (result *v2.ServiceMeshControlPlaneList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(servicemeshcontrolplanesResource, servicemeshcontrolplanesKind, c.ns, opts), &v2.ServiceMeshControlPlaneList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v2.ServiceMeshControlPlaneList{ListMeta: obj.(*v2.ServiceMeshControlPlaneList).ListMeta} + for _, item := range obj.(*v2.ServiceMeshControlPlaneList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested serviceMeshControlPlanes. +func (c *FakeServiceMeshControlPlanes) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(servicemeshcontrolplanesResource, c.ns, opts)) + +} + +// Create takes the representation of a serviceMeshControlPlane and creates it. Returns the server's representation of the serviceMeshControlPlane, and an error, if there is any. +func (c *FakeServiceMeshControlPlanes) Create(ctx context.Context, serviceMeshControlPlane *v2.ServiceMeshControlPlane, opts v1.CreateOptions) (result *v2.ServiceMeshControlPlane, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(servicemeshcontrolplanesResource, c.ns, serviceMeshControlPlane), &v2.ServiceMeshControlPlane{}) + + if obj == nil { + return nil, err + } + return obj.(*v2.ServiceMeshControlPlane), err +} + +// Update takes the representation of a serviceMeshControlPlane and updates it. Returns the server's representation of the serviceMeshControlPlane, and an error, if there is any. +func (c *FakeServiceMeshControlPlanes) Update(ctx context.Context, serviceMeshControlPlane *v2.ServiceMeshControlPlane, opts v1.UpdateOptions) (result *v2.ServiceMeshControlPlane, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(servicemeshcontrolplanesResource, c.ns, serviceMeshControlPlane), &v2.ServiceMeshControlPlane{}) + + if obj == nil { + return nil, err + } + return obj.(*v2.ServiceMeshControlPlane), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeServiceMeshControlPlanes) UpdateStatus(ctx context.Context, serviceMeshControlPlane *v2.ServiceMeshControlPlane, opts v1.UpdateOptions) (*v2.ServiceMeshControlPlane, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(servicemeshcontrolplanesResource, "status", c.ns, serviceMeshControlPlane), &v2.ServiceMeshControlPlane{}) + + if obj == nil { + return nil, err + } + return obj.(*v2.ServiceMeshControlPlane), err +} + +// Delete takes name of the serviceMeshControlPlane and deletes it. Returns an error if one occurs. +func (c *FakeServiceMeshControlPlanes) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(servicemeshcontrolplanesResource, c.ns, name), &v2.ServiceMeshControlPlane{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeServiceMeshControlPlanes) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(servicemeshcontrolplanesResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v2.ServiceMeshControlPlaneList{}) + return err +} + +// Patch applies the patch and returns the patched serviceMeshControlPlane. +func (c *FakeServiceMeshControlPlanes) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ServiceMeshControlPlane, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(servicemeshcontrolplanesResource, c.ns, name, pt, data, subresources...), &v2.ServiceMeshControlPlane{}) + + if obj == nil { + return nil, err + } + return obj.(*v2.ServiceMeshControlPlane), err +} diff --git a/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/generated_expansion.go b/vendor/maistra.io/api/client/versioned/typed/core/v2/generated_expansion.go similarity index 91% rename from pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/generated_expansion.go rename to vendor/maistra.io/api/client/versioned/typed/core/v2/generated_expansion.go index 9e3d02202fa..d0a5e1590b1 100644 --- a/pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/generated_expansion.go +++ b/vendor/maistra.io/api/client/versioned/typed/core/v2/generated_expansion.go @@ -14,6 +14,6 @@ // Code generated by client-gen. DO NOT EDIT. -package v1 +package v2 -type ServiceMeshMemberRollExpansion interface{} +type ServiceMeshControlPlaneExpansion interface{} diff --git a/vendor/maistra.io/api/client/versioned/typed/core/v2/servicemeshcontrolplane.go b/vendor/maistra.io/api/client/versioned/typed/core/v2/servicemeshcontrolplane.go new file mode 100644 index 00000000000..4407eaf9bea --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/core/v2/servicemeshcontrolplane.go @@ -0,0 +1,193 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v2 + +import ( + "context" + "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + scheme "maistra.io/api/client/versioned/scheme" + v2 "maistra.io/api/core/v2" +) + +// ServiceMeshControlPlanesGetter has a method to return a ServiceMeshControlPlaneInterface. +// A group's client should implement this interface. +type ServiceMeshControlPlanesGetter interface { + ServiceMeshControlPlanes(namespace string) ServiceMeshControlPlaneInterface +} + +// ServiceMeshControlPlaneInterface has methods to work with ServiceMeshControlPlane resources. +type ServiceMeshControlPlaneInterface interface { + Create(ctx context.Context, serviceMeshControlPlane *v2.ServiceMeshControlPlane, opts v1.CreateOptions) (*v2.ServiceMeshControlPlane, error) + Update(ctx context.Context, serviceMeshControlPlane *v2.ServiceMeshControlPlane, opts v1.UpdateOptions) (*v2.ServiceMeshControlPlane, error) + UpdateStatus(ctx context.Context, serviceMeshControlPlane *v2.ServiceMeshControlPlane, opts v1.UpdateOptions) (*v2.ServiceMeshControlPlane, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v2.ServiceMeshControlPlane, error) + List(ctx context.Context, opts v1.ListOptions) (*v2.ServiceMeshControlPlaneList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ServiceMeshControlPlane, err error) + ServiceMeshControlPlaneExpansion +} + +// serviceMeshControlPlanes implements ServiceMeshControlPlaneInterface +type serviceMeshControlPlanes struct { + client rest.Interface + ns string +} + +// newServiceMeshControlPlanes returns a ServiceMeshControlPlanes +func newServiceMeshControlPlanes(c *CoreV2Client, namespace string) *serviceMeshControlPlanes { + return &serviceMeshControlPlanes{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the serviceMeshControlPlane, and returns the corresponding serviceMeshControlPlane object, and an error if there is any. +func (c *serviceMeshControlPlanes) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2.ServiceMeshControlPlane, err error) { + result = &v2.ServiceMeshControlPlane{} + err = c.client.Get(). + Namespace(c.ns). + Resource("servicemeshcontrolplanes"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ServiceMeshControlPlanes that match those selectors. +func (c *serviceMeshControlPlanes) List(ctx context.Context, opts v1.ListOptions) (result *v2.ServiceMeshControlPlaneList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v2.ServiceMeshControlPlaneList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("servicemeshcontrolplanes"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested serviceMeshControlPlanes. +func (c *serviceMeshControlPlanes) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("servicemeshcontrolplanes"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a serviceMeshControlPlane and creates it. Returns the server's representation of the serviceMeshControlPlane, and an error, if there is any. +func (c *serviceMeshControlPlanes) Create(ctx context.Context, serviceMeshControlPlane *v2.ServiceMeshControlPlane, opts v1.CreateOptions) (result *v2.ServiceMeshControlPlane, err error) { + result = &v2.ServiceMeshControlPlane{} + err = c.client.Post(). + Namespace(c.ns). + Resource("servicemeshcontrolplanes"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serviceMeshControlPlane). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a serviceMeshControlPlane and updates it. Returns the server's representation of the serviceMeshControlPlane, and an error, if there is any. +func (c *serviceMeshControlPlanes) Update(ctx context.Context, serviceMeshControlPlane *v2.ServiceMeshControlPlane, opts v1.UpdateOptions) (result *v2.ServiceMeshControlPlane, err error) { + result = &v2.ServiceMeshControlPlane{} + err = c.client.Put(). + Namespace(c.ns). + Resource("servicemeshcontrolplanes"). + Name(serviceMeshControlPlane.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serviceMeshControlPlane). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *serviceMeshControlPlanes) UpdateStatus(ctx context.Context, serviceMeshControlPlane *v2.ServiceMeshControlPlane, opts v1.UpdateOptions) (result *v2.ServiceMeshControlPlane, err error) { + result = &v2.ServiceMeshControlPlane{} + err = c.client.Put(). + Namespace(c.ns). + Resource("servicemeshcontrolplanes"). + Name(serviceMeshControlPlane.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serviceMeshControlPlane). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the serviceMeshControlPlane and deletes it. Returns an error if one occurs. +func (c *serviceMeshControlPlanes) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("servicemeshcontrolplanes"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *serviceMeshControlPlanes) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("servicemeshcontrolplanes"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched serviceMeshControlPlane. +func (c *serviceMeshControlPlanes) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2.ServiceMeshControlPlane, err error) { + result = &v2.ServiceMeshControlPlane{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("servicemeshcontrolplanes"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/vendor/maistra.io/api/client/versioned/typed/federation/v1/doc.go b/vendor/maistra.io/api/client/versioned/typed/federation/v1/doc.go new file mode 100644 index 00000000000..4f64357b1f0 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/federation/v1/doc.go @@ -0,0 +1,18 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1 diff --git a/vendor/maistra.io/api/client/versioned/typed/federation/v1/exportedserviceset.go b/vendor/maistra.io/api/client/versioned/typed/federation/v1/exportedserviceset.go new file mode 100644 index 00000000000..1cfe4352e55 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/federation/v1/exportedserviceset.go @@ -0,0 +1,193 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + scheme "maistra.io/api/client/versioned/scheme" + v1 "maistra.io/api/federation/v1" +) + +// ExportedServiceSetsGetter has a method to return a ExportedServiceSetInterface. +// A group's client should implement this interface. +type ExportedServiceSetsGetter interface { + ExportedServiceSets(namespace string) ExportedServiceSetInterface +} + +// ExportedServiceSetInterface has methods to work with ExportedServiceSet resources. +type ExportedServiceSetInterface interface { + Create(ctx context.Context, exportedServiceSet *v1.ExportedServiceSet, opts metav1.CreateOptions) (*v1.ExportedServiceSet, error) + Update(ctx context.Context, exportedServiceSet *v1.ExportedServiceSet, opts metav1.UpdateOptions) (*v1.ExportedServiceSet, error) + UpdateStatus(ctx context.Context, exportedServiceSet *v1.ExportedServiceSet, opts metav1.UpdateOptions) (*v1.ExportedServiceSet, error) + Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error + Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.ExportedServiceSet, error) + List(ctx context.Context, opts metav1.ListOptions) (*v1.ExportedServiceSetList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.ExportedServiceSet, err error) + ExportedServiceSetExpansion +} + +// exportedServiceSets implements ExportedServiceSetInterface +type exportedServiceSets struct { + client rest.Interface + ns string +} + +// newExportedServiceSets returns a ExportedServiceSets +func newExportedServiceSets(c *FederationV1Client, namespace string) *exportedServiceSets { + return &exportedServiceSets{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the exportedServiceSet, and returns the corresponding exportedServiceSet object, and an error if there is any. +func (c *exportedServiceSets) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.ExportedServiceSet, err error) { + result = &v1.ExportedServiceSet{} + err = c.client.Get(). + Namespace(c.ns). + Resource("exportedservicesets"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ExportedServiceSets that match those selectors. +func (c *exportedServiceSets) List(ctx context.Context, opts metav1.ListOptions) (result *v1.ExportedServiceSetList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.ExportedServiceSetList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("exportedservicesets"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested exportedServiceSets. +func (c *exportedServiceSets) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("exportedservicesets"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a exportedServiceSet and creates it. Returns the server's representation of the exportedServiceSet, and an error, if there is any. +func (c *exportedServiceSets) Create(ctx context.Context, exportedServiceSet *v1.ExportedServiceSet, opts metav1.CreateOptions) (result *v1.ExportedServiceSet, err error) { + result = &v1.ExportedServiceSet{} + err = c.client.Post(). + Namespace(c.ns). + Resource("exportedservicesets"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(exportedServiceSet). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a exportedServiceSet and updates it. Returns the server's representation of the exportedServiceSet, and an error, if there is any. +func (c *exportedServiceSets) Update(ctx context.Context, exportedServiceSet *v1.ExportedServiceSet, opts metav1.UpdateOptions) (result *v1.ExportedServiceSet, err error) { + result = &v1.ExportedServiceSet{} + err = c.client.Put(). + Namespace(c.ns). + Resource("exportedservicesets"). + Name(exportedServiceSet.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(exportedServiceSet). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *exportedServiceSets) UpdateStatus(ctx context.Context, exportedServiceSet *v1.ExportedServiceSet, opts metav1.UpdateOptions) (result *v1.ExportedServiceSet, err error) { + result = &v1.ExportedServiceSet{} + err = c.client.Put(). + Namespace(c.ns). + Resource("exportedservicesets"). + Name(exportedServiceSet.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(exportedServiceSet). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the exportedServiceSet and deletes it. Returns an error if one occurs. +func (c *exportedServiceSets) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("exportedservicesets"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *exportedServiceSets) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("exportedservicesets"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched exportedServiceSet. +func (c *exportedServiceSets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.ExportedServiceSet, err error) { + result = &v1.ExportedServiceSet{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("exportedservicesets"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/doc.go b/vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/doc.go new file mode 100644 index 00000000000..52886aa70f6 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/doc.go @@ -0,0 +1,18 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/fake_exportedserviceset.go b/vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/fake_exportedserviceset.go new file mode 100644 index 00000000000..88d530bb6a0 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/fake_exportedserviceset.go @@ -0,0 +1,140 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + federationv1 "maistra.io/api/federation/v1" +) + +// FakeExportedServiceSets implements ExportedServiceSetInterface +type FakeExportedServiceSets struct { + Fake *FakeFederationV1 + ns string +} + +var exportedservicesetsResource = schema.GroupVersionResource{Group: "federation.maistra.io", Version: "v1", Resource: "exportedservicesets"} + +var exportedservicesetsKind = schema.GroupVersionKind{Group: "federation.maistra.io", Version: "v1", Kind: "ExportedServiceSet"} + +// Get takes name of the exportedServiceSet, and returns the corresponding exportedServiceSet object, and an error if there is any. +func (c *FakeExportedServiceSets) Get(ctx context.Context, name string, options v1.GetOptions) (result *federationv1.ExportedServiceSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(exportedservicesetsResource, c.ns, name), &federationv1.ExportedServiceSet{}) + + if obj == nil { + return nil, err + } + return obj.(*federationv1.ExportedServiceSet), err +} + +// List takes label and field selectors, and returns the list of ExportedServiceSets that match those selectors. +func (c *FakeExportedServiceSets) List(ctx context.Context, opts v1.ListOptions) (result *federationv1.ExportedServiceSetList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(exportedservicesetsResource, exportedservicesetsKind, c.ns, opts), &federationv1.ExportedServiceSetList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &federationv1.ExportedServiceSetList{ListMeta: obj.(*federationv1.ExportedServiceSetList).ListMeta} + for _, item := range obj.(*federationv1.ExportedServiceSetList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested exportedServiceSets. +func (c *FakeExportedServiceSets) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(exportedservicesetsResource, c.ns, opts)) + +} + +// Create takes the representation of a exportedServiceSet and creates it. Returns the server's representation of the exportedServiceSet, and an error, if there is any. +func (c *FakeExportedServiceSets) Create(ctx context.Context, exportedServiceSet *federationv1.ExportedServiceSet, opts v1.CreateOptions) (result *federationv1.ExportedServiceSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(exportedservicesetsResource, c.ns, exportedServiceSet), &federationv1.ExportedServiceSet{}) + + if obj == nil { + return nil, err + } + return obj.(*federationv1.ExportedServiceSet), err +} + +// Update takes the representation of a exportedServiceSet and updates it. Returns the server's representation of the exportedServiceSet, and an error, if there is any. +func (c *FakeExportedServiceSets) Update(ctx context.Context, exportedServiceSet *federationv1.ExportedServiceSet, opts v1.UpdateOptions) (result *federationv1.ExportedServiceSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(exportedservicesetsResource, c.ns, exportedServiceSet), &federationv1.ExportedServiceSet{}) + + if obj == nil { + return nil, err + } + return obj.(*federationv1.ExportedServiceSet), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeExportedServiceSets) UpdateStatus(ctx context.Context, exportedServiceSet *federationv1.ExportedServiceSet, opts v1.UpdateOptions) (*federationv1.ExportedServiceSet, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(exportedservicesetsResource, "status", c.ns, exportedServiceSet), &federationv1.ExportedServiceSet{}) + + if obj == nil { + return nil, err + } + return obj.(*federationv1.ExportedServiceSet), err +} + +// Delete takes name of the exportedServiceSet and deletes it. Returns an error if one occurs. +func (c *FakeExportedServiceSets) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(exportedservicesetsResource, c.ns, name), &federationv1.ExportedServiceSet{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeExportedServiceSets) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(exportedservicesetsResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &federationv1.ExportedServiceSetList{}) + return err +} + +// Patch applies the patch and returns the patched exportedServiceSet. +func (c *FakeExportedServiceSets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *federationv1.ExportedServiceSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(exportedservicesetsResource, c.ns, name, pt, data, subresources...), &federationv1.ExportedServiceSet{}) + + if obj == nil { + return nil, err + } + return obj.(*federationv1.ExportedServiceSet), err +} diff --git a/vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/fake_federation_client.go b/vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/fake_federation_client.go new file mode 100644 index 00000000000..a7401b4cdb9 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/fake_federation_client.go @@ -0,0 +1,46 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" + v1 "maistra.io/api/client/versioned/typed/federation/v1" +) + +type FakeFederationV1 struct { + *testing.Fake +} + +func (c *FakeFederationV1) ExportedServiceSets(namespace string) v1.ExportedServiceSetInterface { + return &FakeExportedServiceSets{c, namespace} +} + +func (c *FakeFederationV1) ImportedServiceSets(namespace string) v1.ImportedServiceSetInterface { + return &FakeImportedServiceSets{c, namespace} +} + +func (c *FakeFederationV1) ServiceMeshPeers(namespace string) v1.ServiceMeshPeerInterface { + return &FakeServiceMeshPeers{c, namespace} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeFederationV1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/fake_importedserviceset.go b/vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/fake_importedserviceset.go new file mode 100644 index 00000000000..73937b4cad2 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/fake_importedserviceset.go @@ -0,0 +1,140 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + federationv1 "maistra.io/api/federation/v1" +) + +// FakeImportedServiceSets implements ImportedServiceSetInterface +type FakeImportedServiceSets struct { + Fake *FakeFederationV1 + ns string +} + +var importedservicesetsResource = schema.GroupVersionResource{Group: "federation.maistra.io", Version: "v1", Resource: "importedservicesets"} + +var importedservicesetsKind = schema.GroupVersionKind{Group: "federation.maistra.io", Version: "v1", Kind: "ImportedServiceSet"} + +// Get takes name of the importedServiceSet, and returns the corresponding importedServiceSet object, and an error if there is any. +func (c *FakeImportedServiceSets) Get(ctx context.Context, name string, options v1.GetOptions) (result *federationv1.ImportedServiceSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(importedservicesetsResource, c.ns, name), &federationv1.ImportedServiceSet{}) + + if obj == nil { + return nil, err + } + return obj.(*federationv1.ImportedServiceSet), err +} + +// List takes label and field selectors, and returns the list of ImportedServiceSets that match those selectors. +func (c *FakeImportedServiceSets) List(ctx context.Context, opts v1.ListOptions) (result *federationv1.ImportedServiceSetList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(importedservicesetsResource, importedservicesetsKind, c.ns, opts), &federationv1.ImportedServiceSetList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &federationv1.ImportedServiceSetList{ListMeta: obj.(*federationv1.ImportedServiceSetList).ListMeta} + for _, item := range obj.(*federationv1.ImportedServiceSetList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested importedServiceSets. +func (c *FakeImportedServiceSets) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(importedservicesetsResource, c.ns, opts)) + +} + +// Create takes the representation of a importedServiceSet and creates it. Returns the server's representation of the importedServiceSet, and an error, if there is any. +func (c *FakeImportedServiceSets) Create(ctx context.Context, importedServiceSet *federationv1.ImportedServiceSet, opts v1.CreateOptions) (result *federationv1.ImportedServiceSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(importedservicesetsResource, c.ns, importedServiceSet), &federationv1.ImportedServiceSet{}) + + if obj == nil { + return nil, err + } + return obj.(*federationv1.ImportedServiceSet), err +} + +// Update takes the representation of a importedServiceSet and updates it. Returns the server's representation of the importedServiceSet, and an error, if there is any. +func (c *FakeImportedServiceSets) Update(ctx context.Context, importedServiceSet *federationv1.ImportedServiceSet, opts v1.UpdateOptions) (result *federationv1.ImportedServiceSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(importedservicesetsResource, c.ns, importedServiceSet), &federationv1.ImportedServiceSet{}) + + if obj == nil { + return nil, err + } + return obj.(*federationv1.ImportedServiceSet), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeImportedServiceSets) UpdateStatus(ctx context.Context, importedServiceSet *federationv1.ImportedServiceSet, opts v1.UpdateOptions) (*federationv1.ImportedServiceSet, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(importedservicesetsResource, "status", c.ns, importedServiceSet), &federationv1.ImportedServiceSet{}) + + if obj == nil { + return nil, err + } + return obj.(*federationv1.ImportedServiceSet), err +} + +// Delete takes name of the importedServiceSet and deletes it. Returns an error if one occurs. +func (c *FakeImportedServiceSets) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(importedservicesetsResource, c.ns, name), &federationv1.ImportedServiceSet{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeImportedServiceSets) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(importedservicesetsResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &federationv1.ImportedServiceSetList{}) + return err +} + +// Patch applies the patch and returns the patched importedServiceSet. +func (c *FakeImportedServiceSets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *federationv1.ImportedServiceSet, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(importedservicesetsResource, c.ns, name, pt, data, subresources...), &federationv1.ImportedServiceSet{}) + + if obj == nil { + return nil, err + } + return obj.(*federationv1.ImportedServiceSet), err +} diff --git a/vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/fake_servicemeshpeer.go b/vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/fake_servicemeshpeer.go new file mode 100644 index 00000000000..992244b64d2 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/fake_servicemeshpeer.go @@ -0,0 +1,140 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + federationv1 "maistra.io/api/federation/v1" +) + +// FakeServiceMeshPeers implements ServiceMeshPeerInterface +type FakeServiceMeshPeers struct { + Fake *FakeFederationV1 + ns string +} + +var servicemeshpeersResource = schema.GroupVersionResource{Group: "federation.maistra.io", Version: "v1", Resource: "servicemeshpeers"} + +var servicemeshpeersKind = schema.GroupVersionKind{Group: "federation.maistra.io", Version: "v1", Kind: "ServiceMeshPeer"} + +// Get takes name of the serviceMeshPeer, and returns the corresponding serviceMeshPeer object, and an error if there is any. +func (c *FakeServiceMeshPeers) Get(ctx context.Context, name string, options v1.GetOptions) (result *federationv1.ServiceMeshPeer, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(servicemeshpeersResource, c.ns, name), &federationv1.ServiceMeshPeer{}) + + if obj == nil { + return nil, err + } + return obj.(*federationv1.ServiceMeshPeer), err +} + +// List takes label and field selectors, and returns the list of ServiceMeshPeers that match those selectors. +func (c *FakeServiceMeshPeers) List(ctx context.Context, opts v1.ListOptions) (result *federationv1.ServiceMeshPeerList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(servicemeshpeersResource, servicemeshpeersKind, c.ns, opts), &federationv1.ServiceMeshPeerList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &federationv1.ServiceMeshPeerList{ListMeta: obj.(*federationv1.ServiceMeshPeerList).ListMeta} + for _, item := range obj.(*federationv1.ServiceMeshPeerList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested serviceMeshPeers. +func (c *FakeServiceMeshPeers) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(servicemeshpeersResource, c.ns, opts)) + +} + +// Create takes the representation of a serviceMeshPeer and creates it. Returns the server's representation of the serviceMeshPeer, and an error, if there is any. +func (c *FakeServiceMeshPeers) Create(ctx context.Context, serviceMeshPeer *federationv1.ServiceMeshPeer, opts v1.CreateOptions) (result *federationv1.ServiceMeshPeer, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(servicemeshpeersResource, c.ns, serviceMeshPeer), &federationv1.ServiceMeshPeer{}) + + if obj == nil { + return nil, err + } + return obj.(*federationv1.ServiceMeshPeer), err +} + +// Update takes the representation of a serviceMeshPeer and updates it. Returns the server's representation of the serviceMeshPeer, and an error, if there is any. +func (c *FakeServiceMeshPeers) Update(ctx context.Context, serviceMeshPeer *federationv1.ServiceMeshPeer, opts v1.UpdateOptions) (result *federationv1.ServiceMeshPeer, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(servicemeshpeersResource, c.ns, serviceMeshPeer), &federationv1.ServiceMeshPeer{}) + + if obj == nil { + return nil, err + } + return obj.(*federationv1.ServiceMeshPeer), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeServiceMeshPeers) UpdateStatus(ctx context.Context, serviceMeshPeer *federationv1.ServiceMeshPeer, opts v1.UpdateOptions) (*federationv1.ServiceMeshPeer, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(servicemeshpeersResource, "status", c.ns, serviceMeshPeer), &federationv1.ServiceMeshPeer{}) + + if obj == nil { + return nil, err + } + return obj.(*federationv1.ServiceMeshPeer), err +} + +// Delete takes name of the serviceMeshPeer and deletes it. Returns an error if one occurs. +func (c *FakeServiceMeshPeers) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(servicemeshpeersResource, c.ns, name), &federationv1.ServiceMeshPeer{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeServiceMeshPeers) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(servicemeshpeersResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &federationv1.ServiceMeshPeerList{}) + return err +} + +// Patch applies the patch and returns the patched serviceMeshPeer. +func (c *FakeServiceMeshPeers) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *federationv1.ServiceMeshPeer, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(servicemeshpeersResource, c.ns, name, pt, data, subresources...), &federationv1.ServiceMeshPeer{}) + + if obj == nil { + return nil, err + } + return obj.(*federationv1.ServiceMeshPeer), err +} diff --git a/vendor/maistra.io/api/client/versioned/typed/federation/v1/federation_client.go b/vendor/maistra.io/api/client/versioned/typed/federation/v1/federation_client.go new file mode 100644 index 00000000000..2db522854d2 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/federation/v1/federation_client.go @@ -0,0 +1,97 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + rest "k8s.io/client-go/rest" + "maistra.io/api/client/versioned/scheme" + v1 "maistra.io/api/federation/v1" +) + +type FederationV1Interface interface { + RESTClient() rest.Interface + ExportedServiceSetsGetter + ImportedServiceSetsGetter + ServiceMeshPeersGetter +} + +// FederationV1Client is used to interact with features provided by the federation.maistra.io group. +type FederationV1Client struct { + restClient rest.Interface +} + +func (c *FederationV1Client) ExportedServiceSets(namespace string) ExportedServiceSetInterface { + return newExportedServiceSets(c, namespace) +} + +func (c *FederationV1Client) ImportedServiceSets(namespace string) ImportedServiceSetInterface { + return newImportedServiceSets(c, namespace) +} + +func (c *FederationV1Client) ServiceMeshPeers(namespace string) ServiceMeshPeerInterface { + return newServiceMeshPeers(c, namespace) +} + +// NewForConfig creates a new FederationV1Client for the given config. +func NewForConfig(c *rest.Config) (*FederationV1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &FederationV1Client{client}, nil +} + +// NewForConfigOrDie creates a new FederationV1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *FederationV1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new FederationV1Client for the given RESTClient. +func New(c rest.Interface) *FederationV1Client { + return &FederationV1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FederationV1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/vendor/maistra.io/api/client/versioned/typed/federation/v1/generated_expansion.go b/vendor/maistra.io/api/client/versioned/typed/federation/v1/generated_expansion.go new file mode 100644 index 00000000000..1536004a0ee --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/federation/v1/generated_expansion.go @@ -0,0 +1,23 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +type ExportedServiceSetExpansion interface{} + +type ImportedServiceSetExpansion interface{} + +type ServiceMeshPeerExpansion interface{} diff --git a/vendor/maistra.io/api/client/versioned/typed/federation/v1/importedserviceset.go b/vendor/maistra.io/api/client/versioned/typed/federation/v1/importedserviceset.go new file mode 100644 index 00000000000..81150afa220 --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/federation/v1/importedserviceset.go @@ -0,0 +1,193 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + scheme "maistra.io/api/client/versioned/scheme" + v1 "maistra.io/api/federation/v1" +) + +// ImportedServiceSetsGetter has a method to return a ImportedServiceSetInterface. +// A group's client should implement this interface. +type ImportedServiceSetsGetter interface { + ImportedServiceSets(namespace string) ImportedServiceSetInterface +} + +// ImportedServiceSetInterface has methods to work with ImportedServiceSet resources. +type ImportedServiceSetInterface interface { + Create(ctx context.Context, importedServiceSet *v1.ImportedServiceSet, opts metav1.CreateOptions) (*v1.ImportedServiceSet, error) + Update(ctx context.Context, importedServiceSet *v1.ImportedServiceSet, opts metav1.UpdateOptions) (*v1.ImportedServiceSet, error) + UpdateStatus(ctx context.Context, importedServiceSet *v1.ImportedServiceSet, opts metav1.UpdateOptions) (*v1.ImportedServiceSet, error) + Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error + Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.ImportedServiceSet, error) + List(ctx context.Context, opts metav1.ListOptions) (*v1.ImportedServiceSetList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.ImportedServiceSet, err error) + ImportedServiceSetExpansion +} + +// importedServiceSets implements ImportedServiceSetInterface +type importedServiceSets struct { + client rest.Interface + ns string +} + +// newImportedServiceSets returns a ImportedServiceSets +func newImportedServiceSets(c *FederationV1Client, namespace string) *importedServiceSets { + return &importedServiceSets{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the importedServiceSet, and returns the corresponding importedServiceSet object, and an error if there is any. +func (c *importedServiceSets) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.ImportedServiceSet, err error) { + result = &v1.ImportedServiceSet{} + err = c.client.Get(). + Namespace(c.ns). + Resource("importedservicesets"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ImportedServiceSets that match those selectors. +func (c *importedServiceSets) List(ctx context.Context, opts metav1.ListOptions) (result *v1.ImportedServiceSetList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.ImportedServiceSetList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("importedservicesets"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested importedServiceSets. +func (c *importedServiceSets) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("importedservicesets"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a importedServiceSet and creates it. Returns the server's representation of the importedServiceSet, and an error, if there is any. +func (c *importedServiceSets) Create(ctx context.Context, importedServiceSet *v1.ImportedServiceSet, opts metav1.CreateOptions) (result *v1.ImportedServiceSet, err error) { + result = &v1.ImportedServiceSet{} + err = c.client.Post(). + Namespace(c.ns). + Resource("importedservicesets"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(importedServiceSet). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a importedServiceSet and updates it. Returns the server's representation of the importedServiceSet, and an error, if there is any. +func (c *importedServiceSets) Update(ctx context.Context, importedServiceSet *v1.ImportedServiceSet, opts metav1.UpdateOptions) (result *v1.ImportedServiceSet, err error) { + result = &v1.ImportedServiceSet{} + err = c.client.Put(). + Namespace(c.ns). + Resource("importedservicesets"). + Name(importedServiceSet.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(importedServiceSet). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *importedServiceSets) UpdateStatus(ctx context.Context, importedServiceSet *v1.ImportedServiceSet, opts metav1.UpdateOptions) (result *v1.ImportedServiceSet, err error) { + result = &v1.ImportedServiceSet{} + err = c.client.Put(). + Namespace(c.ns). + Resource("importedservicesets"). + Name(importedServiceSet.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(importedServiceSet). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the importedServiceSet and deletes it. Returns an error if one occurs. +func (c *importedServiceSets) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("importedservicesets"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *importedServiceSets) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("importedservicesets"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched importedServiceSet. +func (c *importedServiceSets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.ImportedServiceSet, err error) { + result = &v1.ImportedServiceSet{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("importedservicesets"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/vendor/maistra.io/api/client/versioned/typed/federation/v1/servicemeshpeer.go b/vendor/maistra.io/api/client/versioned/typed/federation/v1/servicemeshpeer.go new file mode 100644 index 00000000000..2c01776505a --- /dev/null +++ b/vendor/maistra.io/api/client/versioned/typed/federation/v1/servicemeshpeer.go @@ -0,0 +1,193 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" + scheme "maistra.io/api/client/versioned/scheme" + v1 "maistra.io/api/federation/v1" +) + +// ServiceMeshPeersGetter has a method to return a ServiceMeshPeerInterface. +// A group's client should implement this interface. +type ServiceMeshPeersGetter interface { + ServiceMeshPeers(namespace string) ServiceMeshPeerInterface +} + +// ServiceMeshPeerInterface has methods to work with ServiceMeshPeer resources. +type ServiceMeshPeerInterface interface { + Create(ctx context.Context, serviceMeshPeer *v1.ServiceMeshPeer, opts metav1.CreateOptions) (*v1.ServiceMeshPeer, error) + Update(ctx context.Context, serviceMeshPeer *v1.ServiceMeshPeer, opts metav1.UpdateOptions) (*v1.ServiceMeshPeer, error) + UpdateStatus(ctx context.Context, serviceMeshPeer *v1.ServiceMeshPeer, opts metav1.UpdateOptions) (*v1.ServiceMeshPeer, error) + Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error + Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.ServiceMeshPeer, error) + List(ctx context.Context, opts metav1.ListOptions) (*v1.ServiceMeshPeerList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.ServiceMeshPeer, err error) + ServiceMeshPeerExpansion +} + +// serviceMeshPeers implements ServiceMeshPeerInterface +type serviceMeshPeers struct { + client rest.Interface + ns string +} + +// newServiceMeshPeers returns a ServiceMeshPeers +func newServiceMeshPeers(c *FederationV1Client, namespace string) *serviceMeshPeers { + return &serviceMeshPeers{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the serviceMeshPeer, and returns the corresponding serviceMeshPeer object, and an error if there is any. +func (c *serviceMeshPeers) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.ServiceMeshPeer, err error) { + result = &v1.ServiceMeshPeer{} + err = c.client.Get(). + Namespace(c.ns). + Resource("servicemeshpeers"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ServiceMeshPeers that match those selectors. +func (c *serviceMeshPeers) List(ctx context.Context, opts metav1.ListOptions) (result *v1.ServiceMeshPeerList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.ServiceMeshPeerList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("servicemeshpeers"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested serviceMeshPeers. +func (c *serviceMeshPeers) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("servicemeshpeers"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a serviceMeshPeer and creates it. Returns the server's representation of the serviceMeshPeer, and an error, if there is any. +func (c *serviceMeshPeers) Create(ctx context.Context, serviceMeshPeer *v1.ServiceMeshPeer, opts metav1.CreateOptions) (result *v1.ServiceMeshPeer, err error) { + result = &v1.ServiceMeshPeer{} + err = c.client.Post(). + Namespace(c.ns). + Resource("servicemeshpeers"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serviceMeshPeer). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a serviceMeshPeer and updates it. Returns the server's representation of the serviceMeshPeer, and an error, if there is any. +func (c *serviceMeshPeers) Update(ctx context.Context, serviceMeshPeer *v1.ServiceMeshPeer, opts metav1.UpdateOptions) (result *v1.ServiceMeshPeer, err error) { + result = &v1.ServiceMeshPeer{} + err = c.client.Put(). + Namespace(c.ns). + Resource("servicemeshpeers"). + Name(serviceMeshPeer.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serviceMeshPeer). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *serviceMeshPeers) UpdateStatus(ctx context.Context, serviceMeshPeer *v1.ServiceMeshPeer, opts metav1.UpdateOptions) (result *v1.ServiceMeshPeer, err error) { + result = &v1.ServiceMeshPeer{} + err = c.client.Put(). + Namespace(c.ns). + Resource("servicemeshpeers"). + Name(serviceMeshPeer.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(serviceMeshPeer). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the serviceMeshPeer and deletes it. Returns an error if one occurs. +func (c *serviceMeshPeers) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("servicemeshpeers"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *serviceMeshPeers) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("servicemeshpeers"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched serviceMeshPeer. +func (c *serviceMeshPeers) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.ServiceMeshPeer, err error) { + result = &v1.ServiceMeshPeer{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("servicemeshpeers"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/vendor/maistra.io/api/client/xnsinformer/core/interface.go b/vendor/maistra.io/api/client/xnsinformer/core/interface.go new file mode 100644 index 00000000000..a5b8af573ae --- /dev/null +++ b/vendor/maistra.io/api/client/xnsinformer/core/interface.go @@ -0,0 +1,61 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by xns-informer-gen. DO NOT EDIT. + +package core + +import ( + informers "github.com/maistra/xns-informer/pkg/informers" + v1 "maistra.io/api/client/xnsinformer/core/v1" + v1alpha1 "maistra.io/api/client/xnsinformer/core/v1alpha1" + v2 "maistra.io/api/client/xnsinformer/core/v2" + internalinterfaces "maistra.io/api/client/xnsinformer/internalinterfaces" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1 provides access to shared informers for resources in V1. + V1() v1.Interface + // V1alpha1 provides access to shared informers for resources in V1alpha1. + V1alpha1() v1alpha1.Interface + // V2 provides access to shared informers for resources in V2. + V2() v2.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespaces informers.NamespaceSet + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespaces informers.NamespaceSet, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespaces: namespaces, tweakListOptions: tweakListOptions} +} + +// V1 returns a new v1.Interface. +func (g *group) V1() v1.Interface { + return v1.New(g.factory, g.namespaces, g.tweakListOptions) +} + +// V1alpha1 returns a new v1alpha1.Interface. +func (g *group) V1alpha1() v1alpha1.Interface { + return v1alpha1.New(g.factory, g.namespaces, g.tweakListOptions) +} + +// V2 returns a new v2.Interface. +func (g *group) V2() v2.Interface { + return v2.New(g.factory, g.namespaces, g.tweakListOptions) +} diff --git a/vendor/maistra.io/api/client/xnsinformer/core/v1/interface.go b/vendor/maistra.io/api/client/xnsinformer/core/v1/interface.go new file mode 100644 index 00000000000..b04f0b54e73 --- /dev/null +++ b/vendor/maistra.io/api/client/xnsinformer/core/v1/interface.go @@ -0,0 +1,65 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by xns-informer-gen. DO NOT EDIT. + +package v1 + +import ( + informers "github.com/maistra/xns-informer/pkg/informers" + internalinterfaces "maistra.io/api/client/xnsinformer/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // ServiceMeshControlPlanes returns a ServiceMeshControlPlaneInformer. + ServiceMeshControlPlanes() ServiceMeshControlPlaneInformer + // ServiceMeshExtensions returns a ServiceMeshExtensionInformer. + ServiceMeshExtensions() ServiceMeshExtensionInformer + // ServiceMeshMembers returns a ServiceMeshMemberInformer. + ServiceMeshMembers() ServiceMeshMemberInformer + // ServiceMeshMemberRolls returns a ServiceMeshMemberRollInformer. + ServiceMeshMemberRolls() ServiceMeshMemberRollInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespaces informers.NamespaceSet + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespaces informers.NamespaceSet, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespaces: namespaces, tweakListOptions: tweakListOptions} +} + +// ServiceMeshControlPlanes returns a ServiceMeshControlPlaneInformer. +func (v *version) ServiceMeshControlPlanes() ServiceMeshControlPlaneInformer { + return &serviceMeshControlPlaneInformer{factory: v.factory, namespaces: v.namespaces, tweakListOptions: v.tweakListOptions} +} + +// ServiceMeshExtensions returns a ServiceMeshExtensionInformer. +func (v *version) ServiceMeshExtensions() ServiceMeshExtensionInformer { + return &serviceMeshExtensionInformer{factory: v.factory, namespaces: v.namespaces, tweakListOptions: v.tweakListOptions} +} + +// ServiceMeshMembers returns a ServiceMeshMemberInformer. +func (v *version) ServiceMeshMembers() ServiceMeshMemberInformer { + return &serviceMeshMemberInformer{factory: v.factory, namespaces: v.namespaces, tweakListOptions: v.tweakListOptions} +} + +// ServiceMeshMemberRolls returns a ServiceMeshMemberRollInformer. +func (v *version) ServiceMeshMemberRolls() ServiceMeshMemberRollInformer { + return &serviceMeshMemberRollInformer{factory: v.factory, namespaces: v.namespaces, tweakListOptions: v.tweakListOptions} +} diff --git a/vendor/maistra.io/api/client/xnsinformer/core/v1/servicemeshcontrolplane.go b/vendor/maistra.io/api/client/xnsinformer/core/v1/servicemeshcontrolplane.go new file mode 100644 index 00000000000..7c68b4e3ac4 --- /dev/null +++ b/vendor/maistra.io/api/client/xnsinformer/core/v1/servicemeshcontrolplane.go @@ -0,0 +1,93 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by xns-informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + informers "github.com/maistra/xns-informer/pkg/informers" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/client/listers/core/v1" + versioned "maistra.io/api/client/versioned" + internalinterfaces "maistra.io/api/client/xnsinformer/internalinterfaces" + corev1 "maistra.io/api/core/v1" +) + +// ServiceMeshControlPlaneInformer provides access to a shared informer and lister for +// ServiceMeshControlPlanes. +type ServiceMeshControlPlaneInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.ServiceMeshControlPlaneLister +} + +type serviceMeshControlPlaneInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespaces informers.NamespaceSet +} + +// NewServiceMeshControlPlaneInformer constructs a new informer for ServiceMeshControlPlane type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewServiceMeshControlPlaneInformer(client versioned.Interface, namespaces informers.NamespaceSet, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredServiceMeshControlPlaneInformer(client, namespaces, resyncPeriod, indexers, nil) +} + +// NewFilteredServiceMeshControlPlaneInformer constructs a new informer for ServiceMeshControlPlane type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredServiceMeshControlPlaneInformer(client versioned.Interface, namespaces informers.NamespaceSet, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + newInformer := func(namespace string) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV1().ServiceMeshControlPlanes(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV1().ServiceMeshControlPlanes(namespace).Watch(context.TODO(), options) + }, + }, + &corev1.ServiceMeshControlPlane{}, + resyncPeriod, + indexers, + ) + } + + return informers.NewMultiNamespaceInformer(namespaces, resyncPeriod, newInformer) +} + +func (f *serviceMeshControlPlaneInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredServiceMeshControlPlaneInformer(client, f.namespaces, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *serviceMeshControlPlaneInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&corev1.ServiceMeshControlPlane{}, f.defaultInformer) +} + +func (f *serviceMeshControlPlaneInformer) Lister() v1.ServiceMeshControlPlaneLister { + return v1.NewServiceMeshControlPlaneLister(f.Informer().GetIndexer()) +} diff --git a/vendor/maistra.io/api/client/xnsinformer/core/v1/servicemeshextension.go b/vendor/maistra.io/api/client/xnsinformer/core/v1/servicemeshextension.go new file mode 100644 index 00000000000..b1aaf7fcfff --- /dev/null +++ b/vendor/maistra.io/api/client/xnsinformer/core/v1/servicemeshextension.go @@ -0,0 +1,93 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by xns-informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + informers "github.com/maistra/xns-informer/pkg/informers" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/client/listers/core/v1" + versioned "maistra.io/api/client/versioned" + internalinterfaces "maistra.io/api/client/xnsinformer/internalinterfaces" + corev1 "maistra.io/api/core/v1" +) + +// ServiceMeshExtensionInformer provides access to a shared informer and lister for +// ServiceMeshExtensions. +type ServiceMeshExtensionInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.ServiceMeshExtensionLister +} + +type serviceMeshExtensionInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespaces informers.NamespaceSet +} + +// NewServiceMeshExtensionInformer constructs a new informer for ServiceMeshExtension type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewServiceMeshExtensionInformer(client versioned.Interface, namespaces informers.NamespaceSet, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredServiceMeshExtensionInformer(client, namespaces, resyncPeriod, indexers, nil) +} + +// NewFilteredServiceMeshExtensionInformer constructs a new informer for ServiceMeshExtension type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredServiceMeshExtensionInformer(client versioned.Interface, namespaces informers.NamespaceSet, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + newInformer := func(namespace string) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV1().ServiceMeshExtensions(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV1().ServiceMeshExtensions(namespace).Watch(context.TODO(), options) + }, + }, + &corev1.ServiceMeshExtension{}, + resyncPeriod, + indexers, + ) + } + + return informers.NewMultiNamespaceInformer(namespaces, resyncPeriod, newInformer) +} + +func (f *serviceMeshExtensionInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredServiceMeshExtensionInformer(client, f.namespaces, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *serviceMeshExtensionInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&corev1.ServiceMeshExtension{}, f.defaultInformer) +} + +func (f *serviceMeshExtensionInformer) Lister() v1.ServiceMeshExtensionLister { + return v1.NewServiceMeshExtensionLister(f.Informer().GetIndexer()) +} diff --git a/vendor/maistra.io/api/client/xnsinformer/core/v1/servicemeshmember.go b/vendor/maistra.io/api/client/xnsinformer/core/v1/servicemeshmember.go new file mode 100644 index 00000000000..a343ea28ea5 --- /dev/null +++ b/vendor/maistra.io/api/client/xnsinformer/core/v1/servicemeshmember.go @@ -0,0 +1,93 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by xns-informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + informers "github.com/maistra/xns-informer/pkg/informers" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/client/listers/core/v1" + versioned "maistra.io/api/client/versioned" + internalinterfaces "maistra.io/api/client/xnsinformer/internalinterfaces" + corev1 "maistra.io/api/core/v1" +) + +// ServiceMeshMemberInformer provides access to a shared informer and lister for +// ServiceMeshMembers. +type ServiceMeshMemberInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.ServiceMeshMemberLister +} + +type serviceMeshMemberInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespaces informers.NamespaceSet +} + +// NewServiceMeshMemberInformer constructs a new informer for ServiceMeshMember type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewServiceMeshMemberInformer(client versioned.Interface, namespaces informers.NamespaceSet, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredServiceMeshMemberInformer(client, namespaces, resyncPeriod, indexers, nil) +} + +// NewFilteredServiceMeshMemberInformer constructs a new informer for ServiceMeshMember type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredServiceMeshMemberInformer(client versioned.Interface, namespaces informers.NamespaceSet, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + newInformer := func(namespace string) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV1().ServiceMeshMembers(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV1().ServiceMeshMembers(namespace).Watch(context.TODO(), options) + }, + }, + &corev1.ServiceMeshMember{}, + resyncPeriod, + indexers, + ) + } + + return informers.NewMultiNamespaceInformer(namespaces, resyncPeriod, newInformer) +} + +func (f *serviceMeshMemberInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredServiceMeshMemberInformer(client, f.namespaces, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *serviceMeshMemberInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&corev1.ServiceMeshMember{}, f.defaultInformer) +} + +func (f *serviceMeshMemberInformer) Lister() v1.ServiceMeshMemberLister { + return v1.NewServiceMeshMemberLister(f.Informer().GetIndexer()) +} diff --git a/vendor/maistra.io/api/client/xnsinformer/core/v1/servicemeshmemberroll.go b/vendor/maistra.io/api/client/xnsinformer/core/v1/servicemeshmemberroll.go new file mode 100644 index 00000000000..6de95e1e183 --- /dev/null +++ b/vendor/maistra.io/api/client/xnsinformer/core/v1/servicemeshmemberroll.go @@ -0,0 +1,93 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by xns-informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + informers "github.com/maistra/xns-informer/pkg/informers" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/client/listers/core/v1" + versioned "maistra.io/api/client/versioned" + internalinterfaces "maistra.io/api/client/xnsinformer/internalinterfaces" + corev1 "maistra.io/api/core/v1" +) + +// ServiceMeshMemberRollInformer provides access to a shared informer and lister for +// ServiceMeshMemberRolls. +type ServiceMeshMemberRollInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.ServiceMeshMemberRollLister +} + +type serviceMeshMemberRollInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespaces informers.NamespaceSet +} + +// NewServiceMeshMemberRollInformer constructs a new informer for ServiceMeshMemberRoll type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewServiceMeshMemberRollInformer(client versioned.Interface, namespaces informers.NamespaceSet, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredServiceMeshMemberRollInformer(client, namespaces, resyncPeriod, indexers, nil) +} + +// NewFilteredServiceMeshMemberRollInformer constructs a new informer for ServiceMeshMemberRoll type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredServiceMeshMemberRollInformer(client versioned.Interface, namespaces informers.NamespaceSet, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + newInformer := func(namespace string) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV1().ServiceMeshMemberRolls(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV1().ServiceMeshMemberRolls(namespace).Watch(context.TODO(), options) + }, + }, + &corev1.ServiceMeshMemberRoll{}, + resyncPeriod, + indexers, + ) + } + + return informers.NewMultiNamespaceInformer(namespaces, resyncPeriod, newInformer) +} + +func (f *serviceMeshMemberRollInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredServiceMeshMemberRollInformer(client, f.namespaces, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *serviceMeshMemberRollInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&corev1.ServiceMeshMemberRoll{}, f.defaultInformer) +} + +func (f *serviceMeshMemberRollInformer) Lister() v1.ServiceMeshMemberRollLister { + return v1.NewServiceMeshMemberRollLister(f.Informer().GetIndexer()) +} diff --git a/vendor/maistra.io/api/client/xnsinformer/core/v1alpha1/interface.go b/vendor/maistra.io/api/client/xnsinformer/core/v1alpha1/interface.go new file mode 100644 index 00000000000..c13ecd36c2b --- /dev/null +++ b/vendor/maistra.io/api/client/xnsinformer/core/v1alpha1/interface.go @@ -0,0 +1,44 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by xns-informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + informers "github.com/maistra/xns-informer/pkg/informers" + internalinterfaces "maistra.io/api/client/xnsinformer/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // ServiceMeshExtensions returns a ServiceMeshExtensionInformer. + ServiceMeshExtensions() ServiceMeshExtensionInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespaces informers.NamespaceSet + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespaces informers.NamespaceSet, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespaces: namespaces, tweakListOptions: tweakListOptions} +} + +// ServiceMeshExtensions returns a ServiceMeshExtensionInformer. +func (v *version) ServiceMeshExtensions() ServiceMeshExtensionInformer { + return &serviceMeshExtensionInformer{factory: v.factory, namespaces: v.namespaces, tweakListOptions: v.tweakListOptions} +} diff --git a/vendor/maistra.io/api/client/xnsinformer/core/v1alpha1/servicemeshextension.go b/vendor/maistra.io/api/client/xnsinformer/core/v1alpha1/servicemeshextension.go new file mode 100644 index 00000000000..d394b2a0879 --- /dev/null +++ b/vendor/maistra.io/api/client/xnsinformer/core/v1alpha1/servicemeshextension.go @@ -0,0 +1,93 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by xns-informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + informers "github.com/maistra/xns-informer/pkg/informers" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + v1alpha1 "maistra.io/api/client/listers/core/v1alpha1" + versioned "maistra.io/api/client/versioned" + internalinterfaces "maistra.io/api/client/xnsinformer/internalinterfaces" + corev1alpha1 "maistra.io/api/core/v1alpha1" +) + +// ServiceMeshExtensionInformer provides access to a shared informer and lister for +// ServiceMeshExtensions. +type ServiceMeshExtensionInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.ServiceMeshExtensionLister +} + +type serviceMeshExtensionInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespaces informers.NamespaceSet +} + +// NewServiceMeshExtensionInformer constructs a new informer for ServiceMeshExtension type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewServiceMeshExtensionInformer(client versioned.Interface, namespaces informers.NamespaceSet, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredServiceMeshExtensionInformer(client, namespaces, resyncPeriod, indexers, nil) +} + +// NewFilteredServiceMeshExtensionInformer constructs a new informer for ServiceMeshExtension type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredServiceMeshExtensionInformer(client versioned.Interface, namespaces informers.NamespaceSet, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + newInformer := func(namespace string) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV1alpha1().ServiceMeshExtensions(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV1alpha1().ServiceMeshExtensions(namespace).Watch(context.TODO(), options) + }, + }, + &corev1alpha1.ServiceMeshExtension{}, + resyncPeriod, + indexers, + ) + } + + return informers.NewMultiNamespaceInformer(namespaces, resyncPeriod, newInformer) +} + +func (f *serviceMeshExtensionInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredServiceMeshExtensionInformer(client, f.namespaces, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *serviceMeshExtensionInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&corev1alpha1.ServiceMeshExtension{}, f.defaultInformer) +} + +func (f *serviceMeshExtensionInformer) Lister() v1alpha1.ServiceMeshExtensionLister { + return v1alpha1.NewServiceMeshExtensionLister(f.Informer().GetIndexer()) +} diff --git a/vendor/maistra.io/api/client/xnsinformer/core/v2/interface.go b/vendor/maistra.io/api/client/xnsinformer/core/v2/interface.go new file mode 100644 index 00000000000..feda36d7101 --- /dev/null +++ b/vendor/maistra.io/api/client/xnsinformer/core/v2/interface.go @@ -0,0 +1,44 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by xns-informer-gen. DO NOT EDIT. + +package v2 + +import ( + informers "github.com/maistra/xns-informer/pkg/informers" + internalinterfaces "maistra.io/api/client/xnsinformer/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // ServiceMeshControlPlanes returns a ServiceMeshControlPlaneInformer. + ServiceMeshControlPlanes() ServiceMeshControlPlaneInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespaces informers.NamespaceSet + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespaces informers.NamespaceSet, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespaces: namespaces, tweakListOptions: tweakListOptions} +} + +// ServiceMeshControlPlanes returns a ServiceMeshControlPlaneInformer. +func (v *version) ServiceMeshControlPlanes() ServiceMeshControlPlaneInformer { + return &serviceMeshControlPlaneInformer{factory: v.factory, namespaces: v.namespaces, tweakListOptions: v.tweakListOptions} +} diff --git a/vendor/maistra.io/api/client/xnsinformer/core/v2/servicemeshcontrolplane.go b/vendor/maistra.io/api/client/xnsinformer/core/v2/servicemeshcontrolplane.go new file mode 100644 index 00000000000..6450d716e68 --- /dev/null +++ b/vendor/maistra.io/api/client/xnsinformer/core/v2/servicemeshcontrolplane.go @@ -0,0 +1,93 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by xns-informer-gen. DO NOT EDIT. + +package v2 + +import ( + "context" + time "time" + + informers "github.com/maistra/xns-informer/pkg/informers" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + v2 "maistra.io/api/client/listers/core/v2" + versioned "maistra.io/api/client/versioned" + internalinterfaces "maistra.io/api/client/xnsinformer/internalinterfaces" + corev2 "maistra.io/api/core/v2" +) + +// ServiceMeshControlPlaneInformer provides access to a shared informer and lister for +// ServiceMeshControlPlanes. +type ServiceMeshControlPlaneInformer interface { + Informer() cache.SharedIndexInformer + Lister() v2.ServiceMeshControlPlaneLister +} + +type serviceMeshControlPlaneInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespaces informers.NamespaceSet +} + +// NewServiceMeshControlPlaneInformer constructs a new informer for ServiceMeshControlPlane type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewServiceMeshControlPlaneInformer(client versioned.Interface, namespaces informers.NamespaceSet, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredServiceMeshControlPlaneInformer(client, namespaces, resyncPeriod, indexers, nil) +} + +// NewFilteredServiceMeshControlPlaneInformer constructs a new informer for ServiceMeshControlPlane type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredServiceMeshControlPlaneInformer(client versioned.Interface, namespaces informers.NamespaceSet, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + newInformer := func(namespace string) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV2().ServiceMeshControlPlanes(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CoreV2().ServiceMeshControlPlanes(namespace).Watch(context.TODO(), options) + }, + }, + &corev2.ServiceMeshControlPlane{}, + resyncPeriod, + indexers, + ) + } + + return informers.NewMultiNamespaceInformer(namespaces, resyncPeriod, newInformer) +} + +func (f *serviceMeshControlPlaneInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredServiceMeshControlPlaneInformer(client, f.namespaces, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *serviceMeshControlPlaneInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&corev2.ServiceMeshControlPlane{}, f.defaultInformer) +} + +func (f *serviceMeshControlPlaneInformer) Lister() v2.ServiceMeshControlPlaneLister { + return v2.NewServiceMeshControlPlaneLister(f.Informer().GetIndexer()) +} diff --git a/vendor/maistra.io/api/client/xnsinformer/factory.go b/vendor/maistra.io/api/client/xnsinformer/factory.go new file mode 100644 index 00000000000..04640d2b622 --- /dev/null +++ b/vendor/maistra.io/api/client/xnsinformer/factory.go @@ -0,0 +1,186 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by xns-informer-gen. DO NOT EDIT. + +package xnsinformer + +import ( + reflect "reflect" + sync "sync" + time "time" + + informers "github.com/maistra/xns-informer/pkg/informers" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" + versioned "maistra.io/api/client/versioned" + core "maistra.io/api/client/xnsinformer/core" + federation "maistra.io/api/client/xnsinformer/federation" + internalinterfaces "maistra.io/api/client/xnsinformer/internalinterfaces" +) + +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + +type sharedInformerFactory struct { + client versioned.Interface + namespaces informers.NamespaceSet + tweakListOptions internalinterfaces.TweakListOptionsFunc + lock sync.Mutex + defaultResync time.Duration + customResync map[reflect.Type]time.Duration + + informers map[reflect.Type]cache.SharedIndexInformer + // startedInformers is used for tracking which informers have been started. + // This allows Start() to be called multiple times safely. + startedInformers map[reflect.Type]bool +} + +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespaces limits the SharedInformerFactory to the specified namespaces. +func WithNamespaces(namespaces ...string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.SetNamespaces(namespaces...) + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. +func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ + client: client, + namespaces: informers.NewNamespaceSet(v1.NamespaceAll), + defaultResync: defaultResync, + informers: make(map[reflect.Type]cache.SharedIndexInformer), + startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) + } + + return factory +} + +// SetNamespaces updates the set of namespaces for all current and future informers. +func (f *sharedInformerFactory) SetNamespaces(namespaces ...string) { + f.lock.Lock() + defer f.lock.Unlock() + + f.namespaces.SetNamespaces(namespaces...) +} + +// Start initializes all requested informers. +func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { + f.lock.Lock() + defer f.lock.Unlock() + + for informerType, informer := range f.informers { + if !f.startedInformers[informerType] { + go informer.Run(stopCh) + f.startedInformers[informerType] = true + } + } +} + +// WaitForCacheSync waits for all started informers' cache were synced. +func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + informers := func() map[reflect.Type]cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informers := map[reflect.Type]cache.SharedIndexInformer{} + for informerType, informer := range f.informers { + if f.startedInformers[informerType] { + informers[informerType] = informer + } + } + return informers + }() + + res := map[reflect.Type]bool{} + for informType, informer := range informers { + res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) + } + return res +} + +// InternalInformerFor returns the SharedIndexInformer for obj using an internal +// client. +func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(obj) + informer, exists := f.informers[informerType] + if exists { + return informer + } + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) + f.informers[informerType] = informer + + return informer +} + +// SharedInformerFactory provides shared informers for resources in all known +// API group versions. +type SharedInformerFactory interface { + internalinterfaces.SharedInformerFactory + SetNamespaces(namespaces ...string) + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + + Core() core.Interface + Federation() federation.Interface +} + +func (f *sharedInformerFactory) Core() core.Interface { + return core.New(f, f.namespaces, f.tweakListOptions) +} + +func (f *sharedInformerFactory) Federation() federation.Interface { + return federation.New(f, f.namespaces, f.tweakListOptions) +} diff --git a/vendor/maistra.io/api/client/xnsinformer/federation/interface.go b/vendor/maistra.io/api/client/xnsinformer/federation/interface.go new file mode 100644 index 00000000000..3e09b623365 --- /dev/null +++ b/vendor/maistra.io/api/client/xnsinformer/federation/interface.go @@ -0,0 +1,45 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by xns-informer-gen. DO NOT EDIT. + +package federation + +import ( + informers "github.com/maistra/xns-informer/pkg/informers" + v1 "maistra.io/api/client/xnsinformer/federation/v1" + internalinterfaces "maistra.io/api/client/xnsinformer/internalinterfaces" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1 provides access to shared informers for resources in V1. + V1() v1.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespaces informers.NamespaceSet + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespaces informers.NamespaceSet, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespaces: namespaces, tweakListOptions: tweakListOptions} +} + +// V1 returns a new v1.Interface. +func (g *group) V1() v1.Interface { + return v1.New(g.factory, g.namespaces, g.tweakListOptions) +} diff --git a/vendor/maistra.io/api/client/xnsinformer/federation/v1/exportedserviceset.go b/vendor/maistra.io/api/client/xnsinformer/federation/v1/exportedserviceset.go new file mode 100644 index 00000000000..95ce43d020a --- /dev/null +++ b/vendor/maistra.io/api/client/xnsinformer/federation/v1/exportedserviceset.go @@ -0,0 +1,93 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by xns-informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + informers "github.com/maistra/xns-informer/pkg/informers" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/client/listers/federation/v1" + versioned "maistra.io/api/client/versioned" + internalinterfaces "maistra.io/api/client/xnsinformer/internalinterfaces" + federationv1 "maistra.io/api/federation/v1" +) + +// ExportedServiceSetInformer provides access to a shared informer and lister for +// ExportedServiceSets. +type ExportedServiceSetInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.ExportedServiceSetLister +} + +type exportedServiceSetInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespaces informers.NamespaceSet +} + +// NewExportedServiceSetInformer constructs a new informer for ExportedServiceSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewExportedServiceSetInformer(client versioned.Interface, namespaces informers.NamespaceSet, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredExportedServiceSetInformer(client, namespaces, resyncPeriod, indexers, nil) +} + +// NewFilteredExportedServiceSetInformer constructs a new informer for ExportedServiceSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredExportedServiceSetInformer(client versioned.Interface, namespaces informers.NamespaceSet, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + newInformer := func(namespace string) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.FederationV1().ExportedServiceSets(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.FederationV1().ExportedServiceSets(namespace).Watch(context.TODO(), options) + }, + }, + &federationv1.ExportedServiceSet{}, + resyncPeriod, + indexers, + ) + } + + return informers.NewMultiNamespaceInformer(namespaces, resyncPeriod, newInformer) +} + +func (f *exportedServiceSetInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredExportedServiceSetInformer(client, f.namespaces, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *exportedServiceSetInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&federationv1.ExportedServiceSet{}, f.defaultInformer) +} + +func (f *exportedServiceSetInformer) Lister() v1.ExportedServiceSetLister { + return v1.NewExportedServiceSetLister(f.Informer().GetIndexer()) +} diff --git a/vendor/maistra.io/api/client/xnsinformer/federation/v1/importedserviceset.go b/vendor/maistra.io/api/client/xnsinformer/federation/v1/importedserviceset.go new file mode 100644 index 00000000000..d0d777d1dca --- /dev/null +++ b/vendor/maistra.io/api/client/xnsinformer/federation/v1/importedserviceset.go @@ -0,0 +1,93 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by xns-informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + informers "github.com/maistra/xns-informer/pkg/informers" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/client/listers/federation/v1" + versioned "maistra.io/api/client/versioned" + internalinterfaces "maistra.io/api/client/xnsinformer/internalinterfaces" + federationv1 "maistra.io/api/federation/v1" +) + +// ImportedServiceSetInformer provides access to a shared informer and lister for +// ImportedServiceSets. +type ImportedServiceSetInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.ImportedServiceSetLister +} + +type importedServiceSetInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespaces informers.NamespaceSet +} + +// NewImportedServiceSetInformer constructs a new informer for ImportedServiceSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewImportedServiceSetInformer(client versioned.Interface, namespaces informers.NamespaceSet, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredImportedServiceSetInformer(client, namespaces, resyncPeriod, indexers, nil) +} + +// NewFilteredImportedServiceSetInformer constructs a new informer for ImportedServiceSet type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredImportedServiceSetInformer(client versioned.Interface, namespaces informers.NamespaceSet, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + newInformer := func(namespace string) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.FederationV1().ImportedServiceSets(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.FederationV1().ImportedServiceSets(namespace).Watch(context.TODO(), options) + }, + }, + &federationv1.ImportedServiceSet{}, + resyncPeriod, + indexers, + ) + } + + return informers.NewMultiNamespaceInformer(namespaces, resyncPeriod, newInformer) +} + +func (f *importedServiceSetInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredImportedServiceSetInformer(client, f.namespaces, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *importedServiceSetInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&federationv1.ImportedServiceSet{}, f.defaultInformer) +} + +func (f *importedServiceSetInformer) Lister() v1.ImportedServiceSetLister { + return v1.NewImportedServiceSetLister(f.Informer().GetIndexer()) +} diff --git a/vendor/maistra.io/api/client/xnsinformer/federation/v1/interface.go b/vendor/maistra.io/api/client/xnsinformer/federation/v1/interface.go new file mode 100644 index 00000000000..d73f2135923 --- /dev/null +++ b/vendor/maistra.io/api/client/xnsinformer/federation/v1/interface.go @@ -0,0 +1,58 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by xns-informer-gen. DO NOT EDIT. + +package v1 + +import ( + informers "github.com/maistra/xns-informer/pkg/informers" + internalinterfaces "maistra.io/api/client/xnsinformer/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // ExportedServiceSets returns a ExportedServiceSetInformer. + ExportedServiceSets() ExportedServiceSetInformer + // ImportedServiceSets returns a ImportedServiceSetInformer. + ImportedServiceSets() ImportedServiceSetInformer + // ServiceMeshPeers returns a ServiceMeshPeerInformer. + ServiceMeshPeers() ServiceMeshPeerInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespaces informers.NamespaceSet + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespaces informers.NamespaceSet, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespaces: namespaces, tweakListOptions: tweakListOptions} +} + +// ExportedServiceSets returns a ExportedServiceSetInformer. +func (v *version) ExportedServiceSets() ExportedServiceSetInformer { + return &exportedServiceSetInformer{factory: v.factory, namespaces: v.namespaces, tweakListOptions: v.tweakListOptions} +} + +// ImportedServiceSets returns a ImportedServiceSetInformer. +func (v *version) ImportedServiceSets() ImportedServiceSetInformer { + return &importedServiceSetInformer{factory: v.factory, namespaces: v.namespaces, tweakListOptions: v.tweakListOptions} +} + +// ServiceMeshPeers returns a ServiceMeshPeerInformer. +func (v *version) ServiceMeshPeers() ServiceMeshPeerInformer { + return &serviceMeshPeerInformer{factory: v.factory, namespaces: v.namespaces, tweakListOptions: v.tweakListOptions} +} diff --git a/vendor/maistra.io/api/client/xnsinformer/federation/v1/servicemeshpeer.go b/vendor/maistra.io/api/client/xnsinformer/federation/v1/servicemeshpeer.go new file mode 100644 index 00000000000..06c1e68dc7e --- /dev/null +++ b/vendor/maistra.io/api/client/xnsinformer/federation/v1/servicemeshpeer.go @@ -0,0 +1,93 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by xns-informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + informers "github.com/maistra/xns-informer/pkg/informers" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/client/listers/federation/v1" + versioned "maistra.io/api/client/versioned" + internalinterfaces "maistra.io/api/client/xnsinformer/internalinterfaces" + federationv1 "maistra.io/api/federation/v1" +) + +// ServiceMeshPeerInformer provides access to a shared informer and lister for +// ServiceMeshPeers. +type ServiceMeshPeerInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.ServiceMeshPeerLister +} + +type serviceMeshPeerInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespaces informers.NamespaceSet +} + +// NewServiceMeshPeerInformer constructs a new informer for ServiceMeshPeer type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewServiceMeshPeerInformer(client versioned.Interface, namespaces informers.NamespaceSet, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredServiceMeshPeerInformer(client, namespaces, resyncPeriod, indexers, nil) +} + +// NewFilteredServiceMeshPeerInformer constructs a new informer for ServiceMeshPeer type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredServiceMeshPeerInformer(client versioned.Interface, namespaces informers.NamespaceSet, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + newInformer := func(namespace string) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.FederationV1().ServiceMeshPeers(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.FederationV1().ServiceMeshPeers(namespace).Watch(context.TODO(), options) + }, + }, + &federationv1.ServiceMeshPeer{}, + resyncPeriod, + indexers, + ) + } + + return informers.NewMultiNamespaceInformer(namespaces, resyncPeriod, newInformer) +} + +func (f *serviceMeshPeerInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredServiceMeshPeerInformer(client, f.namespaces, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *serviceMeshPeerInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&federationv1.ServiceMeshPeer{}, f.defaultInformer) +} + +func (f *serviceMeshPeerInformer) Lister() v1.ServiceMeshPeerLister { + return v1.NewServiceMeshPeerLister(f.Informer().GetIndexer()) +} diff --git a/vendor/maistra.io/api/client/xnsinformer/generic.go b/vendor/maistra.io/api/client/xnsinformer/generic.go new file mode 100644 index 00000000000..e109dd721d5 --- /dev/null +++ b/vendor/maistra.io/api/client/xnsinformer/generic.go @@ -0,0 +1,85 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by xns-informer-gen. DO NOT EDIT. + +package xnsinformer + +import ( + "fmt" + + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" + v1 "maistra.io/api/core/v1" + v1alpha1 "maistra.io/api/core/v1alpha1" + v2 "maistra.io/api/core/v2" + federationv1 "maistra.io/api/federation/v1" +) + +// GenericInformer is type of SharedIndexInformer which will locate and delegate to other +// sharedInformers based on type +type GenericInformer interface { + Informer() cache.SharedIndexInformer + Lister() cache.GenericLister +} + +type genericInformer struct { + informer cache.SharedIndexInformer + resource schema.GroupResource +} + +// Informer returns the SharedIndexInformer. +func (f *genericInformer) Informer() cache.SharedIndexInformer { + return f.informer +} + +// Lister returns the GenericLister. +func (f *genericInformer) Lister() cache.GenericLister { + return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) +} + +// ForResource gives generic access to a shared informer of the matching type +// TODO extend this to unknown resources with a client pool +func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { + switch resource { + // Group=core, Version=v1 + case v1.SchemeGroupVersion.WithResource("servicemeshcontrolplanes"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Core().V1().ServiceMeshControlPlanes().Informer()}, nil + case v1.SchemeGroupVersion.WithResource("servicemeshextensions"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Core().V1().ServiceMeshExtensions().Informer()}, nil + case v1.SchemeGroupVersion.WithResource("servicemeshmembers"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Core().V1().ServiceMeshMembers().Informer()}, nil + case v1.SchemeGroupVersion.WithResource("servicemeshmemberrolls"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Core().V1().ServiceMeshMemberRolls().Informer()}, nil + + // Group=core, Version=v1alpha1 + case v1alpha1.SchemeGroupVersion.WithResource("servicemeshextensions"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Core().V1alpha1().ServiceMeshExtensions().Informer()}, nil + + // Group=core, Version=v2 + case v2.SchemeGroupVersion.WithResource("servicemeshcontrolplanes"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Core().V2().ServiceMeshControlPlanes().Informer()}, nil + + // Group=federation.maistra.io, Version=v1 + case federationv1.SchemeGroupVersion.WithResource("exportedservicesets"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Federation().V1().ExportedServiceSets().Informer()}, nil + case federationv1.SchemeGroupVersion.WithResource("importedservicesets"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Federation().V1().ImportedServiceSets().Informer()}, nil + case federationv1.SchemeGroupVersion.WithResource("servicemeshpeers"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Federation().V1().ServiceMeshPeers().Informer()}, nil + + } + + return nil, fmt.Errorf("no informer found for %v", resource) +} diff --git a/vendor/maistra.io/api/client/xnsinformer/internalinterfaces/factory_interfaces.go b/vendor/maistra.io/api/client/xnsinformer/internalinterfaces/factory_interfaces.go new file mode 100644 index 00000000000..9032d99a395 --- /dev/null +++ b/vendor/maistra.io/api/client/xnsinformer/internalinterfaces/factory_interfaces.go @@ -0,0 +1,38 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by xns-informer-gen. DO NOT EDIT. + +package internalinterfaces + +import ( + time "time" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + cache "k8s.io/client-go/tools/cache" + versioned "maistra.io/api/client/versioned" +) + +// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. +type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer + +// SharedInformerFactory a small interface to allow for adding an informer without an import cycle +type SharedInformerFactory interface { + Start(stopCh <-chan struct{}) + InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer +} + +// TweakListOptionsFunc is a function that transforms a v1.ListOptions. +type TweakListOptionsFunc func(*v1.ListOptions) diff --git a/vendor/maistra.io/api/core/v1/controlplane_types.go b/vendor/maistra.io/api/core/v1/controlplane_types.go new file mode 100644 index 00000000000..4b360b631b2 --- /dev/null +++ b/vendor/maistra.io/api/core/v1/controlplane_types.go @@ -0,0 +1,141 @@ +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const DefaultTemplate = "default" + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServiceMeshControlPlane represents a deployment of the service mesh control +// plane. The control plane components are deployed in the namespace in which +// the ServiceMeshControlPlane resides. The configuration options for the +// components that comprise the control plane are specified in this object. +// +genclient +// +k8s:openapi-gen=true +// +kubebuilder:resource:shortName=smcp,categories=maistra-io +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.annotations.readyComponentCount",description="How many of the total number of components are ready" +// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Reconciled\")].reason",description="Whether or not the control plane installation is up to date." +// +kubebuilder:printcolumn:name="Template",type="string",JSONPath=".status.lastAppliedConfiguration.template",description="The configuration template to use as the base." +// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".status.lastAppliedConfiguration.version",description="The actual current version of the control plane installation." +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the object" +// +kubebuilder:printcolumn:name="Image HUB",type="string",JSONPath=".status.lastAppliedConfiguration.istio.global.hub",description="The image hub used as the base for all component images.",priority=1 +type ServiceMeshControlPlane struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // The specification of the desired state of this ServiceMeshControlPlane. + // This includes the configuration options for all components that comprise + // the control plane. + // +kubebuilder:validation:Required + Spec ControlPlaneSpec `json:"spec"` + + // The current status of this ServiceMeshControlPlane and the components + // that comprise the control plane. This data may be out of date by some + // window of time. + Status ControlPlaneStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServiceMeshControlPlaneList contains a list of ServiceMeshControlPlane +type ServiceMeshControlPlaneList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ServiceMeshControlPlane `json:"items"` +} + +// ControlPlaneStatus represents the current state of a ServiceMeshControlPlane. +type ControlPlaneStatus struct { + StatusBase `json:",inline"` + + StatusType `json:",inline"` + + // The generation observed by the controller during the most recent + // reconciliation. The information in the status pertains to this particular + // generation of the object. + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + + // The last version that was reconciled. + ReconciledVersion string `json:"reconciledVersion,omitempty"` + + // The list of components comprising the control plane and their statuses. + // +nullable + ComponentStatusList `json:",inline"` + + // The full specification of the configuration options that were applied + // to the components of the control plane during the most recent reconciliation. + // +optional + LastAppliedConfiguration ControlPlaneSpec `json:"lastAppliedConfiguration"` +} + +// GetReconciledVersion returns the reconciled version, or a default for older resources +func (s *ControlPlaneStatus) GetReconciledVersion() string { + if s == nil { + return ComposeReconciledVersion("0.0.0", 0) + } + if s.ReconciledVersion == "" { + return ComposeReconciledVersion("1.0.0", s.ObservedGeneration) + } + return s.ReconciledVersion +} + +// ControlPlaneSpec represents the configuration for installing a control plane. +type ControlPlaneSpec struct { + // Template selects the template to use for default values. Defaults to + // "default" when not set. + // DEPRECATED - use Profiles instead + // +optional + Template string `json:"template,omitempty"` + + // Profiles selects the profile to use for default values. Defaults to + // "default" when not set. Takes precedence over Template. + // +optional + Profiles []string `json:"profiles,omitempty"` + + // Version specifies what Maistra version of the control plane to install. + // When creating a new ServiceMeshControlPlane with an empty version, the + // admission webhook sets the version to the latest version supported by + // the operator. + // Existing ServiceMeshControlPlanes with an empty version are treated as + // having the version set to "v1.0" + // +optional + Version string `json:"version,omitempty"` + + // DEPRECATED: No longer used anywhere. + // Previously used to specify the NetworkType of the cluster. Defaults to "subnet". + // +optional + NetworkType NetworkType `json:"networkType,omitempty"` + + // Specifies the Istio configuration options that are passed to Helm when the + // Istio charts are rendered. These options are usually populated from the + // template specified in the spec.template field, but individual values can + // be overridden here. + // More info: https://maistra.io/docs/installation/installation-options/ + // +optional + // +kubebuilder:validation:Optional + Istio *HelmValues `json:"istio,omitempty"` + + // Specifies the 3Scale configuration options that are passed to Helm when the + // 3Scale charts are rendered. These values are usually populated from the + // template specified in the spec.template field, but individual values can + // be overridden here. + // More info: https://maistra.io/docs/installation/installation-options/#_3scale + // +optional + // +kubebuilder:validation:Optional + ThreeScale *HelmValues `json:"threeScale,omitempty"` +} + +// NetworkType is type definition representing the network type of the cluster +type NetworkType string + +const ( + // NetworkTypeSubnet when using ovs-subnet + NetworkTypeSubnet NetworkType = "subnet" + // NetworkTypeMultitenant when using ovs-multitenant + NetworkTypeMultitenant NetworkType = "multitenant" + // NetworkTypeNetworkPolicy when using ovs-networkpolicy + NetworkTypeNetworkPolicy NetworkType = "networkpolicy" +) diff --git a/security/pkg/pki/ra/leak_test.go b/vendor/maistra.io/api/core/v1/extension_conversion.go similarity index 71% rename from security/pkg/pki/ra/leak_test.go rename to vendor/maistra.io/api/core/v1/extension_conversion.go index d863fa20b36..cd3d0de6781 100644 --- a/security/pkg/pki/ra/leak_test.go +++ b/vendor/maistra.io/api/core/v1/extension_conversion.go @@ -1,4 +1,4 @@ -// Copyright Istio Authors +// Copyright Red Hat, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,15 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ra +package v1 import ( - "testing" - - "istio.io/istio/tests/util/leak" + "sigs.k8s.io/controller-runtime/pkg/conversion" ) -func TestMain(m *testing.M) { - // CheckMain asserts that no goroutines are leaked after a test package exits. - leak.CheckMain(m) -} +var _ conversion.Hub = (*ServiceMeshExtension)(nil) + +// Hub marks v1 SME resource as the storage version +func (sme *ServiceMeshExtension) Hub() {} diff --git a/vendor/maistra.io/api/core/v1/extension_types.go b/vendor/maistra.io/api/core/v1/extension_types.go new file mode 100644 index 00000000000..a2235c8c864 --- /dev/null +++ b/vendor/maistra.io/api/core/v1/extension_types.go @@ -0,0 +1,130 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + "encoding/json" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// ServiceMeshExtensionSpec defines the desired state of ServiceMeshExtension +type ServiceMeshExtensionSpec struct { + Image string `json:"image,omitempty"` + ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` + ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` + WorkloadSelector WorkloadSelector `json:"workloadSelector,omitempty"` + Phase *FilterPhase `json:"phase"` + Priority *int `json:"priority,omitempty"` + + // +kubebuilder:pruning:PreserveUnknownFields + Config ServiceMeshExtensionConfig `json:"config,omitempty"` +} + +// ServiceMeshExtensionStatus defines the observed state of ServiceMeshExtension +type ServiceMeshExtensionStatus struct { + Phase FilterPhase `json:"phase,omitempty"` + Priority int `json:"priority,omitempty"` + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + Deployment DeploymentStatus `json:"deployment,omitempty"` +} + +type DeploymentStatus struct { + // +kubebuilder:validation:Optional + Ready bool `json:"ready"` + ContainerSHA256 string `json:"containerSha256,omitempty"` + SHA256 string `json:"sha256,omitempty"` + URL string `json:"url,omitempty"` + Message string `json:"message,omitempty"` +} + +// WorkloadSelector is used to match workloads based on pod labels +type WorkloadSelector struct { + Labels map[string]string `json:"labels"` +} + +// FilterPhase defines point of injection of Envoy filter +type FilterPhase string + +const ( + FilterPhasePreAuthN = "PreAuthN" + FilterPhasePostAuthN = "PostAuthN" + FilterPhasePreAuthZ = "PreAuthZ" + FilterPhasePostAuthZ = "PostAuthZ" + FilterPhasePreStats = "PreStats" + FilterPhasePostStats = "PostStats" +) + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:storageversion +// +kubebuilder:resource:categories=maistra-io,shortName=sme +// +kubebuilder:printcolumn:name="Ready",type="boolean",JSONPath=".status.deployment.ready",description="Whether this extension is ready to be consumed" +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServiceMeshExtension is the Schema for the servicemeshextensions API +type ServiceMeshExtension struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ServiceMeshExtensionSpec `json:"spec,omitempty"` + Status ServiceMeshExtensionStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServiceMeshExtensionList contains a list of ServiceMeshExtension +type ServiceMeshExtensionList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ServiceMeshExtension `json:"items"` +} + +type ServiceMeshExtensionConfig struct { + Data map[string]interface{} `json:"-"` +} + +func (smec *ServiceMeshExtensionConfig) DeepCopy() *ServiceMeshExtensionConfig { + if smec == nil { + return nil + } + out := new(ServiceMeshExtensionConfig) + out.Data = runtime.DeepCopyJSON(smec.Data) + return out +} + +func (smec *ServiceMeshExtensionConfig) UnmarshalJSON(in []byte) error { + if len(in) == 0 { + return nil + } + + err := json.Unmarshal(in, &smec.Data) + if err != nil { + return err + } + return nil +} + +func (smec *ServiceMeshExtensionConfig) MarshalJSON() ([]byte, error) { + if smec.Data == nil { + return nil, nil + } + + return json.Marshal(smec.Data) +} diff --git a/vendor/maistra.io/api/core/v1/groupversion_info.go b/vendor/maistra.io/api/core/v1/groupversion_info.go new file mode 100644 index 00000000000..d6d1015b17f --- /dev/null +++ b/vendor/maistra.io/api/core/v1/groupversion_info.go @@ -0,0 +1,50 @@ +/* +Copyright Red Hat, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1 contains API Schema definitions for the maistra.io v1 API group +//+kubebuilder:object:generate=true +//+groupName=maistra.io +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: "maistra.io", Version: "v1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +func init() { + SchemeBuilder.Register( + &ServiceMeshExtension{}, &ServiceMeshExtensionList{}, + &ServiceMeshControlPlane{}, &ServiceMeshControlPlaneList{}, + &ServiceMeshMember{}, &ServiceMeshMemberList{}, + &ServiceMeshMemberRoll{}, &ServiceMeshMemberRollList{}, + ) +} diff --git a/vendor/maistra.io/api/core/v1/helmvalues.go b/vendor/maistra.io/api/core/v1/helmvalues.go new file mode 100644 index 00000000000..cdb6b2b4e3f --- /dev/null +++ b/vendor/maistra.io/api/core/v1/helmvalues.go @@ -0,0 +1,287 @@ +package v1 + +import ( + "fmt" + "strconv" + "strings" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/util/json" +) + +// HelmValues is typedef for Helm .Values +// +kubebuilder:validation:Type=object +// +kubebuilder:validation:XPreserveUnknownFields +type HelmValues struct { + data map[string]interface{} `json:"-"` +} + +func NewHelmValues(values map[string]interface{}) *HelmValues { + if values == nil { + values = make(map[string]interface{}) + } + return &HelmValues{data: values} +} + +func (h *HelmValues) GetContent() map[string]interface{} { + if h == nil { + return nil + } + return h.data +} + +func (h *HelmValues) GetFieldNoCopy(path string) (interface{}, bool, error) { + if h == nil || h.data == nil { + return nil, false, nil + } + return unstructured.NestedFieldNoCopy(h.data, strings.Split(path, ".")...) +} + +func (h *HelmValues) GetBool(path string) (bool, bool, error) { + if h == nil || h.data == nil { + return false, false, nil + } + val, found, err := unstructured.NestedFieldNoCopy(h.data, strings.Split(path, ".")...) + if !found || err != nil { + return false, found, err + } + b, ok := val.(bool) + if !ok { + if val == nil { + return false, false, nil + } + return false, false, fmt.Errorf("%v accessor error: %v is of the type %T, expected bool", path, val, val) + } + return b, true, nil +} + +func (h *HelmValues) GetAndRemoveBool(path string) (bool, bool, error) { + value, ok, err := h.GetBool(path) + if err == nil { + h.RemoveField(path) + } + return value, ok, err +} + +func (h *HelmValues) GetString(path string) (string, bool, error) { + if h == nil || h.data == nil { + return "", false, nil + } + val, found, err := unstructured.NestedFieldNoCopy(h.data, strings.Split(path, ".")...) + if !found || err != nil { + return "", found, err + } + s, ok := val.(string) + if !ok { + if val == nil { + return "", false, nil + } + return "", false, fmt.Errorf("%v accessor error: %v is of the type %T, expected string", path, val, val) + } + return s, true, nil +} + +func (h *HelmValues) GetForceNumberToString(path string) (string, bool, error) { + if h == nil || h.data == nil { + return "", false, nil + } + value, ok, err := unstructured.NestedFieldNoCopy(h.data, strings.Split(path, ".")...) + if err != nil { + return "", false, err + } else if !ok { + return "", false, nil + } + switch typeValue := value.(type) { + case int64: + return strconv.FormatInt(typeValue, 10), ok, nil + case float64: + return strconv.FormatFloat(typeValue, 'f', -1, 64), ok, nil + case string: + return typeValue, ok, nil + case nil: + return "", false, nil + } + return "", false, fmt.Errorf("could not convert type to string: %T=%s", value, value) +} + +func (h *HelmValues) GetAndRemoveString(path string) (string, bool, error) { + value, ok, err := h.GetString(path) + if err == nil { + h.RemoveField(path) + } + return value, ok, err +} + +func (h *HelmValues) GetAndRemoveForceNumberToString(path string) (string, bool, error) { + value, ok, err := h.GetForceNumberToString(path) + if err == nil { + h.RemoveField(path) + } + return value, ok, err +} + +func (h *HelmValues) GetInt64(path string) (int64, bool, error) { + if h == nil || h.data == nil { + return 0, false, nil + } + val, found, err := unstructured.NestedFieldNoCopy(h.data, strings.Split(path, ".")...) + if !found || err != nil { + return 0, found, err + } + i, ok := val.(int64) + if !ok { + if val == nil { + return 0, false, nil + } + return 0, false, fmt.Errorf("%v accessor error: %v is of the type %T, expected int64", path, val, val) + } + return i, true, nil +} + +func (h *HelmValues) GetAndRemoveInt64(path string) (int64, bool, error) { + value, ok, err := h.GetInt64(path) + if err == nil { + h.RemoveField(path) + } + return value, ok, err +} + +func (h *HelmValues) GetFloat64(path string) (float64, bool, error) { + if h == nil || h.data == nil { + return 0, false, nil + } + val, found, err := unstructured.NestedFieldNoCopy(h.data, strings.Split(path, ".")...) + if !found || err != nil { + return 0, found, err + } + f, ok := val.(float64) + if !ok { + if val == nil { + return 0, false, nil + } + return 0, false, fmt.Errorf("%v accessor error: %v is of the type %T, expected float64", path, val, val) + } + return f, true, nil +} + +func (h *HelmValues) GetAndRemoveFloat64(path string) (float64, bool, error) { + value, ok, err := h.GetFloat64(path) + if err == nil { + h.RemoveField(path) + } + return value, ok, err +} + +func (h *HelmValues) GetStringSlice(path string) ([]string, bool, error) { + if h == nil || h.data == nil { + return nil, false, nil + } + slice, ok, err := unstructured.NestedStringSlice(h.data, strings.Split(path, ".")...) + if err != nil { + if val, _, _ := h.GetFieldNoCopy(path); val == nil { + return nil, false, nil + } + } + return slice, ok, err +} + +func (h *HelmValues) GetAndRemoveStringSlice(path string) ([]string, bool, error) { + value, ok, err := h.GetStringSlice(path) + if err == nil { + h.RemoveField(path) + } + return value, ok, err +} + +func (h *HelmValues) GetSlice(path string) ([]interface{}, bool, error) { + if h == nil || h.data == nil { + return nil, false, nil + } + slice, ok, err := unstructured.NestedSlice(h.data, strings.Split(path, ".")...) + if err != nil { + if val, _, _ := h.GetFieldNoCopy(path); val == nil { + return nil, false, nil + } + } + return slice, ok, err +} + +func (h *HelmValues) GetAndRemoveSlice(path string) ([]interface{}, bool, error) { + value, ok, err := h.GetSlice(path) + if err == nil { + h.RemoveField(path) + } + return value, ok, err +} + +func (h *HelmValues) GetMap(path string) (map[string]interface{}, bool, error) { + if h == nil || h.data == nil { + return nil, false, nil + } + rawval, ok, err := unstructured.NestedFieldCopy(h.data, strings.Split(path, ".")...) + if ok { + if rawval == nil { + return nil, ok, err + } + if mapval, ok := rawval.(map[string]interface{}); ok { + return mapval, ok, err + } + return nil, false, fmt.Errorf("%v accessor error: %v is of the type %T, expected map[string]interface{}", path, rawval, rawval) + } + return nil, ok, err +} + +func (h *HelmValues) SetField(path string, value interface{}) error { + if h == nil { + panic("Tried to invoke SetField on nil *HelmValues") + } + if h.data == nil { + h.data = map[string]interface{}{} + } + return unstructured.SetNestedField(h.data, value, strings.Split(path, ".")...) +} + +func (h *HelmValues) SetStringSlice(path string, value []string) error { + if h == nil { + panic("Tried to invoke SetField on nil *HelmValues") + } + if h.data == nil { + h.data = map[string]interface{}{} + } + return unstructured.SetNestedStringSlice(h.data, value, strings.Split(path, ".")...) +} + +func (h *HelmValues) RemoveField(path string) { + if h == nil || h.data == nil { + return + } + unstructured.RemoveNestedField(h.data, strings.Split(path, ".")...) +} + +func (h *HelmValues) UnmarshalJSON(in []byte) error { + err := json.Unmarshal(in, &h.data) + if err != nil { + return err + } + return nil +} + +func (h *HelmValues) MarshalJSON() ([]byte, error) { + return json.Marshal(h.data) +} + +func (in *HelmValues) DeepCopyInto(out *HelmValues) { + *out = HelmValues{} + + data, err := json.Marshal(in) + if err != nil { + // panic ??? + return + } + err = json.Unmarshal(data, out) + if err != nil { + // panic ??? + return + } + return +} diff --git a/vendor/maistra.io/api/core/v1/member_types.go b/vendor/maistra.io/api/core/v1/member_types.go new file mode 100644 index 00000000000..74a8ec39431 --- /dev/null +++ b/vendor/maistra.io/api/core/v1/member_types.go @@ -0,0 +1,170 @@ +package v1 + +import ( + "fmt" + + core "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// A ServiceMeshMember object marks the namespace in which it lives as a member +// of the Service Mesh Control Plane referenced in the object. +// The ServiceMeshMember object should be created in each application namespace +// that must be part of the service mesh and must be named "default". +// +// When the ServiceMeshMember object is created, it causes the namespace to be +// added to the ServiceMeshMemberRoll within the namespace of the +// ServiceMeshControlPlane object the ServiceMeshMember references. +// +// To reference a ServiceMeshControlPlane, the user creating the ServiceMeshMember +// object must have the "use" permission on the referenced ServiceMeshControlPlane +// object. This permission is given via the mesh-users RoleBinding (and mesh-user +// Role) in the namespace of the referenced ServiceMeshControlPlane object. +// +genclient +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:storageversion +// +kubebuilder:resource:shortName=smm,categories=maistra-io +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Control Plane",type="string",JSONPath=".status.annotations.controlPlaneRef",description="The ServiceMeshControlPlane this namespace belongs to" +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description="Whether or not namespace is configured as a member of the mesh." +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the object" +type ServiceMeshMember struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // The desired state of this ServiceMeshMember. + // +kubebuilder:validation:Required + Spec ServiceMeshMemberSpec `json:"spec"` + + // The current status of this ServiceMeshMember. This data may be out of + // date by some window of time. + // +optional + Status ServiceMeshMemberStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServiceMeshMemberList contains a list of ServiceMeshMember objects +type ServiceMeshMemberList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ServiceMeshMember `json:"items"` +} + +// ServiceMeshMemberSpec defines the member of the mesh +type ServiceMeshMemberSpec struct { + + // A reference to the ServiceMeshControlPlane object. + ControlPlaneRef ServiceMeshControlPlaneRef `json:"controlPlaneRef"` +} + +// ServiceMeshControlPlaneRef is a reference to a ServiceMeshControlPlane object +type ServiceMeshControlPlaneRef struct { + + // The name of the referenced ServiceMeshControlPlane object. + Name string `json:"name"` + + // The namespace of the referenced ServiceMeshControlPlane object. + Namespace string `json:"namespace"` +} + +func (s ServiceMeshControlPlaneRef) String() string { + return fmt.Sprintf("%s%c%s", s.Namespace, '/', s.Name) +} + +// ServiceMeshMemberStatus represents the current state of a ServiceMeshMember. +type ServiceMeshMemberStatus struct { + StatusBase `json:",inline"` + + // The generation observed by the controller during the most recent + // reconciliation. The information in the status pertains to this particular + // generation of the object. + ObservedGeneration int64 `json:"observedGeneration"` + + // The generation of the ServiceMeshControlPlane object observed by the + // controller during the most recent reconciliation of this + // ServiceMeshMember. + ServiceMeshGeneration int64 `json:"meshGeneration,omitempty"` // TODO: do we need this field at all? + + // The reconciled version of the ServiceMeshControlPlane object observed by + // the controller during the most recent reconciliation of this + // ServiceMeshMember. + ServiceMeshReconciledVersion string `json:"meshReconciledVersion,omitempty"` // TODO: do we need this field at all? + + // Represents the latest available observations of a ServiceMeshMember's + // current state. + Conditions []ServiceMeshMemberCondition `json:"conditions"` +} + +// ServiceMeshMemberConditionType represents the type of the condition. Condition types are: +// Reconciled, NamespaceConfigured +type ServiceMeshMemberConditionType string + +const ( + // ConditionTypeReconciled signifies whether or not the controller has + // updated the ServiceMeshMemberRoll object based on this ServiceMeshMember. + ConditionTypeMemberReconciled ServiceMeshMemberConditionType = "Reconciled" + // ConditionTypeReady signifies whether the namespace has been configured + // to use the mesh + ConditionTypeMemberReady ServiceMeshMemberConditionType = "Ready" // TODO: remove the Ready condition in v2 +) + +type ServiceMeshMemberConditionReason string + +const ( + // ConditionReasonDeletionError ... + ConditionReasonMemberCannotCreateMemberRoll ServiceMeshMemberConditionReason = "CreateMemberRollFailed" + ConditionReasonMemberCannotUpdateMemberRoll ServiceMeshMemberConditionReason = "UpdateMemberRollFailed" + ConditionReasonMemberCannotDeleteMemberRoll ServiceMeshMemberConditionReason = "DeleteMemberRollFailed" + ConditionReasonMemberNamespaceNotExists ServiceMeshMemberConditionReason = "NamespaceNotExists" + ConditionReasonMemberReferencesDifferentControlPlane ServiceMeshMemberConditionReason = "ReferencesDifferentControlPlane" + ConditionReasonMemberTerminating ServiceMeshMemberConditionReason = "Terminating" +) + +// Condition represents a specific condition on a resource +type ServiceMeshMemberCondition struct { + Type ServiceMeshMemberConditionType `json:"type,omitempty"` + Status core.ConditionStatus `json:"status,omitempty"` + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + Reason ServiceMeshMemberConditionReason `json:"reason,omitempty"` + Message string `json:"message,omitempty"` +} + +// GetCondition removes a condition for the list of conditions +func (s *ServiceMeshMemberStatus) GetCondition(conditionType ServiceMeshMemberConditionType) ServiceMeshMemberCondition { + if s == nil { + return ServiceMeshMemberCondition{Type: conditionType, Status: core.ConditionUnknown} + } + for i := range s.Conditions { + if s.Conditions[i].Type == conditionType { + return s.Conditions[i] + } + } + return ServiceMeshMemberCondition{Type: conditionType, Status: core.ConditionUnknown} +} + +// SetCondition sets a specific condition in the list of conditions +func (s *ServiceMeshMemberStatus) SetCondition(condition ServiceMeshMemberCondition) *ServiceMeshMemberStatus { + if s == nil { + return nil + } + now := metav1.Now() + for i := range s.Conditions { + if s.Conditions[i].Type == condition.Type { + if s.Conditions[i].Status != condition.Status { + condition.LastTransitionTime = now + } else { + condition.LastTransitionTime = s.Conditions[i].LastTransitionTime + } + s.Conditions[i] = condition + return s + } + } + + // If the condition does not exist, + // initialize the lastTransitionTime + condition.LastTransitionTime = now + s.Conditions = append(s.Conditions, condition) + return s +} diff --git a/vendor/maistra.io/api/core/v1/memberroll_types.go b/vendor/maistra.io/api/core/v1/memberroll_types.go new file mode 100644 index 00000000000..f8b44db6a06 --- /dev/null +++ b/vendor/maistra.io/api/core/v1/memberroll_types.go @@ -0,0 +1,188 @@ +package v1 + +import ( + core "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// The ServiceMeshMemberRoll object configures which namespaces belong to a +// service mesh. Only namespaces listed in the ServiceMeshMemberRoll will be +// affected by the control plane. Any number of namespaces can be added, but a +// namespace may not exist in more than one service mesh. The +// ServiceMeshMemberRoll object must be created in the same namespace as +// the ServiceMeshControlPlane object and must be named "default". +// +genclient +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:storageversion +// +kubebuilder:resource:shortName=smmr,categories=maistra-io +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.annotations.configuredMemberCount",description="How many of the total number of member namespaces are configured" +// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].reason",description="Whether all member namespaces have been configured or why that's not the case" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the object" +// +kubebuilder:printcolumn:name="Members",type="string",JSONPath=".status.members",description="Namespaces that are members of this Control Plane",priority=1 +type ServiceMeshMemberRoll struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Specification of the desired list of members of the service mesh. + // +kubebuilder:validation:Required + Spec ServiceMeshMemberRollSpec `json:"spec"` + + // The current status of this ServiceMeshMemberRoll. This data may be out + // of date by some window of time. + Status ServiceMeshMemberRollStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServiceMeshMemberRollList contains a list of ServiceMeshMemberRoll +type ServiceMeshMemberRollList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ServiceMeshMemberRoll `json:"items"` +} + +// ServiceMeshMemberRollSpec is the specification of the desired list of +// members of the service mesh. +type ServiceMeshMemberRollSpec struct { + + // List of namespaces that should be members of the service mesh. + // +optional + // +nullable + Members []string `json:"members,omitempty"` +} + +// ServiceMeshMemberRollStatus represents the current state of a ServiceMeshMemberRoll. +type ServiceMeshMemberRollStatus struct { + StatusBase `json:",inline"` + + // The generation observed by the controller during the most recent + // reconciliation. The information in the status pertains to this particular + // generation of the object. + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + + // The generation of the ServiceMeshControlPlane object observed by the + // controller during the most recent reconciliation of this + // ServiceMeshMemberRoll. + ServiceMeshGeneration int64 `json:"meshGeneration,omitempty"` + + // The reconciled version of the ServiceMeshControlPlane object observed by + // the controller during the most recent reconciliation of this + // ServiceMeshMemberRoll. + ServiceMeshReconciledVersion string `json:"meshReconciledVersion,omitempty"` + + // Complete list of namespaces that are configured as members of the service + // mesh - this includes namespaces specified in spec.members and those that + // contain a ServiceMeshMember object + // +optional + // +nullable + Members []string `json:"members"` + + // List of namespaces that are configured as members of the service mesh. + // +optional + // +nullable + ConfiguredMembers []string `json:"configuredMembers"` + + // List of namespaces that haven't been configured as members of the service + // mesh yet. + // +optional + // +nullable + PendingMembers []string `json:"pendingMembers"` + + // List of namespaces that are being removed as members of the service + // mesh. + // +optional + // +nullable + TerminatingMembers []string `json:"terminatingMembers"` + + // Represents the latest available observations of this ServiceMeshMemberRoll's + // current state. + // +optional + // +nullable + Conditions []ServiceMeshMemberRollCondition `json:"conditions"` + + // Represents the latest available observations of each member's + // current state. + // +optional + // +nullable + MemberStatuses []ServiceMeshMemberStatusSummary `json:"memberStatuses"` +} + +// ServiceMeshMemberStatusSummary represents a summary status of a ServiceMeshMember. +type ServiceMeshMemberStatusSummary struct { + Namespace string `json:"namespace"` + Conditions []ServiceMeshMemberCondition `json:"conditions"` +} + +// ServiceMeshMemberRollConditionType represents the type of the condition. Condition types are: +// Reconciled, NamespaceConfigured +type ServiceMeshMemberRollConditionType string + +const ( + // ConditionTypeMemberRollReady signifies whether the namespace has been configured + // to use the mesh + ConditionTypeMemberRollReady ServiceMeshMemberRollConditionType = "Ready" +) + +type ServiceMeshMemberRollConditionReason string + +const ( + // ConditionReasonConfigured indicates that all namespaces were configured + ServiceMeshMemberRollConditionReasonConditionReasonConfigured ServiceMeshMemberRollConditionReason = "Configured" + // ConditionReasonReconcileError indicates that one of the namespaces to configure could not be configured + ServiceMeshMemberRollConditionReasonConditionReasonReconcileError ServiceMeshMemberRollConditionReason = "ReconcileError" + // ConditionReasonSMCPMissing indicates that the ServiceMeshControlPlane resource does not exist + ServiceMeshMemberRollConditionReasonConditionReasonSMCPMissing ServiceMeshMemberRollConditionReason = "ErrSMCPMissing" + // ConditionReasonMultipleSMCP indicates that multiple ServiceMeshControlPlane resources exist in the namespace + ServiceMeshMemberRollConditionReasonConditionReasonMultipleSMCP ServiceMeshMemberRollConditionReason = "ErrMultipleSMCPs" + // ConditionReasonSMCPNotReconciled indicates that reconciliation of the SMMR was skipped because the SMCP has not been reconciled + ServiceMeshMemberRollConditionReasonConditionReasonSMCPNotReconciled ServiceMeshMemberRollConditionReason = "SMCPReconciling" +) + +// Condition represents a specific condition on a resource +type ServiceMeshMemberRollCondition struct { + Type ServiceMeshMemberRollConditionType `json:"type,omitempty"` + Status core.ConditionStatus `json:"status,omitempty"` + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + Reason ServiceMeshMemberRollConditionReason `json:"reason,omitempty"` + Message string `json:"message,omitempty"` +} + +// GetCondition removes a condition for the list of conditions +func (s *ServiceMeshMemberRollStatus) GetCondition(conditionType ServiceMeshMemberRollConditionType) ServiceMeshMemberRollCondition { + if s == nil { + return ServiceMeshMemberRollCondition{Type: conditionType, Status: core.ConditionUnknown} + } + for i := range s.Conditions { + if s.Conditions[i].Type == conditionType { + return s.Conditions[i] + } + } + return ServiceMeshMemberRollCondition{Type: conditionType, Status: core.ConditionUnknown} +} + +// SetCondition sets a specific condition in the list of conditions +func (s *ServiceMeshMemberRollStatus) SetCondition(condition ServiceMeshMemberRollCondition) *ServiceMeshMemberRollStatus { + if s == nil { + return nil + } + now := metav1.Now() + for i := range s.Conditions { + if s.Conditions[i].Type == condition.Type { + if s.Conditions[i].Status != condition.Status { + condition.LastTransitionTime = now + } else { + condition.LastTransitionTime = s.Conditions[i].LastTransitionTime + } + s.Conditions[i] = condition + return s + } + } + + // If the condition does not exist, + // initialize the lastTransitionTime + condition.LastTransitionTime = now + s.Conditions = append(s.Conditions, condition) + return s +} diff --git a/vendor/maistra.io/api/core/v1/status.go b/vendor/maistra.io/api/core/v1/status.go new file mode 100644 index 00000000000..a4840f6edc4 --- /dev/null +++ b/vendor/maistra.io/api/core/v1/status.go @@ -0,0 +1,269 @@ +package v1 + +import ( + "fmt" + "strings" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" +) + +type StatusBase struct { + // Annotations is an unstructured key value map used to store additional, + // usually redundant status information, such as the number of components + // deployed by the ServiceMeshControlPlane (number is redundant because + // you could just as easily count the elements in the ComponentStatus + // array). The reason to add this redundant information is to make it + // available to kubectl, which does not yet allow counting objects in + // JSONPath expressions. + // +optional + Annotations map[string]string `json:"annotations,omitempty"` +} + +func (s *StatusBase) GetAnnotation(name string) string { + if s.Annotations == nil { + return "" + } + return s.Annotations[name] +} + +func (s *StatusBase) SetAnnotation(name string, value string) { + if s.Annotations == nil { + s.Annotations = map[string]string{} + } + s.Annotations[name] = value +} + +func (s *StatusBase) RemoveAnnotation(name string) { + if s.Annotations != nil { + delete(s.Annotations, name) + } +} + +// StatusType represents the status for a control plane, component, or resource +type StatusType struct { + + // Represents the latest available observations of the object's current state. + Conditions []Condition `json:"conditions,omitempty"` +} + +// NewStatus returns a new StatusType object +func NewStatus() StatusType { + return StatusType{Conditions: make([]Condition, 0, 3)} +} + +type ComponentStatusList struct { + //+optional + ComponentStatus []ComponentStatus `json:"components,omitempty"` +} + +// FindComponentByName returns the status for a specific component +func (s *ComponentStatusList) FindComponentByName(name string) *ComponentStatus { + for i, status := range s.ComponentStatus { + if status.Resource == name { + return &s.ComponentStatus[i] + } + } + return nil +} + +// NewComponentStatus returns a new ComponentStatus object +func NewComponentStatus() *ComponentStatus { + return &ComponentStatus{StatusType: NewStatus()} +} + +// ComponentStatus represents the status of an object with children +type ComponentStatus struct { + StatusType `json:",inline"` + + // The name of the component this status pertains to. + Resource string `json:"resource,omitempty"` + + // TODO: can we remove this? it's not used anywhere + // The status of each resource that comprises this component. + Resources []*StatusType `json:"children,omitempty"` +} + +// ConditionType represents the type of the condition. Condition stages are: +// Installed, Reconciled, Ready +type ConditionType string + +const ( + // ConditionTypeInstalled signifies the whether or not the controller has + // installed the resources defined through the CR. + ConditionTypeInstalled ConditionType = "Installed" + // ConditionTypeReconciled signifies the whether or not the controller has + // reconciled the resources defined through the CR. + ConditionTypeReconciled ConditionType = "Reconciled" + // ConditionTypeReady signifies the whether or not any Deployment, StatefulSet, + // etc. resources are Ready. + ConditionTypeReady ConditionType = "Ready" +) + +// ConditionStatus represents the status of the condition +type ConditionStatus string + +const ( + // ConditionStatusTrue represents completion of the condition, e.g. + // Initialized=True signifies that initialization has occurred. + ConditionStatusTrue ConditionStatus = "True" + // ConditionStatusFalse represents incomplete status of the condition, e.g. + // Initialized=False signifies that initialization has not occurred or has + // failed. + ConditionStatusFalse ConditionStatus = "False" + // ConditionStatusUnknown represents unknown completion of the condition, e.g. + // Initialized=Unknown signifies that initialization may or may not have been + // completed. + ConditionStatusUnknown ConditionStatus = "Unknown" +) + +// ConditionReason represents a short message indicating how the condition came +// to be in its present state. +type ConditionReason string + +const ( + // ConditionReasonDeletionError ... + ConditionReasonDeletionError ConditionReason = "DeletionError" + // ConditionReasonInstallSuccessful ... + ConditionReasonInstallSuccessful ConditionReason = "InstallSuccessful" + // ConditionReasonInstallError ... + ConditionReasonInstallError ConditionReason = "InstallError" + // ConditionReasonReconcileSuccessful ... + ConditionReasonReconcileSuccessful ConditionReason = "ReconcileSuccessful" + // ConditionReasonValidationError ... + ConditionReasonValidationError ConditionReason = "ValidationError" + // ConditionReasonDependencyMissingError ... + ConditionReasonDependencyMissingError ConditionReason = "DependencyMissingError" + // ConditionReasonReconcileError ... + ConditionReasonReconcileError ConditionReason = "ReconcileError" + // ConditionReasonResourceCreated ... + ConditionReasonResourceCreated ConditionReason = "ResourceCreated" + // ConditionReasonSpecUpdated ... + ConditionReasonSpecUpdated ConditionReason = "SpecUpdated" + // ConditionReasonUpdateSuccessful ... + ConditionReasonUpdateSuccessful ConditionReason = "UpdateSuccessful" + // ConditionReasonComponentsReady ... + ConditionReasonComponentsReady ConditionReason = "ComponentsReady" + // ConditionReasonComponentsNotReady ... + ConditionReasonComponentsNotReady ConditionReason = "ComponentsNotReady" + // ConditionReasonProbeError ... + ConditionReasonProbeError ConditionReason = "ProbeError" + // ConditionReasonPausingInstall ... + ConditionReasonPausingInstall ConditionReason = "PausingInstall" + // ConditionReasonPausingUpdate ... + ConditionReasonPausingUpdate ConditionReason = "PausingUpdate" + // ConditionReasonDeleting ... + ConditionReasonDeleting ConditionReason = "Deleting" + // ConditionReasonDeleted ... + ConditionReasonDeleted ConditionReason = "Deleted" +) + +// A Condition represents a specific observation of the object's state. +type Condition struct { + + // The type of this condition. + Type ConditionType `json:"type,omitempty"` + + // The status of this condition. Can be True, False or Unknown. + Status ConditionStatus `json:"status,omitempty"` + + // Unique, single-word, CamelCase reason for the condition's last transition. + Reason ConditionReason `json:"reason,omitempty"` + + // Human-readable message indicating details about the last transition. + Message string `json:"message,omitempty"` + + // Last time the condition transitioned from one status to another. + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` +} + +func (c *Condition) Matches(status ConditionStatus, reason ConditionReason, message string) bool { + return c.Status == status && c.Reason == reason && c.Message == message +} + +// ComposeReconciledVersion returns a string for use in ReconciledVersion fields +func ComposeReconciledVersion(operatorVersion string, generation int64) string { + return fmt.Sprintf("%s-%d", operatorVersion, generation) +} + +// GetCondition removes a condition for the list of conditions +func (s *StatusType) GetCondition(conditionType ConditionType) Condition { + if s == nil { + return Condition{Type: conditionType, Status: ConditionStatusUnknown} + } + for i := range s.Conditions { + if s.Conditions[i].Type == conditionType { + return s.Conditions[i] + } + } + return Condition{Type: conditionType, Status: ConditionStatusUnknown} +} + +// SetCondition sets a specific condition in the list of conditions +func (s *StatusType) SetCondition(condition Condition) *StatusType { + if s == nil { + return nil + } + // These only get serialized out to the second. This can break update + // skipping, as the time in the resource returned from the client may not + // match the time in our cached status during a reconcile. We truncate here + // to save any problems down the line. + now := metav1.NewTime(time.Now().Truncate(time.Second)) + for i, prevCondition := range s.Conditions { + if prevCondition.Type == condition.Type { + if prevCondition.Status != condition.Status { + condition.LastTransitionTime = now + } else { + condition.LastTransitionTime = prevCondition.LastTransitionTime + } + s.Conditions[i] = condition + return s + } + } + + // If the condition does not exist, + // initialize the lastTransitionTime + condition.LastTransitionTime = now + s.Conditions = append(s.Conditions, condition) + return s +} + +// RemoveCondition removes a condition for the list of conditions +func (s *StatusType) RemoveCondition(conditionType ConditionType) *StatusType { + if s == nil { + return nil + } + for i := range s.Conditions { + if s.Conditions[i].Type == conditionType { + s.Conditions = append(s.Conditions[:i], s.Conditions[i+1:]...) + return s + } + } + return s +} + +// ResourceKey is a typedef for key used in ManagedGenerations. It is a string +// with the format: namespace/name=group/version,kind +type ResourceKey string + +// NewResourceKey for the object and type +func NewResourceKey(o metav1.Object, t metav1.Type) ResourceKey { + return ResourceKey(fmt.Sprintf("%s/%s=%s,Kind=%s", o.GetNamespace(), o.GetName(), t.GetAPIVersion(), t.GetKind())) +} + +// ToUnstructured returns a an Unstructured object initialized with Namespace, +// Name, APIVersion, and Kind fields from the ResourceKey +func (key ResourceKey) ToUnstructured() *unstructured.Unstructured { + // ResourceKey is guaranteed to be at least "/=," meaning we are guaranteed + // to get two elements in all of the splits + retval := &unstructured.Unstructured{} + parts := strings.SplitN(string(key), "=", 2) + nn := strings.SplitN(parts[0], "/", 2) + gvk := strings.SplitN(parts[1], ",Kind=", 2) + retval.SetNamespace(nn[0]) + retval.SetName(nn[1]) + retval.SetAPIVersion(gvk[0]) + retval.SetKind(gvk[1]) + return retval +} diff --git a/vendor/maistra.io/api/core/v1/zz_generated.deepcopy.go b/vendor/maistra.io/api/core/v1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..e986ceab905 --- /dev/null +++ b/vendor/maistra.io/api/core/v1/zz_generated.deepcopy.go @@ -0,0 +1,696 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by controller-gen. DO NOT EDIT. + +package v1 + +import ( + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentStatus) DeepCopyInto(out *ComponentStatus) { + *out = *in + in.StatusType.DeepCopyInto(&out.StatusType) + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = make([]*StatusType, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(StatusType) + (*in).DeepCopyInto(*out) + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentStatus. +func (in *ComponentStatus) DeepCopy() *ComponentStatus { + if in == nil { + return nil + } + out := new(ComponentStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentStatusList) DeepCopyInto(out *ComponentStatusList) { + *out = *in + if in.ComponentStatus != nil { + in, out := &in.ComponentStatus, &out.ComponentStatus + *out = make([]ComponentStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentStatusList. +func (in *ComponentStatusList) DeepCopy() *ComponentStatusList { + if in == nil { + return nil + } + out := new(ComponentStatusList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Condition) DeepCopyInto(out *Condition) { + *out = *in + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition. +func (in *Condition) DeepCopy() *Condition { + if in == nil { + return nil + } + out := new(Condition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneSpec) DeepCopyInto(out *ControlPlaneSpec) { + *out = *in + if in.Profiles != nil { + in, out := &in.Profiles, &out.Profiles + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Istio != nil { + in, out := &in.Istio, &out.Istio + *out = (*in).DeepCopy() + } + if in.ThreeScale != nil { + in, out := &in.ThreeScale, &out.ThreeScale + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneSpec. +func (in *ControlPlaneSpec) DeepCopy() *ControlPlaneSpec { + if in == nil { + return nil + } + out := new(ControlPlaneSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneStatus) DeepCopyInto(out *ControlPlaneStatus) { + *out = *in + in.StatusBase.DeepCopyInto(&out.StatusBase) + in.StatusType.DeepCopyInto(&out.StatusType) + in.ComponentStatusList.DeepCopyInto(&out.ComponentStatusList) + in.LastAppliedConfiguration.DeepCopyInto(&out.LastAppliedConfiguration) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneStatus. +func (in *ControlPlaneStatus) DeepCopy() *ControlPlaneStatus { + if in == nil { + return nil + } + out := new(ControlPlaneStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeploymentStatus) DeepCopyInto(out *DeploymentStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentStatus. +func (in *DeploymentStatus) DeepCopy() *DeploymentStatus { + if in == nil { + return nil + } + out := new(DeploymentStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmValues. +func (in *HelmValues) DeepCopy() *HelmValues { + if in == nil { + return nil + } + out := new(HelmValues) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshControlPlane) DeepCopyInto(out *ServiceMeshControlPlane) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshControlPlane. +func (in *ServiceMeshControlPlane) DeepCopy() *ServiceMeshControlPlane { + if in == nil { + return nil + } + out := new(ServiceMeshControlPlane) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshControlPlane) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshControlPlaneList) DeepCopyInto(out *ServiceMeshControlPlaneList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ServiceMeshControlPlane, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshControlPlaneList. +func (in *ServiceMeshControlPlaneList) DeepCopy() *ServiceMeshControlPlaneList { + if in == nil { + return nil + } + out := new(ServiceMeshControlPlaneList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshControlPlaneList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshControlPlaneRef) DeepCopyInto(out *ServiceMeshControlPlaneRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshControlPlaneRef. +func (in *ServiceMeshControlPlaneRef) DeepCopy() *ServiceMeshControlPlaneRef { + if in == nil { + return nil + } + out := new(ServiceMeshControlPlaneRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshExtension) DeepCopyInto(out *ServiceMeshExtension) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshExtension. +func (in *ServiceMeshExtension) DeepCopy() *ServiceMeshExtension { + if in == nil { + return nil + } + out := new(ServiceMeshExtension) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshExtension) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshExtensionConfig) DeepCopyInto(out *ServiceMeshExtensionConfig) { + clone := in.DeepCopy() + *out = *clone +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshExtensionList) DeepCopyInto(out *ServiceMeshExtensionList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ServiceMeshExtension, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshExtensionList. +func (in *ServiceMeshExtensionList) DeepCopy() *ServiceMeshExtensionList { + if in == nil { + return nil + } + out := new(ServiceMeshExtensionList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshExtensionList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshExtensionSpec) DeepCopyInto(out *ServiceMeshExtensionSpec) { + *out = *in + if in.ImagePullSecrets != nil { + in, out := &in.ImagePullSecrets, &out.ImagePullSecrets + *out = make([]corev1.LocalObjectReference, len(*in)) + copy(*out, *in) + } + in.WorkloadSelector.DeepCopyInto(&out.WorkloadSelector) + if in.Phase != nil { + in, out := &in.Phase, &out.Phase + *out = new(FilterPhase) + **out = **in + } + if in.Priority != nil { + in, out := &in.Priority, &out.Priority + *out = new(int) + **out = **in + } + in.Config.DeepCopyInto(&out.Config) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshExtensionSpec. +func (in *ServiceMeshExtensionSpec) DeepCopy() *ServiceMeshExtensionSpec { + if in == nil { + return nil + } + out := new(ServiceMeshExtensionSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshExtensionStatus) DeepCopyInto(out *ServiceMeshExtensionStatus) { + *out = *in + out.Deployment = in.Deployment +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshExtensionStatus. +func (in *ServiceMeshExtensionStatus) DeepCopy() *ServiceMeshExtensionStatus { + if in == nil { + return nil + } + out := new(ServiceMeshExtensionStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMember) DeepCopyInto(out *ServiceMeshMember) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMember. +func (in *ServiceMeshMember) DeepCopy() *ServiceMeshMember { + if in == nil { + return nil + } + out := new(ServiceMeshMember) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshMember) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberCondition) DeepCopyInto(out *ServiceMeshMemberCondition) { + *out = *in + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberCondition. +func (in *ServiceMeshMemberCondition) DeepCopy() *ServiceMeshMemberCondition { + if in == nil { + return nil + } + out := new(ServiceMeshMemberCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberList) DeepCopyInto(out *ServiceMeshMemberList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ServiceMeshMember, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberList. +func (in *ServiceMeshMemberList) DeepCopy() *ServiceMeshMemberList { + if in == nil { + return nil + } + out := new(ServiceMeshMemberList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshMemberList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberRoll) DeepCopyInto(out *ServiceMeshMemberRoll) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberRoll. +func (in *ServiceMeshMemberRoll) DeepCopy() *ServiceMeshMemberRoll { + if in == nil { + return nil + } + out := new(ServiceMeshMemberRoll) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshMemberRoll) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberRollCondition) DeepCopyInto(out *ServiceMeshMemberRollCondition) { + *out = *in + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberRollCondition. +func (in *ServiceMeshMemberRollCondition) DeepCopy() *ServiceMeshMemberRollCondition { + if in == nil { + return nil + } + out := new(ServiceMeshMemberRollCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberRollList) DeepCopyInto(out *ServiceMeshMemberRollList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ServiceMeshMemberRoll, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberRollList. +func (in *ServiceMeshMemberRollList) DeepCopy() *ServiceMeshMemberRollList { + if in == nil { + return nil + } + out := new(ServiceMeshMemberRollList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshMemberRollList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberRollSpec) DeepCopyInto(out *ServiceMeshMemberRollSpec) { + *out = *in + if in.Members != nil { + in, out := &in.Members, &out.Members + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberRollSpec. +func (in *ServiceMeshMemberRollSpec) DeepCopy() *ServiceMeshMemberRollSpec { + if in == nil { + return nil + } + out := new(ServiceMeshMemberRollSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberRollStatus) DeepCopyInto(out *ServiceMeshMemberRollStatus) { + *out = *in + in.StatusBase.DeepCopyInto(&out.StatusBase) + if in.Members != nil { + in, out := &in.Members, &out.Members + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ConfiguredMembers != nil { + in, out := &in.ConfiguredMembers, &out.ConfiguredMembers + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.PendingMembers != nil { + in, out := &in.PendingMembers, &out.PendingMembers + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.TerminatingMembers != nil { + in, out := &in.TerminatingMembers, &out.TerminatingMembers + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]ServiceMeshMemberRollCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.MemberStatuses != nil { + in, out := &in.MemberStatuses, &out.MemberStatuses + *out = make([]ServiceMeshMemberStatusSummary, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberRollStatus. +func (in *ServiceMeshMemberRollStatus) DeepCopy() *ServiceMeshMemberRollStatus { + if in == nil { + return nil + } + out := new(ServiceMeshMemberRollStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberSpec) DeepCopyInto(out *ServiceMeshMemberSpec) { + *out = *in + out.ControlPlaneRef = in.ControlPlaneRef +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberSpec. +func (in *ServiceMeshMemberSpec) DeepCopy() *ServiceMeshMemberSpec { + if in == nil { + return nil + } + out := new(ServiceMeshMemberSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberStatus) DeepCopyInto(out *ServiceMeshMemberStatus) { + *out = *in + in.StatusBase.DeepCopyInto(&out.StatusBase) + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]ServiceMeshMemberCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberStatus. +func (in *ServiceMeshMemberStatus) DeepCopy() *ServiceMeshMemberStatus { + if in == nil { + return nil + } + out := new(ServiceMeshMemberStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshMemberStatusSummary) DeepCopyInto(out *ServiceMeshMemberStatusSummary) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]ServiceMeshMemberCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshMemberStatusSummary. +func (in *ServiceMeshMemberStatusSummary) DeepCopy() *ServiceMeshMemberStatusSummary { + if in == nil { + return nil + } + out := new(ServiceMeshMemberStatusSummary) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StatusBase) DeepCopyInto(out *StatusBase) { + *out = *in + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StatusBase. +func (in *StatusBase) DeepCopy() *StatusBase { + if in == nil { + return nil + } + out := new(StatusBase) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StatusType) DeepCopyInto(out *StatusType) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StatusType. +func (in *StatusType) DeepCopy() *StatusType { + if in == nil { + return nil + } + out := new(StatusType) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkloadSelector) DeepCopyInto(out *WorkloadSelector) { + *out = *in + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadSelector. +func (in *WorkloadSelector) DeepCopy() *WorkloadSelector { + if in == nil { + return nil + } + out := new(WorkloadSelector) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/maistra.io/api/core/v1alpha1/conversion_generated.go b/vendor/maistra.io/api/core/v1alpha1/conversion_generated.go new file mode 100644 index 00000000000..e48eed4fcf8 --- /dev/null +++ b/vendor/maistra.io/api/core/v1alpha1/conversion_generated.go @@ -0,0 +1,281 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by conversion-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + unsafe "unsafe" + + corev1 "k8s.io/api/core/v1" + conversion "k8s.io/apimachinery/pkg/conversion" + runtime "k8s.io/apimachinery/pkg/runtime" + v1 "maistra.io/api/core/v1" +) + +func init() { + localSchemeBuilder.Register(RegisterConversions) +} + +// RegisterConversions adds conversion functions to the given scheme. +// Public to allow building arbitrary schemes. +func RegisterConversions(s *runtime.Scheme) error { + if err := s.AddGeneratedConversionFunc((*v1.DeploymentStatus)(nil), (*DeploymentStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_DeploymentStatus_To_v1alpha1_DeploymentStatus(a.(*v1.DeploymentStatus), b.(*DeploymentStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*DeploymentStatus)(nil), (*v1.DeploymentStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_DeploymentStatus_To_v1_DeploymentStatus(a.(*DeploymentStatus), b.(*v1.DeploymentStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1.ServiceMeshExtension)(nil), (*ServiceMeshExtension)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_ServiceMeshExtension_To_v1alpha1_ServiceMeshExtension(a.(*v1.ServiceMeshExtension), b.(*ServiceMeshExtension), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ServiceMeshExtension)(nil), (*v1.ServiceMeshExtension)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ServiceMeshExtension_To_v1_ServiceMeshExtension(a.(*ServiceMeshExtension), b.(*v1.ServiceMeshExtension), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1.ServiceMeshExtensionList)(nil), (*ServiceMeshExtensionList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_ServiceMeshExtensionList_To_v1alpha1_ServiceMeshExtensionList(a.(*v1.ServiceMeshExtensionList), b.(*ServiceMeshExtensionList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ServiceMeshExtensionList)(nil), (*v1.ServiceMeshExtensionList)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ServiceMeshExtensionList_To_v1_ServiceMeshExtensionList(a.(*ServiceMeshExtensionList), b.(*v1.ServiceMeshExtensionList), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1.ServiceMeshExtensionStatus)(nil), (*ServiceMeshExtensionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_ServiceMeshExtensionStatus_To_v1alpha1_ServiceMeshExtensionStatus(a.(*v1.ServiceMeshExtensionStatus), b.(*ServiceMeshExtensionStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*ServiceMeshExtensionStatus)(nil), (*v1.ServiceMeshExtensionStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ServiceMeshExtensionStatus_To_v1_ServiceMeshExtensionStatus(a.(*ServiceMeshExtensionStatus), b.(*v1.ServiceMeshExtensionStatus), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1.WorkloadSelector)(nil), (*WorkloadSelector)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_WorkloadSelector_To_v1alpha1_WorkloadSelector(a.(*v1.WorkloadSelector), b.(*WorkloadSelector), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*WorkloadSelector)(nil), (*v1.WorkloadSelector)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_WorkloadSelector_To_v1_WorkloadSelector(a.(*WorkloadSelector), b.(*v1.WorkloadSelector), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1.ServiceMeshExtensionSpec)(nil), (*ServiceMeshExtensionSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1_ServiceMeshExtensionSpec_To_v1alpha1_ServiceMeshExtensionSpec(a.(*v1.ServiceMeshExtensionSpec), b.(*ServiceMeshExtensionSpec), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*ServiceMeshExtensionSpec)(nil), (*v1.ServiceMeshExtensionSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha1_ServiceMeshExtensionSpec_To_v1_ServiceMeshExtensionSpec(a.(*ServiceMeshExtensionSpec), b.(*v1.ServiceMeshExtensionSpec), scope) + }); err != nil { + return err + } + return nil +} + +func autoConvert_v1_DeploymentStatus_To_v1alpha1_DeploymentStatus(in *v1.DeploymentStatus, out *DeploymentStatus, s conversion.Scope) error { + out.Ready = in.Ready + out.ContainerSHA256 = in.ContainerSHA256 + out.SHA256 = in.SHA256 + out.URL = in.URL + out.Message = in.Message + return nil +} + +// Convert_v1_DeploymentStatus_To_v1alpha1_DeploymentStatus is an autogenerated conversion function. +func Convert_v1_DeploymentStatus_To_v1alpha1_DeploymentStatus(in *v1.DeploymentStatus, out *DeploymentStatus, s conversion.Scope) error { + return autoConvert_v1_DeploymentStatus_To_v1alpha1_DeploymentStatus(in, out, s) +} + +func autoConvert_v1alpha1_DeploymentStatus_To_v1_DeploymentStatus(in *DeploymentStatus, out *v1.DeploymentStatus, s conversion.Scope) error { + out.Ready = in.Ready + out.ContainerSHA256 = in.ContainerSHA256 + out.SHA256 = in.SHA256 + out.URL = in.URL + out.Message = in.Message + return nil +} + +// Convert_v1alpha1_DeploymentStatus_To_v1_DeploymentStatus is an autogenerated conversion function. +func Convert_v1alpha1_DeploymentStatus_To_v1_DeploymentStatus(in *DeploymentStatus, out *v1.DeploymentStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_DeploymentStatus_To_v1_DeploymentStatus(in, out, s) +} + +func autoConvert_v1_ServiceMeshExtension_To_v1alpha1_ServiceMeshExtension(in *v1.ServiceMeshExtension, out *ServiceMeshExtension, s conversion.Scope) error { + out.TypeMeta = in.TypeMeta + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1_ServiceMeshExtensionSpec_To_v1alpha1_ServiceMeshExtensionSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1_ServiceMeshExtensionStatus_To_v1alpha1_ServiceMeshExtensionStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1_ServiceMeshExtension_To_v1alpha1_ServiceMeshExtension is an autogenerated conversion function. +func Convert_v1_ServiceMeshExtension_To_v1alpha1_ServiceMeshExtension(in *v1.ServiceMeshExtension, out *ServiceMeshExtension, s conversion.Scope) error { + return autoConvert_v1_ServiceMeshExtension_To_v1alpha1_ServiceMeshExtension(in, out, s) +} + +func autoConvert_v1alpha1_ServiceMeshExtension_To_v1_ServiceMeshExtension(in *ServiceMeshExtension, out *v1.ServiceMeshExtension, s conversion.Scope) error { + out.TypeMeta = in.TypeMeta + out.ObjectMeta = in.ObjectMeta + if err := Convert_v1alpha1_ServiceMeshExtensionSpec_To_v1_ServiceMeshExtensionSpec(&in.Spec, &out.Spec, s); err != nil { + return err + } + if err := Convert_v1alpha1_ServiceMeshExtensionStatus_To_v1_ServiceMeshExtensionStatus(&in.Status, &out.Status, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_ServiceMeshExtension_To_v1_ServiceMeshExtension is an autogenerated conversion function. +func Convert_v1alpha1_ServiceMeshExtension_To_v1_ServiceMeshExtension(in *ServiceMeshExtension, out *v1.ServiceMeshExtension, s conversion.Scope) error { + return autoConvert_v1alpha1_ServiceMeshExtension_To_v1_ServiceMeshExtension(in, out, s) +} + +func autoConvert_v1_ServiceMeshExtensionList_To_v1alpha1_ServiceMeshExtensionList(in *v1.ServiceMeshExtensionList, out *ServiceMeshExtensionList, s conversion.Scope) error { + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ServiceMeshExtension, len(*in)) + for i := range *in { + if err := Convert_v1_ServiceMeshExtension_To_v1alpha1_ServiceMeshExtension(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1_ServiceMeshExtensionList_To_v1alpha1_ServiceMeshExtensionList is an autogenerated conversion function. +func Convert_v1_ServiceMeshExtensionList_To_v1alpha1_ServiceMeshExtensionList(in *v1.ServiceMeshExtensionList, out *ServiceMeshExtensionList, s conversion.Scope) error { + return autoConvert_v1_ServiceMeshExtensionList_To_v1alpha1_ServiceMeshExtensionList(in, out, s) +} + +func autoConvert_v1alpha1_ServiceMeshExtensionList_To_v1_ServiceMeshExtensionList(in *ServiceMeshExtensionList, out *v1.ServiceMeshExtensionList, s conversion.Scope) error { + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]v1.ServiceMeshExtension, len(*in)) + for i := range *in { + if err := Convert_v1alpha1_ServiceMeshExtension_To_v1_ServiceMeshExtension(&(*in)[i], &(*out)[i], s); err != nil { + return err + } + } + } else { + out.Items = nil + } + return nil +} + +// Convert_v1alpha1_ServiceMeshExtensionList_To_v1_ServiceMeshExtensionList is an autogenerated conversion function. +func Convert_v1alpha1_ServiceMeshExtensionList_To_v1_ServiceMeshExtensionList(in *ServiceMeshExtensionList, out *v1.ServiceMeshExtensionList, s conversion.Scope) error { + return autoConvert_v1alpha1_ServiceMeshExtensionList_To_v1_ServiceMeshExtensionList(in, out, s) +} + +func autoConvert_v1_ServiceMeshExtensionSpec_To_v1alpha1_ServiceMeshExtensionSpec(in *v1.ServiceMeshExtensionSpec, out *ServiceMeshExtensionSpec, s conversion.Scope) error { + out.Image = in.Image + out.ImagePullPolicy = corev1.PullPolicy(in.ImagePullPolicy) + out.ImagePullSecrets = *(*[]corev1.LocalObjectReference)(unsafe.Pointer(&in.ImagePullSecrets)) + if err := Convert_v1_WorkloadSelector_To_v1alpha1_WorkloadSelector(&in.WorkloadSelector, &out.WorkloadSelector, s); err != nil { + return err + } + out.Phase = (*FilterPhase)(unsafe.Pointer(in.Phase)) + out.Priority = (*int)(unsafe.Pointer(in.Priority)) + // WARNING: in.Config requires manual conversion: inconvertible types (maistra.io/api/core/v1.ServiceMeshExtensionConfig vs string) + return nil +} + +func autoConvert_v1alpha1_ServiceMeshExtensionSpec_To_v1_ServiceMeshExtensionSpec(in *ServiceMeshExtensionSpec, out *v1.ServiceMeshExtensionSpec, s conversion.Scope) error { + out.Image = in.Image + out.ImagePullPolicy = corev1.PullPolicy(in.ImagePullPolicy) + out.ImagePullSecrets = *(*[]corev1.LocalObjectReference)(unsafe.Pointer(&in.ImagePullSecrets)) + if err := Convert_v1alpha1_WorkloadSelector_To_v1_WorkloadSelector(&in.WorkloadSelector, &out.WorkloadSelector, s); err != nil { + return err + } + out.Phase = (*v1.FilterPhase)(unsafe.Pointer(in.Phase)) + out.Priority = (*int)(unsafe.Pointer(in.Priority)) + // WARNING: in.Config requires manual conversion: inconvertible types (string vs maistra.io/api/core/v1.ServiceMeshExtensionConfig) + return nil +} + +func autoConvert_v1_ServiceMeshExtensionStatus_To_v1alpha1_ServiceMeshExtensionStatus(in *v1.ServiceMeshExtensionStatus, out *ServiceMeshExtensionStatus, s conversion.Scope) error { + out.Phase = FilterPhase(in.Phase) + out.Priority = in.Priority + out.ObservedGeneration = in.ObservedGeneration + if err := Convert_v1_DeploymentStatus_To_v1alpha1_DeploymentStatus(&in.Deployment, &out.Deployment, s); err != nil { + return err + } + return nil +} + +// Convert_v1_ServiceMeshExtensionStatus_To_v1alpha1_ServiceMeshExtensionStatus is an autogenerated conversion function. +func Convert_v1_ServiceMeshExtensionStatus_To_v1alpha1_ServiceMeshExtensionStatus(in *v1.ServiceMeshExtensionStatus, out *ServiceMeshExtensionStatus, s conversion.Scope) error { + return autoConvert_v1_ServiceMeshExtensionStatus_To_v1alpha1_ServiceMeshExtensionStatus(in, out, s) +} + +func autoConvert_v1alpha1_ServiceMeshExtensionStatus_To_v1_ServiceMeshExtensionStatus(in *ServiceMeshExtensionStatus, out *v1.ServiceMeshExtensionStatus, s conversion.Scope) error { + out.Phase = v1.FilterPhase(in.Phase) + out.Priority = in.Priority + out.ObservedGeneration = in.ObservedGeneration + if err := Convert_v1alpha1_DeploymentStatus_To_v1_DeploymentStatus(&in.Deployment, &out.Deployment, s); err != nil { + return err + } + return nil +} + +// Convert_v1alpha1_ServiceMeshExtensionStatus_To_v1_ServiceMeshExtensionStatus is an autogenerated conversion function. +func Convert_v1alpha1_ServiceMeshExtensionStatus_To_v1_ServiceMeshExtensionStatus(in *ServiceMeshExtensionStatus, out *v1.ServiceMeshExtensionStatus, s conversion.Scope) error { + return autoConvert_v1alpha1_ServiceMeshExtensionStatus_To_v1_ServiceMeshExtensionStatus(in, out, s) +} + +func autoConvert_v1_WorkloadSelector_To_v1alpha1_WorkloadSelector(in *v1.WorkloadSelector, out *WorkloadSelector, s conversion.Scope) error { + out.Labels = *(*map[string]string)(unsafe.Pointer(&in.Labels)) + return nil +} + +// Convert_v1_WorkloadSelector_To_v1alpha1_WorkloadSelector is an autogenerated conversion function. +func Convert_v1_WorkloadSelector_To_v1alpha1_WorkloadSelector(in *v1.WorkloadSelector, out *WorkloadSelector, s conversion.Scope) error { + return autoConvert_v1_WorkloadSelector_To_v1alpha1_WorkloadSelector(in, out, s) +} + +func autoConvert_v1alpha1_WorkloadSelector_To_v1_WorkloadSelector(in *WorkloadSelector, out *v1.WorkloadSelector, s conversion.Scope) error { + out.Labels = *(*map[string]string)(unsafe.Pointer(&in.Labels)) + return nil +} + +// Convert_v1alpha1_WorkloadSelector_To_v1_WorkloadSelector is an autogenerated conversion function. +func Convert_v1alpha1_WorkloadSelector_To_v1_WorkloadSelector(in *WorkloadSelector, out *v1.WorkloadSelector, s conversion.Scope) error { + return autoConvert_v1alpha1_WorkloadSelector_To_v1_WorkloadSelector(in, out, s) +} diff --git a/pilot/pkg/status/distribution/resourcelock.go b/vendor/maistra.io/api/core/v1alpha1/doc.go similarity index 78% rename from pilot/pkg/status/distribution/resourcelock.go rename to vendor/maistra.io/api/core/v1alpha1/doc.go index c66b82ad0bf..7f255086b13 100644 --- a/pilot/pkg/status/distribution/resourcelock.go +++ b/vendor/maistra.io/api/core/v1alpha1/doc.go @@ -1,4 +1,4 @@ -// Copyright Istio Authors +// Copyright Red Hat, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,6 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -package distribution - -type ResourceStatus interface{} +// +k8s:conversion-gen=maistra.io/api/core/v1alpha1 +// +k8s:conversion-gen-external-types=maistra.io/api/core/v1 +package v1alpha1 diff --git a/vendor/maistra.io/api/core/v1alpha1/extension_conversion.go b/vendor/maistra.io/api/core/v1alpha1/extension_conversion.go new file mode 100644 index 00000000000..34a41e3b9ab --- /dev/null +++ b/vendor/maistra.io/api/core/v1alpha1/extension_conversion.go @@ -0,0 +1,75 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1alpha1 + +import ( + "fmt" + "os" + + apiconversion "k8s.io/apimachinery/pkg/conversion" + v1 "maistra.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +const ( + // Key used in v1's Spec.Config map to store the raw string value from v1alpha1's Spec.Config field when the conversion is not successfull + RawV1Alpha1Config = "raw_v1alpha1_config" +) + +// ConvertTo converts this SME to the Hub version (v1) +func (src *ServiceMeshExtension) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*v1.ServiceMeshExtension) + return Convert_v1alpha1_ServiceMeshExtension_To_v1_ServiceMeshExtension(src, dst, nil) +} + +// ConvertFrom converts from the Hub version (v1) to this version. +func (dst *ServiceMeshExtension) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*v1.ServiceMeshExtension) + return Convert_v1_ServiceMeshExtension_To_v1alpha1_ServiceMeshExtension(src, dst, nil) +} + +func Convert_v1_ServiceMeshExtensionSpec_To_v1alpha1_ServiceMeshExtensionSpec(src *v1.ServiceMeshExtensionSpec, dst *ServiceMeshExtensionSpec, scope apiconversion.Scope) error { + if err := autoConvert_v1_ServiceMeshExtensionSpec_To_v1alpha1_ServiceMeshExtensionSpec(src, dst, nil); err != nil { + return err + } + + if raw, ok := src.Config.Data[RawV1Alpha1Config]; ok { + dst.Config = raw.(string) + } else { + res, err := src.Config.MarshalJSON() + if err != nil { + fmt.Fprintf(os.Stderr, "config field could not be converted to string: %v", err) + } + dst.Config = string(res) + } + + return nil +} + +func Convert_v1alpha1_ServiceMeshExtensionSpec_To_v1_ServiceMeshExtensionSpec(src *ServiceMeshExtensionSpec, dst *v1.ServiceMeshExtensionSpec, scope apiconversion.Scope) error { + if err := autoConvert_v1alpha1_ServiceMeshExtensionSpec_To_v1_ServiceMeshExtensionSpec(src, dst, nil); err != nil { + return err + } + + if err := dst.Config.UnmarshalJSON([]byte(src.Config)); err != nil { + fmt.Fprintf(os.Stderr, "v1alpha1 config field (value: %q) could not be converted to v1 json: %v\n", src.Config, err) + if dst.Config.Data == nil { + dst.Config.Data = map[string]interface{}{} + } + dst.Config.Data[RawV1Alpha1Config] = src.Config + } + + return nil +} diff --git a/vendor/maistra.io/api/core/v1alpha1/extension_types.go b/vendor/maistra.io/api/core/v1alpha1/extension_types.go new file mode 100644 index 00000000000..8d48900c54c --- /dev/null +++ b/vendor/maistra.io/api/core/v1alpha1/extension_types.go @@ -0,0 +1,89 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1alpha1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// ServiceMeshExtensionSpec defines the desired state of ServiceMeshExtension +type ServiceMeshExtensionSpec struct { + Image string `json:"image,omitempty"` + ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` + ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` + WorkloadSelector WorkloadSelector `json:"workloadSelector,omitempty"` + Phase *FilterPhase `json:"phase"` + Priority *int `json:"priority,omitempty"` + Config string `json:"config,omitempty"` +} + +// ServiceMeshExtensionStatus defines the observed state of ServiceMeshExtension +type ServiceMeshExtensionStatus struct { + Phase FilterPhase `json:"phase,omitempty"` + Priority int `json:"priority,omitempty"` + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + Deployment DeploymentStatus `json:"deployment,omitempty"` +} + +type DeploymentStatus struct { + Ready bool `json:"ready,omitempty"` + ContainerSHA256 string `json:"containerSha256,omitempty"` + SHA256 string `json:"sha256,omitempty"` + URL string `json:"url,omitempty"` + Message string `json:"message,omitempty"` +} + +// WorkloadSelector is used to match workloads based on pod labels +type WorkloadSelector struct { + Labels map[string]string `json:"labels"` +} + +// FilterPhase defines point of injection of Envoy filter +type FilterPhase string + +const ( + FilterPhasePreAuthN = "PreAuthN" + FilterPhasePostAuthN = "PostAuthN" + FilterPhasePreAuthZ = "PreAuthZ" + FilterPhasePostAuthZ = "PostAuthZ" + FilterPhasePreStats = "PreStats" + FilterPhasePostStats = "PostStats" +) + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:categories=maistra-io,shortName=sme +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServiceMeshExtension is the Schema for the servicemeshextensions API +type ServiceMeshExtension struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ServiceMeshExtensionSpec `json:"spec,omitempty"` + Status ServiceMeshExtensionStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServiceMeshExtensionList contains a list of ServiceMeshExtension +type ServiceMeshExtensionList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ServiceMeshExtension `json:"items"` +} diff --git a/vendor/maistra.io/api/core/v1alpha1/groupversion_info.go b/vendor/maistra.io/api/core/v1alpha1/groupversion_info.go new file mode 100644 index 00000000000..fb326b4827b --- /dev/null +++ b/vendor/maistra.io/api/core/v1alpha1/groupversion_info.go @@ -0,0 +1,49 @@ +/* +Copyright Red Hat, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1alpha1 contains API Schema definitions for the maistra.io v1alpha1 API group +//+kubebuilder:object:generate=true +//+groupName=maistra.io +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: "maistra.io", Version: "v1alpha1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} + + localSchemeBuilder = &SchemeBuilder.SchemeBuilder + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) + +func init() { + SchemeBuilder.Register( + &ServiceMeshExtension{}, &ServiceMeshExtensionList{}, + ) +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} diff --git a/vendor/maistra.io/api/core/v1alpha1/zz_generated.deepcopy.go b/vendor/maistra.io/api/core/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..b4db054b3dc --- /dev/null +++ b/vendor/maistra.io/api/core/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,168 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "k8s.io/api/core/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeploymentStatus) DeepCopyInto(out *DeploymentStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentStatus. +func (in *DeploymentStatus) DeepCopy() *DeploymentStatus { + if in == nil { + return nil + } + out := new(DeploymentStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshExtension) DeepCopyInto(out *ServiceMeshExtension) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshExtension. +func (in *ServiceMeshExtension) DeepCopy() *ServiceMeshExtension { + if in == nil { + return nil + } + out := new(ServiceMeshExtension) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshExtension) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshExtensionList) DeepCopyInto(out *ServiceMeshExtensionList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ServiceMeshExtension, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshExtensionList. +func (in *ServiceMeshExtensionList) DeepCopy() *ServiceMeshExtensionList { + if in == nil { + return nil + } + out := new(ServiceMeshExtensionList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshExtensionList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshExtensionSpec) DeepCopyInto(out *ServiceMeshExtensionSpec) { + *out = *in + if in.ImagePullSecrets != nil { + in, out := &in.ImagePullSecrets, &out.ImagePullSecrets + *out = make([]v1.LocalObjectReference, len(*in)) + copy(*out, *in) + } + in.WorkloadSelector.DeepCopyInto(&out.WorkloadSelector) + if in.Phase != nil { + in, out := &in.Phase, &out.Phase + *out = new(FilterPhase) + **out = **in + } + if in.Priority != nil { + in, out := &in.Priority, &out.Priority + *out = new(int) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshExtensionSpec. +func (in *ServiceMeshExtensionSpec) DeepCopy() *ServiceMeshExtensionSpec { + if in == nil { + return nil + } + out := new(ServiceMeshExtensionSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshExtensionStatus) DeepCopyInto(out *ServiceMeshExtensionStatus) { + *out = *in + out.Deployment = in.Deployment +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshExtensionStatus. +func (in *ServiceMeshExtensionStatus) DeepCopy() *ServiceMeshExtensionStatus { + if in == nil { + return nil + } + out := new(ServiceMeshExtensionStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkloadSelector) DeepCopyInto(out *WorkloadSelector) { + *out = *in + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkloadSelector. +func (in *WorkloadSelector) DeepCopy() *WorkloadSelector { + if in == nil { + return nil + } + out := new(WorkloadSelector) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/maistra.io/api/core/v2/addons.go b/vendor/maistra.io/api/core/v2/addons.go new file mode 100644 index 00000000000..2fec5a6fad2 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/addons.go @@ -0,0 +1,22 @@ +package v2 + +// AddonsConfig configures additional features for use with the mesh +type AddonsConfig struct { + // Prometheus configures Prometheus specific addon capabilities + Prometheus *PrometheusAddonConfig `json:"prometheus,omitempty"` + // Stackdriver configures Stackdriver specific addon capabilities + Stackdriver *StackdriverAddonConfig `json:"stackdriver,omitempty"` + // Jaeger configures Jaeger specific addon capabilities + Jaeger *JaegerAddonConfig `json:"jaeger,omitempty"` + // Grafana configures a grafana instance to use with the mesh + // .Values.grafana.enabled, true if not null + // +optional + Grafana *GrafanaAddonConfig `json:"grafana,omitempty"` + // Kiali configures a kiali instance to use with the mesh + // .Values.kiali.enabled, true if not null + // +optional + Kiali *KialiAddonConfig `json:"kiali,omitempty"` + // ThreeScale configures the 3scale adapter + // +optional + ThreeScale *ThreeScaleAddonConfig `json:"3scale,omitempty"` +} diff --git a/vendor/maistra.io/api/core/v2/cluster.go b/vendor/maistra.io/api/core/v2/cluster.go new file mode 100644 index 00000000000..d8a9c31e1f9 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/cluster.go @@ -0,0 +1,76 @@ +package v2 + +// ControlPlaneClusterConfig configures aspects related to clustering. +type ControlPlaneClusterConfig struct { + // .Values.global.multiCluster.clusterName, defaults to Kubernetes + // +optional + Name string `json:"name,omitempty"` + // .Values.global.network + // XXX: not sure what the difference is between this and cluster name + // +optional + Network string `json:"network,omitempty"` + // .Values.global.multiCluster.enabled, if not null + // +optional + MultiCluster *MultiClusterConfig `json:"multiCluster,omitempty"` + // .Values.global.meshExpansion.enabled, if not null + // XXX: it's not clear whether or not there is any overlap with MultiCluster, + // i.e. does MultiCluster require mesh expansion ports to be configured on + // the ingress gateway? + // +optional + MeshExpansion *MeshExpansionConfig `json:"meshExpansion,omitempty"` +} + +// MultiClusterConfig configures aspects related to multi-cluster. +// implies the following: +// adds external to RequestedNetworkView (ISTIO_META_REQUESTED_NETWORK_VIEW) for egress gateway +// adds "global" and "{{ valueOrDefault .DeploymentMeta.Namespace \"default\" }}.global" to pod dns search suffixes +type MultiClusterConfig struct { + Enablement `json:",inline"` + // .Values.global.meshNetworks + // XXX: if non-empty, local cluster network should be configured as: + // : + // endpoints: + // - fromRegistry: + // gateways: + // - service: + // port: 443 # mtls port + // +optional + MeshNetworks map[string]MeshNetworkConfig `json:"meshNetworks,omitempty"` +} + +// MeshExpansionConfig configures aspects related to mesh expansion +type MeshExpansionConfig struct { + Enablement `json:",inline"` + // .Values.global.meshExpansion.useILB, true if not null, otherwise uses ingress gateway + // +optional + ILBGateway *GatewayConfig `json:"ilbGateway,omitempty"` +} + +// MeshNetworkConfig configures mesh networks for a multi-cluster mesh. +type MeshNetworkConfig struct { + Endpoints []MeshEndpointConfig `json:"endpoints,omitempty"` + Gateways []MeshGatewayConfig `json:"gateways,omitempty"` +} + +// MeshEndpointConfig specifies the endpoint of a mesh network. Only one of +// FromRegistry or FromCIDR may be specified +type MeshEndpointConfig struct { + // +optional + FromRegistry string `json:"fromRegistry,omitempty"` + // +optional + FromCIDR string `json:"fromCIDR,omitempty"` +} + +// MeshGatewayConfig specifies the gateway which should be used for accessing +// the network +type MeshGatewayConfig struct { + // +optional + // +deprecated + Service string `json:"service,omitempty"` + // +optional + RegistryServiceName string `json:"registryServiceName,omitempty"` + // +optional + Address string `json:"address,omitempty"` + // +optional + Port int32 `json:"port,omitempty"` +} diff --git a/vendor/maistra.io/api/core/v2/controlplane_types.go b/vendor/maistra.io/api/core/v2/controlplane_types.go new file mode 100644 index 00000000000..dc40caacf95 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/controlplane_types.go @@ -0,0 +1,179 @@ +package v2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + v1 "maistra.io/api/core/v1" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServiceMeshControlPlane is the Schema for the controlplanes API +// +genclient +// +k8s:openapi-gen=true +// +kubebuilder:storageversion +// +kubebuilder:resource:shortName=smcp,categories=maistra-io +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.annotations.readyComponentCount",description="How many of the total number of components are ready" +// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].reason",description="Whether or not the control plane installation is up to date and ready to handle requests." +// +kubebuilder:printcolumn:name="Profiles",type="string",JSONPath=".status.appliedSpec.profiles",description="The configuration profiles applied to the configuration." +// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".status.chartVersion",description="The actual current version of the control plane installation." +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the object" +// +kubebuilder:printcolumn:name="Image Registry",type="string",JSONPath=".status.appliedSpec.runtime.defaults.container.registry",description="The image registry used as the base for all component images.",priority=1 +type ServiceMeshControlPlane struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // The specification of the desired state of this ServiceMeshControlPlane. + // This includes the configuration options for all components that comprise + // the control plane. + // +kubebuilder:validation:Required + Spec ControlPlaneSpec `json:"spec"` + + // The current status of this ServiceMeshControlPlane and the components + // that comprise the control plane. This data may be out of date by some + // window of time. + // +optional + Status ControlPlaneStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServiceMeshControlPlaneList contains a list of ServiceMeshControlPlane +type ServiceMeshControlPlaneList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ServiceMeshControlPlane `json:"items"` +} + +// ControlPlaneStatus defines the observed state of ServiceMeshControlPlane +// ControlPlaneStatus represents the current state of a ServiceMeshControlPlane. +type ControlPlaneStatus struct { + v1.StatusBase `json:",inline"` + + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file + v1.StatusType `json:",inline"` + + // The generation observed by the controller during the most recent + // reconciliation. The information in the status pertains to this particular + // generation of the object. + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + + // The version of the operator that last processed this resource. + OperatorVersion string `json:"operatorVersion,omitempty"` + + // The version of the charts that were last processed for this resource. + ChartVersion string `json:"chartVersion,omitempty"` + + // The list of components comprising the control plane and their statuses. + v1.ComponentStatusList `json:",inline"` + + // The readiness status of components & owned resources + Readiness ReadinessStatus `json:"readiness"` + + // The resulting specification of the configuration options after all profiles + // have been applied. + // +optional + AppliedSpec ControlPlaneSpec `json:"appliedSpec,omitempty"` + + // The resulting values.yaml used to generate the charts. + // +optional + AppliedValues v1.ControlPlaneSpec `json:"appliedValues,omitempty"` +} + +// ReadinessStatus contains readiness information for each deployed component. +type ReadinessStatus struct { + // The readiness status of components + // +optional + Components ReadinessMap `json:"components,omitempty"` +} + +type ReadinessMap map[string][]string + +// GetReconciledVersion returns the reconciled version, or a default for older resources +func (s *ControlPlaneStatus) GetReconciledVersion() string { + if s == nil { + return v1.ComposeReconciledVersion("0.0.0", 0) + } + return v1.ComposeReconciledVersion(s.OperatorVersion, s.ObservedGeneration) +} + +// ControlPlaneSpec represents the configuration for installing a control plane +type ControlPlaneSpec struct { + // XXX: the resource name is intended to be used as the revision name, which + // is used by istio.io/rev labels/annotations to specify which control plane + // workloads should be connecting with. + + // Profiles selects the profile to use for default values. Defaults to + // "default" when not set. + // +optional + Profiles []string `json:"profiles,omitempty"` + + // Version specifies what Maistra version of the control plane to install. + // When creating a new ServiceMeshControlPlane with an empty version, the + // admission webhook sets the version to the current version. + // Existing ServiceMeshControlPlanes with an empty version are treated as + // having the version set to "v1.0" + // +optional + Version string `json:"version,omitempty"` + // Cluster is the general configuration of the cluster (cluster name, + // network name, multi-cluster, mesh expansion, etc.) + // +optional + Cluster *ControlPlaneClusterConfig `json:"cluster,omitempty"` + // General represents general control plane configuration that does not + // logically fit in another area. + // +optional + General *GeneralConfig `json:"general,omitempty"` + // Policy configures policy checking for the control plane. + // .Values.policy.enabled, true if not null + // +optional + Policy *PolicyConfig `json:"policy,omitempty"` + // Proxy configures the default behavior for sidecars. Many values were + // previously exposed through .Values.global.proxy + // +optional + Proxy *ProxyConfig `json:"proxy,omitempty"` + // Security configures aspects of security for the control plane. + // +optional + Security *SecurityConfig `json:"security,omitempty"` + // Telemetry configures telemetry for the mesh. + // .Values.mixer.telemetry.enabled, true if not null. 1.6, .Values.telemetry.enabled + // +optional + Telemetry *TelemetryConfig `json:"telemetry,omitempty"` + // Tracing configures tracing for the mesh. + // +optional + Tracing *TracingConfig `json:"tracing,omitempty"` + // Gateways configures gateways for the mesh + // .Values.gateways.* + // +optional + Gateways *GatewaysConfig `json:"gateways,omitempty"` + // Runtime configuration for pilot (and galley, etc., pre 2.0) + // +optional + Runtime *ControlPlaneRuntimeConfig `json:"runtime,omitempty"` + // Addons is used to configure additional features beyond core control plane + // components, e.g. visualization, metric storage, etc. + // +optional + Addons *AddonsConfig `json:"addons,omitempty"` + // TechPreview contains switches for features that are not GA yet. + // +optional + TechPreview *v1.HelmValues `json:"techPreview,omitempty"` +} + +// Enablement is a common definition for features that can be enabled +type Enablement struct { + // Enabled specifies whether or not this feature is enabled + Enabled *bool `json:"enabled,omitempty"` +} + +func (s ControlPlaneSpec) IsKialiEnabled() bool { + return s.Addons != nil && + s.Addons.Kiali != nil && + s.Addons.Kiali.Enabled != nil && + *s.Addons.Kiali.Enabled +} + +func (s ControlPlaneSpec) IsPrometheusEnabled() bool { + return s.Addons.Prometheus != nil && + s.Addons.Prometheus.Enabled != nil && + *s.Addons.Prometheus.Enabled +} diff --git a/vendor/maistra.io/api/core/v2/conversion.go b/vendor/maistra.io/api/core/v2/conversion.go new file mode 100644 index 00000000000..18da3864672 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/conversion.go @@ -0,0 +1,10 @@ +package v2 + +import ( + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +var _ conversion.Hub = (*ServiceMeshControlPlane)(nil) + +// Hub marks v2 SMCP resource as the storage version +func (smcp *ServiceMeshControlPlane) Hub() {} diff --git a/vendor/maistra.io/api/core/v2/datadog.go b/vendor/maistra.io/api/core/v2/datadog.go new file mode 100644 index 00000000000..7d05654328e --- /dev/null +++ b/vendor/maistra.io/api/core/v2/datadog.go @@ -0,0 +1,6 @@ +package v2 + +// DatadogTracerConfig configures a Datadog tracer for use with the mesh +type DatadogTracerConfig struct { + // TODO.... +} diff --git a/vendor/maistra.io/api/core/v2/gateways.go b/vendor/maistra.io/api/core/v2/gateways.go new file mode 100644 index 00000000000..06e3c1bb9cc --- /dev/null +++ b/vendor/maistra.io/api/core/v2/gateways.go @@ -0,0 +1,162 @@ +package v2 + +import ( + corev1 "k8s.io/api/core/v1" +) + +// GatewaysConfig configures gateways for the mesh +type GatewaysConfig struct { + Enablement `json:",inline"` + // ClusterIngress configures the istio-ingressgateway for the mesh + // works in conjunction with cluster.meshExpansion.ingress configuration + // (for enabling ILB gateway and mesh expansion ports) + // .Values.gateways.istio-ingressgateway + // +optional + ClusterIngress *ClusterIngressGatewayConfig `json:"ingress,omitempty"` + // ClusterEgress configures the istio-egressgateway for the mesh. + // .Values.gateways.istio-egressgateway + // +optional + ClusterEgress *EgressGatewayConfig `json:"egress,omitempty"` + // Other user defined ingress gateways + // .Values.gateways. + // +optional + IngressGateways map[string]*IngressGatewayConfig `json:"additionalIngress,omitempty"` + // Other user defined egress gateways + // .Values.gateways. + // +optional + EgressGateways map[string]*EgressGatewayConfig `json:"additionalEgress,omitempty"` + // Route configures the Gateway ↔ OpenShift Route integration + OpenShiftRoute *OpenShiftRouteConfig `json:"openshiftRoute,omitempty"` +} + +// OpenShiftRouteConfig represents the Gateway ↔ OpenShift Route integration +type OpenShiftRouteConfig struct { + Enablement `json:",inline"` +} + +// GatewayConfig represents the configuration for a gateway +// XXX: should standard istio secrets be configured automatically, i.e. should +// the user be forced to add these manually? +type GatewayConfig struct { + Enablement `json:",inline"` + // Namespace is the namespace within which the gateway will be installed, + // defaults to control plane namespace. + // .Values.gateways..namespace + // XXX: for the standard gateways, it might be possible that related + // resources could be installed in control plane namespace instead of the + // gateway namespace. not sure if this is a problem or not. + // +optional + Namespace string `json:"namespace,omitempty"` + // Service configures the service associated with the gateway, e.g. port + // mappings, service type, annotations/labels, etc. + // .Values.gateways..ports, .Values.gateways..type, + // .Values.gateways..loadBalancerIP, + // .Values.gateways..serviceAnnotations, + // .Values.gateways..serviceLabels + // XXX: currently there is no distinction between labels and serviceLabels + // +optional + Service GatewayServiceConfig `json:"service,omitempty"` + // The router mode to be used by the gateway. + // .Values.gateways..env.ISTIO_META_ROUTER_MODE, defaults to sni-dnat + // +optional + RouterMode RouterModeType `json:"routerMode,omitempty"` + // Volumes is used to configure additional Secret and ConfigMap volumes that + // should be mounted for the gateway's pod. + // .Values.gateways..secretVolumes, .Values.gateways..configMapVolumes + // +optional + Volumes []VolumeConfig `json:"volumes,omitempty"` + // Runtime is used to configure execution parameters for the pod/containers + // e.g. resources, replicas, etc. + // +optional + Runtime *ComponentRuntimeConfig `json:"runtime,omitempty"` + // XXX: do we need to support additionalContainers??? +} + +// EgressGatewayConfig represents gateway configuration for egress +type EgressGatewayConfig struct { + GatewayConfig `json:",inline"` + // RequestedNetworkView is a list of networks whose services should be made + // available to the gateway. This is used primarily for mesh expansion/multi-cluster. + // .Values.gateways..env.ISTIO_META_REQUESTED_NETWORK_VIEW env, defaults to empty list + // XXX: I think this is only applicable to egress gateways + // +optional + RequestedNetworkView []string `json:"requestedNetworkView,omitempty"` +} + +// IngressGatewayConfig represents gateway configuration for ingress +type IngressGatewayConfig struct { + GatewayConfig `json:",inline"` + // EnableSDS for the gateway. + // .Values.gateways..sds.enabled + // +optional + SDS *SecretDiscoveryService `json:"sds,omitempty"` +} + +// SecretDiscoveryService configures whether or not SDS is configured for the gateway +type SecretDiscoveryService struct { + Enablement `json:",inline"` + // Runtime configuration for sds sidecar + Runtime *ContainerConfig `json:"runtime,omitempty"` +} + +// ClusterIngressGatewayConfig represents gateway configuration for cluster ingress +type ClusterIngressGatewayConfig struct { + IngressGatewayConfig `json:",inline"` + // .Values.global.k8sIngress.enabled + // implies the following: + // .Values.global.k8sIngress.gatewayName will match the ingress gateway + // .Values.global.k8sIngress.enableHttps will be true if gateway service exposes port 443 + // XXX: not sure whether or not this is specific to multicluster, mesh expansion, or both + // +optional + IngressEnabled *bool `json:"ingress,omitempty"` + // MeshExpansionPorts define the port set used with multi-cluster/mesh expansion + // +optional + MeshExpansionPorts []corev1.ServicePort `json:"meshExpansionPorts,omitempty"` +} + +// RouterModeType represents the router modes available. +type RouterModeType string + +const ( + // RouterModeTypeSNIDNAT represents sni-dnat router mode + RouterModeTypeSNIDNAT RouterModeType = "sni-dnat" + // RouterModeTypeStandard represents standard router mode + RouterModeTypeStandard RouterModeType = "standard" +) + +// GatewayServiceConfig configures the k8s Service associated with the gateway +type GatewayServiceConfig struct { + // XXX: selector is ignored + // Service details used to configure the gateway's Service resource + // +optional + corev1.ServiceSpec `json:",inline"` + // metadata to be applied to the gateway's service (annotations and labels) + // +optional + Metadata *MetadataConfig `json:"metadata,omitempty"` +} + +// VolumeConfig is used to specify volumes that should be mounted on the pod. +type VolumeConfig struct { + // Volume.Name maps to .Values.gateways... (type-name is configMapName or secretName) + // .configVolumes -> .configMapName = volume.name + // .secretVolumes -> .secretName = volume.name + // Only ConfigMap and Secret fields are supported + Volume GatewayVolume `json:"volume,omitempty"` + // Mount.Name maps to .Values.gateways...name + // .configVolumes -> .name = mount.name, .mountPath = mount.mountPath + // .secretVolumes -> .name = mount.name, .mountPath = mount.mountPath + // Only Name and MountPath fields are supported + Mount corev1.VolumeMount `json:"volumeMount,omitempty"` +} + +// GatewayVolume is a pared down version of corev1.Volume, which only supports +// specifying ConfigMap and Secret volume types. +type GatewayVolume struct { + // ConfigMap represents a configMap that should populate this volume + // +optional + ConfigMap *corev1.ConfigMapVolumeSource `json:"configMap,omitempty"` + // Secret represents a secret that should populate this volume. + // More info: https://kubernetes.io/docs/concepts/storage/volumes#secret + // +optional + Secret *corev1.SecretVolumeSource `json:"secret,omitempty"` +} diff --git a/vendor/maistra.io/api/core/v2/general.go b/vendor/maistra.io/api/core/v2/general.go new file mode 100644 index 00000000000..ff3838a58b0 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/general.go @@ -0,0 +1,16 @@ +package v2 + +// GeneralConfig for control plane +type GeneralConfig struct { + // Logging represents the logging configuration for the control plane components + // XXX: Should this be separate from Proxy.Logging? + // +optional + Logging *LoggingConfig `json:"logging,omitempty"` + + // ValidationMessages configures the control plane to add validationMessages + // to the status fields of istio.io resources. This can be usefule for + // detecting configuration errors in resources. + // .Values.galley.enableAnalysis (=v2.0) + ValidationMessages *bool `json:"validationMessages,omitempty"` +} diff --git a/vendor/maistra.io/api/core/v2/grafana.go b/vendor/maistra.io/api/core/v2/grafana.go new file mode 100644 index 00000000000..9555ba10112 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/grafana.go @@ -0,0 +1,69 @@ +package v2 + +// GrafanaAddonConfig configures a grafana instance for use with the mesh. Only +// one of install or address may be specified +type GrafanaAddonConfig struct { + Enablement `json:",inline"` + // Install a new grafana instance and manage with control plane + // +optional + Install *GrafanaInstallConfig `json:"install,omitempty"` + // Address is the address of an existing grafana installation + // implies .Values.kiali.dashboard.grafanaURL + // +optional + Address *string `json:"address,omitempty"` +} + +// GrafanaInstallConfig is used to configure a new installation of grafana. +type GrafanaInstallConfig struct { + // SelfManaged, true if the entire install should be managed by Maistra, false if using grafana CR (not supported) + // +optional + SelfManaged bool `json:"selfManaged,omitempty"` + // Config configures the behavior of the grafana installation + // +optional + Config *GrafanaConfig `json:"config,omitempty"` + // Service configures the k8s Service associated with the grafana installation + // XXX: grafana service config does not follow other addon components' structure + // +optional + Service *ComponentServiceConfig `json:"service,omitempty"` + // Persistence configures a PersistentVolume associated with the grafana installation + // .Values.grafana.persist, true if not null + // XXX: capacity is not supported in the charts, hard coded to 5Gi + // +optional + Persistence *ComponentPersistenceConfig `json:"persistence,omitempty"` + // Security is used to secure the grafana service. + // .Values.grafana.security.enabled, true if not null + // XXX: unused for maistra, as we use oauth-proxy + // +optional + Security *GrafanaSecurityConfig `json:"security,omitempty"` +} + +// GrafanaConfig configures the behavior of the grafana installation +type GrafanaConfig struct { + // Env allows specification of various grafana environment variables to be + // configured on the grafana container. + // .Values.grafana.env + // XXX: This is pretty cheesy... + // +optional + Env map[string]string `json:"env,omitempty"` + // EnvSecrets allows specification of secret fields into grafana environment + // variables to be configured on the grafana container + // .Values.grafana.envSecrets + // XXX: This is pretty cheesy... + // +optional + EnvSecrets map[string]string `json:"envSecrets,omitempty"` +} + +// GrafanaSecurityConfig is used to secure access to grafana +type GrafanaSecurityConfig struct { + Enablement `json:",inline"` + // SecretName is the name of a secret containing the username/password that + // should be used to access grafana. + // +optional + SecretName string `json:"secretName,omitempty"` + // UsernameKey is the name of the key within the secret identifying the username. + // +optional + UsernameKey string `json:"usernameKey,omitempty"` + // PassphraseKey is the name of the key within the secret identifying the password. + // +optional + PassphraseKey string `json:"passphraseKey,omitempty"` +} diff --git a/vendor/maistra.io/api/core/v2/groupversion_info.go b/vendor/maistra.io/api/core/v2/groupversion_info.go new file mode 100644 index 00000000000..e908343ade6 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/groupversion_info.go @@ -0,0 +1,47 @@ +/* +Copyright Red Hat, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v2 contains API Schema definitions for the maistra.io v2 API group +//+kubebuilder:object:generate=true +//+groupName=maistra.io +package v2 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: "maistra.io", Version: "v2"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) + +func init() { + SchemeBuilder.Register( + &ServiceMeshControlPlane{}, &ServiceMeshControlPlaneList{}, + ) +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} diff --git a/vendor/maistra.io/api/core/v2/jaeger.go b/vendor/maistra.io/api/core/v2/jaeger.go new file mode 100644 index 00000000000..b1c91e32095 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/jaeger.go @@ -0,0 +1,98 @@ +package v2 + +import v1 "maistra.io/api/core/v1" + +// JaegerAddonConfig configuration specific to Jaeger integration. +// XXX: this currently deviates from upstream, which creates a jaeger all-in-one deployment manually +type JaegerAddonConfig struct { + // Name of Jaeger CR, Namespace must match control plane namespace + Name string `json:"name,omitempty"` + // Install configures a Jaeger installation, which will be created if the + // named Jaeger resource is not present. If null, the named Jaeger resource + // must exist. + // +optional + Install *JaegerInstallConfig `json:"install,omitempty"` +} + +// JaegerInstallConfig configures a Jaeger installation. +type JaegerInstallConfig struct { + // Config represents the configuration of Jaeger behavior. + // +optional + Storage *JaegerStorageConfig `json:"storage,omitempty"` + // Ingress configures k8s Ingress or OpenShift Route for Jaeger services + // .Values.tracing.jaeger.ingress.enabled, false if null + // +optional + Ingress *JaegerIngressConfig `json:"ingress,omitempty"` +} + +// JaegerStorageConfig configures the storage used by the Jaeger installation. +type JaegerStorageConfig struct { + // Type of storage to use + Type JaegerStorageType `json:"type,omitempty"` + // Memory represents configuration of in-memory storage + // implies .Values.tracing.jaeger.template=all-in-one + // +optional + Memory *JaegerMemoryStorageConfig `json:"memory,omitempty"` + // Elasticsearch represents configuration of elasticsearch storage + // implies .Values.tracing.jaeger.template=production-elasticsearch + // +optional + Elasticsearch *JaegerElasticsearchStorageConfig `json:"elasticsearch,omitempty"` +} + +// JaegerStorageType represents the type of storage configured for Jaeger +type JaegerStorageType string + +const ( + // JaegerStorageTypeMemory represents in-memory storage + JaegerStorageTypeMemory JaegerStorageType = "Memory" + // JaegerStorageTypeElasticsearch represents Elasticsearch storage + JaegerStorageTypeElasticsearch JaegerStorageType = "Elasticsearch" +) + +// JaegerMemoryStorageConfig configures in-memory storage parameters for Jaeger +type JaegerMemoryStorageConfig struct { + // MaxTraces to store + // .Values.tracing.jaeger.memory.max_traces, defaults to 100000 + // +optional + MaxTraces *int64 `json:"maxTraces,omitempty"` +} + +// JaegerElasticsearchStorageConfig configures elasticsearch storage parameters for Jaeger +type JaegerElasticsearchStorageConfig struct { + // NodeCount represents the number of elasticsearch nodes to create. + // .Values.tracing.jaeger.elasticsearch.nodeCount, defaults to 3 + // +optional + NodeCount *int32 `json:"nodeCount,omitempty"` + // Storage represents storage configuration for elasticsearch. + // .Values.tracing.jaeger.elasticsearch.storage, raw yaml + // XXX: RawExtension? + // +optional + Storage *v1.HelmValues `json:"storage,omitempty"` + // RedundancyPolicy configures the redundancy policy for elasticsearch + // .Values.tracing.jaeger.elasticsearch.redundancyPolicy, raw yaml + // +optional + RedundancyPolicy string `json:"redundancyPolicy,omitempty"` + // IndexCleaner represents the configuration for the elasticsearch index cleaner + // .Values.tracing.jaeger.elasticsearch.esIndexCleaner, raw yaml + // XXX: RawExtension? + // +optional + IndexCleaner *v1.HelmValues `json:"indexCleaner,omitempty"` +} + +// JaegerIngressConfig configures k8s Ingress or OpenShift Route for exposing +// Jaeger services. +type JaegerIngressConfig struct { + Enablement `json:",inline"` + // Metadata represents addtional annotations/labels to be applied to the ingress/route. + // +optional + Metadata *MetadataConfig `json:"metadata,omitempty"` +} + +// ResourceName returns the resource name for the Jaeger resource, returning a +// sensible default if the Name field is not set ("jaeger"). +func (c JaegerAddonConfig) ResourceName() string { + if c.Name == "" { + return "jaeger" + } + return c.Name +} diff --git a/vendor/maistra.io/api/core/v2/kiali.go b/vendor/maistra.io/api/core/v2/kiali.go new file mode 100644 index 00000000000..3d2415a11e9 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/kiali.go @@ -0,0 +1,52 @@ +package v2 + +// KialiAddonConfig is used to configure a kiali instance for use with the mesh +type KialiAddonConfig struct { + Enablement `json:",inline"` + // Name of Kiali CR, Namespace must match control plane namespace + Name string `json:"name,omitempty"` + // Install a Kiali resource if the named Kiali resource is not present. + // +optional + Install *KialiInstallConfig `json:"install,omitempty"` +} + +// KialiInstallConfig is used to configure a kiali installation +type KialiInstallConfig struct { + // Dashboard configures the behavior of the kiali dashboard. + // +optional + Dashboard *KialiDashboardConfig `json:"dashboard,omitempty"` + // Service is used to configure the k8s Service associated with the kiali + // installation. + // XXX: provided for upstream support, only ingress is used, and then only + // for enablement and contextPath + // +optional + Service *ComponentServiceConfig `json:"service,omitempty"` +} + +// KialiDashboardConfig configures the behavior of the kiali dashboard +type KialiDashboardConfig struct { + // ViewOnly configures view_only_mode for the dashboard + // .Values.kiali.dashboard.viewOnlyMode + // +optional + ViewOnly *bool `json:"viewOnly,omitempty"` + // XXX: should the user have a choice here, or should these be configured + // automatically if they are enabled for the control plane installation? + // Grafana endpoint will be configured based on Grafana configuration + // +optional + EnableGrafana *bool `json:"enableGrafana,omitempty"` + // Prometheus endpoint will be configured based on Prometheus configuration + // +optional + EnablePrometheus *bool `json:"enablePrometheus,omitempty"` + // Tracing endpoint will be configured based on Tracing configuration + // +optional + EnableTracing *bool `json:"enableTracing,omitempty"` +} + +// ResourceName returns the resource name for the Kiali resource, returning a +// sensible default if the Name field is not set ("kiali"). +func (c KialiAddonConfig) ResourceName() string { + if c.Name == "" { + return "kiali" + } + return c.Name +} diff --git a/vendor/maistra.io/api/core/v2/lightstep.go b/vendor/maistra.io/api/core/v2/lightstep.go new file mode 100644 index 00000000000..3494818cb3a --- /dev/null +++ b/vendor/maistra.io/api/core/v2/lightstep.go @@ -0,0 +1,6 @@ +package v2 + +// LightstepTracerConfig configures a Lightstep tracer for use with the mesh +type LightstepTracerConfig struct { + // TODO.... +} diff --git a/vendor/maistra.io/api/core/v2/logging.go b/vendor/maistra.io/api/core/v2/logging.go new file mode 100644 index 00000000000..0a4b8047039 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/logging.go @@ -0,0 +1,93 @@ +package v2 + +// LoggingConfig for control plane components +type LoggingConfig struct { + // ComponentLevels configures log level for specific envoy components + // .Values.global.proxy.componentLogLevel, overridden by sidecar.istio.io/componentLogLevel + // map of : + // +optional + ComponentLevels ComponentLogLevels `json:"componentLevels,omitempty"` + // LogAsJSON enables JSON logging + // .Values.global.logAsJson + // +optional + LogAsJSON *bool `json:"logAsJSON,omitempty"` +} + +// ProxyLoggingConfig configures logging for a component +type ProxyLoggingConfig struct { + // Level the log level + // .Values.global.proxy.logLevel, overridden by sidecar.istio.io/logLevel + // +optional + Level LogLevel `json:"level,omitempty"` + // ComponentLevels configures log level for specific envoy components + // .Values.global.proxy.componentLogLevel, overridden by sidecar.istio.io/componentLogLevel + // map of : + // +optional + ComponentLevels ComponentLogLevels `json:"componentLevels,omitempty"` +} + +// ComponentLogLevels represent various logging levels, e.g. trace, debug, etc. +type ComponentLogLevels map[EnvoyComponent]LogLevel + +// LogLevel represents the logging level +type LogLevel string + +const ( + // LogLevelTrace trace logging level + LogLevelTrace LogLevel = "trace" + // LogLevelDebug debug logging level + LogLevelDebug LogLevel = "debug" + // LogLevelInfo info logging level + LogLevelInfo LogLevel = "info" + // LogLevelWarning warning logging level + LogLevelWarning LogLevel = "warn" + // LogLevelWarningProxy proxy warning logging level + LogLevelWarningProxy LogLevel = "warning" + // LogLevelError error logging level + LogLevelError LogLevel = "error" + // LogLevelCritical critical logging level + LogLevelCritical LogLevel = "critical" + // LogLevelOff disable logging + LogLevelOff LogLevel = "off" +) + +// EnvoyComponent represents an envoy component to configure logging +type EnvoyComponent string + +// not a comprehensive list +const ( + EnvoyComponentAdmin EnvoyComponent = "admin" + EnvoyComponentAssert EnvoyComponent = "assert" + EnvoyComponentBacktrace EnvoyComponent = "backtrace" + EnvoyComponentClient EnvoyComponent = "client" + EnvoyComponentConfig EnvoyComponent = "config" + EnvoyComponentConnection EnvoyComponent = "connection" + EnvoyComponentConnHandler EnvoyComponent = "conn_handler" + EnvoyComponentFile EnvoyComponent = "file" + EnvoyComponentFilter EnvoyComponent = "filter" + EnvoyComponentForwardProxy EnvoyComponent = "forward_proxy" + EnvoyComponentGRPC EnvoyComponent = "grpc" + EnvoyComponentHealth EnvoyComponent = "hc" + EnvoyComponentHealthChecker EnvoyComponent = "health_checker" + EnvoyComponentHTTP EnvoyComponent = "http" + EnvoyComponentHTTP2 EnvoyComponent = "http2" + EnvoyComponentInit EnvoyComponent = "init" + EnvoyComponentIO EnvoyComponent = "io" + EnvoyComponentJWT EnvoyComponent = "jwt" + EnvoyComponentLua EnvoyComponent = "lua" + EnvoyComponentMain EnvoyComponent = "main" + EnvoyComponentMisc EnvoyComponent = "misc" + EnvoyComponentQuic EnvoyComponent = "quic" + EnvoyComponentPool EnvoyComponent = "pool" + EnvoyComponentRBAC EnvoyComponent = "rbac" + EnvoyComponentRouter EnvoyComponent = "router" + EnvoyComponentRuntime EnvoyComponent = "runtime" + EnvoyComponentStats EnvoyComponent = "stats" + EnvoyComponentSecret EnvoyComponent = "secret" + EnvoyComponentTap EnvoyComponent = "tap" + EnvoyComponentTesting EnvoyComponent = "testing" + EnvoyComponentTracing EnvoyComponent = "tracing" + EnvoyComponentUpstream EnvoyComponent = "upstream" + EnvoyComponentUDP EnvoyComponent = "udp" + EnvoyComponentWASM EnvoyComponent = "wasm" +) diff --git a/vendor/maistra.io/api/core/v2/policy.go b/vendor/maistra.io/api/core/v2/policy.go new file mode 100644 index 00000000000..16a87a218e8 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/policy.go @@ -0,0 +1,91 @@ +package v2 + +// PolicyConfig configures policy aspects of the mesh. +type PolicyConfig struct { + // Required, the policy implementation + // defaults to Istiod 1.6+, Mixer pre-1.6 + Type PolicyType `json:"type,omitempty"` + // Mixer configuration (legacy, v1) + // .Values.mixer.policy.enabled + // +optional + Mixer *MixerPolicyConfig `json:"mixer,omitempty"` + // Remote mixer configuration (legacy, v1) + // .Values.global.remotePolicyAddress + // +optional + Remote *RemotePolicyConfig `json:"remote,omitempty"` +} + +// PolicyType represents the type of policy implementation used by the mesh. +type PolicyType string + +const ( + // PolicyTypeNone represents disabling of policy + // XXX: note, this doesn't appear to affect Istio 1.6, i.e. no different than Istiod setting + PolicyTypeNone PolicyType = "None" + // PolicyTypeMixer represents mixer, v1 implementation + PolicyTypeMixer PolicyType = "Mixer" + // PolicyTypeRemote represents remote mixer, v1 implementation + PolicyTypeRemote PolicyType = "Remote" + // PolicyTypeIstiod represents istio, v2 implementation + PolicyTypeIstiod PolicyType = "Istiod" +) + +// MixerPolicyConfig configures a mixer implementation for policy +// .Values.mixer.policy.enabled +type MixerPolicyConfig struct { + // EnableChecks configures whether or not policy checks should be enabled. + // .Values.global.disablePolicyChecks | default "true" (false, inverted logic) + // Set the following variable to false to disable policy checks by the Mixer. + // Note that metrics will still be reported to the Mixer. + // +optional + EnableChecks *bool `json:"enableChecks,omitempty"` + // FailOpen configures policy checks to fail if mixer cannot be reached. + // .Values.global.policyCheckFailOpen, maps to MeshConfig.policyCheckFailOpen + // policyCheckFailOpen allows traffic in cases when the mixer policy service cannot be reached. + // Default is false which means the traffic is denied when the client is unable to connect to Mixer. + // +optional + FailOpen *bool `json:"failOpen,omitempty"` + // SessionAffinity configures session affinity for sidecar policy connections. + // .Values.mixer.policy.sessionAffinityEnabled + // +optional + SessionAffinity *bool `json:"sessionAffinity,omitempty"` + // Adapters configures available adapters. + // +optional + Adapters *MixerPolicyAdaptersConfig `json:"adapters,omitempty"` +} + +// MixerPolicyAdaptersConfig configures policy adapters for mixer. +type MixerPolicyAdaptersConfig struct { + // UseAdapterCRDs configures mixer to support deprecated mixer CRDs. + // .Values.mixer.policy.adapters.useAdapterCRDs, removed in istio 1.4, defaults to false + // Only supported in v1.0, where it defaulted to true + // +optional + UseAdapterCRDs *bool `json:"useAdapterCRDs,omitempty"` + // Kubernetesenv configures the use of the kubernetesenv adapter. + // .Values.mixer.policy.adapters.kubernetesenv.enabled, defaults to true + // +optional + KubernetesEnv *bool `json:"kubernetesenv,omitempty"` +} + +// RemotePolicyConfig configures a remote mixer instance for policy +type RemotePolicyConfig struct { + // Address represents the address of the mixer server. + // .Values.global.remotePolicyAddress, maps to MeshConfig.mixerCheckServer + Address string `json:"address,omitempty"` + // CreateServices specifies whether or not a k8s Service should be created for the remote policy server. + // .Values.global.createRemoteSvcEndpoints + // +optional + CreateService *bool `json:"createService,omitempty"` + // EnableChecks configures whether or not policy checks should be enabled. + // .Values.global.disablePolicyChecks | default "true" (false, inverted logic) + // Set the following variable to false to disable policy checks by the Mixer. + // Note that metrics will still be reported to the Mixer. + // +optional + EnableChecks *bool `json:"enableChecks,omitempty"` + // FailOpen configures policy checks to fail if mixer cannot be reached. + // .Values.global.policyCheckFailOpen, maps to MeshConfig.policyCheckFailOpen + // policyCheckFailOpen allows traffic in cases when the mixer policy service cannot be reached. + // Default is false which means the traffic is denied when the client is unable to connect to Mixer. + // +optional + FailOpen *bool `json:"failOpen,omitempty"` +} diff --git a/vendor/maistra.io/api/core/v2/prometheus.go b/vendor/maistra.io/api/core/v2/prometheus.go new file mode 100644 index 00000000000..ece65ed0d55 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/prometheus.go @@ -0,0 +1,58 @@ +package v2 + +// PrometheusAddonConfig configures a prometheus instance to be used by the +// control plane. Only one of Install or Address may be specified +type PrometheusAddonConfig struct { + Enablement `json:",inline"` + // MetricsExpiryDuration is the duration to hold metrics. (mixer/v1 only) + // .Values.mixer.adapters.prometheus.metricsExpiryDuration, defaults to 10m + // +optional + MetricsExpiryDuration string `json:"metricsExpiryDuration,omitempty"` + // Scrape metrics from the pod if true. (maistra-2.0+) + // defaults to true + // .Values.meshConfig.enablePrometheusMerge + // +optional + Scrape *bool `json:"scrape,omitempty"` + // Install configuration if not using an existing prometheus installation. + // .Values.prometheus.enabled, if not null + // +optional + Install *PrometheusInstallConfig `json:"install,omitempty"` + // Address of existing prometheus installation + // implies .Values.kiali.prometheusAddr + // XXX: do we need to do anything to configure credentials for accessing + // the prometheus server? + // +optional + Address *string `json:"address,omitempty"` +} + +// PrometheusInstallConfig represents the configuration to be applied when +// installing a new instance of prometheus for use with the mesh. +type PrometheusInstallConfig struct { + // SelfManaged specifies whether or not the entire install should be managed + // by Maistra (true) or the Prometheus operator (false, not supported). + // Governs use of either prometheus charts or prometheusOperator charts. + // +optional + SelfManaged bool `json:"selfManaged,omitempty"` + // Retention specifies how long metrics should be retained by prometheus. + // .Values.prometheus.retention, defaults to 6h + // +optional + Retention string `json:"retention,omitempty"` + // ScrapeInterval specifies how frequently prometheus should scrape pods for + // metrics. + // .Values.prometheus.scrapeInterval, defaults to 15s + // +optional + ScrapeInterval string `json:"scrapeInterval,omitempty"` + // Service allows for customization of the k8s Service associated with the + // prometheus installation. + // +optional + Service *ComponentServiceConfig `json:"service,omitempty"` + // UseTLS for the prometheus server + // .Values.prometheus.provisionPrometheusCert + // 1.6+ + //ProvisionCert bool + // this seems to overlap with provision cert, as this manifests something similar to the above + // .Values.prometheus.security.enabled, version < 1.6 + //EnableSecurity bool + // +optional + UseTLS *bool `json:"useTLS,omitempty"` +} diff --git a/vendor/maistra.io/api/core/v2/proxy.go b/vendor/maistra.io/api/core/v2/proxy.go new file mode 100644 index 00000000000..7e657785cb9 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/proxy.go @@ -0,0 +1,387 @@ +package v2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// ProxyConfig configures the default sidecar behavior for workloads. +type ProxyConfig struct { + // Logging configures logging for the sidecar. + // e.g. .Values.global.proxy.logLevel + // +optional + Logging *ProxyLoggingConfig `json:"logging,omitempty"` + // Networking represents network settings to be configured for the sidecars. + // +optional + Networking *ProxyNetworkingConfig `json:"networking,omitempty"` + // Runtime is used to customize runtime configuration for the sidecar container. + // +optional + Runtime *ProxyRuntimeConfig `json:"runtime,omitempty"` + // Injection is used to customize sidecar injection for the mesh. + // +optional + Injection *ProxyInjectionConfig `json:"injection,omitempty"` + // AdminPort configures the admin port exposed by the sidecar. + // maps to defaultConfig.proxyAdminPort, defaults to 15000 + // XXX: currently not configurable in charts + // +optional + AdminPort int32 `json:"adminPort,omitempty"` + // Concurrency configures the number of threads that should be run by the sidecar. + // .Values.global.proxy.concurrency, maps to defaultConfig.concurrency + // XXX: removed in 1.7 + // XXX: this is defaulted to 2 in our values.yaml, but should probably be 0 + // +optional + Concurrency *int32 `json:"concurrency,omitempty"` + // AccessLogging configures access logging for proxies. + // +optional + AccessLogging *ProxyAccessLoggingConfig `json:"accessLogging,omitempty"` + // EnvoyMetricsService configures reporting of Envoy metrics to an external + // service. + // .Values.global.proxy.envoyMetricsService + // +optional + EnvoyMetricsService *ProxyEnvoyServiceConfig `json:"envoyMetricsService,omitempty"` +} + +// ProxyNetworkingConfig is used to configure networking aspects of the sidecar. +type ProxyNetworkingConfig struct { + // ClusterDomain represents the domain for the cluster, defaults to cluster.local + // .Values.global.proxy.clusterDomain + // +optional + ClusterDomain string `json:"clusterDomain,omitempty"` + // maps to meshConfig.defaultConfig.connectionTimeout, defaults to 10s + // XXX: currently not exposed through values.yaml + // +optional + ConnectionTimeout string `json:"connectionTimeout,omitempty"` + // MaxConnectionAge limits how long a sidecar can be connected to pilot. + // This may be used to balance load across pilot instances, at the cost of + // system churn. + // .Values.pilot.keepaliveMaxServerConnectionAge + // +optional + MaxConnectionAge string `json:"maxConnectionAge,omitempty"` + // Initialization is used to specify how the pod's networking through the + // proxy is initialized. This configures the use of CNI or an init container. + // +optional + Initialization *ProxyNetworkInitConfig `json:"initialization,omitempty"` + // TrafficControl configures what network traffic is routed through the proxy. + // +optional + TrafficControl *ProxyTrafficControlConfig `json:"trafficControl,omitempty"` + // Protocol configures how the sidecar works with applicaiton protocols. + // +optional + Protocol *ProxyNetworkProtocolConfig `json:"protocol,omitempty"` + // DNS configures aspects of the sidecar's usage of DNS + // +optional + DNS *ProxyDNSConfig `json:"dns,omitempty"` +} + +// ProxyNetworkInitConfig is used to configure how the pod's networking through +// the proxy is initialized. +type ProxyNetworkInitConfig struct { + // Type of the network initialization implementation. + Type ProxyNetworkInitType `json:"type,omitempty"` + // InitContainer configures the use of a pod init container for initializing + // the pod's networking. + // istio_cni.enabled = false, if InitContainer is used + // +optional + InitContainer *ProxyInitContainerConfig `json:"initContainer,omitempty"` +} + +// ProxyNetworkInitType represents the type of initializer to use for network initialization +type ProxyNetworkInitType string + +const ( + // ProxyNetworkInitTypeCNI to use CNI for network initialization + ProxyNetworkInitTypeCNI ProxyNetworkInitType = "CNI" + // ProxyNetworkInitTypeInitContainer to use an init container for network initialization + ProxyNetworkInitTypeInitContainer ProxyNetworkInitType = "InitContainer" +) + +// ProxyInitContainerConfig configures execution aspects for the init container +type ProxyInitContainerConfig struct { + // Runtime configures customization of the init container (e.g. resources) + // +optional + Runtime *ContainerConfig `json:"runtime,omitempty"` +} + +// ProxyTrafficControlConfig configures what and how traffic is routed through +// the sidecar. +type ProxyTrafficControlConfig struct { + // Inbound configures what inbound traffic is routed through the sidecar + // traffic.sidecar.istio.io/includeInboundPorts defaults to * (all ports) + // +optional + Inbound ProxyInboundTrafficControlConfig `json:"inbound,omitempty"` + // Outbound configures what outbound traffic is routed through the sidecar. + // +optional + Outbound ProxyOutboundTrafficControlConfig `json:"outbound,omitempty"` +} + +// ProxyNetworkInterceptionMode represents the InterceptMode types. +type ProxyNetworkInterceptionMode string + +const ( + // ProxyNetworkInterceptionModeRedirect requests iptables use REDIRECT to route inbound traffic through the sidecar. + ProxyNetworkInterceptionModeRedirect ProxyNetworkInterceptionMode = "REDIRECT" + // ProxyNetworkInterceptionModeTProxy requests iptables use TPROXY to route inbound traffic through the sidecar. + ProxyNetworkInterceptionModeTProxy ProxyNetworkInterceptionMode = "TPROXY" +) + +// ProxyInboundTrafficControlConfig configures what inbound traffic is +// routed through the sidecar. +type ProxyInboundTrafficControlConfig struct { + // InterceptionMode specifies how traffic is directed through the sidecar. + // maps to meshConfig.defaultConfig.interceptionMode, overridden by sidecar.istio.io/interceptionMode + // XXX: currently not configurable through values.yaml + // +optional + InterceptionMode ProxyNetworkInterceptionMode `json:"interceptionMode,omitempty"` + // IncludedPorts to be routed through the sidecar. * or comma separated list of integers + // .Values.global.proxy.includeInboundPorts, defaults to * (all ports), overridden by traffic.sidecar.istio.io/includeInboundPorts + // +optional + IncludedPorts []string `json:"includedPorts,omitempty"` + // ExcludedPorts to be routed around the sidecar. + // .Values.global.proxy.excludeInboundPorts, defaults to empty list, overridden by traffic.sidecar.istio.io/excludeInboundPorts + // +optional + ExcludedPorts []int32 `json:"excludedPorts,omitempty"` +} + +// ProxyOutboundTrafficControlConfig configure what outbound traffic is routed +// through the sidecar +type ProxyOutboundTrafficControlConfig struct { + // IncludedIPRanges specifies which outbound IP ranges should be routed through the sidecar. + // .Values.global.proxy.includeIPRanges, overridden by traffic.sidecar.istio.io/includeOutboundIPRanges + // * or comma separated list of CIDR + // +optional + IncludedIPRanges []string `json:"includedIPRanges,omitempty"` + // ExcludedIPRanges specifies which outbound IP ranges should _not_ be routed through the sidecar. + // .Values.global.proxy.excludeIPRanges, overridden by traffic.sidecar.istio.io/excludeOutboundIPRanges + // * or comma separated list of CIDR + // +optional + ExcludedIPRanges []string `json:"excludedIPRanges,omitempty"` + // ExcludedPorts specifies which outbound ports should _not_ be routed through the sidecar. + // .Values.global.proxy.excludeOutboundPorts, overridden by traffic.sidecar.istio.io/excludeOutboundPorts + // comma separated list of integers + // +optional + ExcludedPorts []int32 `json:"excludedPorts,omitempty"` + // Policy specifies what outbound traffic is allowed through the sidecar. + // .Values.global.outboundTrafficPolicy.mode + // +optional + Policy ProxyOutboundTrafficPolicy `json:"policy,omitempty"` +} + +// ProxyOutboundTrafficPolicy represents the outbound traffic policy type. +type ProxyOutboundTrafficPolicy string + +const ( + // ProxyOutboundTrafficPolicyAllowAny allows all traffic through the sidecar. + ProxyOutboundTrafficPolicyAllowAny ProxyOutboundTrafficPolicy = "ALLOW_ANY" + // ProxyOutboundTrafficPolicyRegistryOnly only allows traffic destined for a + // service in the service registry through the sidecar. This limits outbound + // traffic to only other services in the mesh. + ProxyOutboundTrafficPolicyRegistryOnly ProxyOutboundTrafficPolicy = "REGISTRY_ONLY" +) + +// ProxyNetworkProtocolConfig configures the sidecar's protocol handling. +type ProxyNetworkProtocolConfig struct { + // AutoDetect configures automatic detection of connection protocols. + // +optional + AutoDetect *ProxyNetworkAutoProtocolDetectionConfig `json:"autoDetect,omitempty"` +} + +// ProxyNetworkAutoProtocolDetectionConfig configures automatic protocol detection for the proxies. +type ProxyNetworkAutoProtocolDetectionConfig struct { + // DetectionTimeout specifies how much time the sidecar will spend determining + // the protocol being used for the connection before reverting to raw TCP. + // .Values.global.proxy.protocolDetectionTimeout, maps to protocolDetectionTimeout + // +optional + Timeout string `json:"timeout,omitempty"` + // EnableInboundSniffing enables protocol sniffing on inbound traffic. + // .Values.pilot.enableProtocolSniffingForInbound + // only supported for v1.1 + // +optional + Inbound *bool `json:"inbound,omitempty"` + // EnableOutboundSniffing enables protocol sniffing on outbound traffic. + // .Values.pilot.enableProtocolSniffingForOutbound + // only supported for v1.1 + // +optional + Outbound *bool `json:"outbound,omitempty"` +} + +// ProxyDNSConfig is used to configure aspects of the sidecar's DNS usage. +type ProxyDNSConfig struct { + // SearchSuffixes are additional search suffixes to be used when resolving + // names. + // .Values.global.podDNSSearchNamespaces + // Custom DNS config for the pod to resolve names of services in other + // clusters. Use this to add additional search domains, and other settings. + // see + // https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#dns-config + // This does not apply to gateway pods as they typically need a different + // set of DNS settings than the normal application pods (e.g., in + // multicluster scenarios). + // NOTE: If using templates, follow the pattern in the commented example below. + // podDNSSearchNamespaces: + // - global + // - "{{ valueOrDefault .DeploymentMeta.Namespace \"default\" }}.global" + // +optional + SearchSuffixes []string `json:"searchSuffixes,omitempty"` + // RefreshRate configures the DNS refresh rate for Envoy cluster of type STRICT_DNS + // This must be given it terms of seconds. For example, 300s is valid but 5m is invalid. + // .Values.global.proxy.dnsRefreshRate, default 300s + // +optional + RefreshRate string `json:"refreshRate,omitempty"` +} + +// ProxyRuntimeConfig customizes the runtime parameters of the sidecar container. +type ProxyRuntimeConfig struct { + // Readiness configures the readiness probe behavior for the injected pod. + // +optional + Readiness *ProxyReadinessConfig `json:"readiness,omitempty"` + // Container configures the sidecar container. + // +optional + Container *ContainerConfig `json:"container,omitempty"` +} + +// ProxyReadinessConfig configures the readiness probe for the sidecar. +type ProxyReadinessConfig struct { + // RewriteApplicationProbes specifies whether or not the injector should + // rewrite application container probes to be routed through the sidecar. + // .Values.sidecarInjectorWebhook.rewriteAppHTTPProbe, defaults to false + // rewrite probes for application pods to route through sidecar + // +optional + RewriteApplicationProbes bool `json:"rewriteApplicationProbes,omitempty"` + // StatusPort specifies the port number to be used for status. + // .Values.global.proxy.statusPort, overridden by status.sidecar.istio.io/port, defaults to 15020 + // Default port for Pilot agent health checks. A value of 0 will disable health checking. + // XXX: this has no affect on which port is actually used for status. + // +optional + StatusPort int32 `json:"statusPort,omitempty"` + // InitialDelaySeconds specifies the initial delay for the readiness probe + // .Values.global.proxy.readinessInitialDelaySeconds, overridden by readiness.status.sidecar.istio.io/initialDelaySeconds, defaults to 1 + // +optional + InitialDelaySeconds int32 `json:"initialDelaySeconds,omitempty"` + // PeriodSeconds specifies the period over which the probe is checked. + // .Values.global.proxy.readinessPeriodSeconds, overridden by readiness.status.sidecar.istio.io/periodSeconds, defaults to 2 + // +optional + PeriodSeconds int32 `json:"periodSeconds,omitempty"` + // FailureThreshold represents the number of consecutive failures before the container is marked as not ready. + // .Values.global.proxy.readinessFailureThreshold, overridden by readiness.status.sidecar.istio.io/failureThreshold, defaults to 30 + // +optional + FailureThreshold int32 `json:"failureThreshold,omitempty"` +} + +// ProxyInjectionConfig configures sidecar injection for the mesh. +type ProxyInjectionConfig struct { + // AutoInject configures automatic injection of sidecar proxies + // .Values.global.proxy.autoInject + // .Values.sidecarInjectorWebhook.enableNamespacesByDefault + // +optional + AutoInject *bool `json:"autoInject,omitempty"` + // AlwaysInjectSelector allows specification of a label selector that when + // matched will always inject a sidecar into the pod. + // .Values.sidecarInjectorWebhook.alwaysInjectSelector + // +optional + AlwaysInjectSelector []metav1.LabelSelector `json:"alwaysInjectSelector,omitempty"` + // NeverInjectSelector allows specification of a label selector that when + // matched will never inject a sidecar into the pod. This takes precendence + // over AlwaysInjectSelector. + // .Values.sidecarInjectorWebhook.neverInjectSelector + // +optional + NeverInjectSelector []metav1.LabelSelector `json:"neverInjectSelector,omitempty"` + // InjectedAnnotations allows specification of additional annotations to be + // added to pods that have sidecars injected in them. + // .Values.sidecarInjectorWebhook.injectedAnnotations + // +optional + InjectedAnnotations map[string]string `json:"injectedAnnotations,omitempty"` +} + +// ProxyAccessLoggingConfig configures access logging for proxies. Multiple +// access logs can be configured. +type ProxyAccessLoggingConfig struct { + // File configures access logging to the file system + // +optional + File *ProxyFileAccessLogConfig `json:"file,omitempty"` + // File configures access logging to an envoy service + // .Values.global.proxy.envoyAccessLogService + // +optional + EnvoyService *ProxyEnvoyServiceConfig `json:"envoyService,omitempty"` +} + +// ProxyFileAccessLogConfig configures details related to file access log +type ProxyFileAccessLogConfig struct { + // Name is the name of the file to which access log entries will be written. + // If Name is not specified, no log entries will be written to a file. + // .Values.global.proxy.accessLogFile + // +optional + Name string `json:"name,omitempty"` + // Encoding to use when writing access log entries. Currently, JSON or TEXT + // may be specified. + // .Values.global.proxy.accessLogEncoding + // +optional + Encoding string `json:"encoding,omitempty"` + // Format to use when writing access log entries. + // .Values.global.proxy.accessLogFormat + // +optional + Format string `json:"format,omitempty"` +} + +// ProxyEnvoyServiceConfig configures reporting to an external Envoy service. +type ProxyEnvoyServiceConfig struct { + // Enable sending Envoy metrics to the service. + // .Values.global.proxy.(envoyAccessLogService|envoyMetricsService).enabled + Enablement `json:",inline"` + // Address of the service specified as host:port. + // .Values.global.proxy.(envoyAccessLogService|envoyMetricsService).host + // .Values.global.proxy.(envoyAccessLogService|envoyMetricsService).port + // +optional + Address string `json:"address,omitempty"` + // TCPKeepalive configures keepalive settings to use when connecting to the + // service. + // .Values.global.proxy.(envoyAccessLogService|envoyMetricsService).tcpKeepalive + // +optional + TCPKeepalive *EnvoyServiceTCPKeepalive `json:"tcpKeepalive,omitempty"` + // TLSSettings configures TLS settings to use when connecting to the service. + // .Values.global.proxy.(envoyAccessLogService|envoyMetricsService).tlsSettings + // +optional + TLSSettings *EnvoyServiceClientTLSSettings `json:"tlsSettings,omitempty"` +} + +// EnvoyServiceTCPKeepalive configures keepalive settings for the Envoy service. +// Provides the same interface as networking.v1alpha3.istio.io, ConnectionPoolSettings_TCPSettings_TcpKeepalive +type EnvoyServiceTCPKeepalive struct { + // Probes represents the number of successive probe failures after which the + // connection should be considered "dead." + // +optional + Probes uint32 `json:"probes,omitempty"` + // Time represents the length of idle time that must elapse before a probe + // is sent. + // +optional + Time string `json:"time,omitempty"` + // Interval represents the interval between probes. + // +optional + Interval string `json:"interval,omitempty"` +} + +// EnvoyServiceClientTLSSettings configures TLS settings for the Envoy service. +// Provides the same interface as networking.v1alpha3.istio.io, ClientTLSSettings +type EnvoyServiceClientTLSSettings struct { + // Mode represents the TLS mode to apply to the connection. The following + // values are supported: DISABLE, SIMPLE, MUTUAL, ISTIO_MUTUAL + // +optional + Mode string `json:"mode,omitempty"` + // ClientCertificate represents the file name containing the client certificate + // to show to the Envoy service, e.g. /etc/istio/als/cert-chain.pem + // +optional + ClientCertificate string `json:"clientCertificate,omitempty"` + // PrivateKey represents the file name containing the private key used by + // the client, e.g. /etc/istio/als/key.pem + // +optional + PrivateKey string `json:"privateKey,omitempty"` + // CACertificates represents the file name containing the root certificates + // for the CA, e.g. /etc/istio/als/root-cert.pem + // +optional + CACertificates string `json:"caCertificates,omitempty"` + // SNIHost represents the host name presented to the server during TLS + // handshake, e.g. als.somedomain + // +optional + SNIHost string `json:"sni,omitempty"` + // SubjectAltNames represents the list of alternative names that may be used + // to verify the servers identity, e.g. [als.someotherdomain] + // +optional + SubjectAltNames []string `json:"subjectAltNames,omitempty"` +} diff --git a/vendor/maistra.io/api/core/v2/runtime.go b/vendor/maistra.io/api/core/v2/runtime.go new file mode 100644 index 00000000000..17cfc516961 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/runtime.go @@ -0,0 +1,334 @@ +package v2 + +import ( + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + v1 "maistra.io/api/core/v1" +) + +// ControlPlaneRuntimeConfig configures execution parameters for control plane +// componets. +type ControlPlaneRuntimeConfig struct { + // Components allows specifying execution parameters for specific control plane + // componets. The key of the map is the component name to which the settings + // should be applied. + // +optional + Components map[ControlPlaneComponentName]*ComponentRuntimeConfig `json:"components,omitempty"` + // Defaults will be merged into specific component config. + // .Values.global.defaultResources, e.g. + // +optional + Defaults *DefaultRuntimeConfig `json:"defaults,omitempty"` +} + +// ControlPlaneComponentName simple type for control plane component names +type ControlPlaneComponentName string + +const ( + // ControlPlaneComponentNameSecurity - security (citadel) + ControlPlaneComponentNameSecurity ControlPlaneComponentName = "security" + // ControlPlaneComponentNameGalley - galley + ControlPlaneComponentNameGalley ControlPlaneComponentName = "galley" + // ControlPlaneComponentNamePilot - pilot + ControlPlaneComponentNamePilot ControlPlaneComponentName = "pilot" + // ControlPlaneComponentNameMixer - mixer + ControlPlaneComponentNameMixer ControlPlaneComponentName = "mixer" + // ControlPlaneComponentNameMixerPolicy - mixer.policy + ControlPlaneComponentNameMixerPolicy ControlPlaneComponentName = "mixer.policy" + // ControlPlaneComponentNameMixerTelemetry - mixer.telemetry + ControlPlaneComponentNameMixerTelemetry ControlPlaneComponentName = "mixer.telemetry" + // ControlPlaneComponentNameGlobalOauthProxy - global.oauthproxy + ControlPlaneComponentNameGlobalOauthProxy ControlPlaneComponentName = "global.oauthproxy" + // ControlPlaneComponentNameSidecarInjectoryWebhook - sidecarInjectorWebhook + ControlPlaneComponentNameSidecarInjectoryWebhook ControlPlaneComponentName = "sidecarInjectorWebhook" + // ControlPlaneComponentNameTracing - tracing + ControlPlaneComponentNameTracing ControlPlaneComponentName = "tracing" + // ControlPlaneComponentNameTracingJaeger - tracing.jaeger + ControlPlaneComponentNameTracingJaeger ControlPlaneComponentName = "tracing.jaeger" + // ControlPlaneComponentNameTracingJaegerElasticsearch - tracing.jaeger.elasticsearch + ControlPlaneComponentNameTracingJaegerElasticsearch ControlPlaneComponentName = "tracing.jaeger.elasticsearch" + // ControlPlaneComponentNameTracingJaegerAgent - tracing.jaeger.agent + ControlPlaneComponentNameTracingJaegerAgent ControlPlaneComponentName = "tracing.jaeger.agent" + // ControlPlaneComponentNameTracingJaegerAllInOne - tracing.jaeger.allInOne + ControlPlaneComponentNameTracingJaegerAllInOne ControlPlaneComponentName = "tracing.jaeger.allInOne" + // ControlPlaneComponentNameTracingJaegerCollector - tracing.jaeger.collector + ControlPlaneComponentNameTracingJaegerCollector ControlPlaneComponentName = "tracing.jaeger.collector" + // ControlPlaneComponentNameTracingJaegerQuery - tracing.jaeger.query + ControlPlaneComponentNameTracingJaegerQuery ControlPlaneComponentName = "tracing.jaeger.query" + // ControlPlaneComponentNamePrometheus - prometheus + ControlPlaneComponentNamePrometheus ControlPlaneComponentName = "prometheus" + // ControlPlaneComponentNameKiali - kiali + ControlPlaneComponentNameKiali ControlPlaneComponentName = "kiali" + // ControlPlaneComponentNameGrafana - grafana + ControlPlaneComponentNameGrafana ControlPlaneComponentName = "grafana" + // ControlPlaneComponentNameThreeScale - 3scale + ControlPlaneComponentNameThreeScale ControlPlaneComponentName = "3scale" + // ControlPlaneComponentNameWASMCacher - wasm-extensions cacher + ControlPlaneComponentNameWASMCacher ControlPlaneComponentName = "wasmExtensions.cacher" +) + +// ControlPlaneComponentNames - supported runtime components +var ControlPlaneComponentNames = []ControlPlaneComponentName{ + ControlPlaneComponentNameSecurity, + ControlPlaneComponentNameGalley, + ControlPlaneComponentNamePilot, + ControlPlaneComponentNameMixer, + ControlPlaneComponentNameMixerPolicy, + ControlPlaneComponentNameMixerTelemetry, + ControlPlaneComponentNameGlobalOauthProxy, + ControlPlaneComponentNameSidecarInjectoryWebhook, + ControlPlaneComponentNameTracing, + ControlPlaneComponentNameTracingJaeger, + ControlPlaneComponentNameTracingJaegerElasticsearch, + ControlPlaneComponentNameTracingJaegerAgent, + ControlPlaneComponentNameTracingJaegerAllInOne, + ControlPlaneComponentNameTracingJaegerCollector, + ControlPlaneComponentNameTracingJaegerQuery, + ControlPlaneComponentNamePrometheus, + ControlPlaneComponentNameKiali, + ControlPlaneComponentNameGrafana, + ControlPlaneComponentNameThreeScale, + ControlPlaneComponentNameWASMCacher, +} + +// ComponentRuntimeConfig allows for partial customization of a component's +// runtime configuration (Deployment, PodTemplate, auto scaling, pod disruption, etc.) +type ComponentRuntimeConfig struct { + // Deployment specific overrides + // +optional + Deployment *DeploymentRuntimeConfig `json:"deployment,omitempty"` + + // Pod specific overrides + // +optional + Pod *PodRuntimeConfig `json:"pod,omitempty"` + + // .Values.*.resource, imagePullPolicy, etc. + // +optional + Container *ContainerConfig `json:"container,omitempty"` +} + +// DeploymentRuntimeConfig allow customization of a component's Deployment +// resource, including additional labels/annotations, replica count, autoscaling, +// rollout strategy, etc. +type DeploymentRuntimeConfig struct { + // Number of desired pods. This is a pointer to distinguish between explicit + // zero and not specified. Defaults to 1. + // +optional + // .Values.*.replicaCount + Replicas *int32 `json:"replicas,omitempty"` + + // The deployment strategy to use to replace existing pods with new ones. + // +optional + // +patchStrategy=retainKeys + // .Values.*.rollingMaxSurge, rollingMaxUnavailable, etc. + Strategy *appsv1.DeploymentStrategy `json:"strategy,omitempty" patchStrategy:"retainKeys"` + + // Autoscaling specifies the configuration for a HorizontalPodAutoscaler + // to be applied to this deployment. Null indicates no auto scaling. + // .Values.*.autoscale* fields + // +optional + AutoScaling *AutoScalerConfig `json:"autoScaling,omitempty"` +} + +// CommonDeploymentRuntimeConfig represents deployment settings common to both +// default and component specific settings +type CommonDeploymentRuntimeConfig struct { + // .Values.global.podDisruptionBudget.enabled, if not null + // XXX: this is currently a global setting, not per component. perhaps + // this should only be available on the defaults? + // +optional + PodDisruption *PodDisruptionBudget `json:"podDisruption,omitempty"` +} + +// AutoScalerConfig is used to configure autoscaling for a deployment +type AutoScalerConfig struct { + Enablement `json:",inline"` + // lower limit for the number of pods that can be set by the autoscaler, default 1. + // +optional + MinReplicas *int32 `json:"minReplicas,omitempty"` + // upper limit for the number of pods that can be set by the autoscaler; cannot be smaller than MinReplicas. + // +optional + MaxReplicas *int32 `json:"maxReplicas,omitempty"` + // target average CPU utilization (represented as a percentage of requested CPU) over all the pods; + // if not specified the default autoscaling policy will be used. + // +optional + TargetCPUUtilizationPercentage *int32 `json:"targetCPUUtilizationPercentage,omitempty"` +} + +// PodRuntimeConfig is used to customize pod configuration for a component +type PodRuntimeConfig struct { + CommonPodRuntimeConfig `json:",inline"` + + // Metadata allows additional annotations/labels to be applied to the pod + // .Values.*.podAnnotations + // XXX: currently, additional lables are not supported + // +optional + Metadata *MetadataConfig `json:"metadata,omitempty"` + + // If specified, the pod's scheduling constraints + // +optional + // .Values.podAntiAffinityLabelSelector, podAntiAffinityTermLabelSelector, nodeSelector + // NodeAffinity is not supported at this time + // PodAffinity is not supported at this time + Affinity *Affinity `json:"affinity,omitempty"` +} + +// CommonPodRuntimeConfig represents pod settings common to both defaults and +// component specific configuration +type CommonPodRuntimeConfig struct { + // NodeSelector is a selector which must be true for the pod to fit on a node. + // Selector which must match a node's labels for the pod to be scheduled on that node. + // More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + // +optional + // .Values.nodeSelector + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + + // If specified, the pod's tolerations. + // +optional + // .Values.tolerations + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + + // .Values.global.priorityClassName + // XXX: currently, this is only a global setting. maybe only allow setting in global runtime defaults? + // +optional + PriorityClassName string `json:"priorityClassName,omitempty"` +} + +// Affinity is the structure used by Istio for specifying Pod affinity +// XXX: istio does not support full corev1.Affinity settings, hence the special +// types here. +type Affinity struct { + // XXX: use corev1.PodAntiAffinity instead, the only things not supported are namespaces and weighting + // +optional + PodAntiAffinity PodAntiAffinity `json:"podAntiAffinity,omitempty"` +} + +// PodAntiAffinity configures anti affinity for pod scheduling +type PodAntiAffinity struct { + // +optional + RequiredDuringScheduling []PodAntiAffinityTerm `json:"requiredDuringScheduling,omitempty"` + // +optional + PreferredDuringScheduling []PodAntiAffinityTerm `json:"preferredDuringScheduling,omitempty"` +} + +// PodAntiAffinityTerm is a simplified version of corev1.PodAntiAffinityTerm +type PodAntiAffinityTerm struct { + metav1.LabelSelectorRequirement `json:",inline"` + // This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + // the labelSelector in the specified namespaces, where co-located is defined as running on a node + // whose value of the label with key topologyKey matches that of any node on which any of the + // selected pods is running. + // Empty topologyKey is not allowed. + // +optional + TopologyKey string `json:"topologyKey,omitempty"` +} + +// ContainerConfig to be applied to containers in a pod, in a deployment +type ContainerConfig struct { + CommonContainerConfig `json:",inline"` + // +optional + Image string `json:"imageName,omitempty"` + // +optional + Env map[string]string `json:"env,omitempty"` +} + +// CommonContainerConfig represents container settings common to both defaults +// and component specific configuration. +type CommonContainerConfig struct { + // +optional + ImageRegistry string `json:"imageRegistry,omitempty"` + // +optional + ImageTag string `json:"imageTag,omitempty"` + // +optional + ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` + // +optional + ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` + // +optional + Resources *corev1.ResourceRequirements `json:"resources,omitempty"` +} + +// PodDisruptionBudget details +// XXX: currently only configurable globally (i.e. no component values.yaml equivalent) +type PodDisruptionBudget struct { + Enablement `json:",inline"` + // +optional + MinAvailable *intstr.IntOrString `json:"minAvailable,omitempty"` + // +optional + MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty"` +} + +// DefaultRuntimeConfig specifies default execution parameters to apply to +// control plane deployments/pods when no specific component overrides have been +// specified. These settings will be merged with component specific settings. +type DefaultRuntimeConfig struct { + // Deployment defaults + // +optional + Deployment *CommonDeploymentRuntimeConfig `json:"deployment,omitempty"` + // Pod defaults + // +optional + Pod *CommonPodRuntimeConfig `json:"pod,omitempty"` + // Container overrides to be merged with component specific overrides. + // +optional + Container *CommonContainerConfig `json:"container,omitempty"` +} + +// MetadataConfig represents additional metadata to be applied to resources +type MetadataConfig struct { + // +optional + Labels map[string]string `json:"labels,omitempty"` + // +optional + Annotations map[string]string `json:"annotations,omitempty"` +} + +// ComponentServiceConfig is used to customize the service associated with a component. +type ComponentServiceConfig struct { + // Metadata represents addtional annotations/labels to be applied to the + // component's service. + // +optional + Metadata *MetadataConfig `json:"metadata,omitempty"` + // NodePort specifies a NodePort for the component's Service. + // .Values..service.nodePort.port, ...enabled is true if not null + // +optional + NodePort *int32 `json:"nodePort,omitempty"` + // Ingress specifies details for accessing the component's service through + // a k8s Ingress or OpenShift Route. + // +optional + Ingress *ComponentIngressConfig `json:"ingress,omitempty"` +} + +// ComponentIngressConfig is used to customize a k8s Ingress or OpenShift Route +// for the service associated with a component. +type ComponentIngressConfig struct { + Enablement `json:",inline"` + // Metadata represents additional metadata to be applied to the ingress/route. + // +optional + Metadata *MetadataConfig `json:"metadata,omitempty"` + // Hosts represents a list of host names to configure. Note, OpenShift route + // only supports a single host name per route. An empty host name implies + // a default host name for the Route. + // XXX: is a host name required for k8s Ingress? + // +optional + Hosts []string `json:"hosts,omitempty"` + // ContextPath represents the context path to the service. + // +optional + ContextPath string `json:"contextPath,omitempty"` + // TLS is used to configure TLS for the Ingress/Route + // XXX: should this be something like RawExtension, as the configuration differs between Route and Ingress? + // +optional + TLS *v1.HelmValues `json:"tls,omitempty"` +} + +// ComponentPersistenceConfig is used to configure persistance for a component. +type ComponentPersistenceConfig struct { + Enablement `json:",inline"` + // StorageClassName for the PersistentVolumeClaim + // +optional + StorageClassName string `json:"storageClassName,omitempty"` + // AccessMode for the PersistentVolumeClaim + // +optional + AccessMode corev1.PersistentVolumeAccessMode `json:"accessMode,omitempty"` + // Resources to request for the PersistentVolumeClaim + // +optional + Resources *corev1.ResourceRequirements `json:"capacity,omitempty"` +} diff --git a/vendor/maistra.io/api/core/v2/security.go b/vendor/maistra.io/api/core/v2/security.go new file mode 100644 index 00000000000..f8aedf41585 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/security.go @@ -0,0 +1,276 @@ +package v2 + +// SecurityConfig specifies security aspects of the control plane. +type SecurityConfig struct { + // Trust configures trust aspects associated with mutual TLS clients. + // +optional + Trust *TrustConfig `json:"trust,omitempty"` + // CertificateAuthority configures the certificate authority used by the + // control plane to create and sign client certs and server keys. + // +optional + CertificateAuthority *CertificateAuthorityConfig `json:"certificateAuthority,omitempty"` + // Identity configures the types of user tokens used by clients. + // +optional + Identity *IdentityConfig `json:"identity,omitempty"` + // ControlPlane configures mutual TLS for control plane communication. + // +optional + ControlPlane *ControlPlaneSecurityConfig `json:"controlPlane,omitempty"` + // DataPlane configures mutual TLS for data plane communication. + // +optional + DataPlane *DataPlaneSecurityConfig `json:"dataPlane,omitempty"` +} + +// TrustConfig configures trust aspects associated with mutual TLS clients +type TrustConfig struct { + // Domain specifies the trust domain to be used by the mesh. + //.Values.global.trustDomain, maps to trustDomain + // The trust domain corresponds to the trust root of a system. + // Refer to https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE-ID.md#21-trust-domain + // +optional + Domain string `json:"domain,omitempty"` + // AdditionalDomains are additional SPIFFE trust domains that are accepted as trusted. + // .Values.global.trustDomainAliases, maps to trustDomainAliases + // Any service with the identity "td1/ns/foo/sa/a-service-account", "td2/ns/foo/sa/a-service-account", + // or "td3/ns/foo/sa/a-service-account" will be treated the same in the Istio mesh. + // +optional + AdditionalDomains []string `json:"additionalDomains,omitempty"` +} + +// CertificateAuthorityConfig configures the certificate authority implementation +// used by the control plane. +type CertificateAuthorityConfig struct { + // Type is the certificate authority to use. + Type CertificateAuthorityType `json:"type,omitempty"` + // Istiod is the configuration for Istio's internal certificate authority implementation. + // each of these produces a CAEndpoint, i.e. CA_ADDR + // +optional + Istiod *IstiodCertificateAuthorityConfig `json:"istiod,omitempty"` + // Custom is the configuration for a custom certificate authority. + // +optional + Custom *CustomCertificateAuthorityConfig `json:"custom,omitempty"` +} + +// CertificateAuthorityType represents the type of CertificateAuthority implementation. +type CertificateAuthorityType string + +const ( + // CertificateAuthorityTypeIstiod represents Istio's internal certificate authority implementation + CertificateAuthorityTypeIstiod CertificateAuthorityType = "Istiod" + // CertificateAuthorityTypeCustom represents a custom certificate authority implementation + CertificateAuthorityTypeCustom CertificateAuthorityType = "Custom" +) + +// IstiodCertificateAuthorityConfig is the configuration for Istio's internal +// certificate authority implementation. +type IstiodCertificateAuthorityConfig struct { + // Type of certificate signer to use. + Type IstioCertificateSignerType `json:"type,omitempty"` + // SelfSigned configures istiod to generate and use a self-signed certificate for the root. + // +optional + SelfSigned *IstioSelfSignedCertificateSignerConfig `json:"selfSigned,omitempty"` + // PrivateKey configures istiod to use a user specified private key/cert when signing certificates. + // +optional + PrivateKey *IstioPrivateKeyCertificateSignerConfig `json:"privateKey,omitempty"` + // WorkloadCertTTLDefault is the default TTL for generated workload + // certificates. Used if not specified in CSR (<= 0) + // env DEFAULT_WORKLOAD_CERT_TTL, 1.6 + // --workload-cert-ttl, citadel, pre-1.6 + // defaults to 24 hours + // +optional + WorkloadCertTTLDefault string `json:"workloadCertTTLDefault,omitempty"` + // WorkloadCertTTLMax is the maximum TTL for generated workload certificates. + // env MAX_WORKLOAD_CERT_TTL + // --max-workload-cert-ttl, citadel, pre-1.6 + // defaults to 90 days + // +optional + WorkloadCertTTLMax string `json:"workloadCertTTLMax,omitempty"` +} + +// IstioCertificateSignerType represents the certificate signer implementation used by istiod. +type IstioCertificateSignerType string + +const ( + // IstioCertificateSignerTypePrivateKey is the signer type used when signing with a user specified private key. + IstioCertificateSignerTypePrivateKey IstioCertificateSignerType = "PrivateKey" + // IstioCertificateSignerTypeSelfSigned is the signer type used when signing with a generated, self-signed certificate. + IstioCertificateSignerTypeSelfSigned IstioCertificateSignerType = "SelfSigned" +) + +// IstioSelfSignedCertificateSignerConfig is the configuration for using a +// self-signed root certificate. +type IstioSelfSignedCertificateSignerConfig struct { + // TTL for self-signed root certificate + // env CITADEL_SELF_SIGNED_CA_CERT_TTL + // default is 10 years + // +optional + TTL string `json:"ttl,omitempty"` + // GracePeriod percentile for self-signed cert + // env CITADEL_SELF_SIGNED_ROOT_CERT_GRACE_PERIOD_PERCENTILE + // default is 20% + // +optional + GracePeriod string `json:"gracePeriod,omitempty"` + // CheckPeriod is the interval with which certificate is checked for rotation + // env CITADEL_SELF_SIGNED_ROOT_CERT_CHECK_INTERVAL + // default is 1 hour, zero or negative value disables cert rotation + // +optional + CheckPeriod string `json:"checkPeriod,omitempty"` + // EnableJitter to use jitter for cert rotation + // env CITADEL_ENABLE_JITTER_FOR_ROOT_CERT_ROTATOR + // defaults to true + // +optional + EnableJitter *bool `json:"enableJitter,omitempty"` + // Org is the Org value in the certificate. + // XXX: currently uses TrustDomain. I don't think this is configurable. + // +optional + //Org string `json:"org,omitempty"` +} + +// IstioPrivateKeyCertificateSignerConfig is the configuration when using a user +// supplied private key/cert for signing. +// XXX: nothing in here is currently configurable, except RootCADir +type IstioPrivateKeyCertificateSignerConfig struct { + // hard coded to use a secret named cacerts + // +optional + //EncryptionSecret string `json:"encryptionSecret,omitempty"` + // ROOT_CA_DIR, defaults to /etc/cacerts + // Mount directory for encryption secret + // XXX: currently, not configurable in the charts + // +optional + RootCADir string `json:"rootCADir,omitempty"` + // hard coded to ca-key.pem + // +optional + //SigningKeyFile string `json:"signingKeyFile,omitempty"` + // hard coded to ca-cert.pem + // +optional + //SigningCertFile string `json:"signingCertFile,omitempty"` + // hard coded to root-cert.pem + // +optional + //RootCertFile string `json:"rootCertFile,omitempty"` + // hard coded to cert-chain.pem + // +optional + //CertChainFile string `json:"certChainFile,omitempty"` +} + +// CustomCertificateAuthorityConfig is the configuration for a custom +// certificate authority. +type CustomCertificateAuthorityConfig struct { + // Address is the grpc address for an Istio compatible certificate authority endpoint. + // .Values.global.caAddress + // XXX: assumption is this is a grpc endpoint that provides methods like istio.v1.auth.IstioCertificateService/CreateCertificate + Address string `json:"address,omitempty"` +} + +// IdentityConfig configures the types of user tokens used by clients +type IdentityConfig struct { + // Type is the type of identity tokens being used. + // .Values.global.jwtPolicy + Type IdentityConfigType `json:"type,omitempty"` + // ThirdParty configures istiod to use a third-party token provider for + // identifying users. (basically uses a custom audience, e.g. istio-ca) + // XXX: this is only supported on OCP 4.4+ + // +optional + ThirdParty *ThirdPartyIdentityConfig `json:"thirdParty,omitempty"` +} + +// IdentityConfigType represents the identity implementation being used. +type IdentityConfigType string + +const ( + // IdentityConfigTypeKubernetes specifies Kubernetes as the token provider. + IdentityConfigTypeKubernetes IdentityConfigType = "Kubernetes" // first-party-jwt + // IdentityConfigTypeThirdParty specifies a third-party token provider. + IdentityConfigTypeThirdParty IdentityConfigType = "ThirdParty" // third-party-jwt +) + +// ThirdPartyIdentityConfig configures a third-party token provider for use with +// istiod. +type ThirdPartyIdentityConfig struct { + // TokenPath is the path to the token used to identify the workload. + // default /var/run/secrets/tokens/istio-token + // XXX: projects service account token with specified audience (istio-ca) + // XXX: not configurable + // +optional + //TokenPath string `json:"tokenPath,omitempty"` + + // Issuer is the URL of the issuer. + // env TOKEN_ISSUER, defaults to iss in specified token + // only supported in 1.6+ + // +optional + Issuer string `json:"issuer,omitempty"` + // Audience is the audience for whom the token is intended. + // env AUDIENCE + // .Values.global.sds.token.aud, defaults to istio-ca + // +optional + Audience string `json:"audience,omitempty"` +} + +// ControlPlaneSecurityConfig is the mutual TLS configuration specific to the +// control plane. +type ControlPlaneSecurityConfig struct { + // Enable mutual TLS for the control plane components. + // .Values.global.controlPlaneSecurityEnabled + // +optional + MTLS *bool `json:"mtls,omitempty"` + // CertProvider is the certificate authority used to generate the serving + // certificates for the control plane components. + // .Values.global.pilotCertProvider + // Provider used to generate serving certs for istiod (pilot) + // +optional + CertProvider ControlPlaneCertProviderType `json:"certProvider,omitempty"` + + // TLS configures aspects of TLS listeners created by control plane components. + // +optional + TLS *ControlPlaneTLSConfig `json:"tls,omitempty"` +} + +// DataPlaneSecurityConfig is the mutual TLS configuration specific to the +// control plane. +type DataPlaneSecurityConfig struct { + // Enable mutual TLS by default. + // .Values.global.mtls.enabled + MTLS *bool `json:"mtls,omitempty"` + // Auto configures the mesh to automatically detect whether or not mutual + // TLS is required for a specific connection. + // .Values.global.mtls.auto + // +optional + AutoMTLS *bool `json:"automtls,omitempty"` +} + +// ControlPlaneCertProviderType represents the provider used to generate serving +// certificates for the control plane. +type ControlPlaneCertProviderType string + +const ( + // ControlPlaneCertProviderTypeIstiod identifies istiod as the provider generating the serving certifications. + ControlPlaneCertProviderTypeIstiod ControlPlaneCertProviderType = "Istiod" + // ControlPlaneCertProviderTypeKubernetes identifies Kubernetes as the provider generating the serving certificates. + ControlPlaneCertProviderTypeKubernetes ControlPlaneCertProviderType = "Kubernetes" + // ControlPlaneCertProviderTypeCustom identifies a custom provider has generated the serving certificates. + // XXX: Not quite sure what this means. Presumably, the key and cert chain have been mounted specially + ControlPlaneCertProviderTypeCustom ControlPlaneCertProviderType = "Custom" +) + +// ControlPlaneTLSConfig configures settings on TLS listeners created by +// control plane components, e.g. webhooks, grpc (if mtls is enabled), etc. +type ControlPlaneTLSConfig struct { + // CipherSuites configures the cipher suites that are available for use by + // TLS listeners. + // .Values.global.tls.cipherSuites + // +optional + CipherSuites []string `json:"cipherSuites,omitempty"` + // ECDHCurves configures the ECDH curves that are available for use by + // TLS listeners. + // .Values.global.tls.ecdhCurves + // +optional + ECDHCurves []string `json:"ecdhCurves,omitempty"` + // MinProtocolVersion the minimum TLS version that should be supported by + // the listeners. + // .Values.global.tls.minProtocolVersion + // +optional + MinProtocolVersion string `json:"minProtocolVersion,omitempty"` + // MaxProtocolVersion the maximum TLS version that should be supported by + // the listeners. + // .Values.global.tls.maxProtocolVersion + // +optional + MaxProtocolVersion string `json:"maxProtocolVersion,omitempty"` +} diff --git a/vendor/maistra.io/api/core/v2/smcp_new.yaml b/vendor/maistra.io/api/core/v2/smcp_new.yaml new file mode 100644 index 00000000000..ad80c2fce2f --- /dev/null +++ b/vendor/maistra.io/api/core/v2/smcp_new.yaml @@ -0,0 +1,481 @@ +spec: + template: default + version: v2.0 + cluster: + name: Kubernetes + network: main + multiCluster: # null to disable multi-cluster + meshNetworks: {} + # local cluster network is added automatically by default, e.g. + # main + # endpoints: + # - fromRegistry: Kubernetes + # gateways: + # - service: istio-ingressgateway.istio-system.svc.cluster.local + # port: 443 + ingress: false + # not sure if this should be under multiCluster or not + meshExpansion: # null to disable mesh expansion, note meshExpansion is enabled if multiCluster is configured + ilbGateway: # if null, ingress gateway will be used for expansion and expansion ports will be added to it automatically + # these apply to all gateway definitions, with the following exceptions for ILB gateway: + # * service.type is forced to be LoadBalancer, regardless of user setting + # * mesh expansion ports are added automatically to service.ports + namespace: istio-system # install namespace is default + routerMode: sni-dnat # default + requestedNetworkView: [] # "external" added to egress gateway if multiCluster is enabled + sds: + enabled: false # default + runtime: + resources: {} + # this is corev1.ServiceSpec. not sure if we should create our own, pruning unapplied fields + service: + metadata: + annotations: + cloud.google.com/load-balancer-type: "internal" # default for istio-ilbgateway, from gateways/values.yaml + labels: {} # additional labels. applied to selector + type: LoadBalancer # default is ClusterIP for other gateways. LoadBalancer cannot be overriden for ILB gateway + loadBalancerIP: "" # if any + loadBalancerSourceRanges: [] # if any + externalTrafficPolicy: "" # if any + externalIPs: [] # if any + ports: [] # additional corev1.ServicePort definitions + runtime: + # this applies to most components (i.e. if you see runtime: all these settings will be available) + deployment: + replicas: 1 # default + strategy: + type: RollingUpdate # default, only type supported (i.e. charts apply this setting) + rollingUpdate: + maxUnavailable: 25% # default in values.yaml + maxSurge: 100% # default in values.yaml + autoScaling: # defaults to null, no autoscaling + minReplicas: 1 # default in values.yaml + maxReplicas: 5 # default in values.yaml + targetCPUUtilizationPercentage: 80 # default in values.yaml + pod: + metadata: + annotations: {} # maps to podAnnotations + nodeSelector: {} + tolerations: {} + priorityClassName: "" # i think this can only be applied globally, not per component/deployment + affinity: {} + container: + # container definition also includes image, imagePullPolicy, + # imageRegistry, imageTag, imagePullSecrets, but the following are + # only supported for gateways + resources: {} # limits and requirements for istio-proxy container + volumes: + - volume: + name: some-extra-secret + secret: + secretName: some-secret + mount: + name: some-extra-secret-mount + mountPath: /path/to/secret/files + - volume: # note, config maps are currently not mounted, but can be specified. not sure if this is a bug in the charts + name: some-extra-configmap + configMap: + name: some-configmap + mount: + name: some-extra-configmap-mount + mountPath: /path/to/configmap/files + + + # this would apply to control plane components + general: + logging: + componentLevels: {} + # misc: error + logAsJSON: false + + validationMessages: true + + policy: + type: Istiod # or Mixer or Remote, Mixer is default for pre v2.0 + # one of the following. if omitted, will default to whatever settings are in values.yaml + mixer: # legacy v1 + enableChecks: false # default + failOpen: false # default + sessionAffinity: true + adapters: + useAdapterCRDs: false + kubernetesenv: true + # or + remote: + address: my-remote-policy.example.com + createServices: false # applies to both mixer policy and telemetry, i.e. no separate setting for each + enableChecks: false + failOpen: false + # or v2 + istiod: {} + + telemetry: + type: Istiod # or Mixer or Remote + # one of the following + mixer: # legacy v1 + sessionAffinity: false + batching: + maxEntries: 100 + maxTime: 1s + loadshedding: + mode: enforce + latencyThreshold: 100ms + adapters: + useAdapterCRDs: false # i think this should be removed, as it's not available in istio 1.1, and has been removed from 1.4+ + kubernetesenv: true + stdio: + outputAsJSON: false + # or + remote: + address: my-remote-telemetry.example.com + createServices: false # also applies to policy, as mentioned above + sessionAffinity: false + batching: + maxEntries: 100 + maxTime: 1s + # no config if using istiod + + tracing: + type: Jaeger # or Stackdriver, following not yet configurable: Zipkin, Lightstep, Datadog + sampling: 10000 # scaled integer, 0-100% in 0.01% increments, i.e. 1=.001%, 100=1%, 10000=100% + + proxy: + autoInject: true + adminPort: 15000 + concurrency: 0 + # this would apply only to proxies + logging: + level: info + componentLevel: {} + # misc: error + networking: + clusterDomain: cluster.local + connectionTimeout: 10s + maxConnectionAge: 30m + injection: + autoInject: true + alwaysInjectSelector: [] # label selector + neverInjectSelector: [] # label selector + injectedAnnotations: {} # string:string, annotations to be added to injected pods + trafficControl: + inbound: + interceptionMode: REDIRECT + includedPorts: + - "*" + excludedPorts: [] + outbound: + includedIPRanges: [] + excludedIPRanges: [] + excludedPorts: [] + policy: ALLOW_ANY + protocol: + autoDetect: + timeout: 100ms + inbound: false + outbound: false + dns: + refreshRate: 300s + searchSuffixes: [ + # the following are added automatically, if multiCluster is enabled + # "global", + # "{{ valueOrDefault .DeploymentMeta.Namespace \"istio-system\" }}.global", + ] + initialization: + type: CNI # or InitContainer + initContainer: + runtime: + image: proxy-init + imageRegistry: registry.redhat.io + imageTag: "2.0" + imagePullPolicy: Always + imagePullSecrets: [] + resources: {} + accessLogging: + # both may be specified + file: + name: /dev/stdout # file name + encoding: TEXT # TEXT or JSON + format: cutom-format # format for log messages + envoySerivce: + enabled: false + address: accesslog-service.istio-system:15000 + tlsSettings: + mode: DISABLE # DISABLE, SIMPLE, MUTUAL, ISTIO_MUTUAL + clientCertificate: # example: /etc/istio/als/cert-chain.pem + privateKey: # example: /etc/istio/als/key.pem + caCertificates: # example: /etc/istio/als/root-cert.pem + sni: # example: als.somedomain + subjectAltNames: [] + # - als.somedomain + tcpKeepalive: + probes: 3 + time: 10s + interval: 10s + envoyMetricsService: + enabled: false + address: metrics-service.istio-system:15000 + tlsSettings: + mode: DISABLE # DISABLE, SIMPLE, MUTUAL, ISTIO_MUTUAL + clientCertificate: # example: /etc/istio/ms/cert-chain.pem + privateKey: # example: /etc/istio/ms/key.pem + caCertificates: # example: /etc/istio/ms/root-cert.pem + sni: # example: ms.somedomain + subjectAltNames: [] + # - ms.somedomain + tcpKeepalive: + probes: 3 + time: 10s + interval: 10s + runtime: + readiness: + rewriteApplicationProbes: false + statusPort: 15020 + initialDelaySeconds: 1 + periodSeconds: 2 + failureThreshold: 30 + container: + imageName: proxyv2 + resources: {} # requirements and limits + + security: + trust: + domain: cluster.local + additionalDomains: [some-other.cluster] + certificateAuthority: + workloadCertTTLDefault: 24h + workloadCertTTLMax: 90d + type: Istiod # or Custom + # one of the following + istiod: + type: SelfSigned # or PrivateKey + # one of the following + selfSigned: + ttl: 10y + gracePeriod: 20% + checkPeriod: 1h + enableJitter: true + org: cluster.local # XXX: there is overlap between this and security.trust.domain. this isn't used, so should probably be removed + # or + privateKey: + encryptionSecret: cacerts # currently not configurable + rootCADir: /etc/cacerts + signingKeyFile: ca-key.pem # currently not configurable + signingCertFile: ca-cert.pem # currently not configurable + rootCertFile: root-cert.pem # currently not configurable + certChainFile: cert-chain.pem # currently not configurable + # or + custom: # i have no idea about this + address: some.location.domain + identity: # specifies how service tokens are verified + type: Kubernetes # or ThirdParty + # one of + kubernetes: {} # local k8s token review + # or + thirdParty: # simply mounts service account token to a different directory with a specified audience + tokenPath: /var/run/secrets/tokens/istio-token # currently not configurable + issuer: "" # uses token's iss by default + audience: istio-ca + controlPlane: + mtls: true # enable mtls for control plane + certProvider: Istiod # or Kubernetes or Custom, who's providing the serving cert for the control plane + tls: + cipherSuites: [] + ecdhCurves: [] + minProtocolVersion: TLSv1_2 + maxProtocolVersion: TLSv1_3 + dataPlane: + mlts: true # enable mtls for data plane + automtls: true + gateways: + ingress: # _the_ istio-ingressgateway + # same settings as ilb gateway above + service: + type: ClusterIP + ports: + - name: status-port + port: 15020 + - name: http2 + port: 80 + targetPort: 8080 + - name: https + port: 443 + targetPort: 8443 + meshExpansionPorts: [] # additional expansion ports. default expansion ports will be added automatically if multiCluster is configured + egress: # _the_ istio-egressgateway + service: + type: ClusterIP + ports: + - name: status-port + port: 15020 + - name: http2 + port: 80 + targetPort: 8080 + - name: https + port: 443 + targetPort: 8443 + # requestedNetworkView: [external] set automatically if multi-cluster is enabled + additionalIngress: + some-other-ingress-gateway: {} + additionalEgress: + some-other-egress-gateway: {} + openshiftRoute: # configures the Gateway ↔ OpenShift Route integration + enabled: true + + runtime: + components: + # component specific overrides + pilot: # same as gateway.runtime structure illustrated above + deployment: + replicas: 2 + pod: + affinity: {} + container: + imageName: my-pilot + env: + SOME_ENV: some-value + resources: + limits: {} + requirements: {} + security: {} # for configuring citadel,, similar to pilot above + galley: {} # similar to pilot above + mixer: {} # v1.x mixer, similar to pilot above + mixer.policy: {} # v2.x mixer policy, similar to pilot above + mixer.telemetry: {} # v2.x mixer telemetry, similar to pilot above + sidecarInjectorWebhook: {} # similar to pilot above + tracing: {} # similar to pilot above + tracing.jaeger: {} # similar to pilot above + tracing.jaeger.elasticsearch: {} # similar to pilot above + tracing.jaeger.agent: {} # similar to pilot above + tracing.jaeger.allInOne: {} # similar to pilot above + tracing.jaeger.collector: {} # similar to pilot above + tracing.jaeger.query: {} # similar to pilot above + prometheus: {} # similar to pilot above + kiali: {} # similar to pilot above + grafana: {} # similar to pilot above + prometheus: {} # similar to pilot above + # default runtime settings + defaults: # merged into any component specific overrides. component specific overrides take precedence + deployment: {} # similar to gateway.runtime.deployment + pod: + nodeSelector: {} + tolerations: {} + priorityClassName: "" + container: + imageRegistry: registry.redhat.io # old global.hub + imageTag: "2.0" # old global.tag + imagePullPolicy: Always + imagePullSecrets: + - name: registry-token-secret + resources: # old global.defaultResources + limits: {} + requirements: {} + + addons: + prometheus: + enabled: true + scrape: true # configure scraping of telemetry by prometheus + metricsExpiryDuration: 10m + address: some-url-to-prometheus # specify this or install (i'm not sure if we can support this or not) + install: # install prometheus, as opposed to using an existing install at address + selfManaged: true # use prometheus CR, maybe poor naming? + retention: 6h + scrapeInterval: 15s + useTLS: true # .Values.prometheus.security.enabled, i don't think this applies to us + service: + metadata: {} + nodePort: null # use node port if not null + ingress: # enables Ingress/Route if not null + contextPath: /prometheus + tls: # raw yaml, so it can be used with both Route and Ingress resources + termination: reencrypt + + jaeger: + name: jaeger # name of Jaeger CR to reference/create + install: # create a jaeger CR if it doesn't already exist + storage: + type: Memory # or Elasticsearch + memory: # implies tracing.jaeger.template=all-in-one + maxTraces: 100000 + # or + elasticSearch: # implies tracing.jaeger.template=production-elasticsearch + nodeCount: 3 + storage: {} # raw jaeger config, .Values.tracing.jaeger.elasticsearch.storage + redundancyPolicy: {} # raw jaeger config, .Values.tracing.jaeger.elasticsearch.redundancyPolicy + indexCleaner: {} # raw jaeger config, .Values.tracing.jaeger.elasticsearch.esIndexCleaner + runtime: {} # .Values.tracing.jaeger.elasticsearch. + ingress: # configure Ingress/Route if not null + metadata: + labels: {} + annotations: {} + grafana: + address: some-grafana-url # use existing grafana install, or... + install: # install grafana if not null + selfManaged: true # use grafana CR, maybe poor naming? + config: + env: {} # .Values.grafana.env + envSecrets: {} # .Values.grafana.envSecrets + persistence: + storageClassName: "" + accessMode: ReadWriteOnce + capacity: 5Gi # not supported in charts + service: # similar to addons.tracing.jaeger.install.config.service + ingress: + contextPath: /grafana + tls: + termination: reencrypt + kiali: + name: kiali # kiali CR to create/reference + install: # install kiali CR if not present + dashboard: + viewOnly: false + # not sure if the following should be supported or just based on other addon config + enableGrafana: true + enableTracing: true + enablePrometheus: true + service: # similar to addons.tracing.jaeger.install.config.service + ingress: + contextPath: /kiali + 3scale: + enabled: false + listen_addr: 3333 + log_grpc: false + log_json: true + log_level: info + metrics: + port: 8080 + report: true + system: + cache_max_size: 1000 + cache_refresh_retries: 1 + cache_refresh_interval: 180 + cache_ttl: 300 + client: + allow_insecure_connections: false + timeout: 10 + grpc: + max_conn_timeout: 60 + backend: + enable_cache: false + cache_flush_interval: 15 + policy_fail_closed: true + stackdriver: + telemetry: + enabled: false + enableContextGraph: false + enableLogging: false + enableMetrics: false + accessLogging: + logWindowDuration: 12h + auth: + appCredentials: false + apiKey: "" + serviceAccountPath: "" + tracer: + # enables trace output to stdout. + debug: false + # The global default max number of attributes per span. + maxNumberOfAttributes: 200 + # The global default max number of annotation events per span. + maxNumberOfAnnotations: 200 + # The global default max number of message events per span. + maxNumberOfMessageEvents: 200 diff --git a/vendor/maistra.io/api/core/v2/stackdriver.go b/vendor/maistra.io/api/core/v2/stackdriver.go new file mode 100644 index 00000000000..cbf8e5583b4 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/stackdriver.go @@ -0,0 +1,97 @@ +package v2 + +import ( + v1 "maistra.io/api/core/v1" +) + +// StackdriverAddonConfig configuration specific to Stackdriver integration. +type StackdriverAddonConfig struct { + // Configuration for Stackdriver tracer. Applies when Addons.Tracer.Type=Stackdriver + Tracer *StackdriverTracerConfig `json:"tracer,omitempty"` + // Configuration for Stackdriver telemetry plugins. Applies when telemetry + // is enabled + Telemetry *StackdriverTelemetryConfig `json:"telemetry,omitempty"` +} + +// StackdriverTracerConfig configures the Stackdriver tracer +type StackdriverTracerConfig struct { + // .Values.global.tracer.stackdriver.debug + // +optional + Debug *bool `json:"debug,omitempty"` + // .Values.global.tracer.stackdriver.maxNumberOfAttributes + // +optional + MaxNumberOfAttributes *int64 `json:"maxNumberOfAttributes,omitempty"` + // .Values.global.tracer.stackdriver.maxNumberOfAnnotations + // +optional + MaxNumberOfAnnotations *int64 `json:"maxNumberOfAnnotations,omitempty"` + // .Values.global.tracer.stackdriver.maxNumberOfMessageEvents + // +optional + MaxNumberOfMessageEvents *int64 `json:"maxNumberOfMessageEvents,omitempty"` +} + +// StackdriverTelemetryConfig adds telemetry filters for Stackdriver. +type StackdriverTelemetryConfig struct { + // Enable installation of Stackdriver telemetry filters (mixer or v2/envoy). + // These will only be installed if this is enabled an telemetry is enabled. + Enablement `json:",inline"` + // Auth configuration for stackdriver adapter (mixer/v1 telemetry only) + // .Values.mixer.adapters.stackdriver.auth + // +optional + Auth *StackdriverAuthConfig `json:"auth,omitempty"` + // EnableContextGraph for stackdriver adapter (edge reporting) + // .Values.mixer.adapters.stackdriver.contextGraph.enabled, defaults to false + // .Values.telemetry.v2.stackdriver.topology, defaults to false + // +optional + EnableContextGraph *bool `json:"enableContextGraph,omitempty"` + // EnableLogging for stackdriver adapter + // .Values.mixer.adapters.stackdriver.logging.enabled, defaults to true + // .Values.telemetry.v2.stackdriver.logging, defaults to false + // +optional + EnableLogging *bool `json:"enableLogging,omitempty"` + // EnableMetrics for stackdriver adapter + // .Values.mixer.adapters.stackdriver.metrics.enabled, defaults to true + // .Values.telemetry.v2.stackdriver.monitoring??? defaults to false + // +optional + EnableMetrics *bool `json:"enableMetrics,omitempty"` + // DisableOutbound disables intallation of sidecar outbound filter + // .Values.telemetry.v2.stackdriver.disableOutbound, defaults to false + // +optional + //DisableOutbound bool `json:"disableOutbound,omitempty"` + // AccessLogging configures access logging for stackdriver + AccessLogging *StackdriverAccessLogTelemetryConfig `json:"accessLogging,omitempty"` + //ConfigOverride apply custom configuration to Stackdriver filters (v2 + // telemetry only) + // .Values.telemetry.v2.stackdriver.configOverride + // +optional + ConfigOverride *v1.HelmValues `json:"configOverride,omitempty"` +} + +// StackdriverAuthConfig is the auth config for stackdriver. Only one field may be set +type StackdriverAuthConfig struct { + // AppCredentials if true, use default app credentials. + // .Values.mixer.adapters.stackdriver.auth.appCredentials, defaults to false + // +optional + AppCredentials *bool `json:"appCredentials,omitempty"` + // APIKey use the specified key. + // .Values.mixer.adapters.stackdriver.auth.apiKey + // +optional + APIKey string `json:"apiKey,omitempty"` + // ServiceAccountPath use the path to the service account. + // .Values.mixer.adapters.stackdriver.auth.serviceAccountPath + // +optional + ServiceAccountPath string `json:"serviceAccountPath,omitempty"` +} + +// StackdriverAccessLogTelemetryConfig for v2 telemetry. +type StackdriverAccessLogTelemetryConfig struct { + // Enable installation of access log filter. + // .Values.telemetry.v2.accessLogPolicy.enabled + Enablement `json:",inline"` + // LogWindowDuration configures the log window duration for access logs. + // defaults to 43200s + // To reduce the number of successful logs, default log window duration is + // set to 12 hours. + // .Values.telemetry.v2.accessLogPolicy.logWindowDuration + // +optional + LogWindowDuration string `json:"logWindowDuration,omitempty"` +} diff --git a/vendor/maistra.io/api/core/v2/telemetry.go b/vendor/maistra.io/api/core/v2/telemetry.go new file mode 100644 index 00000000000..eaf5597cca2 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/telemetry.go @@ -0,0 +1,119 @@ +package v2 + +// TelemetryConfig for the mesh +type TelemetryConfig struct { + // Type of telemetry implementation to use. + Type TelemetryType `json:"type,omitempty"` + // Mixer represents legacy, v1 telemetry. + // implies .Values.telemetry.v1.enabled, if not null + // +optional + Mixer *MixerTelemetryConfig `json:"mixer,omitempty"` + // Remote represents a remote, legacy, v1 telemetry. + // +optional + Remote *RemoteTelemetryConfig `json:"remote,omitempty"` +} + +// TelemetryType represents the telemetry implementation used. +type TelemetryType string + +const ( + // TelemetryTypeNone disables telemetry + TelemetryTypeNone TelemetryType = "None" + // TelemetryTypeMixer represents mixer telemetry, v1 + TelemetryTypeMixer TelemetryType = "Mixer" + // TelemetryTypeRemote represents remote mixer telemetry server, v1 + TelemetryTypeRemote TelemetryType = "Remote" + // TelemetryTypeIstiod represents istio, v2 + TelemetryTypeIstiod TelemetryType = "Istiod" +) + +// MixerTelemetryConfig is the configuration for legacy, v1 mixer telemetry. +// .Values.telemetry.v1.enabled +type MixerTelemetryConfig struct { + // SessionAffinity configures session affinity for sidecar telemetry connections. + // .Values.mixer.telemetry.sessionAffinityEnabled, maps to MeshConfig.sidecarToTelemetrySessionAffinity + // +optional + SessionAffinity *bool `json:"sessionAffinity,omitempty"` + // Loadshedding configuration for telemetry + // .Values.mixer.telemetry.loadshedding + // +optional + Loadshedding *TelemetryLoadSheddingConfig `json:"loadshedding,omitempty"` + // Batching settings used when sending telemetry. + // +optional + Batching *TelemetryBatchingConfig `json:"batching,omitempty"` + // Adapters configures the adapters used by mixer telemetry. + // +optional + Adapters *MixerTelemetryAdaptersConfig `json:"adapters,omitempty"` +} + +// TelemetryLoadSheddingConfig configures how mixer telemetry loadshedding behaves +type TelemetryLoadSheddingConfig struct { + // Mode represents the loadshedding mode applied to mixer when it becomes + // overloaded. Valid values: disabled, logonly or enforce + // .Values.mixer.telemetry.loadshedding.mode + // +optional + Mode string `json:"mode,omitempty"` + // LatencyThreshold -- + // .Values.mixer.telemetry.loadshedding.latencyThreshold + // +optional + LatencyThreshold string `json:"latencyThreshold,omitempty"` +} + +// TelemetryBatchingConfig configures how telemetry data is batched. +type TelemetryBatchingConfig struct { + // MaxEntries represents the maximum number of entries to collect before sending them to mixer. + // .Values.mixer.telemetry.reportBatchMaxEntries, maps to MeshConfig.reportBatchMaxEntries + // Set reportBatchMaxEntries to 0 to use the default batching behavior (i.e., every 100 requests). + // A positive value indicates the number of requests that are batched before telemetry data + // is sent to the mixer server + // +optional + MaxEntries *int32 `json:"maxEntries,omitempty"` + // MaxTime represents the maximum amount of time to hold entries before sending them to mixer. + // .Values.mixer.telemetry.reportBatchMaxTime, maps to MeshConfig.reportBatchMaxTime + // Set reportBatchMaxTime to 0 to use the default batching behavior (i.e., every 1 second). + // A positive time value indicates the maximum wait time since the last request will telemetry data + // be batched before being sent to the mixer server + // +optional + MaxTime string `json:"maxTime,omitempty"` +} + +// MixerTelemetryAdaptersConfig is the configuration for mixer telemetry adapters. +type MixerTelemetryAdaptersConfig struct { + // UseAdapterCRDs specifies whether or not mixer should support deprecated CRDs. + // .Values.mixer.adapters.useAdapterCRDs, removed in istio 1.4, defaults to false + // XXX: i think this can be removed completely + // +optional + UseAdapterCRDs *bool `json:"useAdapterCRDs,omitempty"` + // KubernetesEnv enables support for the kubernetesenv adapter. + // .Values.mixer.adapters.kubernetesenv.enabled, defaults to true + // +optional + KubernetesEnv *bool `json:"kubernetesenv,omitempty"` + // Stdio enables and configures the stdio adapter. + // +optional + Stdio *MixerTelemetryStdioConfig `json:"stdio,omitempty"` +} + +// MixerTelemetryStdioConfig configures the stdio adapter for mixer telemetry. +type MixerTelemetryStdioConfig struct { + // .Values.mixer.adapters.stdio.enabled + Enablement `json:",inline"` + // OutputAsJSON if true. + // .Values.mixer.adapters.stdio.outputAsJson, defaults to false + // +optional + OutputAsJSON *bool `json:"outputAsJSON,omitempty"` +} + +// RemoteTelemetryConfig configures a remote, legacy, v1 mixer telemetry. +// .Values.telemetry.v1.enabled true +type RemoteTelemetryConfig struct { + // Address is the address of the remote telemetry server + // .Values.global.remoteTelemetryAddress, maps to MeshConfig.mixerReportServer + Address string `json:"address,omitempty"` + // CreateService for the remote server. + // .Values.global.createRemoteSvcEndpoints + // +optional + CreateService *bool `json:"createService,omitempty"` + // Batching settings used when sending telemetry. + // +optional + Batching *TelemetryBatchingConfig `json:"batching,omitempty"` +} diff --git a/vendor/maistra.io/api/core/v2/threescale.go b/vendor/maistra.io/api/core/v2/threescale.go new file mode 100644 index 00000000000..890e48a9511 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/threescale.go @@ -0,0 +1,130 @@ +package v2 + +// ThreeScaleAddonConfig represents configuration options for the installation of the +// 3scale adapter. The options are structured similarly to what is defined by +// the 3scale ConfigMap. +type ThreeScaleAddonConfig struct { + Enablement `json:",inline"` + + // ListenerAddr sets the listen address for the gRPC server. + // PARAM_THREESCALE_LISTEN_ADDR + // +optional + ListenAddr *int32 `json:"listen_addr,omitempty"` + // LogGRPC controls whether the log includes gRPC info + // PARAM_THREESCALE_LOG_GRPC + // +optional + LogGRPC *bool `json:"log_grpc,omitempty"` + // LogJSON controls whether the log is formatted as JSON + // PARAM_THREESCALE_LOG_JSON + // +optional + LogJSON *bool `json:"log_json,omitempty"` + // LogLevel sets the minimum log output level. Accepted values are one of: + // debug, info, warn, error, none + // PARAM_THREESCALE_LOG_LEVEL + // +optional + LogLevel string `json:"log_level,omitempty"` + + // Metrics configures metrics specific details + // +optional + Metrics *ThreeScaleMetricsConfig `json:"metrics,omitempty"` + + // System configures system specific details + // +optional + System *ThreeScaleSystemConfig `json:"system,omitempty"` + + // Client configures client specific details + // +optional + Client *ThreeScaleClientConfig `json:"client,omitempty"` + + // GRPC configures gRPC specific details + // +optional + GRPC *ThreeScaleGRPCConfig `json:"grpc,omitempty"` + + // Backend configures backend specific details + // +optional + Backend *ThreeScaleBackendConfig `json:"backend,omitempty"` +} + +// ThreeScaleMetricsConfig represents 3scale adapter options for its 'metrics' +// section. +type ThreeScaleMetricsConfig struct { + // Port sets the port which 3scale /metrics endpoint can be scrapped from + // PARAM_THREESCALE_METRICS_PORT + // +optional + Port *int32 `json:"port,omitempty"` + // Report controls whether 3scale system and backend metrics are collected + // and reported to Prometheus + // PARAM_THREESCALE_REPORT_METRICS + // +optional + Report *bool `json:"report,omitempty"` +} + +// ThreeScaleSystemConfig represents 3scale adapter options for its 'system' +// section. +type ThreeScaleSystemConfig struct { + // CacheMaxSize is the max number of items that can be stored in the cache + // at any time. Set to 0 to disable caching + // PARAM_THREESCALE_CACHE_ENTRIES_MAX + // +optional + CacheMaxSize *int64 `json:"cache_max_size,omitempty"` + // CacheRefreshRetries sets the number of times unreachable hosts will be + // retried during a cache update loop + // PARAM_THREESCALE_CACHE_REFRESH_RETRIES + // +optional + CacheRefreshRetries *int32 `json:"cache_refresh_retries,omitempty"` + // CacheRefreshInterval is the time period in seconds, before a background + // process attempts to refresh cached entries + // PARAM_THREESCALE_CACHE_REFRESH_SECONDS + // +optional + CacheRefreshInterval *int32 `json:"cache_refresh_interval,omitempty"` + // CacheTTL is the time period, in seconds, to wait before purging expired + // items from the cache + // PARAM_THREESCALE_CACHE_TTL_SECONDS + // +optional + CacheTTL *int32 `json:"cache_ttl,omitempty"` +} + +// ThreeScaleClientConfig represents 3scale adapter options for its 'client' +// section. +type ThreeScaleClientConfig struct { + // AllowInsecureConnections skips certificate verification when calling + // 3scale API's. Enabling is not recommended + // PARAM_THREESCALE_ALLOW_INSECURE_CONN + // +optional + AllowInsecureConnections *bool `json:"allow_insecure_connections,omitempty"` + // Timeout sets the number of seconds to wait before terminating requests + // to 3scale System and Backend + // PARAM_THREESCALE_CLIENT_TIMEOUT_SECONDS + // +optional + Timeout *int32 `json:"timeout,omitempty"` +} + +// ThreeScaleGRPCConfig represents 3scale adapter options for its 'grpc' +// section. +type ThreeScaleGRPCConfig struct { + // MaxConnTimeout sets the maximum amount of seconds (+/-10% jitter) a + // connection may exist before it will be closed + // PARAM_THREESCALE_GRPC_CONN_MAX_SECONDS + // +optional + MaxConnTimeout *int32 `json:"max_conn_timeout,omitempty"` +} + +// ThreeScaleBackendConfig represents 3scale adapter options for its 'backend' +// section. +type ThreeScaleBackendConfig struct { + // EnableCache if true, attempts to create an in-memory apisonator cache for + // authorization requests + // PARAM_THREESCALE_USE_CACHED_BACKEND + // +optional + EnableCache *bool `json:"enable_cache,omitempty"` + // CacheFlushInterval sets the interval at which metrics get reported from + // the cache to 3scale + // PARAM_THREESCALE_BACKEND_CACHE_FLUSH_INTERVAL_SECONDS + // +optional + CacheFlushInterval *int32 `json:"cache_flush_interval,omitempty"` + // PolicyFailClosed if true, request will fail if 3scale Apisonator is + // unreachable + // PARAM_THREESCALE_BACKEND_CACHE_POLICY_FAIL_CLOSED + // +optional + PolicyFailClosed *bool `json:"policy_fail_closed,omitempty"` +} diff --git a/vendor/maistra.io/api/core/v2/tracing.go b/vendor/maistra.io/api/core/v2/tracing.go new file mode 100644 index 00000000000..290bc46932c --- /dev/null +++ b/vendor/maistra.io/api/core/v2/tracing.go @@ -0,0 +1,31 @@ +package v2 + +// TracingConfig configures tracing solutions for the mesh. +// .Values.global.enableTracing +type TracingConfig struct { + // Type represents the type of tracer to be installed. + Type TracerType `json:"type,omitempty"` + // Sampling sets the mesh-wide trace sampling percentage. Should be between + // 0.0 - 100.0. Precision to 0.01, scaled as 0 to 10000, e.g.: 100% = 10000, + // 1% = 100 + // .Values.pilot.traceSampling + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=10000 + // +optional + Sampling *int32 `json:"sampling,omitempty"` +} + +// TracerType represents the tracer type to use +type TracerType string + +const ( + // TracerTypeNone is used to represent no tracer + TracerTypeNone TracerType = "None" + // TracerTypeJaeger is used to represent Jaeger as the tracer + TracerTypeJaeger TracerType = "Jaeger" + // TracerTypeStackdriver is used to represent Stackdriver as the tracer + TracerTypeStackdriver TracerType = "Stackdriver" + // TracerTypeZipkin TracerType = "Zipkin" + // TracerTypeLightstep TracerType = "Lightstep" + // TracerTypeDatadog TracerType = "Datadog" +) diff --git a/vendor/maistra.io/api/core/v2/zipkin.go b/vendor/maistra.io/api/core/v2/zipkin.go new file mode 100644 index 00000000000..322ad69a475 --- /dev/null +++ b/vendor/maistra.io/api/core/v2/zipkin.go @@ -0,0 +1,6 @@ +package v2 + +// ZipkinTracerConfig configures a Zipkin tracer for use with the mesh +type ZipkinTracerConfig struct { + // TODO.... +} diff --git a/vendor/maistra.io/api/core/v2/zz_generated.deepcopy.go b/vendor/maistra.io/api/core/v2/zz_generated.deepcopy.go new file mode 100644 index 00000000000..be50de1e74f --- /dev/null +++ b/vendor/maistra.io/api/core/v2/zz_generated.deepcopy.go @@ -0,0 +1,3040 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by controller-gen. DO NOT EDIT. + +package v2 + +import ( + appsv1 "k8s.io/api/apps/v1" + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/intstr" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AddonsConfig) DeepCopyInto(out *AddonsConfig) { + *out = *in + if in.Prometheus != nil { + in, out := &in.Prometheus, &out.Prometheus + *out = new(PrometheusAddonConfig) + (*in).DeepCopyInto(*out) + } + if in.Stackdriver != nil { + in, out := &in.Stackdriver, &out.Stackdriver + *out = new(StackdriverAddonConfig) + (*in).DeepCopyInto(*out) + } + if in.Jaeger != nil { + in, out := &in.Jaeger, &out.Jaeger + *out = new(JaegerAddonConfig) + (*in).DeepCopyInto(*out) + } + if in.Grafana != nil { + in, out := &in.Grafana, &out.Grafana + *out = new(GrafanaAddonConfig) + (*in).DeepCopyInto(*out) + } + if in.Kiali != nil { + in, out := &in.Kiali, &out.Kiali + *out = new(KialiAddonConfig) + (*in).DeepCopyInto(*out) + } + if in.ThreeScale != nil { + in, out := &in.ThreeScale, &out.ThreeScale + *out = new(ThreeScaleAddonConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonsConfig. +func (in *AddonsConfig) DeepCopy() *AddonsConfig { + if in == nil { + return nil + } + out := new(AddonsConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Affinity) DeepCopyInto(out *Affinity) { + *out = *in + in.PodAntiAffinity.DeepCopyInto(&out.PodAntiAffinity) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Affinity. +func (in *Affinity) DeepCopy() *Affinity { + if in == nil { + return nil + } + out := new(Affinity) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AutoScalerConfig) DeepCopyInto(out *AutoScalerConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.MinReplicas != nil { + in, out := &in.MinReplicas, &out.MinReplicas + *out = new(int32) + **out = **in + } + if in.MaxReplicas != nil { + in, out := &in.MaxReplicas, &out.MaxReplicas + *out = new(int32) + **out = **in + } + if in.TargetCPUUtilizationPercentage != nil { + in, out := &in.TargetCPUUtilizationPercentage, &out.TargetCPUUtilizationPercentage + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutoScalerConfig. +func (in *AutoScalerConfig) DeepCopy() *AutoScalerConfig { + if in == nil { + return nil + } + out := new(AutoScalerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CertificateAuthorityConfig) DeepCopyInto(out *CertificateAuthorityConfig) { + *out = *in + if in.Istiod != nil { + in, out := &in.Istiod, &out.Istiod + *out = new(IstiodCertificateAuthorityConfig) + (*in).DeepCopyInto(*out) + } + if in.Custom != nil { + in, out := &in.Custom, &out.Custom + *out = new(CustomCertificateAuthorityConfig) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertificateAuthorityConfig. +func (in *CertificateAuthorityConfig) DeepCopy() *CertificateAuthorityConfig { + if in == nil { + return nil + } + out := new(CertificateAuthorityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterIngressGatewayConfig) DeepCopyInto(out *ClusterIngressGatewayConfig) { + *out = *in + in.IngressGatewayConfig.DeepCopyInto(&out.IngressGatewayConfig) + if in.IngressEnabled != nil { + in, out := &in.IngressEnabled, &out.IngressEnabled + *out = new(bool) + **out = **in + } + if in.MeshExpansionPorts != nil { + in, out := &in.MeshExpansionPorts, &out.MeshExpansionPorts + *out = make([]v1.ServicePort, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterIngressGatewayConfig. +func (in *ClusterIngressGatewayConfig) DeepCopy() *ClusterIngressGatewayConfig { + if in == nil { + return nil + } + out := new(ClusterIngressGatewayConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CommonContainerConfig) DeepCopyInto(out *CommonContainerConfig) { + *out = *in + if in.ImagePullSecrets != nil { + in, out := &in.ImagePullSecrets, &out.ImagePullSecrets + *out = make([]v1.LocalObjectReference, len(*in)) + copy(*out, *in) + } + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = new(v1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommonContainerConfig. +func (in *CommonContainerConfig) DeepCopy() *CommonContainerConfig { + if in == nil { + return nil + } + out := new(CommonContainerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CommonDeploymentRuntimeConfig) DeepCopyInto(out *CommonDeploymentRuntimeConfig) { + *out = *in + if in.PodDisruption != nil { + in, out := &in.PodDisruption, &out.PodDisruption + *out = new(PodDisruptionBudget) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommonDeploymentRuntimeConfig. +func (in *CommonDeploymentRuntimeConfig) DeepCopy() *CommonDeploymentRuntimeConfig { + if in == nil { + return nil + } + out := new(CommonDeploymentRuntimeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CommonPodRuntimeConfig) DeepCopyInto(out *CommonPodRuntimeConfig) { + *out = *in + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]v1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommonPodRuntimeConfig. +func (in *CommonPodRuntimeConfig) DeepCopy() *CommonPodRuntimeConfig { + if in == nil { + return nil + } + out := new(CommonPodRuntimeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentIngressConfig) DeepCopyInto(out *ComponentIngressConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.Metadata != nil { + in, out := &in.Metadata, &out.Metadata + *out = new(MetadataConfig) + (*in).DeepCopyInto(*out) + } + if in.Hosts != nil { + in, out := &in.Hosts, &out.Hosts + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentIngressConfig. +func (in *ComponentIngressConfig) DeepCopy() *ComponentIngressConfig { + if in == nil { + return nil + } + out := new(ComponentIngressConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in ComponentLogLevels) DeepCopyInto(out *ComponentLogLevels) { + { + in := &in + *out = make(ComponentLogLevels, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentLogLevels. +func (in ComponentLogLevels) DeepCopy() ComponentLogLevels { + if in == nil { + return nil + } + out := new(ComponentLogLevels) + in.DeepCopyInto(out) + return *out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentPersistenceConfig) DeepCopyInto(out *ComponentPersistenceConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = new(v1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentPersistenceConfig. +func (in *ComponentPersistenceConfig) DeepCopy() *ComponentPersistenceConfig { + if in == nil { + return nil + } + out := new(ComponentPersistenceConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentRuntimeConfig) DeepCopyInto(out *ComponentRuntimeConfig) { + *out = *in + if in.Deployment != nil { + in, out := &in.Deployment, &out.Deployment + *out = new(DeploymentRuntimeConfig) + (*in).DeepCopyInto(*out) + } + if in.Pod != nil { + in, out := &in.Pod, &out.Pod + *out = new(PodRuntimeConfig) + (*in).DeepCopyInto(*out) + } + if in.Container != nil { + in, out := &in.Container, &out.Container + *out = new(ContainerConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentRuntimeConfig. +func (in *ComponentRuntimeConfig) DeepCopy() *ComponentRuntimeConfig { + if in == nil { + return nil + } + out := new(ComponentRuntimeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ComponentServiceConfig) DeepCopyInto(out *ComponentServiceConfig) { + *out = *in + if in.Metadata != nil { + in, out := &in.Metadata, &out.Metadata + *out = new(MetadataConfig) + (*in).DeepCopyInto(*out) + } + if in.NodePort != nil { + in, out := &in.NodePort, &out.NodePort + *out = new(int32) + **out = **in + } + if in.Ingress != nil { + in, out := &in.Ingress, &out.Ingress + *out = new(ComponentIngressConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentServiceConfig. +func (in *ComponentServiceConfig) DeepCopy() *ComponentServiceConfig { + if in == nil { + return nil + } + out := new(ComponentServiceConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ContainerConfig) DeepCopyInto(out *ContainerConfig) { + *out = *in + in.CommonContainerConfig.DeepCopyInto(&out.CommonContainerConfig) + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerConfig. +func (in *ContainerConfig) DeepCopy() *ContainerConfig { + if in == nil { + return nil + } + out := new(ContainerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneClusterConfig) DeepCopyInto(out *ControlPlaneClusterConfig) { + *out = *in + if in.MultiCluster != nil { + in, out := &in.MultiCluster, &out.MultiCluster + *out = new(MultiClusterConfig) + (*in).DeepCopyInto(*out) + } + if in.MeshExpansion != nil { + in, out := &in.MeshExpansion, &out.MeshExpansion + *out = new(MeshExpansionConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneClusterConfig. +func (in *ControlPlaneClusterConfig) DeepCopy() *ControlPlaneClusterConfig { + if in == nil { + return nil + } + out := new(ControlPlaneClusterConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneRuntimeConfig) DeepCopyInto(out *ControlPlaneRuntimeConfig) { + *out = *in + if in.Components != nil { + in, out := &in.Components, &out.Components + *out = make(map[ControlPlaneComponentName]*ComponentRuntimeConfig, len(*in)) + for key, val := range *in { + var outVal *ComponentRuntimeConfig + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = new(ComponentRuntimeConfig) + (*in).DeepCopyInto(*out) + } + (*out)[key] = outVal + } + } + if in.Defaults != nil { + in, out := &in.Defaults, &out.Defaults + *out = new(DefaultRuntimeConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneRuntimeConfig. +func (in *ControlPlaneRuntimeConfig) DeepCopy() *ControlPlaneRuntimeConfig { + if in == nil { + return nil + } + out := new(ControlPlaneRuntimeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneSecurityConfig) DeepCopyInto(out *ControlPlaneSecurityConfig) { + *out = *in + if in.MTLS != nil { + in, out := &in.MTLS, &out.MTLS + *out = new(bool) + **out = **in + } + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(ControlPlaneTLSConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneSecurityConfig. +func (in *ControlPlaneSecurityConfig) DeepCopy() *ControlPlaneSecurityConfig { + if in == nil { + return nil + } + out := new(ControlPlaneSecurityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneSpec) DeepCopyInto(out *ControlPlaneSpec) { + *out = *in + if in.Profiles != nil { + in, out := &in.Profiles, &out.Profiles + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Cluster != nil { + in, out := &in.Cluster, &out.Cluster + *out = new(ControlPlaneClusterConfig) + (*in).DeepCopyInto(*out) + } + if in.General != nil { + in, out := &in.General, &out.General + *out = new(GeneralConfig) + (*in).DeepCopyInto(*out) + } + if in.Policy != nil { + in, out := &in.Policy, &out.Policy + *out = new(PolicyConfig) + (*in).DeepCopyInto(*out) + } + if in.Proxy != nil { + in, out := &in.Proxy, &out.Proxy + *out = new(ProxyConfig) + (*in).DeepCopyInto(*out) + } + if in.Security != nil { + in, out := &in.Security, &out.Security + *out = new(SecurityConfig) + (*in).DeepCopyInto(*out) + } + if in.Telemetry != nil { + in, out := &in.Telemetry, &out.Telemetry + *out = new(TelemetryConfig) + (*in).DeepCopyInto(*out) + } + if in.Tracing != nil { + in, out := &in.Tracing, &out.Tracing + *out = new(TracingConfig) + (*in).DeepCopyInto(*out) + } + if in.Gateways != nil { + in, out := &in.Gateways, &out.Gateways + *out = new(GatewaysConfig) + (*in).DeepCopyInto(*out) + } + if in.Runtime != nil { + in, out := &in.Runtime, &out.Runtime + *out = new(ControlPlaneRuntimeConfig) + (*in).DeepCopyInto(*out) + } + if in.Addons != nil { + in, out := &in.Addons, &out.Addons + *out = new(AddonsConfig) + (*in).DeepCopyInto(*out) + } + if in.TechPreview != nil { + in, out := &in.TechPreview, &out.TechPreview + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneSpec. +func (in *ControlPlaneSpec) DeepCopy() *ControlPlaneSpec { + if in == nil { + return nil + } + out := new(ControlPlaneSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneStatus) DeepCopyInto(out *ControlPlaneStatus) { + *out = *in + in.StatusBase.DeepCopyInto(&out.StatusBase) + in.StatusType.DeepCopyInto(&out.StatusType) + in.ComponentStatusList.DeepCopyInto(&out.ComponentStatusList) + in.Readiness.DeepCopyInto(&out.Readiness) + in.AppliedSpec.DeepCopyInto(&out.AppliedSpec) + in.AppliedValues.DeepCopyInto(&out.AppliedValues) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneStatus. +func (in *ControlPlaneStatus) DeepCopy() *ControlPlaneStatus { + if in == nil { + return nil + } + out := new(ControlPlaneStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneTLSConfig) DeepCopyInto(out *ControlPlaneTLSConfig) { + *out = *in + if in.CipherSuites != nil { + in, out := &in.CipherSuites, &out.CipherSuites + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ECDHCurves != nil { + in, out := &in.ECDHCurves, &out.ECDHCurves + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneTLSConfig. +func (in *ControlPlaneTLSConfig) DeepCopy() *ControlPlaneTLSConfig { + if in == nil { + return nil + } + out := new(ControlPlaneTLSConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomCertificateAuthorityConfig) DeepCopyInto(out *CustomCertificateAuthorityConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomCertificateAuthorityConfig. +func (in *CustomCertificateAuthorityConfig) DeepCopy() *CustomCertificateAuthorityConfig { + if in == nil { + return nil + } + out := new(CustomCertificateAuthorityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataPlaneSecurityConfig) DeepCopyInto(out *DataPlaneSecurityConfig) { + *out = *in + if in.MTLS != nil { + in, out := &in.MTLS, &out.MTLS + *out = new(bool) + **out = **in + } + if in.AutoMTLS != nil { + in, out := &in.AutoMTLS, &out.AutoMTLS + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataPlaneSecurityConfig. +func (in *DataPlaneSecurityConfig) DeepCopy() *DataPlaneSecurityConfig { + if in == nil { + return nil + } + out := new(DataPlaneSecurityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DatadogTracerConfig) DeepCopyInto(out *DatadogTracerConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatadogTracerConfig. +func (in *DatadogTracerConfig) DeepCopy() *DatadogTracerConfig { + if in == nil { + return nil + } + out := new(DatadogTracerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DefaultRuntimeConfig) DeepCopyInto(out *DefaultRuntimeConfig) { + *out = *in + if in.Deployment != nil { + in, out := &in.Deployment, &out.Deployment + *out = new(CommonDeploymentRuntimeConfig) + (*in).DeepCopyInto(*out) + } + if in.Pod != nil { + in, out := &in.Pod, &out.Pod + *out = new(CommonPodRuntimeConfig) + (*in).DeepCopyInto(*out) + } + if in.Container != nil { + in, out := &in.Container, &out.Container + *out = new(CommonContainerConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DefaultRuntimeConfig. +func (in *DefaultRuntimeConfig) DeepCopy() *DefaultRuntimeConfig { + if in == nil { + return nil + } + out := new(DefaultRuntimeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeploymentRuntimeConfig) DeepCopyInto(out *DeploymentRuntimeConfig) { + *out = *in + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(int32) + **out = **in + } + if in.Strategy != nil { + in, out := &in.Strategy, &out.Strategy + *out = new(appsv1.DeploymentStrategy) + (*in).DeepCopyInto(*out) + } + if in.AutoScaling != nil { + in, out := &in.AutoScaling, &out.AutoScaling + *out = new(AutoScalerConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentRuntimeConfig. +func (in *DeploymentRuntimeConfig) DeepCopy() *DeploymentRuntimeConfig { + if in == nil { + return nil + } + out := new(DeploymentRuntimeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EgressGatewayConfig) DeepCopyInto(out *EgressGatewayConfig) { + *out = *in + in.GatewayConfig.DeepCopyInto(&out.GatewayConfig) + if in.RequestedNetworkView != nil { + in, out := &in.RequestedNetworkView, &out.RequestedNetworkView + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EgressGatewayConfig. +func (in *EgressGatewayConfig) DeepCopy() *EgressGatewayConfig { + if in == nil { + return nil + } + out := new(EgressGatewayConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Enablement) DeepCopyInto(out *Enablement) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Enablement. +func (in *Enablement) DeepCopy() *Enablement { + if in == nil { + return nil + } + out := new(Enablement) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnvoyServiceClientTLSSettings) DeepCopyInto(out *EnvoyServiceClientTLSSettings) { + *out = *in + if in.SubjectAltNames != nil { + in, out := &in.SubjectAltNames, &out.SubjectAltNames + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyServiceClientTLSSettings. +func (in *EnvoyServiceClientTLSSettings) DeepCopy() *EnvoyServiceClientTLSSettings { + if in == nil { + return nil + } + out := new(EnvoyServiceClientTLSSettings) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnvoyServiceTCPKeepalive) DeepCopyInto(out *EnvoyServiceTCPKeepalive) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyServiceTCPKeepalive. +func (in *EnvoyServiceTCPKeepalive) DeepCopy() *EnvoyServiceTCPKeepalive { + if in == nil { + return nil + } + out := new(EnvoyServiceTCPKeepalive) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayConfig) DeepCopyInto(out *GatewayConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + in.Service.DeepCopyInto(&out.Service) + if in.Volumes != nil { + in, out := &in.Volumes, &out.Volumes + *out = make([]VolumeConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Runtime != nil { + in, out := &in.Runtime, &out.Runtime + *out = new(ComponentRuntimeConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayConfig. +func (in *GatewayConfig) DeepCopy() *GatewayConfig { + if in == nil { + return nil + } + out := new(GatewayConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayServiceConfig) DeepCopyInto(out *GatewayServiceConfig) { + *out = *in + in.ServiceSpec.DeepCopyInto(&out.ServiceSpec) + if in.Metadata != nil { + in, out := &in.Metadata, &out.Metadata + *out = new(MetadataConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayServiceConfig. +func (in *GatewayServiceConfig) DeepCopy() *GatewayServiceConfig { + if in == nil { + return nil + } + out := new(GatewayServiceConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayVolume) DeepCopyInto(out *GatewayVolume) { + *out = *in + if in.ConfigMap != nil { + in, out := &in.ConfigMap, &out.ConfigMap + *out = new(v1.ConfigMapVolumeSource) + (*in).DeepCopyInto(*out) + } + if in.Secret != nil { + in, out := &in.Secret, &out.Secret + *out = new(v1.SecretVolumeSource) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayVolume. +func (in *GatewayVolume) DeepCopy() *GatewayVolume { + if in == nil { + return nil + } + out := new(GatewayVolume) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewaysConfig) DeepCopyInto(out *GatewaysConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.ClusterIngress != nil { + in, out := &in.ClusterIngress, &out.ClusterIngress + *out = new(ClusterIngressGatewayConfig) + (*in).DeepCopyInto(*out) + } + if in.ClusterEgress != nil { + in, out := &in.ClusterEgress, &out.ClusterEgress + *out = new(EgressGatewayConfig) + (*in).DeepCopyInto(*out) + } + if in.IngressGateways != nil { + in, out := &in.IngressGateways, &out.IngressGateways + *out = make(map[string]*IngressGatewayConfig, len(*in)) + for key, val := range *in { + var outVal *IngressGatewayConfig + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = new(IngressGatewayConfig) + (*in).DeepCopyInto(*out) + } + (*out)[key] = outVal + } + } + if in.EgressGateways != nil { + in, out := &in.EgressGateways, &out.EgressGateways + *out = make(map[string]*EgressGatewayConfig, len(*in)) + for key, val := range *in { + var outVal *EgressGatewayConfig + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = new(EgressGatewayConfig) + (*in).DeepCopyInto(*out) + } + (*out)[key] = outVal + } + } + if in.OpenShiftRoute != nil { + in, out := &in.OpenShiftRoute, &out.OpenShiftRoute + *out = new(OpenShiftRouteConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewaysConfig. +func (in *GatewaysConfig) DeepCopy() *GatewaysConfig { + if in == nil { + return nil + } + out := new(GatewaysConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GeneralConfig) DeepCopyInto(out *GeneralConfig) { + *out = *in + if in.Logging != nil { + in, out := &in.Logging, &out.Logging + *out = new(LoggingConfig) + (*in).DeepCopyInto(*out) + } + if in.ValidationMessages != nil { + in, out := &in.ValidationMessages, &out.ValidationMessages + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GeneralConfig. +func (in *GeneralConfig) DeepCopy() *GeneralConfig { + if in == nil { + return nil + } + out := new(GeneralConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaAddonConfig) DeepCopyInto(out *GrafanaAddonConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.Install != nil { + in, out := &in.Install, &out.Install + *out = new(GrafanaInstallConfig) + (*in).DeepCopyInto(*out) + } + if in.Address != nil { + in, out := &in.Address, &out.Address + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaAddonConfig. +func (in *GrafanaAddonConfig) DeepCopy() *GrafanaAddonConfig { + if in == nil { + return nil + } + out := new(GrafanaAddonConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaConfig) DeepCopyInto(out *GrafanaConfig) { + *out = *in + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.EnvSecrets != nil { + in, out := &in.EnvSecrets, &out.EnvSecrets + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaConfig. +func (in *GrafanaConfig) DeepCopy() *GrafanaConfig { + if in == nil { + return nil + } + out := new(GrafanaConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaInstallConfig) DeepCopyInto(out *GrafanaInstallConfig) { + *out = *in + if in.Config != nil { + in, out := &in.Config, &out.Config + *out = new(GrafanaConfig) + (*in).DeepCopyInto(*out) + } + if in.Service != nil { + in, out := &in.Service, &out.Service + *out = new(ComponentServiceConfig) + (*in).DeepCopyInto(*out) + } + if in.Persistence != nil { + in, out := &in.Persistence, &out.Persistence + *out = new(ComponentPersistenceConfig) + (*in).DeepCopyInto(*out) + } + if in.Security != nil { + in, out := &in.Security, &out.Security + *out = new(GrafanaSecurityConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaInstallConfig. +func (in *GrafanaInstallConfig) DeepCopy() *GrafanaInstallConfig { + if in == nil { + return nil + } + out := new(GrafanaInstallConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaSecurityConfig) DeepCopyInto(out *GrafanaSecurityConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaSecurityConfig. +func (in *GrafanaSecurityConfig) DeepCopy() *GrafanaSecurityConfig { + if in == nil { + return nil + } + out := new(GrafanaSecurityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IdentityConfig) DeepCopyInto(out *IdentityConfig) { + *out = *in + if in.ThirdParty != nil { + in, out := &in.ThirdParty, &out.ThirdParty + *out = new(ThirdPartyIdentityConfig) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IdentityConfig. +func (in *IdentityConfig) DeepCopy() *IdentityConfig { + if in == nil { + return nil + } + out := new(IdentityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IngressGatewayConfig) DeepCopyInto(out *IngressGatewayConfig) { + *out = *in + in.GatewayConfig.DeepCopyInto(&out.GatewayConfig) + if in.SDS != nil { + in, out := &in.SDS, &out.SDS + *out = new(SecretDiscoveryService) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressGatewayConfig. +func (in *IngressGatewayConfig) DeepCopy() *IngressGatewayConfig { + if in == nil { + return nil + } + out := new(IngressGatewayConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IstioPrivateKeyCertificateSignerConfig) DeepCopyInto(out *IstioPrivateKeyCertificateSignerConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IstioPrivateKeyCertificateSignerConfig. +func (in *IstioPrivateKeyCertificateSignerConfig) DeepCopy() *IstioPrivateKeyCertificateSignerConfig { + if in == nil { + return nil + } + out := new(IstioPrivateKeyCertificateSignerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IstioSelfSignedCertificateSignerConfig) DeepCopyInto(out *IstioSelfSignedCertificateSignerConfig) { + *out = *in + if in.EnableJitter != nil { + in, out := &in.EnableJitter, &out.EnableJitter + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IstioSelfSignedCertificateSignerConfig. +func (in *IstioSelfSignedCertificateSignerConfig) DeepCopy() *IstioSelfSignedCertificateSignerConfig { + if in == nil { + return nil + } + out := new(IstioSelfSignedCertificateSignerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IstiodCertificateAuthorityConfig) DeepCopyInto(out *IstiodCertificateAuthorityConfig) { + *out = *in + if in.SelfSigned != nil { + in, out := &in.SelfSigned, &out.SelfSigned + *out = new(IstioSelfSignedCertificateSignerConfig) + (*in).DeepCopyInto(*out) + } + if in.PrivateKey != nil { + in, out := &in.PrivateKey, &out.PrivateKey + *out = new(IstioPrivateKeyCertificateSignerConfig) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IstiodCertificateAuthorityConfig. +func (in *IstiodCertificateAuthorityConfig) DeepCopy() *IstiodCertificateAuthorityConfig { + if in == nil { + return nil + } + out := new(IstiodCertificateAuthorityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JaegerAddonConfig) DeepCopyInto(out *JaegerAddonConfig) { + *out = *in + if in.Install != nil { + in, out := &in.Install, &out.Install + *out = new(JaegerInstallConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JaegerAddonConfig. +func (in *JaegerAddonConfig) DeepCopy() *JaegerAddonConfig { + if in == nil { + return nil + } + out := new(JaegerAddonConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JaegerElasticsearchStorageConfig) DeepCopyInto(out *JaegerElasticsearchStorageConfig) { + *out = *in + if in.NodeCount != nil { + in, out := &in.NodeCount, &out.NodeCount + *out = new(int32) + **out = **in + } + if in.Storage != nil { + in, out := &in.Storage, &out.Storage + *out = (*in).DeepCopy() + } + if in.IndexCleaner != nil { + in, out := &in.IndexCleaner, &out.IndexCleaner + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JaegerElasticsearchStorageConfig. +func (in *JaegerElasticsearchStorageConfig) DeepCopy() *JaegerElasticsearchStorageConfig { + if in == nil { + return nil + } + out := new(JaegerElasticsearchStorageConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JaegerIngressConfig) DeepCopyInto(out *JaegerIngressConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.Metadata != nil { + in, out := &in.Metadata, &out.Metadata + *out = new(MetadataConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JaegerIngressConfig. +func (in *JaegerIngressConfig) DeepCopy() *JaegerIngressConfig { + if in == nil { + return nil + } + out := new(JaegerIngressConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JaegerInstallConfig) DeepCopyInto(out *JaegerInstallConfig) { + *out = *in + if in.Storage != nil { + in, out := &in.Storage, &out.Storage + *out = new(JaegerStorageConfig) + (*in).DeepCopyInto(*out) + } + if in.Ingress != nil { + in, out := &in.Ingress, &out.Ingress + *out = new(JaegerIngressConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JaegerInstallConfig. +func (in *JaegerInstallConfig) DeepCopy() *JaegerInstallConfig { + if in == nil { + return nil + } + out := new(JaegerInstallConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JaegerMemoryStorageConfig) DeepCopyInto(out *JaegerMemoryStorageConfig) { + *out = *in + if in.MaxTraces != nil { + in, out := &in.MaxTraces, &out.MaxTraces + *out = new(int64) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JaegerMemoryStorageConfig. +func (in *JaegerMemoryStorageConfig) DeepCopy() *JaegerMemoryStorageConfig { + if in == nil { + return nil + } + out := new(JaegerMemoryStorageConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JaegerStorageConfig) DeepCopyInto(out *JaegerStorageConfig) { + *out = *in + if in.Memory != nil { + in, out := &in.Memory, &out.Memory + *out = new(JaegerMemoryStorageConfig) + (*in).DeepCopyInto(*out) + } + if in.Elasticsearch != nil { + in, out := &in.Elasticsearch, &out.Elasticsearch + *out = new(JaegerElasticsearchStorageConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JaegerStorageConfig. +func (in *JaegerStorageConfig) DeepCopy() *JaegerStorageConfig { + if in == nil { + return nil + } + out := new(JaegerStorageConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KialiAddonConfig) DeepCopyInto(out *KialiAddonConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.Install != nil { + in, out := &in.Install, &out.Install + *out = new(KialiInstallConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KialiAddonConfig. +func (in *KialiAddonConfig) DeepCopy() *KialiAddonConfig { + if in == nil { + return nil + } + out := new(KialiAddonConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KialiDashboardConfig) DeepCopyInto(out *KialiDashboardConfig) { + *out = *in + if in.ViewOnly != nil { + in, out := &in.ViewOnly, &out.ViewOnly + *out = new(bool) + **out = **in + } + if in.EnableGrafana != nil { + in, out := &in.EnableGrafana, &out.EnableGrafana + *out = new(bool) + **out = **in + } + if in.EnablePrometheus != nil { + in, out := &in.EnablePrometheus, &out.EnablePrometheus + *out = new(bool) + **out = **in + } + if in.EnableTracing != nil { + in, out := &in.EnableTracing, &out.EnableTracing + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KialiDashboardConfig. +func (in *KialiDashboardConfig) DeepCopy() *KialiDashboardConfig { + if in == nil { + return nil + } + out := new(KialiDashboardConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KialiInstallConfig) DeepCopyInto(out *KialiInstallConfig) { + *out = *in + if in.Dashboard != nil { + in, out := &in.Dashboard, &out.Dashboard + *out = new(KialiDashboardConfig) + (*in).DeepCopyInto(*out) + } + if in.Service != nil { + in, out := &in.Service, &out.Service + *out = new(ComponentServiceConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KialiInstallConfig. +func (in *KialiInstallConfig) DeepCopy() *KialiInstallConfig { + if in == nil { + return nil + } + out := new(KialiInstallConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LightstepTracerConfig) DeepCopyInto(out *LightstepTracerConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LightstepTracerConfig. +func (in *LightstepTracerConfig) DeepCopy() *LightstepTracerConfig { + if in == nil { + return nil + } + out := new(LightstepTracerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LoggingConfig) DeepCopyInto(out *LoggingConfig) { + *out = *in + if in.ComponentLevels != nil { + in, out := &in.ComponentLevels, &out.ComponentLevels + *out = make(ComponentLogLevels, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.LogAsJSON != nil { + in, out := &in.LogAsJSON, &out.LogAsJSON + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoggingConfig. +func (in *LoggingConfig) DeepCopy() *LoggingConfig { + if in == nil { + return nil + } + out := new(LoggingConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MeshEndpointConfig) DeepCopyInto(out *MeshEndpointConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MeshEndpointConfig. +func (in *MeshEndpointConfig) DeepCopy() *MeshEndpointConfig { + if in == nil { + return nil + } + out := new(MeshEndpointConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MeshExpansionConfig) DeepCopyInto(out *MeshExpansionConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.ILBGateway != nil { + in, out := &in.ILBGateway, &out.ILBGateway + *out = new(GatewayConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MeshExpansionConfig. +func (in *MeshExpansionConfig) DeepCopy() *MeshExpansionConfig { + if in == nil { + return nil + } + out := new(MeshExpansionConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MeshGatewayConfig) DeepCopyInto(out *MeshGatewayConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MeshGatewayConfig. +func (in *MeshGatewayConfig) DeepCopy() *MeshGatewayConfig { + if in == nil { + return nil + } + out := new(MeshGatewayConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MeshNetworkConfig) DeepCopyInto(out *MeshNetworkConfig) { + *out = *in + if in.Endpoints != nil { + in, out := &in.Endpoints, &out.Endpoints + *out = make([]MeshEndpointConfig, len(*in)) + copy(*out, *in) + } + if in.Gateways != nil { + in, out := &in.Gateways, &out.Gateways + *out = make([]MeshGatewayConfig, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MeshNetworkConfig. +func (in *MeshNetworkConfig) DeepCopy() *MeshNetworkConfig { + if in == nil { + return nil + } + out := new(MeshNetworkConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MetadataConfig) DeepCopyInto(out *MetadataConfig) { + *out = *in + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetadataConfig. +func (in *MetadataConfig) DeepCopy() *MetadataConfig { + if in == nil { + return nil + } + out := new(MetadataConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MixerPolicyAdaptersConfig) DeepCopyInto(out *MixerPolicyAdaptersConfig) { + *out = *in + if in.UseAdapterCRDs != nil { + in, out := &in.UseAdapterCRDs, &out.UseAdapterCRDs + *out = new(bool) + **out = **in + } + if in.KubernetesEnv != nil { + in, out := &in.KubernetesEnv, &out.KubernetesEnv + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MixerPolicyAdaptersConfig. +func (in *MixerPolicyAdaptersConfig) DeepCopy() *MixerPolicyAdaptersConfig { + if in == nil { + return nil + } + out := new(MixerPolicyAdaptersConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MixerPolicyConfig) DeepCopyInto(out *MixerPolicyConfig) { + *out = *in + if in.EnableChecks != nil { + in, out := &in.EnableChecks, &out.EnableChecks + *out = new(bool) + **out = **in + } + if in.FailOpen != nil { + in, out := &in.FailOpen, &out.FailOpen + *out = new(bool) + **out = **in + } + if in.SessionAffinity != nil { + in, out := &in.SessionAffinity, &out.SessionAffinity + *out = new(bool) + **out = **in + } + if in.Adapters != nil { + in, out := &in.Adapters, &out.Adapters + *out = new(MixerPolicyAdaptersConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MixerPolicyConfig. +func (in *MixerPolicyConfig) DeepCopy() *MixerPolicyConfig { + if in == nil { + return nil + } + out := new(MixerPolicyConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MixerTelemetryAdaptersConfig) DeepCopyInto(out *MixerTelemetryAdaptersConfig) { + *out = *in + if in.UseAdapterCRDs != nil { + in, out := &in.UseAdapterCRDs, &out.UseAdapterCRDs + *out = new(bool) + **out = **in + } + if in.KubernetesEnv != nil { + in, out := &in.KubernetesEnv, &out.KubernetesEnv + *out = new(bool) + **out = **in + } + if in.Stdio != nil { + in, out := &in.Stdio, &out.Stdio + *out = new(MixerTelemetryStdioConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MixerTelemetryAdaptersConfig. +func (in *MixerTelemetryAdaptersConfig) DeepCopy() *MixerTelemetryAdaptersConfig { + if in == nil { + return nil + } + out := new(MixerTelemetryAdaptersConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MixerTelemetryConfig) DeepCopyInto(out *MixerTelemetryConfig) { + *out = *in + if in.SessionAffinity != nil { + in, out := &in.SessionAffinity, &out.SessionAffinity + *out = new(bool) + **out = **in + } + if in.Loadshedding != nil { + in, out := &in.Loadshedding, &out.Loadshedding + *out = new(TelemetryLoadSheddingConfig) + **out = **in + } + if in.Batching != nil { + in, out := &in.Batching, &out.Batching + *out = new(TelemetryBatchingConfig) + (*in).DeepCopyInto(*out) + } + if in.Adapters != nil { + in, out := &in.Adapters, &out.Adapters + *out = new(MixerTelemetryAdaptersConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MixerTelemetryConfig. +func (in *MixerTelemetryConfig) DeepCopy() *MixerTelemetryConfig { + if in == nil { + return nil + } + out := new(MixerTelemetryConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MixerTelemetryStdioConfig) DeepCopyInto(out *MixerTelemetryStdioConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.OutputAsJSON != nil { + in, out := &in.OutputAsJSON, &out.OutputAsJSON + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MixerTelemetryStdioConfig. +func (in *MixerTelemetryStdioConfig) DeepCopy() *MixerTelemetryStdioConfig { + if in == nil { + return nil + } + out := new(MixerTelemetryStdioConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MultiClusterConfig) DeepCopyInto(out *MultiClusterConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.MeshNetworks != nil { + in, out := &in.MeshNetworks, &out.MeshNetworks + *out = make(map[string]MeshNetworkConfig, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MultiClusterConfig. +func (in *MultiClusterConfig) DeepCopy() *MultiClusterConfig { + if in == nil { + return nil + } + out := new(MultiClusterConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OpenShiftRouteConfig) DeepCopyInto(out *OpenShiftRouteConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenShiftRouteConfig. +func (in *OpenShiftRouteConfig) DeepCopy() *OpenShiftRouteConfig { + if in == nil { + return nil + } + out := new(OpenShiftRouteConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodAntiAffinity) DeepCopyInto(out *PodAntiAffinity) { + *out = *in + if in.RequiredDuringScheduling != nil { + in, out := &in.RequiredDuringScheduling, &out.RequiredDuringScheduling + *out = make([]PodAntiAffinityTerm, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.PreferredDuringScheduling != nil { + in, out := &in.PreferredDuringScheduling, &out.PreferredDuringScheduling + *out = make([]PodAntiAffinityTerm, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodAntiAffinity. +func (in *PodAntiAffinity) DeepCopy() *PodAntiAffinity { + if in == nil { + return nil + } + out := new(PodAntiAffinity) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodAntiAffinityTerm) DeepCopyInto(out *PodAntiAffinityTerm) { + *out = *in + in.LabelSelectorRequirement.DeepCopyInto(&out.LabelSelectorRequirement) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodAntiAffinityTerm. +func (in *PodAntiAffinityTerm) DeepCopy() *PodAntiAffinityTerm { + if in == nil { + return nil + } + out := new(PodAntiAffinityTerm) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodDisruptionBudget) DeepCopyInto(out *PodDisruptionBudget) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.MinAvailable != nil { + in, out := &in.MinAvailable, &out.MinAvailable + *out = new(intstr.IntOrString) + **out = **in + } + if in.MaxUnavailable != nil { + in, out := &in.MaxUnavailable, &out.MaxUnavailable + *out = new(intstr.IntOrString) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodDisruptionBudget. +func (in *PodDisruptionBudget) DeepCopy() *PodDisruptionBudget { + if in == nil { + return nil + } + out := new(PodDisruptionBudget) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodRuntimeConfig) DeepCopyInto(out *PodRuntimeConfig) { + *out = *in + in.CommonPodRuntimeConfig.DeepCopyInto(&out.CommonPodRuntimeConfig) + if in.Metadata != nil { + in, out := &in.Metadata, &out.Metadata + *out = new(MetadataConfig) + (*in).DeepCopyInto(*out) + } + if in.Affinity != nil { + in, out := &in.Affinity, &out.Affinity + *out = new(Affinity) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodRuntimeConfig. +func (in *PodRuntimeConfig) DeepCopy() *PodRuntimeConfig { + if in == nil { + return nil + } + out := new(PodRuntimeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PolicyConfig) DeepCopyInto(out *PolicyConfig) { + *out = *in + if in.Mixer != nil { + in, out := &in.Mixer, &out.Mixer + *out = new(MixerPolicyConfig) + (*in).DeepCopyInto(*out) + } + if in.Remote != nil { + in, out := &in.Remote, &out.Remote + *out = new(RemotePolicyConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyConfig. +func (in *PolicyConfig) DeepCopy() *PolicyConfig { + if in == nil { + return nil + } + out := new(PolicyConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrometheusAddonConfig) DeepCopyInto(out *PrometheusAddonConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.Scrape != nil { + in, out := &in.Scrape, &out.Scrape + *out = new(bool) + **out = **in + } + if in.Install != nil { + in, out := &in.Install, &out.Install + *out = new(PrometheusInstallConfig) + (*in).DeepCopyInto(*out) + } + if in.Address != nil { + in, out := &in.Address, &out.Address + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrometheusAddonConfig. +func (in *PrometheusAddonConfig) DeepCopy() *PrometheusAddonConfig { + if in == nil { + return nil + } + out := new(PrometheusAddonConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrometheusInstallConfig) DeepCopyInto(out *PrometheusInstallConfig) { + *out = *in + if in.Service != nil { + in, out := &in.Service, &out.Service + *out = new(ComponentServiceConfig) + (*in).DeepCopyInto(*out) + } + if in.UseTLS != nil { + in, out := &in.UseTLS, &out.UseTLS + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrometheusInstallConfig. +func (in *PrometheusInstallConfig) DeepCopy() *PrometheusInstallConfig { + if in == nil { + return nil + } + out := new(PrometheusInstallConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyAccessLoggingConfig) DeepCopyInto(out *ProxyAccessLoggingConfig) { + *out = *in + if in.File != nil { + in, out := &in.File, &out.File + *out = new(ProxyFileAccessLogConfig) + **out = **in + } + if in.EnvoyService != nil { + in, out := &in.EnvoyService, &out.EnvoyService + *out = new(ProxyEnvoyServiceConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyAccessLoggingConfig. +func (in *ProxyAccessLoggingConfig) DeepCopy() *ProxyAccessLoggingConfig { + if in == nil { + return nil + } + out := new(ProxyAccessLoggingConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyConfig) DeepCopyInto(out *ProxyConfig) { + *out = *in + if in.Logging != nil { + in, out := &in.Logging, &out.Logging + *out = new(ProxyLoggingConfig) + (*in).DeepCopyInto(*out) + } + if in.Networking != nil { + in, out := &in.Networking, &out.Networking + *out = new(ProxyNetworkingConfig) + (*in).DeepCopyInto(*out) + } + if in.Runtime != nil { + in, out := &in.Runtime, &out.Runtime + *out = new(ProxyRuntimeConfig) + (*in).DeepCopyInto(*out) + } + if in.Injection != nil { + in, out := &in.Injection, &out.Injection + *out = new(ProxyInjectionConfig) + (*in).DeepCopyInto(*out) + } + if in.Concurrency != nil { + in, out := &in.Concurrency, &out.Concurrency + *out = new(int32) + **out = **in + } + if in.AccessLogging != nil { + in, out := &in.AccessLogging, &out.AccessLogging + *out = new(ProxyAccessLoggingConfig) + (*in).DeepCopyInto(*out) + } + if in.EnvoyMetricsService != nil { + in, out := &in.EnvoyMetricsService, &out.EnvoyMetricsService + *out = new(ProxyEnvoyServiceConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyConfig. +func (in *ProxyConfig) DeepCopy() *ProxyConfig { + if in == nil { + return nil + } + out := new(ProxyConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyDNSConfig) DeepCopyInto(out *ProxyDNSConfig) { + *out = *in + if in.SearchSuffixes != nil { + in, out := &in.SearchSuffixes, &out.SearchSuffixes + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyDNSConfig. +func (in *ProxyDNSConfig) DeepCopy() *ProxyDNSConfig { + if in == nil { + return nil + } + out := new(ProxyDNSConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyEnvoyServiceConfig) DeepCopyInto(out *ProxyEnvoyServiceConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.TCPKeepalive != nil { + in, out := &in.TCPKeepalive, &out.TCPKeepalive + *out = new(EnvoyServiceTCPKeepalive) + **out = **in + } + if in.TLSSettings != nil { + in, out := &in.TLSSettings, &out.TLSSettings + *out = new(EnvoyServiceClientTLSSettings) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyEnvoyServiceConfig. +func (in *ProxyEnvoyServiceConfig) DeepCopy() *ProxyEnvoyServiceConfig { + if in == nil { + return nil + } + out := new(ProxyEnvoyServiceConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyFileAccessLogConfig) DeepCopyInto(out *ProxyFileAccessLogConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyFileAccessLogConfig. +func (in *ProxyFileAccessLogConfig) DeepCopy() *ProxyFileAccessLogConfig { + if in == nil { + return nil + } + out := new(ProxyFileAccessLogConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyInboundTrafficControlConfig) DeepCopyInto(out *ProxyInboundTrafficControlConfig) { + *out = *in + if in.IncludedPorts != nil { + in, out := &in.IncludedPorts, &out.IncludedPorts + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ExcludedPorts != nil { + in, out := &in.ExcludedPorts, &out.ExcludedPorts + *out = make([]int32, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyInboundTrafficControlConfig. +func (in *ProxyInboundTrafficControlConfig) DeepCopy() *ProxyInboundTrafficControlConfig { + if in == nil { + return nil + } + out := new(ProxyInboundTrafficControlConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyInitContainerConfig) DeepCopyInto(out *ProxyInitContainerConfig) { + *out = *in + if in.Runtime != nil { + in, out := &in.Runtime, &out.Runtime + *out = new(ContainerConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyInitContainerConfig. +func (in *ProxyInitContainerConfig) DeepCopy() *ProxyInitContainerConfig { + if in == nil { + return nil + } + out := new(ProxyInitContainerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyInjectionConfig) DeepCopyInto(out *ProxyInjectionConfig) { + *out = *in + if in.AutoInject != nil { + in, out := &in.AutoInject, &out.AutoInject + *out = new(bool) + **out = **in + } + if in.AlwaysInjectSelector != nil { + in, out := &in.AlwaysInjectSelector, &out.AlwaysInjectSelector + *out = make([]metav1.LabelSelector, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.NeverInjectSelector != nil { + in, out := &in.NeverInjectSelector, &out.NeverInjectSelector + *out = make([]metav1.LabelSelector, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.InjectedAnnotations != nil { + in, out := &in.InjectedAnnotations, &out.InjectedAnnotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyInjectionConfig. +func (in *ProxyInjectionConfig) DeepCopy() *ProxyInjectionConfig { + if in == nil { + return nil + } + out := new(ProxyInjectionConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyLoggingConfig) DeepCopyInto(out *ProxyLoggingConfig) { + *out = *in + if in.ComponentLevels != nil { + in, out := &in.ComponentLevels, &out.ComponentLevels + *out = make(ComponentLogLevels, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyLoggingConfig. +func (in *ProxyLoggingConfig) DeepCopy() *ProxyLoggingConfig { + if in == nil { + return nil + } + out := new(ProxyLoggingConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyNetworkAutoProtocolDetectionConfig) DeepCopyInto(out *ProxyNetworkAutoProtocolDetectionConfig) { + *out = *in + if in.Inbound != nil { + in, out := &in.Inbound, &out.Inbound + *out = new(bool) + **out = **in + } + if in.Outbound != nil { + in, out := &in.Outbound, &out.Outbound + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyNetworkAutoProtocolDetectionConfig. +func (in *ProxyNetworkAutoProtocolDetectionConfig) DeepCopy() *ProxyNetworkAutoProtocolDetectionConfig { + if in == nil { + return nil + } + out := new(ProxyNetworkAutoProtocolDetectionConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyNetworkInitConfig) DeepCopyInto(out *ProxyNetworkInitConfig) { + *out = *in + if in.InitContainer != nil { + in, out := &in.InitContainer, &out.InitContainer + *out = new(ProxyInitContainerConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyNetworkInitConfig. +func (in *ProxyNetworkInitConfig) DeepCopy() *ProxyNetworkInitConfig { + if in == nil { + return nil + } + out := new(ProxyNetworkInitConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyNetworkProtocolConfig) DeepCopyInto(out *ProxyNetworkProtocolConfig) { + *out = *in + if in.AutoDetect != nil { + in, out := &in.AutoDetect, &out.AutoDetect + *out = new(ProxyNetworkAutoProtocolDetectionConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyNetworkProtocolConfig. +func (in *ProxyNetworkProtocolConfig) DeepCopy() *ProxyNetworkProtocolConfig { + if in == nil { + return nil + } + out := new(ProxyNetworkProtocolConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyNetworkingConfig) DeepCopyInto(out *ProxyNetworkingConfig) { + *out = *in + if in.Initialization != nil { + in, out := &in.Initialization, &out.Initialization + *out = new(ProxyNetworkInitConfig) + (*in).DeepCopyInto(*out) + } + if in.TrafficControl != nil { + in, out := &in.TrafficControl, &out.TrafficControl + *out = new(ProxyTrafficControlConfig) + (*in).DeepCopyInto(*out) + } + if in.Protocol != nil { + in, out := &in.Protocol, &out.Protocol + *out = new(ProxyNetworkProtocolConfig) + (*in).DeepCopyInto(*out) + } + if in.DNS != nil { + in, out := &in.DNS, &out.DNS + *out = new(ProxyDNSConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyNetworkingConfig. +func (in *ProxyNetworkingConfig) DeepCopy() *ProxyNetworkingConfig { + if in == nil { + return nil + } + out := new(ProxyNetworkingConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyOutboundTrafficControlConfig) DeepCopyInto(out *ProxyOutboundTrafficControlConfig) { + *out = *in + if in.IncludedIPRanges != nil { + in, out := &in.IncludedIPRanges, &out.IncludedIPRanges + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ExcludedIPRanges != nil { + in, out := &in.ExcludedIPRanges, &out.ExcludedIPRanges + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ExcludedPorts != nil { + in, out := &in.ExcludedPorts, &out.ExcludedPorts + *out = make([]int32, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyOutboundTrafficControlConfig. +func (in *ProxyOutboundTrafficControlConfig) DeepCopy() *ProxyOutboundTrafficControlConfig { + if in == nil { + return nil + } + out := new(ProxyOutboundTrafficControlConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyReadinessConfig) DeepCopyInto(out *ProxyReadinessConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyReadinessConfig. +func (in *ProxyReadinessConfig) DeepCopy() *ProxyReadinessConfig { + if in == nil { + return nil + } + out := new(ProxyReadinessConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyRuntimeConfig) DeepCopyInto(out *ProxyRuntimeConfig) { + *out = *in + if in.Readiness != nil { + in, out := &in.Readiness, &out.Readiness + *out = new(ProxyReadinessConfig) + **out = **in + } + if in.Container != nil { + in, out := &in.Container, &out.Container + *out = new(ContainerConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyRuntimeConfig. +func (in *ProxyRuntimeConfig) DeepCopy() *ProxyRuntimeConfig { + if in == nil { + return nil + } + out := new(ProxyRuntimeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProxyTrafficControlConfig) DeepCopyInto(out *ProxyTrafficControlConfig) { + *out = *in + in.Inbound.DeepCopyInto(&out.Inbound) + in.Outbound.DeepCopyInto(&out.Outbound) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyTrafficControlConfig. +func (in *ProxyTrafficControlConfig) DeepCopy() *ProxyTrafficControlConfig { + if in == nil { + return nil + } + out := new(ProxyTrafficControlConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in ReadinessMap) DeepCopyInto(out *ReadinessMap) { + { + in := &in + *out = make(ReadinessMap, len(*in)) + for key, val := range *in { + var outVal []string + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = make([]string, len(*in)) + copy(*out, *in) + } + (*out)[key] = outVal + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReadinessMap. +func (in ReadinessMap) DeepCopy() ReadinessMap { + if in == nil { + return nil + } + out := new(ReadinessMap) + in.DeepCopyInto(out) + return *out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReadinessStatus) DeepCopyInto(out *ReadinessStatus) { + *out = *in + if in.Components != nil { + in, out := &in.Components, &out.Components + *out = make(ReadinessMap, len(*in)) + for key, val := range *in { + var outVal []string + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = make([]string, len(*in)) + copy(*out, *in) + } + (*out)[key] = outVal + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReadinessStatus. +func (in *ReadinessStatus) DeepCopy() *ReadinessStatus { + if in == nil { + return nil + } + out := new(ReadinessStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemotePolicyConfig) DeepCopyInto(out *RemotePolicyConfig) { + *out = *in + if in.CreateService != nil { + in, out := &in.CreateService, &out.CreateService + *out = new(bool) + **out = **in + } + if in.EnableChecks != nil { + in, out := &in.EnableChecks, &out.EnableChecks + *out = new(bool) + **out = **in + } + if in.FailOpen != nil { + in, out := &in.FailOpen, &out.FailOpen + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemotePolicyConfig. +func (in *RemotePolicyConfig) DeepCopy() *RemotePolicyConfig { + if in == nil { + return nil + } + out := new(RemotePolicyConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemoteTelemetryConfig) DeepCopyInto(out *RemoteTelemetryConfig) { + *out = *in + if in.CreateService != nil { + in, out := &in.CreateService, &out.CreateService + *out = new(bool) + **out = **in + } + if in.Batching != nil { + in, out := &in.Batching, &out.Batching + *out = new(TelemetryBatchingConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoteTelemetryConfig. +func (in *RemoteTelemetryConfig) DeepCopy() *RemoteTelemetryConfig { + if in == nil { + return nil + } + out := new(RemoteTelemetryConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretDiscoveryService) DeepCopyInto(out *SecretDiscoveryService) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.Runtime != nil { + in, out := &in.Runtime, &out.Runtime + *out = new(ContainerConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretDiscoveryService. +func (in *SecretDiscoveryService) DeepCopy() *SecretDiscoveryService { + if in == nil { + return nil + } + out := new(SecretDiscoveryService) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecurityConfig) DeepCopyInto(out *SecurityConfig) { + *out = *in + if in.Trust != nil { + in, out := &in.Trust, &out.Trust + *out = new(TrustConfig) + (*in).DeepCopyInto(*out) + } + if in.CertificateAuthority != nil { + in, out := &in.CertificateAuthority, &out.CertificateAuthority + *out = new(CertificateAuthorityConfig) + (*in).DeepCopyInto(*out) + } + if in.Identity != nil { + in, out := &in.Identity, &out.Identity + *out = new(IdentityConfig) + (*in).DeepCopyInto(*out) + } + if in.ControlPlane != nil { + in, out := &in.ControlPlane, &out.ControlPlane + *out = new(ControlPlaneSecurityConfig) + (*in).DeepCopyInto(*out) + } + if in.DataPlane != nil { + in, out := &in.DataPlane, &out.DataPlane + *out = new(DataPlaneSecurityConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityConfig. +func (in *SecurityConfig) DeepCopy() *SecurityConfig { + if in == nil { + return nil + } + out := new(SecurityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshControlPlane) DeepCopyInto(out *ServiceMeshControlPlane) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshControlPlane. +func (in *ServiceMeshControlPlane) DeepCopy() *ServiceMeshControlPlane { + if in == nil { + return nil + } + out := new(ServiceMeshControlPlane) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshControlPlane) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshControlPlaneList) DeepCopyInto(out *ServiceMeshControlPlaneList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ServiceMeshControlPlane, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshControlPlaneList. +func (in *ServiceMeshControlPlaneList) DeepCopy() *ServiceMeshControlPlaneList { + if in == nil { + return nil + } + out := new(ServiceMeshControlPlaneList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshControlPlaneList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StackdriverAccessLogTelemetryConfig) DeepCopyInto(out *StackdriverAccessLogTelemetryConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StackdriverAccessLogTelemetryConfig. +func (in *StackdriverAccessLogTelemetryConfig) DeepCopy() *StackdriverAccessLogTelemetryConfig { + if in == nil { + return nil + } + out := new(StackdriverAccessLogTelemetryConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StackdriverAddonConfig) DeepCopyInto(out *StackdriverAddonConfig) { + *out = *in + if in.Tracer != nil { + in, out := &in.Tracer, &out.Tracer + *out = new(StackdriverTracerConfig) + (*in).DeepCopyInto(*out) + } + if in.Telemetry != nil { + in, out := &in.Telemetry, &out.Telemetry + *out = new(StackdriverTelemetryConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StackdriverAddonConfig. +func (in *StackdriverAddonConfig) DeepCopy() *StackdriverAddonConfig { + if in == nil { + return nil + } + out := new(StackdriverAddonConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StackdriverAuthConfig) DeepCopyInto(out *StackdriverAuthConfig) { + *out = *in + if in.AppCredentials != nil { + in, out := &in.AppCredentials, &out.AppCredentials + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StackdriverAuthConfig. +func (in *StackdriverAuthConfig) DeepCopy() *StackdriverAuthConfig { + if in == nil { + return nil + } + out := new(StackdriverAuthConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StackdriverTelemetryConfig) DeepCopyInto(out *StackdriverTelemetryConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.Auth != nil { + in, out := &in.Auth, &out.Auth + *out = new(StackdriverAuthConfig) + (*in).DeepCopyInto(*out) + } + if in.EnableContextGraph != nil { + in, out := &in.EnableContextGraph, &out.EnableContextGraph + *out = new(bool) + **out = **in + } + if in.EnableLogging != nil { + in, out := &in.EnableLogging, &out.EnableLogging + *out = new(bool) + **out = **in + } + if in.EnableMetrics != nil { + in, out := &in.EnableMetrics, &out.EnableMetrics + *out = new(bool) + **out = **in + } + if in.AccessLogging != nil { + in, out := &in.AccessLogging, &out.AccessLogging + *out = new(StackdriverAccessLogTelemetryConfig) + (*in).DeepCopyInto(*out) + } + if in.ConfigOverride != nil { + in, out := &in.ConfigOverride, &out.ConfigOverride + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StackdriverTelemetryConfig. +func (in *StackdriverTelemetryConfig) DeepCopy() *StackdriverTelemetryConfig { + if in == nil { + return nil + } + out := new(StackdriverTelemetryConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StackdriverTracerConfig) DeepCopyInto(out *StackdriverTracerConfig) { + *out = *in + if in.Debug != nil { + in, out := &in.Debug, &out.Debug + *out = new(bool) + **out = **in + } + if in.MaxNumberOfAttributes != nil { + in, out := &in.MaxNumberOfAttributes, &out.MaxNumberOfAttributes + *out = new(int64) + **out = **in + } + if in.MaxNumberOfAnnotations != nil { + in, out := &in.MaxNumberOfAnnotations, &out.MaxNumberOfAnnotations + *out = new(int64) + **out = **in + } + if in.MaxNumberOfMessageEvents != nil { + in, out := &in.MaxNumberOfMessageEvents, &out.MaxNumberOfMessageEvents + *out = new(int64) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StackdriverTracerConfig. +func (in *StackdriverTracerConfig) DeepCopy() *StackdriverTracerConfig { + if in == nil { + return nil + } + out := new(StackdriverTracerConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TelemetryBatchingConfig) DeepCopyInto(out *TelemetryBatchingConfig) { + *out = *in + if in.MaxEntries != nil { + in, out := &in.MaxEntries, &out.MaxEntries + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TelemetryBatchingConfig. +func (in *TelemetryBatchingConfig) DeepCopy() *TelemetryBatchingConfig { + if in == nil { + return nil + } + out := new(TelemetryBatchingConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TelemetryConfig) DeepCopyInto(out *TelemetryConfig) { + *out = *in + if in.Mixer != nil { + in, out := &in.Mixer, &out.Mixer + *out = new(MixerTelemetryConfig) + (*in).DeepCopyInto(*out) + } + if in.Remote != nil { + in, out := &in.Remote, &out.Remote + *out = new(RemoteTelemetryConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TelemetryConfig. +func (in *TelemetryConfig) DeepCopy() *TelemetryConfig { + if in == nil { + return nil + } + out := new(TelemetryConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TelemetryLoadSheddingConfig) DeepCopyInto(out *TelemetryLoadSheddingConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TelemetryLoadSheddingConfig. +func (in *TelemetryLoadSheddingConfig) DeepCopy() *TelemetryLoadSheddingConfig { + if in == nil { + return nil + } + out := new(TelemetryLoadSheddingConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ThirdPartyIdentityConfig) DeepCopyInto(out *ThirdPartyIdentityConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ThirdPartyIdentityConfig. +func (in *ThirdPartyIdentityConfig) DeepCopy() *ThirdPartyIdentityConfig { + if in == nil { + return nil + } + out := new(ThirdPartyIdentityConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ThreeScaleAddonConfig) DeepCopyInto(out *ThreeScaleAddonConfig) { + *out = *in + in.Enablement.DeepCopyInto(&out.Enablement) + if in.ListenAddr != nil { + in, out := &in.ListenAddr, &out.ListenAddr + *out = new(int32) + **out = **in + } + if in.LogGRPC != nil { + in, out := &in.LogGRPC, &out.LogGRPC + *out = new(bool) + **out = **in + } + if in.LogJSON != nil { + in, out := &in.LogJSON, &out.LogJSON + *out = new(bool) + **out = **in + } + if in.Metrics != nil { + in, out := &in.Metrics, &out.Metrics + *out = new(ThreeScaleMetricsConfig) + (*in).DeepCopyInto(*out) + } + if in.System != nil { + in, out := &in.System, &out.System + *out = new(ThreeScaleSystemConfig) + (*in).DeepCopyInto(*out) + } + if in.Client != nil { + in, out := &in.Client, &out.Client + *out = new(ThreeScaleClientConfig) + (*in).DeepCopyInto(*out) + } + if in.GRPC != nil { + in, out := &in.GRPC, &out.GRPC + *out = new(ThreeScaleGRPCConfig) + (*in).DeepCopyInto(*out) + } + if in.Backend != nil { + in, out := &in.Backend, &out.Backend + *out = new(ThreeScaleBackendConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ThreeScaleAddonConfig. +func (in *ThreeScaleAddonConfig) DeepCopy() *ThreeScaleAddonConfig { + if in == nil { + return nil + } + out := new(ThreeScaleAddonConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ThreeScaleBackendConfig) DeepCopyInto(out *ThreeScaleBackendConfig) { + *out = *in + if in.EnableCache != nil { + in, out := &in.EnableCache, &out.EnableCache + *out = new(bool) + **out = **in + } + if in.CacheFlushInterval != nil { + in, out := &in.CacheFlushInterval, &out.CacheFlushInterval + *out = new(int32) + **out = **in + } + if in.PolicyFailClosed != nil { + in, out := &in.PolicyFailClosed, &out.PolicyFailClosed + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ThreeScaleBackendConfig. +func (in *ThreeScaleBackendConfig) DeepCopy() *ThreeScaleBackendConfig { + if in == nil { + return nil + } + out := new(ThreeScaleBackendConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ThreeScaleClientConfig) DeepCopyInto(out *ThreeScaleClientConfig) { + *out = *in + if in.AllowInsecureConnections != nil { + in, out := &in.AllowInsecureConnections, &out.AllowInsecureConnections + *out = new(bool) + **out = **in + } + if in.Timeout != nil { + in, out := &in.Timeout, &out.Timeout + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ThreeScaleClientConfig. +func (in *ThreeScaleClientConfig) DeepCopy() *ThreeScaleClientConfig { + if in == nil { + return nil + } + out := new(ThreeScaleClientConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ThreeScaleGRPCConfig) DeepCopyInto(out *ThreeScaleGRPCConfig) { + *out = *in + if in.MaxConnTimeout != nil { + in, out := &in.MaxConnTimeout, &out.MaxConnTimeout + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ThreeScaleGRPCConfig. +func (in *ThreeScaleGRPCConfig) DeepCopy() *ThreeScaleGRPCConfig { + if in == nil { + return nil + } + out := new(ThreeScaleGRPCConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ThreeScaleMetricsConfig) DeepCopyInto(out *ThreeScaleMetricsConfig) { + *out = *in + if in.Port != nil { + in, out := &in.Port, &out.Port + *out = new(int32) + **out = **in + } + if in.Report != nil { + in, out := &in.Report, &out.Report + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ThreeScaleMetricsConfig. +func (in *ThreeScaleMetricsConfig) DeepCopy() *ThreeScaleMetricsConfig { + if in == nil { + return nil + } + out := new(ThreeScaleMetricsConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ThreeScaleSystemConfig) DeepCopyInto(out *ThreeScaleSystemConfig) { + *out = *in + if in.CacheMaxSize != nil { + in, out := &in.CacheMaxSize, &out.CacheMaxSize + *out = new(int64) + **out = **in + } + if in.CacheRefreshRetries != nil { + in, out := &in.CacheRefreshRetries, &out.CacheRefreshRetries + *out = new(int32) + **out = **in + } + if in.CacheRefreshInterval != nil { + in, out := &in.CacheRefreshInterval, &out.CacheRefreshInterval + *out = new(int32) + **out = **in + } + if in.CacheTTL != nil { + in, out := &in.CacheTTL, &out.CacheTTL + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ThreeScaleSystemConfig. +func (in *ThreeScaleSystemConfig) DeepCopy() *ThreeScaleSystemConfig { + if in == nil { + return nil + } + out := new(ThreeScaleSystemConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TracingConfig) DeepCopyInto(out *TracingConfig) { + *out = *in + if in.Sampling != nil { + in, out := &in.Sampling, &out.Sampling + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TracingConfig. +func (in *TracingConfig) DeepCopy() *TracingConfig { + if in == nil { + return nil + } + out := new(TracingConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrustConfig) DeepCopyInto(out *TrustConfig) { + *out = *in + if in.AdditionalDomains != nil { + in, out := &in.AdditionalDomains, &out.AdditionalDomains + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrustConfig. +func (in *TrustConfig) DeepCopy() *TrustConfig { + if in == nil { + return nil + } + out := new(TrustConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeConfig) DeepCopyInto(out *VolumeConfig) { + *out = *in + in.Volume.DeepCopyInto(&out.Volume) + in.Mount.DeepCopyInto(&out.Mount) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeConfig. +func (in *VolumeConfig) DeepCopy() *VolumeConfig { + if in == nil { + return nil + } + out := new(VolumeConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ZipkinTracerConfig) DeepCopyInto(out *ZipkinTracerConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ZipkinTracerConfig. +func (in *ZipkinTracerConfig) DeepCopy() *ZipkinTracerConfig { + if in == nil { + return nil + } + out := new(ZipkinTracerConfig) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/servicemesh/apis/servicemesh/v1/doc.go b/vendor/maistra.io/api/federation/v1/doc.go similarity index 87% rename from pkg/servicemesh/apis/servicemesh/v1/doc.go rename to vendor/maistra.io/api/federation/v1/doc.go index cef4c8cebb0..a61fe851654 100644 --- a/pkg/servicemesh/apis/servicemesh/v1/doc.go +++ b/vendor/maistra.io/api/federation/v1/doc.go @@ -12,8 +12,5 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +k8s:deepcopy-gen=package -// +k8s:defaulter-gen=TypeMeta -// +groupName=maistra.io - +// +groupName=federation.maistra.io package v1 diff --git a/vendor/maistra.io/api/federation/v1/exportedserviceset_types.go b/vendor/maistra.io/api/federation/v1/exportedserviceset_types.go new file mode 100644 index 00000000000..b7d1699f504 --- /dev/null +++ b/vendor/maistra.io/api/federation/v1/exportedserviceset_types.go @@ -0,0 +1,80 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ExportedServiceSet is the Schema for configuring exported services. It must be created +// in the same namespace as the control plane. The name of the ExportedServiceSet +// resource must match the name of a ServiceMeshPeer resource defining the remote mesh +// to which the services will be exported. This implies there will be at most one +// ExportedServiceSet resource per peer and control plane. +type ExportedServiceSet struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines rules for matching services to be exported. + Spec ExportedServiceSetSpec `json:"spec,omitempty"` + Status ExportedServiceSetStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ExportedServiceSetList contains a list of ExportedServiceSet +type ExportedServiceSetList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ExportedServiceSet `json:"items"` +} + +type ExportedServiceSetSpec struct { + // ExportRules are the rules that determine which services are exported from the + // mesh. The list is processed in order and the first spec in the list that + // applies to a service is the one that will be applied. This allows more + // specific selectors to be placed before more general selectors. + ExportRules []ExportedServiceRule `json:"exportRules,omitempty"` +} + +type ExportedServiceRule struct { + // Type of rule. One of NameSelector or LabelSelector. + // +required + Type ServiceImportExportSelectorType `json:"type"` + // LabelSelector provides a mechanism for selecting services to export by + // using a label selector to match Service resources for export. + // +optional + LabelSelector *ServiceImportExportLabelSelector `json:"labelSelector,omitempty"` + // NameSelector provides a simple name matcher for exporting services in + // the mesh. + // +optional + NameSelector *ServiceNameMapping `json:"nameSelector,omitempty"` +} + +type ExportedServiceSetStatus struct { + // Exports provides details about the services exported by this mesh. + // +required + // +listType=map + // +listMapKey=exportedName + // +patchMergeKey=exportedName + // +patchStrategy=merge,retainKeys + ExportedServices []PeerServiceMapping `json:"exportedServices"` +} diff --git a/vendor/maistra.io/api/federation/v1/groupversion_info.go b/vendor/maistra.io/api/federation/v1/groupversion_info.go new file mode 100644 index 00000000000..c9c80013088 --- /dev/null +++ b/vendor/maistra.io/api/federation/v1/groupversion_info.go @@ -0,0 +1,49 @@ +/* +Copyright Red Hat, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1 contains API Schema definitions for the maistra.io v1 API group +//+kubebuilder:object:generate=true +//+groupName=maistra.io +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: "federation.maistra.io", Version: "v1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +func init() { + SchemeBuilder.Register( + &ServiceMeshPeer{}, &ServiceMeshPeerList{}, + &ExportedServiceSet{}, &ExportedServiceSetList{}, + &ImportedServiceSet{}, &ImportedServiceSetList{}, + ) +} diff --git a/vendor/maistra.io/api/federation/v1/import_export_mapping.go b/vendor/maistra.io/api/federation/v1/import_export_mapping.go new file mode 100644 index 00000000000..4ff40718120 --- /dev/null +++ b/vendor/maistra.io/api/federation/v1/import_export_mapping.go @@ -0,0 +1,104 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type ServiceImportExportSelectorType string + +const ( + LabelSelectorType ServiceImportExportSelectorType = "LabelSelector" + NameSelectorType ServiceImportExportSelectorType = "NameSelector" +) + +type ServiceName struct { + Namespace string `json:"namespace,omitempty"` + Name string `json:"name,omitempty"` +} + +func (s ServiceName) String() string { + return fmt.Sprintf("%s/%s", s.Namespace, s.Name) +} + +// XXX: this messes up crd generation +// func (s ServiceName) NamespacedName() types.NamespacedName { +// return types.NamespacedName{Namespace: s.Namespace, Name: s.Name} +// } + +const MatchAny = "*" + +type ServiceNameMapping struct { + ServiceName `json:",inline"` + Alias *ServiceName `json:"alias,omitempty"` +} + +type ServiceImportExportLabelSelector struct { + // Namespace specifies to which namespace the selector applies. An empty + // value applies to all namespaces in the mesh. + // +optional + Namespace string `json:"namespace,omitempty"` + // Selector used to select Service resources in the namespace/mesh. An + // empty selector selects all services. + // +required + Selector metav1.LabelSelector `json:"selector,omitempty"` + + // Aliases is a map of aliases to apply to exported services. If a name is + // not found in the map, the original service name is exported. A '*' will + // match any name. The Aliases list will be processed in order, with the + // first match found being applied to the exported service. + // Examples: + // */foo->*/bar will match foo service in any namesapce, exporting it as bar from its original namespace. + // */foo->bar/bar will match foo service in any namespace, exporting it as bar/bar. + // foo/*->bar/* will match any service in foo namespace, exporting it from the bar namespace with its original name + // */*->bar/* will match any service and export it from the bar namespace with its original name. + // */*->*/* is the same as not specifying anything + // +optional + Aliases []ServiceNameMapping `json:"aliases,omitempty"` +} + +// ServiceKey provides all the details about a Service +type ServiceKey struct { + // Name represents the simple name of the service, e.g. the metadata.name + // field of a kubernetes Service. + // +required + Name string `json:"name"` + // Namespace represents the namespace within which the service resides. + // +required + Namespace string `json:"namespace"` + // Hostname represents fully qualified domain name (FQDN) used to access + // the service. + // +required + Hostname string `json:"hostname"` +} + +// PeerServiceMapping represents the name mapping between an exported service +// and its local counterpart. +type PeerServiceMapping struct { + // LocalService represents the service in the local (i.e. this) mesh. For an + // exporting mesh, this would be the service being exported. For an + // importing mesh, this would be the imported service. + // +required + LocalService ServiceKey `json:"localService"` + // ExportedName represents the fully qualified domain name (FQDN) of an + // exported service. For an exporting mesh, this is the name that is + // exported to the remote mesh. For an importing mesh, this would be the + // name of the service exported by the remote mesh. + // +required + ExportedName string `json:"exportedName"` +} diff --git a/vendor/maistra.io/api/federation/v1/importedserviceset_types.go b/vendor/maistra.io/api/federation/v1/importedserviceset_types.go new file mode 100644 index 00000000000..ef6798a16ff --- /dev/null +++ b/vendor/maistra.io/api/federation/v1/importedserviceset_types.go @@ -0,0 +1,110 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ImportedServiceSet is the Schema for configuring imported services. It must be created +// in the same namespace as the control plane. The name of the ImportedServiceSet +// resource must match the name of a ServiceMeshPeer resource defining the remote mesh +// from which the services will be imported. This implies there will be at most one +// ImportedServiceSet resource per peer and control plane. +type ImportedServiceSet struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec defines rules for matching services to be imported. + Spec ImportedServiceSetSpec `json:"spec,omitempty"` + Status ImportedServiceSetStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ImportedServiceSetList contains a list of ImportedService +type ImportedServiceSetList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ImportedServiceSet `json:"items"` +} + +type ImportedServiceSetSpec struct { + // DomainSuffix specifies the domain suffix to be applies to imported + // services. If no domain suffix is specified, imported services will be + // named as follows: + // ..svc.-imports.local + // If a domain suffix is specified, imported services will be named as + // follows: + // .. + // +optional + DomainSuffix string `json:"domainSuffix,omitempty"` + // Locality within which imported services should be associated. + Locality *ImportedServiceLocality `json:"locality,omitempty"` + // ImportRules are the rules that determine which services are imported to the + // mesh. The list is processed in order and the first spec in the list that + // applies to a service is the one that will be applied. This allows more + // specific selectors to be placed before more general selectors. + ImportRules []ImportedServiceRule `json:"importRules,omitempty"` +} + +type ImportedServiceRule struct { + // DomainSuffix applies the specified suffix to services imported by this + // rule. The behavior is identical to that of ImportedServiceSetSpec.DomainSuffix. + // +optional + DomainSuffix string `json:"domainSuffix,omitempty"` + // ImportAsLocal imports the service as a local service in the mesh. For + // example, if an exported service, foo/bar is imported as some-ns/service, + // the service will be imported as service.some-ns.svc.cluster.local in the + // some-ns namespace. If a service of this name already exists in the mesh, + // the imported service's endpoints will be aggregated with any other + // workloads associated with the service. This setting overrides DomainSuffix. + // +optional + ImportAsLocal bool `json:"importAsLocal,omitempty"` + // Type of rule. Only NameSelector type is supported. + // +required + Type ServiceImportExportSelectorType `json:"type"` + // NameSelector provides a simple name matcher for importing services in + // the mesh. + // +optional + NameSelector *ServiceNameMapping `json:"nameSelector,omitempty"` +} + +type ImportedServiceLocality struct { + // Region within which imported services are located. + Region string `json:"region,omitempty"` + // Zone within which imported services are located. If Zone is specified, + // Region must also be specified. + Zone string `json:"zone,omitempty"` + // Subzone within which imported services are located. If Subzone is + // specified, Zone must also be specified. + Subzone string `json:"subzone,omitempty"` +} + +type ImportedServiceSetStatus struct { + // Imports provides details about the services imported by this mesh. + // +required + // +listType=map + // +listMapKey=exportedName + // +patchMergeKey=exportedName + // +patchStrategy=merge,retainKeys + ImportedServices []PeerServiceMapping `json:"importedServices"` +} diff --git a/vendor/maistra.io/api/federation/v1/servicemeshpeer_types.go b/vendor/maistra.io/api/federation/v1/servicemeshpeer_types.go new file mode 100644 index 00000000000..f976f66aebd --- /dev/null +++ b/vendor/maistra.io/api/federation/v1/servicemeshpeer_types.go @@ -0,0 +1,223 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package v1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:resource:categories=maistra-io +// +groupName=maistra.io + +// ServiceMeshPeer is the Schema for joining two meshes together. The resource +// name will be used to identify the 'cluster' to which imported services +// belong. +type ServiceMeshPeer struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ServiceMeshPeerSpec `json:"spec,omitempty"` + Status ServiceMeshPeerStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ServiceMeshPeerList contains a list of ServiceMeshPeer +type ServiceMeshPeerList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ServiceMeshPeer `json:"items"` +} + +type ServiceMeshPeerSecurity struct { + // ClientID of the remote mesh. This is used to authenticate incoming + // requrests from the remote mesh's discovery client. + // +required + ClientID string `json:"clientID,omitempty"` + + // TrustDomain of remote mesh. + // +required + TrustDomain string `json:"trustDomain,omitempty"` + + // Name of ConfigMap containing certificate chain to be used to + // validate the remote. This is also used to validate certificates used by + // the remote services (both client and server certificates). The name of + // the entry should be root-cert.pem. If unspecified, it will look for a + // ConfigMap named -ca-root-cert, e.g. if this resource is + // named mesh1, it will look for a ConfigMap named mesh1-ca-root-cert. + // +optional + CertificateChain corev1.TypedLocalObjectReference `json:"certificateChain,omitempty"` + + // AllowDirectInbound determines whether or not external service + // invocations will be terminated at the ingress gateway. + // XXX: should this also be configurable per exported service? + // +optional + AllowDirectInbound bool `json:"-"` + + // AllowDirectOutbound determines whether or not external service + // invocations will be proxied through and terminated at the egress gateway + // XXX: should this also be configurable per imported service? + // +optional + AllowDirectOutbound bool `json:"-"` +} + +type ServiceMeshPeerGateways struct { + // Gateway through which inbound federated service traffic will travel. + // +optional + Ingress corev1.LocalObjectReference `json:"ingress,omitempty"` + + // Gateway through which outbound federated service traffic will travel. + Egress corev1.LocalObjectReference `json:"egress,omitempty"` +} + +// ServiceMeshPeerSpec configures details required to support federation with +// another service mesh. +type ServiceMeshPeerSpec struct { + // Remote configures details related to the remote mesh with which this mesh + // is federating. + // +required + Remote ServiceMeshPeerRemote `json:"remote,omitempty"` + + // Gateways configures the gateways used to facilitate ingress and egress + // with the other mesh. + Gateways ServiceMeshPeerGateways `json:"gateways,omitempty"` + + // Security configures details for securing communication with the other + // mesh. + Security ServiceMeshPeerSecurity `json:"security,omitempty"` +} + +type ServiceMeshPeerRemote struct { + // Addresses are the addresses to which discovery and service requests + // should be sent (i.e. the addresses of ingress gateways on the remote + // mesh). These may be specified as resolveable DNS names or IP addresses. + Addresses []string `json:"addresses,omitempty"` + // DiscoveryPort is the port on which the addresses are handling discovery + // requests. Defaults to 8188, if unspecified. + DiscoveryPort int32 `json:"discoveryPort,omitempty"` + // ServicePort is the port on which the addresses are handling service + // requests. Defaults to 15443, if unspecified. + ServicePort int32 `json:"servicePort,omitempty"` +} + +// ServiceMeshPeerStatus provides information related to the other mesh. +type ServiceMeshPeerStatus struct { + // DiscoveryStatus represents the discovery status of each pilot/istiod pod + // in the mesh. + // +optional + DiscoveryStatus ServiceMeshPeerDiscoveryStatus `json:"discoveryStatus,omitempty"` +} + +// ServiceMeshPeerDiscoveryStatus provides details about the discovery status of each +// pilot/istiod instance in the mesh. This is separated into lists of active +// and inactive pods. Active pods will all have their watch.connected value set +// to true. +type ServiceMeshPeerDiscoveryStatus struct { + // Active represents the pilot/istiod pods actively watching the other mesh + // for discovery. + // +optional + // +nullable + // +listType=map + // +listMapKey=pod + // +patchMergeKey=pod + // +patchStrategy=merge,retainKeys + Active []PodPeerDiscoveryStatus `json:"active,omitempty"` + // Inactive represents the pilot/istiod pods not actively watching the other + // mesh for discovery. + // +optional + // +nullable + // +listType=map + // +listMapKey=pod + // +patchMergeKey=pod + // +patchStrategy=merge,retainKeys + Inactive []PodPeerDiscoveryStatus `json:"inactive,omitempty"` +} + +// PodPeerDiscoveryStatus provides discovery details related to a specific +// pilot/istiod pod. +type PodPeerDiscoveryStatus struct { + // PeerDiscoveryStatus provides details about the connection to the remote mesh. + // +required + PeerDiscoveryStatus `json:",inline"` + // Pod is the pod name to which these details apply. This maps to a + // a pilot/istiod pod. + // +required + Pod string `json:"pod"` +} + +// PeerDiscoveryStatus represents the status of the discovery connection between +// meshes. +type PeerDiscoveryStatus struct { + // Remotes represents details related to the inbound connections from remote + // meshes. + // +optional + // +listType=map + // +listMapKey=source + // +patchMergeKey=source + // +patchStrategy=merge,retainKeys + Remotes []DiscoveryRemoteStatus `json:"remotes,omitempty"` + // Watch represents details related to the outbound connection to the + // remote mesh. + // +required + Watch DiscoveryWatchStatus `json:"watch,omitempty"` +} + +// DiscoveryRemoteStatus represents details related to an inbound connection +// from a remote mesh. +type DiscoveryRemoteStatus struct { + DiscoveryConnectionStatus `json:",inline"` + // Source represents the source of the remote watch. + // +required + Source string `json:"source"` +} + +// DiscoveryWatchStatus represents details related to the outbound connection +// to the remote mesh. +type DiscoveryWatchStatus struct { + DiscoveryConnectionStatus `json:",inline"` +} + +// DiscoveryConnectionStatus represents details related to connections with +// remote meshes. +type DiscoveryConnectionStatus struct { + // Connected identfies an active connection with the remote mesh. + // +required + Connected bool `json:"connected"` + // LastConnected represents the last time a connection with the remote mesh + // was successful. + // +optional + LastConnected metav1.Time `json:"lastConnected,omitempty"` + // LastEvent represents the last time an event was received from the remote + // mesh. + // +optional + LastEvent metav1.Time `json:"lastEvent,omitempty"` + // LastFullSync represents the last time a full sync was performed with the + // remote mesh. + // +optional + LastFullSync metav1.Time `json:"lastFullSync,omitempty"` + // LastDisconnect represents the last time the connection with the remote + // mesh was disconnected. + // +optional + LastDisconnect metav1.Time `json:"lastDisconnect,omitempty"` + // LastDisconnectStatus is the status returned the last time the connection + // with the remote mesh was terminated. + // +optional + LastDisconnectStatus string `json:"lastDisconnectStatus,omitempty"` +} diff --git a/vendor/maistra.io/api/federation/v1/zz_generated.deepcopy.go b/vendor/maistra.io/api/federation/v1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..2ebc8a63227 --- /dev/null +++ b/vendor/maistra.io/api/federation/v1/zz_generated.deepcopy.go @@ -0,0 +1,646 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by controller-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiscoveryConnectionStatus) DeepCopyInto(out *DiscoveryConnectionStatus) { + *out = *in + in.LastConnected.DeepCopyInto(&out.LastConnected) + in.LastEvent.DeepCopyInto(&out.LastEvent) + in.LastFullSync.DeepCopyInto(&out.LastFullSync) + in.LastDisconnect.DeepCopyInto(&out.LastDisconnect) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiscoveryConnectionStatus. +func (in *DiscoveryConnectionStatus) DeepCopy() *DiscoveryConnectionStatus { + if in == nil { + return nil + } + out := new(DiscoveryConnectionStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiscoveryRemoteStatus) DeepCopyInto(out *DiscoveryRemoteStatus) { + *out = *in + in.DiscoveryConnectionStatus.DeepCopyInto(&out.DiscoveryConnectionStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiscoveryRemoteStatus. +func (in *DiscoveryRemoteStatus) DeepCopy() *DiscoveryRemoteStatus { + if in == nil { + return nil + } + out := new(DiscoveryRemoteStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiscoveryWatchStatus) DeepCopyInto(out *DiscoveryWatchStatus) { + *out = *in + in.DiscoveryConnectionStatus.DeepCopyInto(&out.DiscoveryConnectionStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiscoveryWatchStatus. +func (in *DiscoveryWatchStatus) DeepCopy() *DiscoveryWatchStatus { + if in == nil { + return nil + } + out := new(DiscoveryWatchStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExportedServiceRule) DeepCopyInto(out *ExportedServiceRule) { + *out = *in + if in.LabelSelector != nil { + in, out := &in.LabelSelector, &out.LabelSelector + *out = new(ServiceImportExportLabelSelector) + (*in).DeepCopyInto(*out) + } + if in.NameSelector != nil { + in, out := &in.NameSelector, &out.NameSelector + *out = new(ServiceNameMapping) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExportedServiceRule. +func (in *ExportedServiceRule) DeepCopy() *ExportedServiceRule { + if in == nil { + return nil + } + out := new(ExportedServiceRule) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExportedServiceSet) DeepCopyInto(out *ExportedServiceSet) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExportedServiceSet. +func (in *ExportedServiceSet) DeepCopy() *ExportedServiceSet { + if in == nil { + return nil + } + out := new(ExportedServiceSet) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ExportedServiceSet) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExportedServiceSetList) DeepCopyInto(out *ExportedServiceSetList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ExportedServiceSet, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExportedServiceSetList. +func (in *ExportedServiceSetList) DeepCopy() *ExportedServiceSetList { + if in == nil { + return nil + } + out := new(ExportedServiceSetList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ExportedServiceSetList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExportedServiceSetSpec) DeepCopyInto(out *ExportedServiceSetSpec) { + *out = *in + if in.ExportRules != nil { + in, out := &in.ExportRules, &out.ExportRules + *out = make([]ExportedServiceRule, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExportedServiceSetSpec. +func (in *ExportedServiceSetSpec) DeepCopy() *ExportedServiceSetSpec { + if in == nil { + return nil + } + out := new(ExportedServiceSetSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExportedServiceSetStatus) DeepCopyInto(out *ExportedServiceSetStatus) { + *out = *in + if in.ExportedServices != nil { + in, out := &in.ExportedServices, &out.ExportedServices + *out = make([]PeerServiceMapping, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExportedServiceSetStatus. +func (in *ExportedServiceSetStatus) DeepCopy() *ExportedServiceSetStatus { + if in == nil { + return nil + } + out := new(ExportedServiceSetStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImportedServiceLocality) DeepCopyInto(out *ImportedServiceLocality) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImportedServiceLocality. +func (in *ImportedServiceLocality) DeepCopy() *ImportedServiceLocality { + if in == nil { + return nil + } + out := new(ImportedServiceLocality) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImportedServiceRule) DeepCopyInto(out *ImportedServiceRule) { + *out = *in + if in.NameSelector != nil { + in, out := &in.NameSelector, &out.NameSelector + *out = new(ServiceNameMapping) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImportedServiceRule. +func (in *ImportedServiceRule) DeepCopy() *ImportedServiceRule { + if in == nil { + return nil + } + out := new(ImportedServiceRule) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImportedServiceSet) DeepCopyInto(out *ImportedServiceSet) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImportedServiceSet. +func (in *ImportedServiceSet) DeepCopy() *ImportedServiceSet { + if in == nil { + return nil + } + out := new(ImportedServiceSet) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ImportedServiceSet) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImportedServiceSetList) DeepCopyInto(out *ImportedServiceSetList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ImportedServiceSet, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImportedServiceSetList. +func (in *ImportedServiceSetList) DeepCopy() *ImportedServiceSetList { + if in == nil { + return nil + } + out := new(ImportedServiceSetList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ImportedServiceSetList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImportedServiceSetSpec) DeepCopyInto(out *ImportedServiceSetSpec) { + *out = *in + if in.Locality != nil { + in, out := &in.Locality, &out.Locality + *out = new(ImportedServiceLocality) + **out = **in + } + if in.ImportRules != nil { + in, out := &in.ImportRules, &out.ImportRules + *out = make([]ImportedServiceRule, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImportedServiceSetSpec. +func (in *ImportedServiceSetSpec) DeepCopy() *ImportedServiceSetSpec { + if in == nil { + return nil + } + out := new(ImportedServiceSetSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ImportedServiceSetStatus) DeepCopyInto(out *ImportedServiceSetStatus) { + *out = *in + if in.ImportedServices != nil { + in, out := &in.ImportedServices, &out.ImportedServices + *out = make([]PeerServiceMapping, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImportedServiceSetStatus. +func (in *ImportedServiceSetStatus) DeepCopy() *ImportedServiceSetStatus { + if in == nil { + return nil + } + out := new(ImportedServiceSetStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PeerDiscoveryStatus) DeepCopyInto(out *PeerDiscoveryStatus) { + *out = *in + if in.Remotes != nil { + in, out := &in.Remotes, &out.Remotes + *out = make([]DiscoveryRemoteStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.Watch.DeepCopyInto(&out.Watch) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PeerDiscoveryStatus. +func (in *PeerDiscoveryStatus) DeepCopy() *PeerDiscoveryStatus { + if in == nil { + return nil + } + out := new(PeerDiscoveryStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PeerServiceMapping) DeepCopyInto(out *PeerServiceMapping) { + *out = *in + out.LocalService = in.LocalService +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PeerServiceMapping. +func (in *PeerServiceMapping) DeepCopy() *PeerServiceMapping { + if in == nil { + return nil + } + out := new(PeerServiceMapping) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PodPeerDiscoveryStatus) DeepCopyInto(out *PodPeerDiscoveryStatus) { + *out = *in + in.PeerDiscoveryStatus.DeepCopyInto(&out.PeerDiscoveryStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodPeerDiscoveryStatus. +func (in *PodPeerDiscoveryStatus) DeepCopy() *PodPeerDiscoveryStatus { + if in == nil { + return nil + } + out := new(PodPeerDiscoveryStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceImportExportLabelSelector) DeepCopyInto(out *ServiceImportExportLabelSelector) { + *out = *in + in.Selector.DeepCopyInto(&out.Selector) + if in.Aliases != nil { + in, out := &in.Aliases, &out.Aliases + *out = make([]ServiceNameMapping, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceImportExportLabelSelector. +func (in *ServiceImportExportLabelSelector) DeepCopy() *ServiceImportExportLabelSelector { + if in == nil { + return nil + } + out := new(ServiceImportExportLabelSelector) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceKey) DeepCopyInto(out *ServiceKey) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceKey. +func (in *ServiceKey) DeepCopy() *ServiceKey { + if in == nil { + return nil + } + out := new(ServiceKey) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshPeer) DeepCopyInto(out *ServiceMeshPeer) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshPeer. +func (in *ServiceMeshPeer) DeepCopy() *ServiceMeshPeer { + if in == nil { + return nil + } + out := new(ServiceMeshPeer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshPeer) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshPeerDiscoveryStatus) DeepCopyInto(out *ServiceMeshPeerDiscoveryStatus) { + *out = *in + if in.Active != nil { + in, out := &in.Active, &out.Active + *out = make([]PodPeerDiscoveryStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Inactive != nil { + in, out := &in.Inactive, &out.Inactive + *out = make([]PodPeerDiscoveryStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshPeerDiscoveryStatus. +func (in *ServiceMeshPeerDiscoveryStatus) DeepCopy() *ServiceMeshPeerDiscoveryStatus { + if in == nil { + return nil + } + out := new(ServiceMeshPeerDiscoveryStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshPeerGateways) DeepCopyInto(out *ServiceMeshPeerGateways) { + *out = *in + out.Ingress = in.Ingress + out.Egress = in.Egress +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshPeerGateways. +func (in *ServiceMeshPeerGateways) DeepCopy() *ServiceMeshPeerGateways { + if in == nil { + return nil + } + out := new(ServiceMeshPeerGateways) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshPeerList) DeepCopyInto(out *ServiceMeshPeerList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ServiceMeshPeer, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshPeerList. +func (in *ServiceMeshPeerList) DeepCopy() *ServiceMeshPeerList { + if in == nil { + return nil + } + out := new(ServiceMeshPeerList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServiceMeshPeerList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshPeerRemote) DeepCopyInto(out *ServiceMeshPeerRemote) { + *out = *in + if in.Addresses != nil { + in, out := &in.Addresses, &out.Addresses + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshPeerRemote. +func (in *ServiceMeshPeerRemote) DeepCopy() *ServiceMeshPeerRemote { + if in == nil { + return nil + } + out := new(ServiceMeshPeerRemote) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshPeerSecurity) DeepCopyInto(out *ServiceMeshPeerSecurity) { + *out = *in + in.CertificateChain.DeepCopyInto(&out.CertificateChain) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshPeerSecurity. +func (in *ServiceMeshPeerSecurity) DeepCopy() *ServiceMeshPeerSecurity { + if in == nil { + return nil + } + out := new(ServiceMeshPeerSecurity) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshPeerSpec) DeepCopyInto(out *ServiceMeshPeerSpec) { + *out = *in + in.Remote.DeepCopyInto(&out.Remote) + out.Gateways = in.Gateways + in.Security.DeepCopyInto(&out.Security) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshPeerSpec. +func (in *ServiceMeshPeerSpec) DeepCopy() *ServiceMeshPeerSpec { + if in == nil { + return nil + } + out := new(ServiceMeshPeerSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceMeshPeerStatus) DeepCopyInto(out *ServiceMeshPeerStatus) { + *out = *in + in.DiscoveryStatus.DeepCopyInto(&out.DiscoveryStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceMeshPeerStatus. +func (in *ServiceMeshPeerStatus) DeepCopy() *ServiceMeshPeerStatus { + if in == nil { + return nil + } + out := new(ServiceMeshPeerStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceName) DeepCopyInto(out *ServiceName) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceName. +func (in *ServiceName) DeepCopy() *ServiceName { + if in == nil { + return nil + } + out := new(ServiceName) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceNameMapping) DeepCopyInto(out *ServiceNameMapping) { + *out = *in + out.ServiceName = in.ServiceName + if in.Alias != nil { + in, out := &in.Alias, &out.Alias + *out = new(ServiceName) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceNameMapping. +func (in *ServiceNameMapping) DeepCopy() *ServiceNameMapping { + if in == nil { + return nil + } + out := new(ServiceNameMapping) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/maistra.io/api/security/v1/trustbundle.pb.go b/vendor/maistra.io/api/security/v1/trustbundle.pb.go new file mode 100644 index 00000000000..bf7e274057b --- /dev/null +++ b/vendor/maistra.io/api/security/v1/trustbundle.pb.go @@ -0,0 +1,789 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: security/v1/trustbundle.proto + +package v1 + +import ( + context "context" + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type TrustBundle struct { + TrustDomain string `protobuf:"bytes,1,opt,name=trust_domain,json=trustDomain,proto3" json:"trust_domain,omitempty"` + // PEM-encoded root cert + RootCert string `protobuf:"bytes,2,opt,name=root_cert,json=rootCert,proto3" json:"root_cert,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *TrustBundle) Reset() { *m = TrustBundle{} } +func (m *TrustBundle) String() string { return proto.CompactTextString(m) } +func (*TrustBundle) ProtoMessage() {} +func (*TrustBundle) Descriptor() ([]byte, []int) { + return fileDescriptor_92c0df365cdc5ea2, []int{0} +} +func (m *TrustBundle) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TrustBundle) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TrustBundle.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TrustBundle) XXX_Merge(src proto.Message) { + xxx_messageInfo_TrustBundle.Merge(m, src) +} +func (m *TrustBundle) XXX_Size() int { + return m.Size() +} +func (m *TrustBundle) XXX_DiscardUnknown() { + xxx_messageInfo_TrustBundle.DiscardUnknown(m) +} + +var xxx_messageInfo_TrustBundle proto.InternalMessageInfo + +func (m *TrustBundle) GetTrustDomain() string { + if m != nil { + return m.TrustDomain + } + return "" +} + +func (m *TrustBundle) GetRootCert() string { + if m != nil { + return m.RootCert + } + return "" +} + +type TrustBundleRequest struct { + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *TrustBundleRequest) Reset() { *m = TrustBundleRequest{} } +func (m *TrustBundleRequest) String() string { return proto.CompactTextString(m) } +func (*TrustBundleRequest) ProtoMessage() {} +func (*TrustBundleRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_92c0df365cdc5ea2, []int{1} +} +func (m *TrustBundleRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TrustBundleRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TrustBundleRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TrustBundleRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_TrustBundleRequest.Merge(m, src) +} +func (m *TrustBundleRequest) XXX_Size() int { + return m.Size() +} +func (m *TrustBundleRequest) XXX_DiscardUnknown() { + xxx_messageInfo_TrustBundleRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_TrustBundleRequest proto.InternalMessageInfo + +type TrustBundleResponse struct { + TrustBundles []*TrustBundle `protobuf:"bytes,13,rep,name=trust_bundles,json=trustBundles,proto3" json:"trust_bundles,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *TrustBundleResponse) Reset() { *m = TrustBundleResponse{} } +func (m *TrustBundleResponse) String() string { return proto.CompactTextString(m) } +func (*TrustBundleResponse) ProtoMessage() {} +func (*TrustBundleResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_92c0df365cdc5ea2, []int{2} +} +func (m *TrustBundleResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TrustBundleResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TrustBundleResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *TrustBundleResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_TrustBundleResponse.Merge(m, src) +} +func (m *TrustBundleResponse) XXX_Size() int { + return m.Size() +} +func (m *TrustBundleResponse) XXX_DiscardUnknown() { + xxx_messageInfo_TrustBundleResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_TrustBundleResponse proto.InternalMessageInfo + +func (m *TrustBundleResponse) GetTrustBundles() []*TrustBundle { + if m != nil { + return m.TrustBundles + } + return nil +} + +func init() { + proto.RegisterType((*TrustBundle)(nil), "maistra.security.v1.TrustBundle") + proto.RegisterType((*TrustBundleRequest)(nil), "maistra.security.v1.TrustBundleRequest") + proto.RegisterType((*TrustBundleResponse)(nil), "maistra.security.v1.TrustBundleResponse") +} + +func init() { proto.RegisterFile("security/v1/trustbundle.proto", fileDescriptor_92c0df365cdc5ea2) } + +var fileDescriptor_92c0df365cdc5ea2 = []byte{ + // 254 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2d, 0x4e, 0x4d, 0x2e, + 0x2d, 0xca, 0x2c, 0xa9, 0xd4, 0x2f, 0x33, 0xd4, 0x2f, 0x29, 0x2a, 0x2d, 0x2e, 0x49, 0x2a, 0xcd, + 0x4b, 0xc9, 0x49, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0xce, 0x4d, 0xcc, 0x2c, 0x2e, + 0x29, 0x4a, 0xd4, 0x83, 0x29, 0xd3, 0x2b, 0x33, 0x54, 0xf2, 0xe5, 0xe2, 0x0e, 0x01, 0xa9, 0x74, + 0x02, 0xab, 0x14, 0x52, 0xe4, 0xe2, 0x01, 0x6b, 0x8c, 0x4f, 0xc9, 0xcf, 0x4d, 0xcc, 0xcc, 0x93, + 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0c, 0xe2, 0x06, 0x8b, 0xb9, 0x80, 0x85, 0x84, 0xa4, 0xb9, 0x38, + 0x8b, 0xf2, 0xf3, 0x4b, 0xe2, 0x93, 0x53, 0x8b, 0x4a, 0x24, 0x98, 0xc0, 0xf2, 0x1c, 0x20, 0x01, + 0xe7, 0xd4, 0xa2, 0x12, 0x25, 0x11, 0x2e, 0x21, 0x24, 0xe3, 0x82, 0x52, 0x0b, 0x4b, 0x53, 0x8b, + 0x4b, 0x94, 0x62, 0xb8, 0x84, 0x51, 0x44, 0x8b, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x85, 0x5c, 0xb9, + 0x78, 0x21, 0x96, 0x41, 0x9c, 0x59, 0x2c, 0xc1, 0xab, 0xc0, 0xac, 0xc1, 0x6d, 0xa4, 0xa0, 0x87, + 0xc5, 0xa1, 0x7a, 0xc8, 0x06, 0x40, 0xdc, 0x08, 0xe1, 0x14, 0x1b, 0xd5, 0xa0, 0xd8, 0x19, 0x9c, + 0x5a, 0x54, 0x96, 0x99, 0x9c, 0x2a, 0x94, 0xc6, 0xc5, 0xef, 0x9e, 0x5a, 0x82, 0x24, 0x51, 0x2c, + 0xa4, 0x4e, 0xd0, 0x60, 0x88, 0x7b, 0xa5, 0x34, 0x08, 0x2b, 0x84, 0x78, 0x41, 0x89, 0xc1, 0x49, + 0xe3, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x8c, 0x92, 0x82, + 0x69, 0xcc, 0xcc, 0xd7, 0x4f, 0x2c, 0xc8, 0xd4, 0x47, 0x8a, 0x91, 0x24, 0x36, 0x70, 0x34, 0x18, + 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x8b, 0x09, 0x9e, 0x74, 0xa7, 0x01, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// TrustBundleServiceClient is the client API for TrustBundleService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type TrustBundleServiceClient interface { + GetTrustBundles(ctx context.Context, in *TrustBundleRequest, opts ...grpc.CallOption) (*TrustBundleResponse, error) +} + +type trustBundleServiceClient struct { + cc *grpc.ClientConn +} + +func NewTrustBundleServiceClient(cc *grpc.ClientConn) TrustBundleServiceClient { + return &trustBundleServiceClient{cc} +} + +func (c *trustBundleServiceClient) GetTrustBundles(ctx context.Context, in *TrustBundleRequest, opts ...grpc.CallOption) (*TrustBundleResponse, error) { + out := new(TrustBundleResponse) + err := c.cc.Invoke(ctx, "/maistra.security.v1.TrustBundleService/GetTrustBundles", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// TrustBundleServiceServer is the server API for TrustBundleService service. +type TrustBundleServiceServer interface { + GetTrustBundles(context.Context, *TrustBundleRequest) (*TrustBundleResponse, error) +} + +// UnimplementedTrustBundleServiceServer can be embedded to have forward compatible implementations. +type UnimplementedTrustBundleServiceServer struct { +} + +func (*UnimplementedTrustBundleServiceServer) GetTrustBundles(ctx context.Context, req *TrustBundleRequest) (*TrustBundleResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetTrustBundles not implemented") +} + +func RegisterTrustBundleServiceServer(s *grpc.Server, srv TrustBundleServiceServer) { + s.RegisterService(&_TrustBundleService_serviceDesc, srv) +} + +func _TrustBundleService_GetTrustBundles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(TrustBundleRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TrustBundleServiceServer).GetTrustBundles(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/maistra.security.v1.TrustBundleService/GetTrustBundles", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TrustBundleServiceServer).GetTrustBundles(ctx, req.(*TrustBundleRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _TrustBundleService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "maistra.security.v1.TrustBundleService", + HandlerType: (*TrustBundleServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetTrustBundles", + Handler: _TrustBundleService_GetTrustBundles_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "security/v1/trustbundle.proto", +} + +func (m *TrustBundle) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TrustBundle) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TrustBundle) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + if len(m.RootCert) > 0 { + i -= len(m.RootCert) + copy(dAtA[i:], m.RootCert) + i = encodeVarintTrustbundle(dAtA, i, uint64(len(m.RootCert))) + i-- + dAtA[i] = 0x12 + } + if len(m.TrustDomain) > 0 { + i -= len(m.TrustDomain) + copy(dAtA[i:], m.TrustDomain) + i = encodeVarintTrustbundle(dAtA, i, uint64(len(m.TrustDomain))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *TrustBundleRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TrustBundleRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TrustBundleRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + return len(dAtA) - i, nil +} + +func (m *TrustBundleResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *TrustBundleResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TrustBundleResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + if len(m.TrustBundles) > 0 { + for iNdEx := len(m.TrustBundles) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.TrustBundles[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTrustbundle(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x6a + } + } + return len(dAtA) - i, nil +} + +func encodeVarintTrustbundle(dAtA []byte, offset int, v uint64) int { + offset -= sovTrustbundle(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *TrustBundle) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.TrustDomain) + if l > 0 { + n += 1 + l + sovTrustbundle(uint64(l)) + } + l = len(m.RootCert) + if l > 0 { + n += 1 + l + sovTrustbundle(uint64(l)) + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + +func (m *TrustBundleRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + +func (m *TrustBundleResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.TrustBundles) > 0 { + for _, e := range m.TrustBundles { + l = e.Size() + n += 1 + l + sovTrustbundle(uint64(l)) + } + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + +func sovTrustbundle(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTrustbundle(x uint64) (n int) { + return sovTrustbundle(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *TrustBundle) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTrustbundle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TrustBundle: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TrustBundle: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TrustDomain", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTrustbundle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTrustbundle + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTrustbundle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TrustDomain = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RootCert", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTrustbundle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTrustbundle + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTrustbundle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RootCert = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTrustbundle(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTrustbundle + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TrustBundleRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTrustbundle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TrustBundleRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TrustBundleRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTrustbundle(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTrustbundle + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TrustBundleResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTrustbundle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: TrustBundleResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TrustBundleResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TrustBundles", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTrustbundle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTrustbundle + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTrustbundle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TrustBundles = append(m.TrustBundles, &TrustBundle{}) + if err := m.TrustBundles[len(m.TrustBundles)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTrustbundle(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTrustbundle + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTrustbundle(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTrustbundle + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTrustbundle + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTrustbundle + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTrustbundle + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTrustbundle + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTrustbundle + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTrustbundle = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTrustbundle = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTrustbundle = fmt.Errorf("proto: unexpected end of group") +) diff --git a/vendor/maistra.io/api/security/v1/trustbundle.proto b/vendor/maistra.io/api/security/v1/trustbundle.proto new file mode 100644 index 00000000000..8040e0ad985 --- /dev/null +++ b/vendor/maistra.io/api/security/v1/trustbundle.proto @@ -0,0 +1,38 @@ +// Copyright Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package maistra.security.v1; + +option go_package="maistra.io/api/security/v1"; + + +message TrustBundle { + string trust_domain = 1; + // PEM-encoded root cert + string root_cert = 2; +} + +message TrustBundleRequest {} + +message TrustBundleResponse { + repeated TrustBundle trust_bundles = 13; +} + +service TrustBundleService { + rpc GetTrustBundles(TrustBundleRequest) + returns (TrustBundleResponse) { + } +} diff --git a/vendor/maistra.io/api/security/v1/trustbundle_deepcopy.gen.go b/vendor/maistra.io/api/security/v1/trustbundle_deepcopy.gen.go new file mode 100644 index 00000000000..fd8fb18e89d --- /dev/null +++ b/vendor/maistra.io/api/security/v1/trustbundle_deepcopy.gen.go @@ -0,0 +1,78 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: security/v1/trustbundle.proto + +package v1 + +import ( + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// DeepCopyInto supports using TrustBundle within kubernetes types, where deepcopy-gen is used. +func (in *TrustBundle) DeepCopyInto(out *TrustBundle) { + p := proto.Clone(in).(*TrustBundle) + *out = *p +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrustBundle. Required by controller-gen. +func (in *TrustBundle) DeepCopy() *TrustBundle { + if in == nil { + return nil + } + out := new(TrustBundle) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TrustBundle. Required by controller-gen. +func (in *TrustBundle) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using TrustBundleRequest within kubernetes types, where deepcopy-gen is used. +func (in *TrustBundleRequest) DeepCopyInto(out *TrustBundleRequest) { + p := proto.Clone(in).(*TrustBundleRequest) + *out = *p +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrustBundleRequest. Required by controller-gen. +func (in *TrustBundleRequest) DeepCopy() *TrustBundleRequest { + if in == nil { + return nil + } + out := new(TrustBundleRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TrustBundleRequest. Required by controller-gen. +func (in *TrustBundleRequest) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using TrustBundleResponse within kubernetes types, where deepcopy-gen is used. +func (in *TrustBundleResponse) DeepCopyInto(out *TrustBundleResponse) { + p := proto.Clone(in).(*TrustBundleResponse) + *out = *p +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrustBundleResponse. Required by controller-gen. +func (in *TrustBundleResponse) DeepCopy() *TrustBundleResponse { + if in == nil { + return nil + } + out := new(TrustBundleResponse) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new TrustBundleResponse. Required by controller-gen. +func (in *TrustBundleResponse) DeepCopyInterface() interface{} { + return in.DeepCopy() +} diff --git a/vendor/modules.txt b/vendor/modules.txt index f9bb94337f5..dbe0a154f4b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -79,6 +79,9 @@ github.com/asaskevich/govalidator # github.com/beorn7/perks v1.0.1 ## explicit; go 1.11 github.com/beorn7/perks/quantile +# github.com/cenkalti/backoff v2.2.1+incompatible +## explicit +github.com/cenkalti/backoff # github.com/cenkalti/backoff/v4 v4.1.3 ## explicit; go 1.13 github.com/cenkalti/backoff/v4 @@ -941,13 +944,16 @@ github.com/mitchellh/go-homedir # github.com/mitchellh/go-wordwrap v1.0.0 ## explicit github.com/mitchellh/go-wordwrap +# github.com/mitchellh/hashstructure/v2 v2.0.2 +## explicit; go 1.14 +github.com/mitchellh/hashstructure/v2 # github.com/mitchellh/mapstructure v1.4.3 ## explicit; go 1.14 github.com/mitchellh/mapstructure # github.com/mitchellh/reflectwalk v1.0.2 ## explicit github.com/mitchellh/reflectwalk -# github.com/moby/buildkit v0.10.1 +# github.com/moby/buildkit v0.10.4 ## explicit; go 1.17 github.com/moby/buildkit/frontend/dockerfile/command github.com/moby/buildkit/frontend/dockerfile/parser @@ -1570,7 +1576,7 @@ gopkg.in/tomb.v1 # gopkg.in/yaml.v2 v2.4.0 ## explicit; go 1.15 gopkg.in/yaml.v2 -# gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b +# gopkg.in/yaml.v3 v3.0.0 ## explicit gopkg.in/yaml.v3 # helm.sh/helm/v3 v3.8.2 @@ -2176,7 +2182,43 @@ k8s.io/utils/pointer k8s.io/utils/trace # maistra.io/api v0.0.0-20220301154558-8f6a12a9464b ## explicit; go 1.15 +maistra.io/api/client/informers/externalversions +maistra.io/api/client/informers/externalversions/core +maistra.io/api/client/informers/externalversions/core/v1 +maistra.io/api/client/informers/externalversions/core/v1alpha1 +maistra.io/api/client/informers/externalversions/core/v2 +maistra.io/api/client/informers/externalversions/federation +maistra.io/api/client/informers/externalversions/federation/v1 +maistra.io/api/client/informers/externalversions/internalinterfaces +maistra.io/api/client/listers/core/v1 +maistra.io/api/client/listers/core/v1alpha1 +maistra.io/api/client/listers/core/v2 +maistra.io/api/client/listers/federation/v1 +maistra.io/api/client/versioned +maistra.io/api/client/versioned/fake +maistra.io/api/client/versioned/scheme +maistra.io/api/client/versioned/typed/core/v1 +maistra.io/api/client/versioned/typed/core/v1/fake +maistra.io/api/client/versioned/typed/core/v1alpha1 +maistra.io/api/client/versioned/typed/core/v1alpha1/fake +maistra.io/api/client/versioned/typed/core/v2 +maistra.io/api/client/versioned/typed/core/v2/fake +maistra.io/api/client/versioned/typed/federation/v1 +maistra.io/api/client/versioned/typed/federation/v1/fake +maistra.io/api/client/xnsinformer +maistra.io/api/client/xnsinformer/core +maistra.io/api/client/xnsinformer/core/v1 +maistra.io/api/client/xnsinformer/core/v1alpha1 +maistra.io/api/client/xnsinformer/core/v2 +maistra.io/api/client/xnsinformer/federation +maistra.io/api/client/xnsinformer/federation/v1 +maistra.io/api/client/xnsinformer/internalinterfaces +maistra.io/api/core/v1 +maistra.io/api/core/v1alpha1 +maistra.io/api/core/v2 +maistra.io/api/federation/v1 maistra.io/api/manifests +maistra.io/api/security/v1 # sigs.k8s.io/controller-runtime v0.11.2 ## explicit; go 1.17 sigs.k8s.io/controller-runtime