From e4538b61741bfeb23efe3bc7272bdbd89160733f Mon Sep 17 00:00:00 2001 From: Jacek Ewertowski Date: Mon, 22 Aug 2022 16:31:38 +0200 Subject: [PATCH] Federation deployment (#585) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [federation] Initial federation implementation * MAISTRA-2194 Add server/client code for Federation Service Discovery v1 * MAISTRA-2195 Implement /watch endpoint * MAISTRA-2293 add CRD and controller for federating meshes * MAISTRA-2294 create CRD for federation ServiceExport (#324) * MAISTRA-2294 update example VirtualService resources for ratings and mongodb (#333) * [federation] MAISTRA-2295 create CRD for federation ServiceImport (#336) Signed-off-by: rcernich * [misc] Use objects and clients from maistra/api repo - Remove local objects and clients - Update Makefile * [federation] MAISTRA-2309 create CRD for FederationStatus (#348) Signed-off-by: rcernich * [federation] Federation fixes and improvements MAISTRA-2423 update federation api to v1 Signed-off-by: rcernich MAISTRA-2424 minor updates to federation api Signed-off-by: rcernich MAISTRA-2427 configure locality info on imported services Signed-off-by: rcernich Cherry-pick multi-root support (#387) * Update go-control-plane to v0.9.9 * Support multiple roots Squashed commit, contains: - MAISTRA-2325 Distribute trust bundles over SDS - MAISTRA-2390 Push trust bundle updates through xDS (#357) MAISTRA-2425 move spec.security.certificateChain to ConfigMap reference; add ability to specify ports for service and discovery (#392) Signed-off-by: rcernich MAISTRA-2426 move FederationStatus into MeshFederation (#393) Signed-off-by: rcernich MAISTRA-2513 federation API refinements Signed-off-by: rcernich [federation] MAISTRA-2237 Encrypt service discovery traffic (#411) MAISTRA-2610 Prefix federation discovery endpoints with /v1/ (#422) MAISTRA-2297 Support updates of federation resources (#417) MAISTRA-2375: Do not create automatic routes for Federation Gateways Remove a redundant call `setHostname()` is already being called within `NameForService()` see https://github.com/maistra/istio/blob/21ee900cf8825711f70d88dc97afcf6862ed2626/pkg/servicemesh/federation/common/namemapping.go lines 83, 120, 129 Remove techPreview.meshConfig from PoC example It's set by default now. MAISTRA-2611 Fix deletion of service exports to federated mesh (#421) Fix test MAISTRA-2658 Ensure ImportedServiceSet.status.importedServices is never nil (#437) * MAISTRA-2658 Ensure ImportedServiceSet.status.importedServices is never nil * Fix test MAISTRA-2682 Fix watch mechanism in federation (#439) Previously, no events were read from the watch response, because the read started with an endless loop that waited for data to be available in the decoder's buffer. This never happened, because the buffer is only written to when you call decoder.Decode(); this function was never called because the code waited for the buffer to have data. MAISTRA-2683 Properly close incoming watch connections when shutting down (#440) Log actual error returned by pollServices() (#441) Previously, instead of the actual error, only the following error message was logged: "expected condition not met". MAISTRA-2439: Prevent federation from exporting services that are not visible to the federation gateway (#432) By taking into consideration the service annotation `networking.istio.io/exportTo`. This annotation restricts where this service is visible: https://istio.io/latest/docs/reference/config/annotations/ If a service is not reachable from the federation gateway namespace due to this annotation, it should not be exported. MAISTRA-2617: Do not watch all namespaces in Extensions controller (#425) When using MemberRoll, we should rely on it to provide the list of namespaces to watch. If not using it, defaults to command line arguments. This fixes an istiod startup error as seen in the logs: ``` github.com/maistra/xns-informer/pkg/informers/informer.go:204: Failed to watch *v1.ServiceMeshExtension: failed to list *v1.ServiceMeshExtension: servicemeshextensions.maistra.io is forbidden: User "system:serviceaccount:i1:istiod-service-account-basic" cannot list resource "servicemeshextensions" in API group "maistra.io" at the cluster scope ``` * Remove package export and extensions Signed-off-by: Jacek Ewertowski * Fix creating discovery.Controller Signed-off-by: Jacek Ewertowski * Fix calling nil ResourceManager Signed-off-by: Jacek Ewertowski * Remove panicing from AppendNetworkGatewayHandler Signed-off-by: Jacek Ewertowski * [misc] OSSM-774 Fix flaky TestStatusManager (#456) This adds a little sleep to our unit tests for the StatusManager, because without it, we're running into the issue that we're updating a ServiceMeshPeer's status very quickly, and in some cases it might be that the last change has not been propagated when we're generating the patch for the next status change, which can lead to failures. This can happen in the real world, but you would need to change a ServiceMeshPeer's status within a few milliseconds, I doubt that it affects users. It would also be fixed with the next status update. For those reasons, I'm only fixing it in the test, with a Sleep() call. * Refactor manager_test Signed-off-by: Jacek Ewertowski * OSSM-1150 Fix flaky TestStatusManager unit test (#478) Co-authored-by: Marko Lukša * OSSM-1252 Fix federation status updates (#512) * Copy federation privileges from base to istio-discovery * Remove unnecessary ServiceMeshExtensions CRD Signed-off-by: Jacek Ewertowski * Add model.NetworkGatewaysHandler to federation controller to implement AppendNetworkGatewayHandler Signed-off-by: Jacek Ewertowski * [federation] MAISTRA-2640 Add federation integration test (#447) * Fix building federation test Signed-off-by: Jacek Ewertowski * Add package gogo from maistra-2.2 to temporarily fix TbdsGenerator Signed-off-by: Jacek Ewertowski * Disable configuring remote cluster in federation deployment Signed-off-by: Jacek Ewertowski * [federation] OSSM-1128 Fix federation (#480) * Fix SecretCacheClient Signed-off-by: Jacek Ewertowski * Send initial XDS request for trust bundle from proxy Signed-off-by: Jacek Ewertowski * Disable using EndpointSlices to fix error on getting federation-egress endpoints Signed-off-by: Jacek Ewertowski * Remove unused serviceMeshExtensionController Signed-off-by: Jacek Ewertowski * Fix lint errors Signed-off-by: Jacek Ewertowski * Update maistra CRDs Signed-off-by: Jacek Ewertowski * fedration_cp_version_update (#521) * OSSM-1529 Improve federation example script (#522) * OSSM-1529 Improve federation example install.sh Previously, the script would fall back to using nodeports when the load balancer IP wasn't set. This meant that if the provision of the load balancer took too long, the SMCPs would be misconfigured and you had to run the install script again. With this change, the script now waits for the load balancer IP to appear. It never falls back to using node ports, because they never really worked (the nodes' hostnames typically aren't FQDN and the node ports are typically protected by firewalls). If the user wants to expose the federation ingresses in a different way, they can now set the environment variables MESH1_ADDRESS, MESH1_DISCOVERY_PORT, and MESH2_SERVICE_PORT (likewise for MESH2) and run the script. * Update Federation example README * Better "Waiting for load balancer" message * OSSM-1211 Fix federation locality failover issues (#561) Signed-off-by: Yuanlin Signed-off-by: rcernich Signed-off-by: Jacek Ewertowski Signed-off-by: Yuanlin Co-authored-by: Daniel Grimm Co-authored-by: Rob Cernich Co-authored-by: Jonh Wendell Co-authored-by: maistra-bot <57098434+maistra-bot@users.noreply.github.com> Co-authored-by: Marko Lukša Co-authored-by: Praneeth Bajjuri Co-authored-by: Yuanlin Xu --- Makefile.core.mk | 6 +- bin/update_maistra_deps.sh | 6 +- common/config/.golangci-format.yml | 2 + go.mod | 8 +- go.sum | 14 +- licenses/github.com/cenkalti/backoff/LICENSE | 20 + .../mitchellh/hashstructure/v2/LICENSE | 21 + licenses/maistra.io/api/LICENSE | 202 ++ maistra.mk | 7 + ...ration.maistra.io_exportedservicesets.yaml | 221 ++ ...ration.maistra.io_importedservicesets.yaml | 171 + ...ederation.maistra.io_servicemeshpeers.yaml | 353 ++ .../charts/base/files/gen-istio-cluster.yaml | 759 ++++ manifests/charts/base/templates/crds.yaml | 4 + manifests/charts/base/templates/role.yaml | 5 + .../istio-discovery/files/gen-istio.yaml | 34 + .../istio-discovery/templates/deployment.yaml | 4 + .../istio-discovery/templates/federation.yaml | 21 + .../istio-discovery/templates/role.yaml | 5 + .../istio-discovery/templates/service.yaml | 3 + .../istio-control/istio-discovery/values.yaml | 1 + .../charts/istiod-remote/templates/role.yaml | 5 + manifests/charts/istiod-remote/values.yaml | 1 + pilot/cmd/pilot-discovery/app/cmd.go | 4 + pilot/pkg/bootstrap/configcontroller.go | 8 + pilot/pkg/bootstrap/options.go | 5 + pilot/pkg/bootstrap/server.go | 99 +- pilot/pkg/features/pilot.go | 5 + .../grpcgen/testdata/xds_bootstrap.json | 2 +- pilot/pkg/security/trustdomain/bundle.go | 2 +- .../serviceregistry/aggregate/controller.go | 15 +- .../aggregate/controller_test.go | 92 +- .../serviceregistry/federation/controller.go | 1130 ++++++ .../federation/controller_test.go | 62 + .../pkg/serviceregistry/federation/routing.go | 177 + .../kube/controller/controller.go | 1 + .../pkg/serviceregistry/provider/providers.go | 2 + pilot/pkg/xds/tbds.go | 71 + pilot/pkg/xds/v3/model.go | 7 + pkg/istio-agent/xds_proxy.go | 51 + pkg/kube/controller/controller.go | 151 + pkg/security/security.go | 2 + .../apis/servicemesh/v1/register.go | 76 - .../apis/servicemesh/v1/servicemesh.go | 53 - .../servicemesh/v1/zz_generated.deepcopy.go | 128 - .../servicemesh/v1/servicemesh_client.go | 105 - .../informers/externalversions/generic.go | 60 - pkg/servicemesh/controller/controller.go | 10 +- pkg/servicemesh/federation/common/const.go | 31 + pkg/servicemesh/federation/common/exports.go | 106 + pkg/servicemesh/federation/common/imports.go | 106 + .../federation/common/namemapping.go | 133 + pkg/servicemesh/federation/common/options.go | 47 + .../federation/common/resources.go | 109 + pkg/servicemesh/federation/common/testing.go | 73 + pkg/servicemesh/federation/common/util.go | 82 + .../federation/discovery/controller.go | 362 ++ .../federation/discovery/controller_test.go | 383 +++ .../federation/discovery/discovery.go | 664 ++++ .../federation/example/config-poc/README.md | 63 + .../example/config-poc/cacerts/README.md | 20 + .../example/config-poc/cacerts/ca-cert.pem | 22 + .../example/config-poc/cacerts/ca-key.pem | 27 + .../example/config-poc/cacerts/cert-chain.pem | 22 + .../config-poc/cacerts/generate-workload.sh | 65 + .../example/config-poc/cacerts/root-cert.pem | 24 + .../config-poc/cacerts/workload-bar-cert.pem | 43 + .../config-poc/cacerts/workload-bar-key.pem | 27 + .../config-poc/cacerts/workload-foo-cert.pem | 43 + .../config-poc/cacerts/workload-foo-key.pem | 27 + .../federation/example/config-poc/cleanup.sh | 28 + .../federation/example/config-poc/common.sh | 54 + .../authorizationpolicy-direct-to-direct.yaml | 52 + ...authorizationpolicy-direct-to-proxied.yaml | 38 + .../mongodb-remote-virtualservice.yaml | 15 + .../ratings-split-virtualservice.yaml | 19 + .../example/config-poc/export/configmap.yaml | 8 + .../config-poc/export/exportedserviceset.yaml | 21 + .../config-poc/export/servicemeshpeer.yaml | 23 + .../example/config-poc/export/smcp.yaml | 94 + .../example/config-poc/export/smmr.yaml | 8 + .../example/config-poc/import/configmap.yaml | 8 + .../config-poc/import/importedserviceset.yaml | 16 + .../config-poc/import/mongodb-service.yaml | 12 + .../config-poc/import/servicemeshpeer.yaml | 23 + .../example/config-poc/import/smcp.yaml | 94 + .../example/config-poc/import/smmr.yaml | 8 + .../federation/example/config-poc/install.sh | 154 + .../federation/exports/controller.go | 112 + pkg/servicemesh/federation/federation.go | 209 ++ pkg/servicemesh/federation/federation_test.go | 75 + .../federation/imports/controller.go | 134 + pkg/servicemesh/federation/model/model.go | 79 + pkg/servicemesh/federation/server/routing.go | 281 ++ pkg/servicemesh/federation/server/server.go | 723 ++++ .../federation/server/server_test.go | 1033 ++++++ pkg/servicemesh/federation/status/handler.go | 629 ++++ pkg/servicemesh/federation/status/manager.go | 162 + .../federation/status/manager_test.go | 868 +++++ pkg/servicemesh/maistra.mk | 61 - pkg/servicemesh/model/extension.go | 46 + pkg/test/framework/components/istio/config.go | 10 + .../framework/components/istio/operator.go | 25 +- pkg/test/framework/label/labels.go | 7 +- pkg/util/gogo/conversion.go | 71 + pkg/util/gogo/conversion_test.go | 95 + security/pkg/nodeagent/cache/secretcache.go | 53 + security/pkg/nodeagent/sds/sdsservice.go | 110 +- .../iop-integration-test-defaults.yaml | 7 + .../servicemesh/federation/federation.go | 272 ++ .../servicemesh/federation/federation_test.go | 59 + .../servicemesh/maistra/maistra.go | 2 +- vendor/github.com/cenkalti/backoff/.gitignore | 22 + .../github.com/cenkalti/backoff/.travis.yml | 10 + vendor/github.com/cenkalti/backoff/LICENSE | 20 + vendor/github.com/cenkalti/backoff/README.md | 30 + vendor/github.com/cenkalti/backoff/backoff.go | 66 + vendor/github.com/cenkalti/backoff/context.go | 63 + .../cenkalti/backoff/exponential.go | 153 + vendor/github.com/cenkalti/backoff/retry.go | 82 + vendor/github.com/cenkalti/backoff/ticker.go | 82 + vendor/github.com/cenkalti/backoff/tries.go | 35 + .../mitchellh/hashstructure/v2/LICENSE | 21 + .../mitchellh/hashstructure/v2/README.md | 76 + .../mitchellh/hashstructure/v2/errors.go | 22 + .../hashstructure/v2/hashstructure.go | 482 +++ .../mitchellh/hashstructure/v2/include.go | 22 + vendor/gopkg.in/yaml.v3/decode.go | 78 +- .../externalversions/core/interface.go | 60 + .../externalversions/core/v1/interface.go | 64 + .../core/v1/servicemeshcontrolplane.go | 88 + .../core/v1/servicemeshextension.go | 88 + .../core/v1/servicemeshmember.go | 88 + .../core}/v1/servicemeshmemberroll.go | 16 +- .../core/v1alpha1}/interface.go | 14 +- .../core/v1alpha1/servicemeshextension.go | 88 + .../externalversions/core/v2/interface.go | 43 + .../core/v2/servicemeshcontrolplane.go | 88 + .../informers/externalversions/factory.go | 18 +- .../externalversions/federation}/interface.go | 6 +- .../federation/v1/exportedserviceset.go | 88 + .../federation/v1/importedserviceset.go | 88 + .../federation/v1/interface.go | 57 + .../federation/v1/servicemeshpeer.go | 88 + .../informers/externalversions/generic.go | 85 + .../internalinterfaces/factory_interfaces.go | 2 +- .../listers/core/v1/expansion_generated.go | 49 + .../core/v1/servicemeshcontrolplane.go | 97 + .../listers/core/v1/servicemeshextension.go | 97 + .../listers/core/v1/servicemeshmember.go | 97 + .../listers/core}/v1/servicemeshmemberroll.go | 2 +- .../core/v1alpha1}/expansion_generated.go | 14 +- .../core/v1alpha1/servicemeshextension.go | 97 + .../listers/core/v2/expansion_generated.go | 25 + .../core/v2/servicemeshcontrolplane.go | 97 + .../federation/v1/expansion_generated.go | 41 + .../federation/v1/exportedserviceset.go | 97 + .../federation/v1/importedserviceset.go | 97 + .../listers/federation/v1/servicemeshpeer.go | 97 + .../api/client}/versioned/clientset.go | 90 +- .../maistra.io/api/client}/versioned/doc.go | 0 .../versioned/fake/clientset_generated.go | 33 +- .../api/client}/versioned/fake/doc.go | 0 .../api/client}/versioned/fake/register.go | 10 +- .../api/client}/versioned/scheme/doc.go | 0 .../api/client}/versioned/scheme/register.go | 10 +- .../versioned/typed/core/v1/core_client.go | 102 + .../client/versioned/typed/core}/v1/doc.go | 0 .../versioned/typed/core}/v1/fake/doc.go | 0 .../typed/core/v1/fake/fake_core_client.go | 50 + .../v1/fake/fake_servicemeshcontrolplane.go | 140 + .../core/v1/fake/fake_servicemeshextension.go | 140 + .../core/v1/fake/fake_servicemeshmember.go | 140 + .../v1/fake/fake_servicemeshmemberroll.go | 46 +- .../typed/core/v1/generated_expansion.go | 25 + .../typed/core/v1/servicemeshcontrolplane.go | 193 ++ .../typed/core/v1/servicemeshextension.go | 193 ++ .../typed/core/v1/servicemeshmember.go | 193 ++ .../typed/core}/v1/servicemeshmemberroll.go | 6 +- .../typed/core/v1alpha1/core_client.go | 87 + .../versioned/typed/core/v1alpha1/doc.go | 18 + .../versioned/typed/core/v1alpha1/fake/doc.go | 18 + .../core/v1alpha1/fake/fake_core_client.go | 10 +- .../fake/fake_servicemeshextension.go | 140 + .../core/v1alpha1/generated_expansion.go | 5 + .../core/v1alpha1/servicemeshextension.go | 193 ++ .../versioned/typed/core/v2/core_client.go | 87 + .../api/client/versioned/typed/core/v2/doc.go | 18 + .../versioned/typed/core/v2/fake/doc.go | 18 + .../typed/core/v2/fake/fake_core_client.go | 38 + .../v2/fake/fake_servicemeshcontrolplane.go | 140 + .../typed/core/v2}/generated_expansion.go | 4 +- .../typed/core/v2/servicemeshcontrolplane.go | 193 ++ .../versioned/typed/federation/v1/doc.go | 18 + .../typed/federation/v1/exportedserviceset.go | 193 ++ .../versioned/typed/federation/v1/fake/doc.go | 18 + .../v1/fake/fake_exportedserviceset.go | 140 + .../v1/fake/fake_federation_client.go | 46 + .../v1/fake/fake_importedserviceset.go | 140 + .../v1/fake/fake_servicemeshpeer.go | 140 + .../typed/federation/v1/federation_client.go | 97 + .../federation/v1/generated_expansion.go | 23 + .../typed/federation/v1/importedserviceset.go | 193 ++ .../typed/federation/v1/servicemeshpeer.go | 193 ++ .../api/client/xnsinformer/core/interface.go | 61 + .../client/xnsinformer/core/v1/interface.go | 65 + .../core/v1/servicemeshcontrolplane.go | 93 + .../core/v1/servicemeshextension.go | 93 + .../xnsinformer/core/v1/servicemeshmember.go | 93 + .../core/v1/servicemeshmemberroll.go | 93 + .../xnsinformer/core/v1alpha1/interface.go | 44 + .../core/v1alpha1/servicemeshextension.go | 93 + .../client/xnsinformer/core/v2/interface.go | 44 + .../core/v2/servicemeshcontrolplane.go | 93 + .../api/client/xnsinformer/factory.go | 186 + .../xnsinformer/federation/interface.go | 45 + .../federation/v1/exportedserviceset.go | 93 + .../federation/v1/importedserviceset.go | 93 + .../xnsinformer/federation/v1/interface.go | 58 + .../federation/v1/servicemeshpeer.go | 93 + .../api/client/xnsinformer/generic.go | 85 + .../internalinterfaces/factory_interfaces.go | 38 + .../api/core/v1/controlplane_types.go | 141 + .../api/core/v1/extension_conversion.go | 16 +- .../maistra.io/api/core/v1/extension_types.go | 130 + .../api/core/v1/groupversion_info.go | 50 + vendor/maistra.io/api/core/v1/helmvalues.go | 287 ++ vendor/maistra.io/api/core/v1/member_types.go | 170 + .../api/core/v1/memberroll_types.go | 188 + vendor/maistra.io/api/core/v1/status.go | 269 ++ .../api/core/v1/zz_generated.deepcopy.go | 696 ++++ .../api/core/v1alpha1/conversion_generated.go | 281 ++ .../maistra.io/api/core/v1alpha1/doc.go | 8 +- .../api/core/v1alpha1/extension_conversion.go | 75 + .../api/core/v1alpha1/extension_types.go | 89 + .../api/core/v1alpha1/groupversion_info.go | 49 + .../core/v1alpha1/zz_generated.deepcopy.go | 168 + vendor/maistra.io/api/core/v2/addons.go | 22 + vendor/maistra.io/api/core/v2/cluster.go | 76 + .../api/core/v2/controlplane_types.go | 179 + vendor/maistra.io/api/core/v2/conversion.go | 10 + vendor/maistra.io/api/core/v2/datadog.go | 6 + vendor/maistra.io/api/core/v2/gateways.go | 162 + vendor/maistra.io/api/core/v2/general.go | 16 + vendor/maistra.io/api/core/v2/grafana.go | 69 + .../api/core/v2/groupversion_info.go | 47 + vendor/maistra.io/api/core/v2/jaeger.go | 98 + vendor/maistra.io/api/core/v2/kiali.go | 52 + vendor/maistra.io/api/core/v2/lightstep.go | 6 + vendor/maistra.io/api/core/v2/logging.go | 93 + vendor/maistra.io/api/core/v2/policy.go | 91 + vendor/maistra.io/api/core/v2/prometheus.go | 58 + vendor/maistra.io/api/core/v2/proxy.go | 387 +++ vendor/maistra.io/api/core/v2/runtime.go | 334 ++ vendor/maistra.io/api/core/v2/security.go | 276 ++ vendor/maistra.io/api/core/v2/smcp_new.yaml | 481 +++ vendor/maistra.io/api/core/v2/stackdriver.go | 97 + vendor/maistra.io/api/core/v2/telemetry.go | 119 + vendor/maistra.io/api/core/v2/threescale.go | 130 + vendor/maistra.io/api/core/v2/tracing.go | 31 + vendor/maistra.io/api/core/v2/zipkin.go | 6 + .../api/core/v2/zz_generated.deepcopy.go | 3040 +++++++++++++++++ .../maistra.io/api/federation}/v1/doc.go | 5 +- .../federation/v1/exportedserviceset_types.go | 80 + .../api/federation/v1/groupversion_info.go | 49 + .../federation/v1/import_export_mapping.go | 104 + .../federation/v1/importedserviceset_types.go | 110 + .../federation/v1/servicemeshpeer_types.go | 223 ++ .../federation/v1/zz_generated.deepcopy.go | 646 ++++ .../api/security/v1/trustbundle.pb.go | 789 +++++ .../api/security/v1/trustbundle.proto | 38 + .../security/v1/trustbundle_deepcopy.gen.go | 78 + vendor/modules.txt | 46 +- 273 files changed, 30665 insertions(+), 718 deletions(-) create mode 100644 licenses/github.com/cenkalti/backoff/LICENSE create mode 100644 licenses/github.com/mitchellh/hashstructure/v2/LICENSE create mode 100644 licenses/maistra.io/api/LICENSE create mode 100644 maistra.mk create mode 100644 manifests/charts/base/crds/federation.maistra.io_exportedservicesets.yaml create mode 100644 manifests/charts/base/crds/federation.maistra.io_importedservicesets.yaml create mode 100644 manifests/charts/base/crds/federation.maistra.io_servicemeshpeers.yaml create mode 100644 manifests/charts/istio-control/istio-discovery/templates/federation.yaml create mode 100644 pilot/pkg/serviceregistry/federation/controller.go create mode 100644 pilot/pkg/serviceregistry/federation/controller_test.go create mode 100644 pilot/pkg/serviceregistry/federation/routing.go create mode 100644 pilot/pkg/xds/tbds.go create mode 100644 pkg/kube/controller/controller.go delete mode 100644 pkg/servicemesh/apis/servicemesh/v1/register.go delete mode 100644 pkg/servicemesh/apis/servicemesh/v1/servicemesh.go delete mode 100644 pkg/servicemesh/apis/servicemesh/v1/zz_generated.deepcopy.go delete mode 100644 pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/servicemesh_client.go delete mode 100644 pkg/servicemesh/client/informers/externalversions/generic.go create mode 100644 pkg/servicemesh/federation/common/const.go create mode 100644 pkg/servicemesh/federation/common/exports.go create mode 100644 pkg/servicemesh/federation/common/imports.go create mode 100644 pkg/servicemesh/federation/common/namemapping.go create mode 100644 pkg/servicemesh/federation/common/options.go create mode 100644 pkg/servicemesh/federation/common/resources.go create mode 100644 pkg/servicemesh/federation/common/testing.go create mode 100644 pkg/servicemesh/federation/common/util.go create mode 100644 pkg/servicemesh/federation/discovery/controller.go create mode 100644 pkg/servicemesh/federation/discovery/controller_test.go create mode 100644 pkg/servicemesh/federation/discovery/discovery.go create mode 100644 pkg/servicemesh/federation/example/config-poc/README.md create mode 100644 pkg/servicemesh/federation/example/config-poc/cacerts/README.md create mode 100644 pkg/servicemesh/federation/example/config-poc/cacerts/ca-cert.pem create mode 100644 pkg/servicemesh/federation/example/config-poc/cacerts/ca-key.pem create mode 100644 pkg/servicemesh/federation/example/config-poc/cacerts/cert-chain.pem create mode 100755 pkg/servicemesh/federation/example/config-poc/cacerts/generate-workload.sh create mode 100644 pkg/servicemesh/federation/example/config-poc/cacerts/root-cert.pem create mode 100644 pkg/servicemesh/federation/example/config-poc/cacerts/workload-bar-cert.pem create mode 100644 pkg/servicemesh/federation/example/config-poc/cacerts/workload-bar-key.pem create mode 100644 pkg/servicemesh/federation/example/config-poc/cacerts/workload-foo-cert.pem create mode 100644 pkg/servicemesh/federation/example/config-poc/cacerts/workload-foo-key.pem create mode 100755 pkg/servicemesh/federation/example/config-poc/cleanup.sh create mode 100644 pkg/servicemesh/federation/example/config-poc/common.sh create mode 100644 pkg/servicemesh/federation/example/config-poc/examples/authorizationpolicy-direct-to-direct.yaml create mode 100644 pkg/servicemesh/federation/example/config-poc/examples/authorizationpolicy-direct-to-proxied.yaml create mode 100644 pkg/servicemesh/federation/example/config-poc/examples/mongodb-remote-virtualservice.yaml create mode 100644 pkg/servicemesh/federation/example/config-poc/examples/ratings-split-virtualservice.yaml create mode 100644 pkg/servicemesh/federation/example/config-poc/export/configmap.yaml create mode 100644 pkg/servicemesh/federation/example/config-poc/export/exportedserviceset.yaml create mode 100644 pkg/servicemesh/federation/example/config-poc/export/servicemeshpeer.yaml create mode 100644 pkg/servicemesh/federation/example/config-poc/export/smcp.yaml create mode 100644 pkg/servicemesh/federation/example/config-poc/export/smmr.yaml create mode 100644 pkg/servicemesh/federation/example/config-poc/import/configmap.yaml create mode 100644 pkg/servicemesh/federation/example/config-poc/import/importedserviceset.yaml create mode 100644 pkg/servicemesh/federation/example/config-poc/import/mongodb-service.yaml create mode 100644 pkg/servicemesh/federation/example/config-poc/import/servicemeshpeer.yaml create mode 100644 pkg/servicemesh/federation/example/config-poc/import/smcp.yaml create mode 100644 pkg/servicemesh/federation/example/config-poc/import/smmr.yaml create mode 100755 pkg/servicemesh/federation/example/config-poc/install.sh create mode 100644 pkg/servicemesh/federation/exports/controller.go create mode 100644 pkg/servicemesh/federation/federation.go create mode 100644 pkg/servicemesh/federation/federation_test.go create mode 100644 pkg/servicemesh/federation/imports/controller.go create mode 100644 pkg/servicemesh/federation/model/model.go create mode 100644 pkg/servicemesh/federation/server/routing.go create mode 100644 pkg/servicemesh/federation/server/server.go create mode 100644 pkg/servicemesh/federation/server/server_test.go create mode 100644 pkg/servicemesh/federation/status/handler.go create mode 100644 pkg/servicemesh/federation/status/manager.go create mode 100644 pkg/servicemesh/federation/status/manager_test.go delete mode 100644 pkg/servicemesh/maistra.mk create mode 100644 pkg/servicemesh/model/extension.go create mode 100644 pkg/util/gogo/conversion.go create mode 100644 pkg/util/gogo/conversion_test.go create mode 100644 tests/integration/servicemesh/federation/federation.go create mode 100644 tests/integration/servicemesh/federation/federation_test.go create mode 100644 vendor/github.com/cenkalti/backoff/.gitignore create mode 100644 vendor/github.com/cenkalti/backoff/.travis.yml create mode 100644 vendor/github.com/cenkalti/backoff/LICENSE create mode 100644 vendor/github.com/cenkalti/backoff/README.md create mode 100644 vendor/github.com/cenkalti/backoff/backoff.go create mode 100644 vendor/github.com/cenkalti/backoff/context.go create mode 100644 vendor/github.com/cenkalti/backoff/exponential.go create mode 100644 vendor/github.com/cenkalti/backoff/retry.go create mode 100644 vendor/github.com/cenkalti/backoff/ticker.go create mode 100644 vendor/github.com/cenkalti/backoff/tries.go create mode 100644 vendor/github.com/mitchellh/hashstructure/v2/LICENSE create mode 100644 vendor/github.com/mitchellh/hashstructure/v2/README.md create mode 100644 vendor/github.com/mitchellh/hashstructure/v2/errors.go create mode 100644 vendor/github.com/mitchellh/hashstructure/v2/hashstructure.go create mode 100644 vendor/github.com/mitchellh/hashstructure/v2/include.go create mode 100644 vendor/maistra.io/api/client/informers/externalversions/core/interface.go create mode 100644 vendor/maistra.io/api/client/informers/externalversions/core/v1/interface.go create mode 100644 vendor/maistra.io/api/client/informers/externalversions/core/v1/servicemeshcontrolplane.go create mode 100644 vendor/maistra.io/api/client/informers/externalversions/core/v1/servicemeshextension.go create mode 100644 vendor/maistra.io/api/client/informers/externalversions/core/v1/servicemeshmember.go rename {pkg/servicemesh/client/informers/externalversions/servicemesh => vendor/maistra.io/api/client/informers/externalversions/core}/v1/servicemeshmemberroll.go (83%) rename {pkg/servicemesh/client/informers/externalversions/servicemesh/v1 => vendor/maistra.io/api/client/informers/externalversions/core/v1alpha1}/interface.go (70%) create mode 100644 vendor/maistra.io/api/client/informers/externalversions/core/v1alpha1/servicemeshextension.go create mode 100644 vendor/maistra.io/api/client/informers/externalversions/core/v2/interface.go create mode 100644 vendor/maistra.io/api/client/informers/externalversions/core/v2/servicemeshcontrolplane.go rename {pkg/servicemesh => vendor/maistra.io/api}/client/informers/externalversions/factory.go (91%) rename {pkg/servicemesh/client/informers/externalversions/servicemesh => vendor/maistra.io/api/client/informers/externalversions/federation}/interface.go (86%) create mode 100644 vendor/maistra.io/api/client/informers/externalversions/federation/v1/exportedserviceset.go create mode 100644 vendor/maistra.io/api/client/informers/externalversions/federation/v1/importedserviceset.go create mode 100644 vendor/maistra.io/api/client/informers/externalversions/federation/v1/interface.go create mode 100644 vendor/maistra.io/api/client/informers/externalversions/federation/v1/servicemeshpeer.go create mode 100644 vendor/maistra.io/api/client/informers/externalversions/generic.go rename {pkg/servicemesh => vendor/maistra.io/api}/client/informers/externalversions/internalinterfaces/factory_interfaces.go (95%) create mode 100644 vendor/maistra.io/api/client/listers/core/v1/expansion_generated.go create mode 100644 vendor/maistra.io/api/client/listers/core/v1/servicemeshcontrolplane.go create mode 100644 vendor/maistra.io/api/client/listers/core/v1/servicemeshextension.go create mode 100644 vendor/maistra.io/api/client/listers/core/v1/servicemeshmember.go rename {pkg/servicemesh/client/listers/servicemesh => vendor/maistra.io/api/client/listers/core}/v1/servicemeshmemberroll.go (98%) rename {pkg/servicemesh/client/listers/servicemesh/v1 => vendor/maistra.io/api/client/listers/core/v1alpha1}/expansion_generated.go (63%) create mode 100644 vendor/maistra.io/api/client/listers/core/v1alpha1/servicemeshextension.go create mode 100644 vendor/maistra.io/api/client/listers/core/v2/expansion_generated.go create mode 100644 vendor/maistra.io/api/client/listers/core/v2/servicemeshcontrolplane.go create mode 100644 vendor/maistra.io/api/client/listers/federation/v1/expansion_generated.go create mode 100644 vendor/maistra.io/api/client/listers/federation/v1/exportedserviceset.go create mode 100644 vendor/maistra.io/api/client/listers/federation/v1/importedserviceset.go create mode 100644 vendor/maistra.io/api/client/listers/federation/v1/servicemeshpeer.go rename {pkg/servicemesh/client/clientset => vendor/maistra.io/api/client}/versioned/clientset.go (57%) rename {pkg/servicemesh/client/clientset => vendor/maistra.io/api/client}/versioned/doc.go (100%) rename {pkg/servicemesh/client/clientset => vendor/maistra.io/api/client}/versioned/fake/clientset_generated.go (66%) rename {pkg/servicemesh/client/clientset => vendor/maistra.io/api/client}/versioned/fake/doc.go (100%) rename {pkg/servicemesh/client/clientset => vendor/maistra.io/api/client}/versioned/fake/register.go (87%) rename {pkg/servicemesh/client/clientset => vendor/maistra.io/api/client}/versioned/scheme/doc.go (100%) rename {pkg/servicemesh/client/clientset => vendor/maistra.io/api/client}/versioned/scheme/register.go (87%) create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v1/core_client.go rename {pkg/servicemesh/client/clientset/versioned/typed/servicemesh => vendor/maistra.io/api/client/versioned/typed/core}/v1/doc.go (100%) rename {pkg/servicemesh/client/clientset/versioned/typed/servicemesh => vendor/maistra.io/api/client/versioned/typed/core}/v1/fake/doc.go (100%) create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_core_client.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_servicemeshcontrolplane.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_servicemeshextension.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v1/fake/fake_servicemeshmember.go rename {pkg/servicemesh/client/clientset/versioned/typed/servicemesh => vendor/maistra.io/api/client/versioned/typed/core}/v1/fake/fake_servicemeshmemberroll.go (69%) create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v1/generated_expansion.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v1/servicemeshcontrolplane.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v1/servicemeshextension.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v1/servicemeshmember.go rename {pkg/servicemesh/client/clientset/versioned/typed/servicemesh => vendor/maistra.io/api/client/versioned/typed/core}/v1/servicemeshmemberroll.go (97%) create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/core_client.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/doc.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/fake/doc.go rename pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1/fake/fake_servicemesh_client.go => vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/fake/fake_core_client.go (73%) create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/fake/fake_servicemeshextension.go rename pkg/servicemesh/header.go.txt => vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/generated_expansion.go (83%) create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v1alpha1/servicemeshextension.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v2/core_client.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v2/doc.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v2/fake/doc.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v2/fake/fake_core_client.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v2/fake/fake_servicemeshcontrolplane.go rename {pkg/servicemesh/client/clientset/versioned/typed/servicemesh/v1 => vendor/maistra.io/api/client/versioned/typed/core/v2}/generated_expansion.go (91%) create mode 100644 vendor/maistra.io/api/client/versioned/typed/core/v2/servicemeshcontrolplane.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/federation/v1/doc.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/federation/v1/exportedserviceset.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/doc.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/fake_exportedserviceset.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/fake_federation_client.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/fake_importedserviceset.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/federation/v1/fake/fake_servicemeshpeer.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/federation/v1/federation_client.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/federation/v1/generated_expansion.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/federation/v1/importedserviceset.go create mode 100644 vendor/maistra.io/api/client/versioned/typed/federation/v1/servicemeshpeer.go create mode 100644 vendor/maistra.io/api/client/xnsinformer/core/interface.go create mode 100644 vendor/maistra.io/api/client/xnsinformer/core/v1/interface.go create mode 100644 vendor/maistra.io/api/client/xnsinformer/core/v1/servicemeshcontrolplane.go create mode 100644 vendor/maistra.io/api/client/xnsinformer/core/v1/servicemeshextension.go create mode 100644 vendor/maistra.io/api/client/xnsinformer/core/v1/servicemeshmember.go create mode 100644 vendor/maistra.io/api/client/xnsinformer/core/v1/servicemeshmemberroll.go create mode 100644 vendor/maistra.io/api/client/xnsinformer/core/v1alpha1/interface.go create mode 100644 vendor/maistra.io/api/client/xnsinformer/core/v1alpha1/servicemeshextension.go create mode 100644 vendor/maistra.io/api/client/xnsinformer/core/v2/interface.go create mode 100644 vendor/maistra.io/api/client/xnsinformer/core/v2/servicemeshcontrolplane.go create mode 100644 vendor/maistra.io/api/client/xnsinformer/factory.go create mode 100644 vendor/maistra.io/api/client/xnsinformer/federation/interface.go create mode 100644 vendor/maistra.io/api/client/xnsinformer/federation/v1/exportedserviceset.go create mode 100644 vendor/maistra.io/api/client/xnsinformer/federation/v1/importedserviceset.go create mode 100644 vendor/maistra.io/api/client/xnsinformer/federation/v1/interface.go create mode 100644 vendor/maistra.io/api/client/xnsinformer/federation/v1/servicemeshpeer.go create mode 100644 vendor/maistra.io/api/client/xnsinformer/generic.go create mode 100644 vendor/maistra.io/api/client/xnsinformer/internalinterfaces/factory_interfaces.go create mode 100644 vendor/maistra.io/api/core/v1/controlplane_types.go rename security/pkg/pki/ra/leak_test.go => vendor/maistra.io/api/core/v1/extension_conversion.go (71%) create mode 100644 vendor/maistra.io/api/core/v1/extension_types.go create mode 100644 vendor/maistra.io/api/core/v1/groupversion_info.go create mode 100644 vendor/maistra.io/api/core/v1/helmvalues.go create mode 100644 vendor/maistra.io/api/core/v1/member_types.go create mode 100644 vendor/maistra.io/api/core/v1/memberroll_types.go create mode 100644 vendor/maistra.io/api/core/v1/status.go create mode 100644 vendor/maistra.io/api/core/v1/zz_generated.deepcopy.go create mode 100644 vendor/maistra.io/api/core/v1alpha1/conversion_generated.go rename pilot/pkg/status/distribution/resourcelock.go => vendor/maistra.io/api/core/v1alpha1/doc.go (78%) create mode 100644 vendor/maistra.io/api/core/v1alpha1/extension_conversion.go create mode 100644 vendor/maistra.io/api/core/v1alpha1/extension_types.go create mode 100644 vendor/maistra.io/api/core/v1alpha1/groupversion_info.go create mode 100644 vendor/maistra.io/api/core/v1alpha1/zz_generated.deepcopy.go create mode 100644 vendor/maistra.io/api/core/v2/addons.go create mode 100644 vendor/maistra.io/api/core/v2/cluster.go create mode 100644 vendor/maistra.io/api/core/v2/controlplane_types.go create mode 100644 vendor/maistra.io/api/core/v2/conversion.go create mode 100644 vendor/maistra.io/api/core/v2/datadog.go create mode 100644 vendor/maistra.io/api/core/v2/gateways.go create mode 100644 vendor/maistra.io/api/core/v2/general.go create mode 100644 vendor/maistra.io/api/core/v2/grafana.go create mode 100644 vendor/maistra.io/api/core/v2/groupversion_info.go create mode 100644 vendor/maistra.io/api/core/v2/jaeger.go create mode 100644 vendor/maistra.io/api/core/v2/kiali.go create mode 100644 vendor/maistra.io/api/core/v2/lightstep.go create mode 100644 vendor/maistra.io/api/core/v2/logging.go create mode 100644 vendor/maistra.io/api/core/v2/policy.go create mode 100644 vendor/maistra.io/api/core/v2/prometheus.go create mode 100644 vendor/maistra.io/api/core/v2/proxy.go create mode 100644 vendor/maistra.io/api/core/v2/runtime.go create mode 100644 vendor/maistra.io/api/core/v2/security.go create mode 100644 vendor/maistra.io/api/core/v2/smcp_new.yaml create mode 100644 vendor/maistra.io/api/core/v2/stackdriver.go create mode 100644 vendor/maistra.io/api/core/v2/telemetry.go create mode 100644 vendor/maistra.io/api/core/v2/threescale.go create mode 100644 vendor/maistra.io/api/core/v2/tracing.go create mode 100644 vendor/maistra.io/api/core/v2/zipkin.go create mode 100644 vendor/maistra.io/api/core/v2/zz_generated.deepcopy.go rename {pkg/servicemesh/apis/servicemesh => vendor/maistra.io/api/federation}/v1/doc.go (87%) create mode 100644 vendor/maistra.io/api/federation/v1/exportedserviceset_types.go create mode 100644 vendor/maistra.io/api/federation/v1/groupversion_info.go create mode 100644 vendor/maistra.io/api/federation/v1/import_export_mapping.go create mode 100644 vendor/maistra.io/api/federation/v1/importedserviceset_types.go create mode 100644 vendor/maistra.io/api/federation/v1/servicemeshpeer_types.go create mode 100644 vendor/maistra.io/api/federation/v1/zz_generated.deepcopy.go create mode 100644 vendor/maistra.io/api/security/v1/trustbundle.pb.go create mode 100644 vendor/maistra.io/api/security/v1/trustbundle.proto create mode 100644 vendor/maistra.io/api/security/v1/trustbundle_deepcopy.gen.go 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